Support reading/polling multiple registers
In Idle and Command mode it is now possible to specify a list of registers which shall be periodically read from the MMU. To keep the code and RAM size down registers are intentionally separated into 8bit and 16bit sets. Adding a register into the set is just a matter of parametrization, there is no need to change the state machines anymore.
This commit is contained in:
parent
ebb79351a7
commit
013ce588a5
|
|
@ -8,6 +8,17 @@ namespace MMU2 {
|
|||
|
||||
static const uint8_t supportedMmuFWVersion[3] PROGMEM = { 2, 1, 3 };
|
||||
|
||||
const uint8_t ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = {
|
||||
8, // FINDA state
|
||||
0x1b, // Selector slot
|
||||
0x1c, // Idler slot
|
||||
};
|
||||
|
||||
const uint8_t ProtocolLogic::regs16Addrs[ProtocolLogic::regs16Count] PROGMEM = {
|
||||
4, // MMU errors - aka statistics
|
||||
0x1a, // Pulley position [mm]
|
||||
};
|
||||
|
||||
void ProtocolLogic::CheckAndReportAsyncEvents() {
|
||||
// even when waiting for a query period, we need to report a change in filament sensor's state
|
||||
// - it is vital for a precise synchronization of moves of the printer and the MMU
|
||||
|
|
@ -22,9 +33,36 @@ void ProtocolLogic::SendQuery() {
|
|||
scopeState = ScopeState::QuerySent;
|
||||
}
|
||||
|
||||
void ProtocolLogic::SendFINDAQuery() {
|
||||
SendMsg(RequestMsg(RequestMsgCodes::Finda, 0));
|
||||
scopeState = ScopeState::FINDAReqSent;
|
||||
void ProtocolLogic::StartReading8bitRegisters() {
|
||||
regIndex = 0;
|
||||
SendReadRegister(pgm_read_byte(regs8Addrs + regIndex), ScopeState::Reading8bitRegisters);
|
||||
}
|
||||
|
||||
void ProtocolLogic::ProcessRead8bitRegister(){
|
||||
regs8[regIndex] = rsp.paramValue;
|
||||
++regIndex;
|
||||
if(regIndex >= regs8Count){
|
||||
// proceed with reading 16bit registers
|
||||
StartReading16bitRegisters();
|
||||
} else {
|
||||
SendReadRegister(pgm_read_byte(regs8Addrs + regIndex), ScopeState::Reading8bitRegisters);
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolLogic::StartReading16bitRegisters() {
|
||||
regIndex = 0;
|
||||
SendReadRegister(pgm_read_byte(regs16Addrs + regIndex), ScopeState::Reading16bitRegisters);
|
||||
}
|
||||
|
||||
ProtocolLogic::ScopeState __attribute__((noinline)) ProtocolLogic::ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd){
|
||||
regs16[regIndex] = rsp.paramValue;
|
||||
++regIndex;
|
||||
if(regIndex >= regs16Count){
|
||||
return stateAtEnd;
|
||||
} else {
|
||||
SendReadRegister(pgm_read_byte(regs16Addrs + regIndex), ScopeState::Reading16bitRegisters);
|
||||
}
|
||||
return ScopeState::Reading16bitRegisters;
|
||||
}
|
||||
|
||||
void ProtocolLogic::SendAndUpdateFilamentSensor() {
|
||||
|
|
@ -313,14 +351,13 @@ StepStatus ProtocolLogic::CommandStep() {
|
|||
case ScopeState::QuerySent:
|
||||
return ProcessCommandQueryResponse();
|
||||
case ScopeState::FilamentSensorStateSent:
|
||||
SendFINDAQuery();
|
||||
StartReading8bitRegisters();
|
||||
return Processing;
|
||||
case ScopeState::FINDAReqSent:
|
||||
findaPressed = rsp.paramValue;
|
||||
SendReadRegister(4, ScopeState::StatisticsSent);
|
||||
case ScopeState::Reading8bitRegisters:
|
||||
ProcessRead8bitRegister();
|
||||
return Processing;
|
||||
case ScopeState::StatisticsSent:
|
||||
scopeState = ScopeState::Wait;
|
||||
case ScopeState::Reading16bitRegisters:
|
||||
scopeState = ProcessRead16bitRegister(ScopeState::Wait);
|
||||
return Processing;
|
||||
case ScopeState::ButtonSent:
|
||||
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
||||
|
|
@ -371,7 +408,7 @@ StepStatus ProtocolLogic::IdleStep() {
|
|||
// The user pushed a button on the MMU. Save it, do what we need to do
|
||||
// to prepare, then pass it back to the MMU so it can work its magic.
|
||||
buttonCode = static_cast<Buttons>(rsp.paramValue);
|
||||
SendFINDAQuery();
|
||||
StartReading8bitRegisters();
|
||||
return ButtonPushed;
|
||||
case ResponseMsgParamCodes::Processing:
|
||||
// @@TODO we may actually use this branch to report progress of manual operation on the MMU
|
||||
|
|
@ -382,29 +419,27 @@ StepStatus ProtocolLogic::IdleStep() {
|
|||
break;
|
||||
default:
|
||||
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
||||
SendFINDAQuery(); // continue Idle state without restarting the communication
|
||||
StartReading8bitRegisters(); // continue Idle state without restarting the communication
|
||||
return CommandError;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ProtocolError;
|
||||
}
|
||||
SendFINDAQuery();
|
||||
StartReading8bitRegisters();
|
||||
return Processing;
|
||||
case ScopeState::FINDAReqSent:
|
||||
findaPressed = rsp.paramValue;
|
||||
SendReadRegister(4, ScopeState::StatisticsSent);
|
||||
case ScopeState::Reading8bitRegisters:
|
||||
ProcessRead8bitRegister();
|
||||
return Processing;
|
||||
case ScopeState::StatisticsSent:
|
||||
failStatistics = rsp.paramValue;
|
||||
scopeState = ScopeState::Ready;
|
||||
return Finished;
|
||||
case ScopeState::Reading16bitRegisters:
|
||||
scopeState = ProcessRead16bitRegister(ScopeState::Ready);
|
||||
return scopeState == ScopeState::Ready ? Finished : Processing;
|
||||
case ScopeState::ButtonSent:
|
||||
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
||||
// Button was accepted, decrement the retry.
|
||||
mmu2.DecrementRetryAttempts();
|
||||
}
|
||||
SendFINDAQuery();
|
||||
StartReading8bitRegisters();
|
||||
return Processing;
|
||||
case ScopeState::ReadRegisterSent:
|
||||
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
||||
|
|
@ -444,8 +479,9 @@ ProtocolLogic::ProtocolLogic(MMU2Serial *uart)
|
|||
, progressCode(ProgressCode::OK)
|
||||
, buttonCode(NoButton)
|
||||
, lastFSensor((uint8_t)WhereIsFilament())
|
||||
, findaPressed(false)
|
||||
, failStatistics(0)
|
||||
, regs8 { 0, 0, 0 }
|
||||
, regs16 { 0, 0 }
|
||||
, regIndex(0)
|
||||
, mmuFwVersion { 0, 0, 0 }
|
||||
{}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
// #include <array> //@@TODO Don't we have STL for AVR somewhere?
|
||||
template<typename T, uint8_t N>
|
||||
class array {
|
||||
|
|
@ -110,11 +111,11 @@ public:
|
|||
}
|
||||
|
||||
inline bool FindaPressed() const {
|
||||
return findaPressed;
|
||||
return regs8[0];
|
||||
}
|
||||
|
||||
inline uint16_t FailStatistics() const {
|
||||
return failStatistics;
|
||||
return regs16[0];
|
||||
}
|
||||
|
||||
inline uint8_t MmuFwVersionMajor() const {
|
||||
|
|
@ -187,10 +188,10 @@ private:
|
|||
QuerySent,
|
||||
CommandSent,
|
||||
FilamentSensorStateSent,
|
||||
FINDAReqSent,
|
||||
StatisticsSent,
|
||||
Reading8bitRegisters,
|
||||
Reading16bitRegisters,
|
||||
ButtonSent,
|
||||
ReadRegisterSent,
|
||||
ReadRegisterSent, // standalone requests for reading registers - from higher layers
|
||||
WriteRegisterSent,
|
||||
|
||||
// States which do not expect a message - MSb set
|
||||
|
|
@ -217,7 +218,10 @@ private:
|
|||
/// So far, the only such a case is the filament sensor, but there can be more like this in the future.
|
||||
void CheckAndReportAsyncEvents();
|
||||
void SendQuery();
|
||||
void SendFINDAQuery();
|
||||
void StartReading8bitRegisters();
|
||||
void ProcessRead8bitRegister();
|
||||
void StartReading16bitRegisters();
|
||||
ScopeState ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd);
|
||||
void SendAndUpdateFilamentSensor();
|
||||
void SendButton(uint8_t btn);
|
||||
void SendVersion(uint8_t stage);
|
||||
|
|
@ -278,7 +282,7 @@ private:
|
|||
State state; ///< internal state of ProtocolLogic
|
||||
|
||||
Protocol protocol; ///< protocol codec
|
||||
|
||||
|
||||
array<uint8_t, 16> lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes
|
||||
uint8_t lrb;
|
||||
|
||||
|
|
@ -290,8 +294,19 @@ private:
|
|||
|
||||
uint8_t lastFSensor; ///< last state of filament sensor
|
||||
|
||||
bool findaPressed;
|
||||
uint16_t failStatistics;
|
||||
// 8bit registers
|
||||
static constexpr uint8_t regs8Count = 3;
|
||||
static_assert(regs8Count > 0); // code is not ready for empty lists of registers
|
||||
static const uint8_t regs8Addrs[regs8Count] PROGMEM;
|
||||
uint8_t regs8[regs8Count];
|
||||
|
||||
// 16bit registers
|
||||
static constexpr uint8_t regs16Count = 2;
|
||||
static_assert(regs16Count > 0); // code is not ready for empty lists of registers
|
||||
static const uint8_t regs16Addrs[regs16Count] PROGMEM;
|
||||
uint16_t regs16[regs16Count];
|
||||
|
||||
uint8_t regIndex;
|
||||
|
||||
uint8_t mmuFwVersion[3];
|
||||
uint16_t mmuFwVersionBuild;
|
||||
|
|
|
|||
Loading…
Reference in New Issue