Skip to content

Commit 013ce58

Browse files
D.R.racerDRracer
D.R.racer
authored andcommitted
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.
1 parent ebb7935 commit 013ce58

File tree

2 files changed

+82
-31
lines changed

2 files changed

+82
-31
lines changed

Firmware/mmu2_protocol_logic.cpp

+58-22
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ namespace MMU2 {
88

99
static const uint8_t supportedMmuFWVersion[3] PROGMEM = { 2, 1, 3 };
1010

11+
const uint8_t ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = {
12+
8, // FINDA state
13+
0x1b, // Selector slot
14+
0x1c, // Idler slot
15+
};
16+
17+
const uint8_t ProtocolLogic::regs16Addrs[ProtocolLogic::regs16Count] PROGMEM = {
18+
4, // MMU errors - aka statistics
19+
0x1a, // Pulley position [mm]
20+
};
21+
1122
void ProtocolLogic::CheckAndReportAsyncEvents() {
1223
// even when waiting for a query period, we need to report a change in filament sensor's state
1324
// - it is vital for a precise synchronization of moves of the printer and the MMU
@@ -22,9 +33,36 @@ void ProtocolLogic::SendQuery() {
2233
scopeState = ScopeState::QuerySent;
2334
}
2435

25-
void ProtocolLogic::SendFINDAQuery() {
26-
SendMsg(RequestMsg(RequestMsgCodes::Finda, 0));
27-
scopeState = ScopeState::FINDAReqSent;
36+
void ProtocolLogic::StartReading8bitRegisters() {
37+
regIndex = 0;
38+
SendReadRegister(pgm_read_byte(regs8Addrs + regIndex), ScopeState::Reading8bitRegisters);
39+
}
40+
41+
void ProtocolLogic::ProcessRead8bitRegister(){
42+
regs8[regIndex] = rsp.paramValue;
43+
++regIndex;
44+
if(regIndex >= regs8Count){
45+
// proceed with reading 16bit registers
46+
StartReading16bitRegisters();
47+
} else {
48+
SendReadRegister(pgm_read_byte(regs8Addrs + regIndex), ScopeState::Reading8bitRegisters);
49+
}
50+
}
51+
52+
void ProtocolLogic::StartReading16bitRegisters() {
53+
regIndex = 0;
54+
SendReadRegister(pgm_read_byte(regs16Addrs + regIndex), ScopeState::Reading16bitRegisters);
55+
}
56+
57+
ProtocolLogic::ScopeState __attribute__((noinline)) ProtocolLogic::ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd){
58+
regs16[regIndex] = rsp.paramValue;
59+
++regIndex;
60+
if(regIndex >= regs16Count){
61+
return stateAtEnd;
62+
} else {
63+
SendReadRegister(pgm_read_byte(regs16Addrs + regIndex), ScopeState::Reading16bitRegisters);
64+
}
65+
return ScopeState::Reading16bitRegisters;
2866
}
2967

3068
void ProtocolLogic::SendAndUpdateFilamentSensor() {
@@ -313,14 +351,13 @@ StepStatus ProtocolLogic::CommandStep() {
313351
case ScopeState::QuerySent:
314352
return ProcessCommandQueryResponse();
315353
case ScopeState::FilamentSensorStateSent:
316-
SendFINDAQuery();
354+
StartReading8bitRegisters();
317355
return Processing;
318-
case ScopeState::FINDAReqSent:
319-
findaPressed = rsp.paramValue;
320-
SendReadRegister(4, ScopeState::StatisticsSent);
356+
case ScopeState::Reading8bitRegisters:
357+
ProcessRead8bitRegister();
321358
return Processing;
322-
case ScopeState::StatisticsSent:
323-
scopeState = ScopeState::Wait;
359+
case ScopeState::Reading16bitRegisters:
360+
scopeState = ProcessRead16bitRegister(ScopeState::Wait);
324361
return Processing;
325362
case ScopeState::ButtonSent:
326363
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
@@ -371,7 +408,7 @@ StepStatus ProtocolLogic::IdleStep() {
371408
// The user pushed a button on the MMU. Save it, do what we need to do
372409
// to prepare, then pass it back to the MMU so it can work its magic.
373410
buttonCode = static_cast<Buttons>(rsp.paramValue);
374-
SendFINDAQuery();
411+
StartReading8bitRegisters();
375412
return ButtonPushed;
376413
case ResponseMsgParamCodes::Processing:
377414
// @@TODO we may actually use this branch to report progress of manual operation on the MMU
@@ -382,29 +419,27 @@ StepStatus ProtocolLogic::IdleStep() {
382419
break;
383420
default:
384421
errorCode = static_cast<ErrorCode>(rsp.paramValue);
385-
SendFINDAQuery(); // continue Idle state without restarting the communication
422+
StartReading8bitRegisters(); // continue Idle state without restarting the communication
386423
return CommandError;
387424
}
388425
break;
389426
default:
390427
return ProtocolError;
391428
}
392-
SendFINDAQuery();
429+
StartReading8bitRegisters();
393430
return Processing;
394-
case ScopeState::FINDAReqSent:
395-
findaPressed = rsp.paramValue;
396-
SendReadRegister(4, ScopeState::StatisticsSent);
431+
case ScopeState::Reading8bitRegisters:
432+
ProcessRead8bitRegister();
397433
return Processing;
398-
case ScopeState::StatisticsSent:
399-
failStatistics = rsp.paramValue;
400-
scopeState = ScopeState::Ready;
401-
return Finished;
434+
case ScopeState::Reading16bitRegisters:
435+
scopeState = ProcessRead16bitRegister(ScopeState::Ready);
436+
return scopeState == ScopeState::Ready ? Finished : Processing;
402437
case ScopeState::ButtonSent:
403438
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
404439
// Button was accepted, decrement the retry.
405440
mmu2.DecrementRetryAttempts();
406441
}
407-
SendFINDAQuery();
442+
StartReading8bitRegisters();
408443
return Processing;
409444
case ScopeState::ReadRegisterSent:
410445
if (rsp.paramCode == ResponseMsgParamCodes::Accepted) {
@@ -444,8 +479,9 @@ ProtocolLogic::ProtocolLogic(MMU2Serial *uart)
444479
, progressCode(ProgressCode::OK)
445480
, buttonCode(NoButton)
446481
, lastFSensor((uint8_t)WhereIsFilament())
447-
, findaPressed(false)
448-
, failStatistics(0)
482+
, regs8 { 0, 0, 0 }
483+
, regs16 { 0, 0 }
484+
, regIndex(0)
449485
, mmuFwVersion { 0, 0, 0 }
450486
{}
451487

Firmware/mmu2_protocol_logic.h

+24-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <stdint.h>
3+
#include <avr/pgmspace.h>
34
// #include <array> //@@TODO Don't we have STL for AVR somewhere?
45
template<typename T, uint8_t N>
56
class array {
@@ -110,11 +111,11 @@ class ProtocolLogic {
110111
}
111112

112113
inline bool FindaPressed() const {
113-
return findaPressed;
114+
return regs8[0];
114115
}
115116

116117
inline uint16_t FailStatistics() const {
117-
return failStatistics;
118+
return regs16[0];
118119
}
119120

120121
inline uint8_t MmuFwVersionMajor() const {
@@ -187,10 +188,10 @@ class ProtocolLogic {
187188
QuerySent,
188189
CommandSent,
189190
FilamentSensorStateSent,
190-
FINDAReqSent,
191-
StatisticsSent,
191+
Reading8bitRegisters,
192+
Reading16bitRegisters,
192193
ButtonSent,
193-
ReadRegisterSent,
194+
ReadRegisterSent, // standalone requests for reading registers - from higher layers
194195
WriteRegisterSent,
195196

196197
// States which do not expect a message - MSb set
@@ -217,7 +218,10 @@ class ProtocolLogic {
217218
/// So far, the only such a case is the filament sensor, but there can be more like this in the future.
218219
void CheckAndReportAsyncEvents();
219220
void SendQuery();
220-
void SendFINDAQuery();
221+
void StartReading8bitRegisters();
222+
void ProcessRead8bitRegister();
223+
void StartReading16bitRegisters();
224+
ScopeState ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd);
221225
void SendAndUpdateFilamentSensor();
222226
void SendButton(uint8_t btn);
223227
void SendVersion(uint8_t stage);
@@ -278,7 +282,7 @@ class ProtocolLogic {
278282
State state; ///< internal state of ProtocolLogic
279283

280284
Protocol protocol; ///< protocol codec
281-
285+
282286
array<uint8_t, 16> lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes
283287
uint8_t lrb;
284288

@@ -290,8 +294,19 @@ class ProtocolLogic {
290294

291295
uint8_t lastFSensor; ///< last state of filament sensor
292296

293-
bool findaPressed;
294-
uint16_t failStatistics;
297+
// 8bit registers
298+
static constexpr uint8_t regs8Count = 3;
299+
static_assert(regs8Count > 0); // code is not ready for empty lists of registers
300+
static const uint8_t regs8Addrs[regs8Count] PROGMEM;
301+
uint8_t regs8[regs8Count];
302+
303+
// 16bit registers
304+
static constexpr uint8_t regs16Count = 2;
305+
static_assert(regs16Count > 0); // code is not ready for empty lists of registers
306+
static const uint8_t regs16Addrs[regs16Count] PROGMEM;
307+
uint16_t regs16[regs16Count];
308+
309+
uint8_t regIndex;
295310

296311
uint8_t mmuFwVersion[3];
297312
uint16_t mmuFwVersionBuild;

0 commit comments

Comments
 (0)