Prusa3d Marlin fork
mmu2_protocol.h
1 #pragma once
3 #include <stdint.h>
4 #include "mmu2_crc.h"
5 
6 namespace modules {
7 
11 namespace protocol {
12 
14 enum class RequestMsgCodes : uint8_t {
15  unknown = 0,
16  Query = 'Q',
17  Tool = 'T',
18  Load = 'L',
19  Mode = 'M',
20  Unload = 'U',
21  Reset = 'X',
22  Finda = 'P',
23  Version = 'S',
24  Button = 'B',
25  Eject = 'E',
26  Write = 'W',
27  Cut = 'K',
28  FilamentType = 'F',
29  FilamentSensor = 'f',
30  Home = 'H',
31  Read = 'R'
32 };
33 
35 enum class ResponseMsgParamCodes : uint8_t {
36  unknown = 0,
37  Processing = 'P',
38  Error = 'E',
39  Finished = 'F',
40  Accepted = 'A',
41  Rejected = 'R',
42  Button = 'B' // the MMU registered a button press and is sending it to the printer for processing
43 };
44 
46 struct RequestMsg {
48  uint8_t value;
49  uint16_t value2;
50 
54  uint8_t crc8;
55 
56  constexpr uint8_t ComputeCRC8() const {
57  uint8_t crc = 0;
58  crc = modules::crc::CRC8::CCITT_updateCX(0, (uint8_t)code);
59  crc = modules::crc::CRC8::CCITT_updateCX(crc, value);
61  return crc;
62  }
63 
66  inline constexpr RequestMsg(RequestMsgCodes code, uint8_t value)
67  : code(code)
68  , value(value)
69  , value2(0)
70  , crc8(ComputeCRC8()) {
71  }
72 
77  inline constexpr RequestMsg(RequestMsgCodes code, uint8_t address, uint16_t value)
78  : code(code)
79  , value(address)
80  , value2(value)
81  , crc8(ComputeCRC8()) {
82  }
83 
84  constexpr uint8_t CRC() const { return crc8; }
85 };
86 
88 struct ResponseMsg {
91  uint16_t paramValue;
92 
93  constexpr uint8_t ComputeCRC8() const {
94  uint8_t crc = request.ComputeCRC8();
95  crc = modules::crc::CRC8::CCITT_updateCX(crc, (uint8_t)paramCode);
97  return crc;
98  }
99 
104  : request(request)
107  this->request.crc8 = ComputeCRC8();
108  }
109 
110  constexpr uint8_t CRC() const { return request.crc8; }
111 };
112 
116  uint16_t value;
117  inline constexpr ResponseCommandStatus(ResponseMsgParamCodes code, uint16_t value)
118  : code(code)
119  , value(value) {}
120 };
121 
123 enum class DecodeStatus : uint_fast8_t {
125  NeedMoreData,
126  Error,
127 };
128 
133 class Protocol {
134 public:
135  inline Protocol()
136  : rqState(RequestStates::Code)
137  , requestMsg(RequestMsgCodes::unknown, 0)
138  , rspState(ResponseStates::RequestCode)
139  , responseMsg(RequestMsg(RequestMsgCodes::unknown, 0), ResponseMsgParamCodes::unknown, 0) {
140  }
141 
144  DecodeStatus DecodeRequest(uint8_t c);
145 
148  DecodeStatus DecodeResponse(uint8_t c);
149 
153  static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff);
154 
158  static uint8_t EncodeWriteRequest(uint8_t address, uint16_t value, uint8_t *txbuff);
159 
162  static constexpr uint8_t MaxRequestSize() { return 13; }
163 
166  static constexpr uint8_t MaxResponseSize() { return 14; }
167 
173  static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
174 
180  static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
181 
182 
183 
184 
185 
186 
187 
188 
195  static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseCommandStatus rcs, uint8_t *txbuff);
196 
203  static uint8_t EncodeResponseRead(const RequestMsg &msg, bool accepted, uint16_t value2, uint8_t *txbuff);
204 
206  inline const RequestMsg GetRequestMsg() const { return requestMsg; }
207 
209  inline const ResponseMsg GetResponseMsg() const { return responseMsg; }
210 
213  rqState = RequestStates::Code;
214  }
215 
218  rspState = ResponseStates::RequestCode;
219  }
220 
221 #ifndef UNITTEST
222 private:
223 #endif
224  enum class RequestStates : uint8_t {
225  Code,
226  Value,
227  Address,
228  WriteValue,
229  CRC,
230  Error
231  };
232 
233  RequestStates rqState;
234  RequestMsg requestMsg;
235 
236  enum class ResponseStates : uint8_t {
237  RequestCode,
238  RequestValue,
239  ParamCode,
240  ParamValue,
241  CRC,
242  Error
243  };
244 
245  ResponseStates rspState;
246  ResponseMsg responseMsg;
247 
248  static constexpr bool IsNewLine(uint8_t c) {
249  return c == '\n' || c == '\r';
250  }
251  static constexpr bool IsDigit(uint8_t c) {
252  return c >= '0' && c <= '9';
253  }
254  static constexpr bool IsCRCSeparator(uint8_t c) {
255  return c == '*';
256  }
257  static constexpr bool IsHexDigit(uint8_t c) {
258  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
259  }
260  static constexpr uint8_t Char2Nibble(uint8_t c) {
261  switch (c) {
262  case '0':
263  case '1':
264  case '2':
265  case '3':
266  case '4':
267  case '5':
268  case '6':
269  case '7':
270  case '8':
271  case '9':
272  return c - '0';
273  case 'a':
274  case 'b':
275  case 'c':
276  case 'd':
277  case 'e':
278  case 'f':
279  return c - 'a' + 10;
280  default:
281  return 0;
282  }
283  }
284 
285  static constexpr uint8_t Nibble2Char(uint8_t n) {
286  switch (n) {
287  case 0:
288  case 1:
289  case 2:
290  case 3:
291  case 4:
292  case 5:
293  case 6:
294  case 7:
295  case 8:
296  case 9:
297  return n + '0';
298  case 0xa:
299  case 0xb:
300  case 0xc:
301  case 0xd:
302  case 0xe:
303  case 0xf:
304  return n - 10 + 'a';
305  default:
306  return 0;
307  }
308  }
309 
311  static uint8_t UInt8ToHex(uint8_t value, uint8_t *dst);
312 
314  static uint8_t UInt16ToHex(uint16_t value, uint8_t *dst);
315 
316  static uint8_t BeginEncodeRequest(const RequestMsg &msg, uint8_t *dst);
317 
318  static uint8_t AppendCRC(uint8_t crc, uint8_t *dst);
319 };
320 
321 } // namespace protocol
322 } // namespace modules
323 
324 namespace mp = modules::protocol;
static constexpr uint8_t CCITT_updateW(uint8_t crc, uint16_t w)
Compute/update CRC8 CCIIT from 16bits (convenience wrapper)
Definition: mmu2_crc.h:33
Definition: mmu2_protocol.h:133
static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff)
Definition: mmu2_protocol.cpp:132
static uint8_t EncodeWriteRequest(uint8_t address, uint16_t value, uint8_t *txbuff)
Definition: mmu2_protocol.cpp:144
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff)
Definition: mmu2_protocol.cpp:284
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseCommandStatus rcs, uint8_t *txbuff)
Definition: mmu2_protocol.cpp:288
DecodeStatus DecodeRequest(uint8_t c)
Definition: mmu2_protocol.cpp:29
const ResponseMsg GetResponseMsg() const
Definition: mmu2_protocol.h:209
static uint8_t EncodeResponseRead(const RequestMsg &msg, bool accepted, uint16_t value2, uint8_t *txbuff)
Definition: mmu2_protocol.cpp:299
static constexpr uint8_t MaxRequestSize()
Definition: mmu2_protocol.h:162
void ResetRequestDecoder()
resets the internal request decoding state (typically after an error)
Definition: mmu2_protocol.h:212
DecodeStatus DecodeResponse(uint8_t c)
Definition: mmu2_protocol.cpp:157
static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff)
Definition: mmu2_protocol.cpp:265
static constexpr uint8_t MaxResponseSize()
Definition: mmu2_protocol.h:166
void ResetResponseDecoder()
resets the internal response decoding state (typically after an error)
Definition: mmu2_protocol.h:217
const RequestMsg GetRequestMsg() const
Definition: mmu2_protocol.h:206
The MMU communication protocol implementation and related stuff.
Definition: mmu2_protocol.cpp:15
DecodeStatus
Message decoding return values.
Definition: mmu2_protocol.h:123
@ MessageCompleted
message completed and successfully lexed
@ Error
input character broke message decoding
@ NeedMoreData
message incomplete yet, waiting for another byte to come
ResponseMsgParamCodes
Definition of response message parameter codes.
Definition: mmu2_protocol.h:35
RequestMsgCodes
Definition of request message codes.
Definition: mmu2_protocol.h:14
A request message - requests are being sent by the printer into the MMU.
Definition: mmu2_protocol.h:46
constexpr RequestMsg(RequestMsgCodes code, uint8_t value)
Definition: mmu2_protocol.h:66
uint16_t value2
in case or write messages - value to be written into the register
Definition: mmu2_protocol.h:49
uint8_t crc8
Definition: mmu2_protocol.h:54
uint8_t value
value of the request message or address of variable to read/write
Definition: mmu2_protocol.h:48
constexpr RequestMsg(RequestMsgCodes code, uint8_t address, uint16_t value)
Definition: mmu2_protocol.h:77
RequestMsgCodes code
code of the request message
Definition: mmu2_protocol.h:47
Combined commandStatus and its value into one data structure (optimization purposes)
Definition: mmu2_protocol.h:114
A response message - responses are being sent from the MMU into the printer as a response to a reques...
Definition: mmu2_protocol.h:88
ResponseMsgParamCodes paramCode
code of the parameter
Definition: mmu2_protocol.h:90
uint16_t paramValue
value of the parameter
Definition: mmu2_protocol.h:91
RequestMsg request
response is always preceeded by the request message
Definition: mmu2_protocol.h:89
constexpr ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint16_t paramValue)
Definition: mmu2_protocol.h:103