mmu2_protocol.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /// @file protocol.h
  2. #pragma once
  3. #include <stdint.h>
  4. namespace modules {
  5. /// @brief The MMU communication protocol implementation and related stuff.
  6. ///
  7. /// See description of the new protocol in the MMU 2021 doc
  8. /// @@TODO possibly add some checksum to verify the correctness of messages
  9. namespace protocol {
  10. /// Definition of request message codes
  11. enum class RequestMsgCodes : uint8_t {
  12. unknown = 0,
  13. Query = 'Q',
  14. Tool = 'T',
  15. Load = 'L',
  16. Mode = 'M',
  17. Unload = 'U',
  18. Reset = 'X',
  19. Finda = 'P',
  20. Version = 'S',
  21. Button = 'B',
  22. Eject = 'E',
  23. Wait = 'W',
  24. Cut = 'K',
  25. FilamentType = 'F',
  26. FilamentSensor = 'f',
  27. Home = 'H'
  28. };
  29. /// Definition of response message parameter codes
  30. enum class ResponseMsgParamCodes : uint8_t {
  31. unknown = 0,
  32. Processing = 'P',
  33. Error = 'E',
  34. Finished = 'F',
  35. Accepted = 'A',
  36. Rejected = 'R'
  37. };
  38. /// A request message - requests are being sent by the printer into the MMU.
  39. struct RequestMsg {
  40. RequestMsgCodes code; ///< code of the request message
  41. uint8_t value; ///< value of the request message
  42. /// @param code of the request message
  43. /// @param value of the request message
  44. inline RequestMsg(RequestMsgCodes code, uint8_t value)
  45. : code(code)
  46. , value(value) {}
  47. };
  48. /// A response message - responses are being sent from the MMU into the printer as a response to a request message.
  49. struct ResponseMsg {
  50. RequestMsg request; ///< response is always preceeded by the request message
  51. ResponseMsgParamCodes paramCode; ///< code of the parameter
  52. uint16_t paramValue; ///< value of the parameter
  53. /// @param request the source request message this response is a reply to
  54. /// @param paramCode code of the parameter
  55. /// @param paramValue value of the parameter
  56. inline ResponseMsg(RequestMsg request, ResponseMsgParamCodes paramCode, uint16_t paramValue)
  57. : request(request)
  58. , paramCode(paramCode)
  59. , paramValue(paramValue) {}
  60. };
  61. /// Message decoding return values
  62. enum class DecodeStatus : uint_fast8_t {
  63. MessageCompleted, ///< message completed and successfully lexed
  64. NeedMoreData, ///< message incomplete yet, waiting for another byte to come
  65. Error, ///< input character broke message decoding
  66. };
  67. /// Protocol class is responsible for creating/decoding messages in Rx/Tx buffer
  68. ///
  69. /// Beware - in the decoding more, it is meant to be a statefull instance which works through public methods
  70. /// processing one input byte per call.
  71. class Protocol {
  72. public:
  73. inline Protocol()
  74. : rqState(RequestStates::Code)
  75. , requestMsg(RequestMsgCodes::unknown, 0)
  76. , rspState(ResponseStates::RequestCode)
  77. , responseMsg(RequestMsg(RequestMsgCodes::unknown, 0), ResponseMsgParamCodes::unknown, 0) {
  78. }
  79. /// Takes the input byte c and steps one step through the state machine
  80. /// @returns state of the message being decoded
  81. DecodeStatus DecodeRequest(uint8_t c);
  82. /// Decodes response message in rxbuff
  83. /// @returns decoded response message structure
  84. DecodeStatus DecodeResponse(uint8_t c);
  85. /// Encodes request message msg into txbuff memory
  86. /// It is expected the txbuff is large enough to fit the message
  87. /// @returns number of bytes written into txbuff
  88. static uint8_t EncodeRequest(const RequestMsg &msg, uint8_t *txbuff);
  89. /// @returns the maximum byte length necessary to encode a request message
  90. /// Beneficial in case of pre-allocating a buffer for enconding a RequestMsg.
  91. static constexpr uint8_t MaxRequestSize() { return 3; }
  92. /// Encode generic response Command Accepted or Rejected
  93. /// @param msg source request message for this response
  94. /// @param ar code of response parameter
  95. /// @param txbuff where to format the message
  96. /// @returns number of bytes written into txbuff
  97. static uint8_t EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff);
  98. /// Encode response to Read FINDA query
  99. /// @param msg source request message for this response
  100. /// @param findaValue 1/0 (on/off) status of FINDA
  101. /// @param txbuff where to format the message
  102. /// @returns number of bytes written into txbuff
  103. static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
  104. /// Encode response to Version query
  105. /// @param msg source request message for this response
  106. /// @param value version number (0-255)
  107. /// @param txbuff where to format the message
  108. /// @returns number of bytes written into txbuff
  109. static uint8_t EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff);
  110. /// Encode response to Query operation status
  111. /// @param msg source request message for this response
  112. /// @param code status of operation (Processing, Error, Finished)
  113. /// @param value related to status of operation(e.g. error code or progress)
  114. /// @param txbuff where to format the message
  115. /// @returns number of bytes written into txbuff
  116. static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint16_t value, uint8_t *txbuff);
  117. /// @returns the most recently lexed request message
  118. inline const RequestMsg GetRequestMsg() const { return requestMsg; }
  119. /// @returns the most recently lexed response message
  120. inline const ResponseMsg GetResponseMsg() const { return responseMsg; }
  121. /// resets the internal request decoding state (typically after an error)
  122. void ResetRequestDecoder() {
  123. rqState = RequestStates::Code;
  124. }
  125. /// resets the internal response decoding state (typically after an error)
  126. void ResetResponseDecoder() {
  127. rspState = ResponseStates::RequestCode;
  128. }
  129. private:
  130. enum class RequestStates : uint8_t {
  131. Code, ///< starting state - expects message code
  132. Value, ///< expecting code value
  133. Error ///< automaton in error state
  134. };
  135. RequestStates rqState;
  136. RequestMsg requestMsg;
  137. enum class ResponseStates : uint8_t {
  138. RequestCode, ///< starting state - expects message code
  139. RequestValue, ///< expecting code value
  140. ParamCode, ///< expecting param code
  141. ParamValue, ///< expecting param value
  142. Error ///< automaton in error state
  143. };
  144. ResponseStates rspState;
  145. ResponseMsg responseMsg;
  146. static bool IsNewLine(uint8_t c) {
  147. return c == '\n' || c == '\r';
  148. }
  149. static bool IsDigit(uint8_t c) {
  150. return c >= '0' && c <= '9';
  151. }
  152. };
  153. } // namespace protocol
  154. } // namespace modules
  155. namespace mp = modules::protocol;