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 };
|
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() {
|
void ProtocolLogic::CheckAndReportAsyncEvents() {
|
||||||
// even when waiting for a query period, we need to report a change in filament sensor's state
|
// 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
|
// - 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;
|
scopeState = ScopeState::QuerySent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolLogic::SendFINDAQuery() {
|
void ProtocolLogic::StartReading8bitRegisters() {
|
||||||
SendMsg(RequestMsg(RequestMsgCodes::Finda, 0));
|
regIndex = 0;
|
||||||
scopeState = ScopeState::FINDAReqSent;
|
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() {
|
void ProtocolLogic::SendAndUpdateFilamentSensor() {
|
||||||
|
|
@ -313,14 +351,13 @@ StepStatus ProtocolLogic::CommandStep() {
|
||||||
case ScopeState::QuerySent:
|
case ScopeState::QuerySent:
|
||||||
return ProcessCommandQueryResponse();
|
return ProcessCommandQueryResponse();
|
||||||
case ScopeState::FilamentSensorStateSent:
|
case ScopeState::FilamentSensorStateSent:
|
||||||
SendFINDAQuery();
|
StartReading8bitRegisters();
|
||||||
return Processing;
|
return Processing;
|
||||||
case ScopeState::FINDAReqSent:
|
case ScopeState::Reading8bitRegisters:
|
||||||
findaPressed = rsp.paramValue;
|
ProcessRead8bitRegister();
|
||||||
SendReadRegister(4, ScopeState::StatisticsSent);
|
|
||||||
return Processing;
|
return Processing;
|
||||||
case ScopeState::StatisticsSent:
|
case ScopeState::Reading16bitRegisters:
|
||||||
scopeState = ScopeState::Wait;
|
scopeState = ProcessRead16bitRegister(ScopeState::Wait);
|
||||||
return Processing;
|
return Processing;
|
||||||
case ScopeState::ButtonSent:
|
case ScopeState::ButtonSent:
|
||||||
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
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
|
// 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.
|
// to prepare, then pass it back to the MMU so it can work its magic.
|
||||||
buttonCode = static_cast<Buttons>(rsp.paramValue);
|
buttonCode = static_cast<Buttons>(rsp.paramValue);
|
||||||
SendFINDAQuery();
|
StartReading8bitRegisters();
|
||||||
return ButtonPushed;
|
return ButtonPushed;
|
||||||
case ResponseMsgParamCodes::Processing:
|
case ResponseMsgParamCodes::Processing:
|
||||||
// @@TODO we may actually use this branch to report progress of manual operation on the MMU
|
// @@TODO we may actually use this branch to report progress of manual operation on the MMU
|
||||||
|
|
@ -382,29 +419,27 @@ StepStatus ProtocolLogic::IdleStep() {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
||||||
SendFINDAQuery(); // continue Idle state without restarting the communication
|
StartReading8bitRegisters(); // continue Idle state without restarting the communication
|
||||||
return CommandError;
|
return CommandError;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ProtocolError;
|
return ProtocolError;
|
||||||
}
|
}
|
||||||
SendFINDAQuery();
|
StartReading8bitRegisters();
|
||||||
return Processing;
|
return Processing;
|
||||||
case ScopeState::FINDAReqSent:
|
case ScopeState::Reading8bitRegisters:
|
||||||
findaPressed = rsp.paramValue;
|
ProcessRead8bitRegister();
|
||||||
SendReadRegister(4, ScopeState::StatisticsSent);
|
|
||||||
return Processing;
|
return Processing;
|
||||||
case ScopeState::StatisticsSent:
|
case ScopeState::Reading16bitRegisters:
|
||||||
failStatistics = rsp.paramValue;
|
scopeState = ProcessRead16bitRegister(ScopeState::Ready);
|
||||||
scopeState = ScopeState::Ready;
|
return scopeState == ScopeState::Ready ? Finished : Processing;
|
||||||
return Finished;
|
|
||||||
case ScopeState::ButtonSent:
|
case ScopeState::ButtonSent:
|
||||||
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
||||||
// Button was accepted, decrement the retry.
|
// Button was accepted, decrement the retry.
|
||||||
mmu2.DecrementRetryAttempts();
|
mmu2.DecrementRetryAttempts();
|
||||||
}
|
}
|
||||||
SendFINDAQuery();
|
StartReading8bitRegisters();
|
||||||
return Processing;
|
return Processing;
|
||||||
case ScopeState::ReadRegisterSent:
|
case ScopeState::ReadRegisterSent:
|
||||||
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
|
||||||
|
|
@ -444,8 +479,9 @@ ProtocolLogic::ProtocolLogic(MMU2Serial *uart)
|
||||||
, progressCode(ProgressCode::OK)
|
, progressCode(ProgressCode::OK)
|
||||||
, buttonCode(NoButton)
|
, buttonCode(NoButton)
|
||||||
, lastFSensor((uint8_t)WhereIsFilament())
|
, lastFSensor((uint8_t)WhereIsFilament())
|
||||||
, findaPressed(false)
|
, regs8 { 0, 0, 0 }
|
||||||
, failStatistics(0)
|
, regs16 { 0, 0 }
|
||||||
|
, regIndex(0)
|
||||||
, mmuFwVersion { 0, 0, 0 }
|
, mmuFwVersion { 0, 0, 0 }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
// #include <array> //@@TODO Don't we have STL for AVR somewhere?
|
// #include <array> //@@TODO Don't we have STL for AVR somewhere?
|
||||||
template<typename T, uint8_t N>
|
template<typename T, uint8_t N>
|
||||||
class array {
|
class array {
|
||||||
|
|
@ -110,11 +111,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool FindaPressed() const {
|
inline bool FindaPressed() const {
|
||||||
return findaPressed;
|
return regs8[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16_t FailStatistics() const {
|
inline uint16_t FailStatistics() const {
|
||||||
return failStatistics;
|
return regs16[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t MmuFwVersionMajor() const {
|
inline uint8_t MmuFwVersionMajor() const {
|
||||||
|
|
@ -187,10 +188,10 @@ private:
|
||||||
QuerySent,
|
QuerySent,
|
||||||
CommandSent,
|
CommandSent,
|
||||||
FilamentSensorStateSent,
|
FilamentSensorStateSent,
|
||||||
FINDAReqSent,
|
Reading8bitRegisters,
|
||||||
StatisticsSent,
|
Reading16bitRegisters,
|
||||||
ButtonSent,
|
ButtonSent,
|
||||||
ReadRegisterSent,
|
ReadRegisterSent, // standalone requests for reading registers - from higher layers
|
||||||
WriteRegisterSent,
|
WriteRegisterSent,
|
||||||
|
|
||||||
// States which do not expect a message - MSb set
|
// 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.
|
/// So far, the only such a case is the filament sensor, but there can be more like this in the future.
|
||||||
void CheckAndReportAsyncEvents();
|
void CheckAndReportAsyncEvents();
|
||||||
void SendQuery();
|
void SendQuery();
|
||||||
void SendFINDAQuery();
|
void StartReading8bitRegisters();
|
||||||
|
void ProcessRead8bitRegister();
|
||||||
|
void StartReading16bitRegisters();
|
||||||
|
ScopeState ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd);
|
||||||
void SendAndUpdateFilamentSensor();
|
void SendAndUpdateFilamentSensor();
|
||||||
void SendButton(uint8_t btn);
|
void SendButton(uint8_t btn);
|
||||||
void SendVersion(uint8_t stage);
|
void SendVersion(uint8_t stage);
|
||||||
|
|
@ -278,7 +282,7 @@ private:
|
||||||
State state; ///< internal state of ProtocolLogic
|
State state; ///< internal state of ProtocolLogic
|
||||||
|
|
||||||
Protocol protocol; ///< protocol codec
|
Protocol protocol; ///< protocol codec
|
||||||
|
|
||||||
array<uint8_t, 16> lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes
|
array<uint8_t, 16> lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes
|
||||||
uint8_t lrb;
|
uint8_t lrb;
|
||||||
|
|
||||||
|
|
@ -290,8 +294,19 @@ private:
|
||||||
|
|
||||||
uint8_t lastFSensor; ///< last state of filament sensor
|
uint8_t lastFSensor; ///< last state of filament sensor
|
||||||
|
|
||||||
bool findaPressed;
|
// 8bit registers
|
||||||
uint16_t failStatistics;
|
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];
|
uint8_t mmuFwVersion[3];
|
||||||
uint16_t mmuFwVersionBuild;
|
uint16_t mmuFwVersionBuild;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue