mmu2_protocol.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /// @file
  2. #include "mmu2_protocol.h"
  3. // protocol definition
  4. // command: Q0
  5. // meaning: query operation status
  6. // Query/command: query
  7. // Expected reply from the MMU:
  8. // any of the running operation statuses: OID: [T|L|U|E|C|W|K][0-4]
  9. // <OID> P[0-9] : command being processed i.e. operation running, may contain a state number
  10. // <OID> E[0-9][0-9] : error 1-9 while doing a tool change
  11. // <OID> F : operation finished - will be repeated to "Q" messages until a new command is issued
  12. namespace modules {
  13. namespace protocol {
  14. // decoding automaton
  15. // states: input -> transition into state
  16. // Code QTLMUXPSBEWK -> msgcode
  17. // \n ->start
  18. // * ->error
  19. // error \n ->start
  20. // * ->error
  21. // msgcode 0-9 ->msgvalue
  22. // * ->error
  23. // msgvalue 0-9 ->msgvalue
  24. // \n ->start successfully accepted command
  25. DecodeStatus Protocol::DecodeRequest(uint8_t c) {
  26. switch (rqState) {
  27. case RequestStates::Code:
  28. switch (c) {
  29. case 'Q':
  30. case 'T':
  31. case 'L':
  32. case 'M':
  33. case 'U':
  34. case 'X':
  35. case 'P':
  36. case 'S':
  37. case 'B':
  38. case 'E':
  39. case 'W':
  40. case 'K':
  41. case 'F':
  42. case 'f':
  43. case 'H':
  44. requestMsg.code = (RequestMsgCodes)c;
  45. requestMsg.value = 0;
  46. rqState = RequestStates::Value;
  47. return DecodeStatus::NeedMoreData;
  48. default:
  49. requestMsg.code = RequestMsgCodes::unknown;
  50. rqState = RequestStates::Error;
  51. return DecodeStatus::Error;
  52. }
  53. case RequestStates::Value:
  54. if (IsDigit(c)) {
  55. requestMsg.value *= 10;
  56. requestMsg.value += c - '0';
  57. return DecodeStatus::NeedMoreData;
  58. } else if (IsNewLine(c)) {
  59. rqState = RequestStates::Code;
  60. return DecodeStatus::MessageCompleted;
  61. } else {
  62. requestMsg.code = RequestMsgCodes::unknown;
  63. rqState = RequestStates::Error;
  64. return DecodeStatus::Error;
  65. }
  66. default: //case error:
  67. if (IsNewLine(c)) {
  68. rqState = RequestStates::Code;
  69. return DecodeStatus::MessageCompleted;
  70. } else {
  71. requestMsg.code = RequestMsgCodes::unknown;
  72. rqState = RequestStates::Error;
  73. return DecodeStatus::Error;
  74. }
  75. }
  76. }
  77. uint8_t Protocol::EncodeRequest(const RequestMsg &msg, uint8_t *txbuff) {
  78. constexpr uint8_t reqSize = 3;
  79. txbuff[0] = (uint8_t)msg.code;
  80. txbuff[1] = msg.value + '0';
  81. txbuff[2] = '\n';
  82. return reqSize;
  83. static_assert(reqSize <= MaxRequestSize(), "Request message length exceeded the maximum size, increase the magic constant in MaxRequestSize()");
  84. }
  85. DecodeStatus Protocol::DecodeResponse(uint8_t c) {
  86. switch (rspState) {
  87. case ResponseStates::RequestCode:
  88. switch (c) {
  89. case 'Q':
  90. case 'T':
  91. case 'L':
  92. case 'M':
  93. case 'U':
  94. case 'X':
  95. case 'P':
  96. case 'S':
  97. case 'B':
  98. case 'E':
  99. case 'W':
  100. case 'K':
  101. case 'F':
  102. case 'f':
  103. case 'H':
  104. responseMsg.request.code = (RequestMsgCodes)c;
  105. responseMsg.request.value = 0;
  106. rspState = ResponseStates::RequestValue;
  107. return DecodeStatus::NeedMoreData;
  108. case 0x0a:
  109. case 0x0d:
  110. // skip leading whitespace if any (makes integration with other SW easier/tolerant)
  111. return DecodeStatus::NeedMoreData;
  112. default:
  113. rspState = ResponseStates::Error;
  114. return DecodeStatus::Error;
  115. }
  116. case ResponseStates::RequestValue:
  117. if (IsDigit(c)) {
  118. responseMsg.request.value *= 10;
  119. responseMsg.request.value += c - '0';
  120. return DecodeStatus::NeedMoreData;
  121. } else if (c == ' ') {
  122. rspState = ResponseStates::ParamCode;
  123. return DecodeStatus::NeedMoreData;
  124. } else {
  125. rspState = ResponseStates::Error;
  126. return DecodeStatus::Error;
  127. }
  128. case ResponseStates::ParamCode:
  129. switch (c) {
  130. case 'P':
  131. case 'E':
  132. case 'F':
  133. case 'A':
  134. case 'R':
  135. rspState = ResponseStates::ParamValue;
  136. responseMsg.paramCode = (ResponseMsgParamCodes)c;
  137. responseMsg.paramValue = 0;
  138. return DecodeStatus::NeedMoreData;
  139. default:
  140. responseMsg.paramCode = ResponseMsgParamCodes::unknown;
  141. rspState = ResponseStates::Error;
  142. return DecodeStatus::Error;
  143. }
  144. case ResponseStates::ParamValue:
  145. if (IsDigit(c)) {
  146. responseMsg.paramValue *= 10;
  147. responseMsg.paramValue += c - '0';
  148. return DecodeStatus::NeedMoreData;
  149. } else if (IsNewLine(c)) {
  150. rspState = ResponseStates::RequestCode;
  151. return DecodeStatus::MessageCompleted;
  152. } else {
  153. responseMsg.paramCode = ResponseMsgParamCodes::unknown;
  154. rspState = ResponseStates::Error;
  155. return DecodeStatus::Error;
  156. }
  157. default: //case error:
  158. if (IsNewLine(c)) {
  159. rspState = ResponseStates::RequestCode;
  160. return DecodeStatus::MessageCompleted;
  161. } else {
  162. responseMsg.paramCode = ResponseMsgParamCodes::unknown;
  163. return DecodeStatus::Error;
  164. }
  165. }
  166. }
  167. uint8_t Protocol::EncodeResponseCmdAR(const RequestMsg &msg, ResponseMsgParamCodes ar, uint8_t *txbuff) {
  168. txbuff[0] = (uint8_t)msg.code;
  169. txbuff[1] = msg.value + '0';
  170. txbuff[2] = ' ';
  171. txbuff[3] = (uint8_t)ar;
  172. txbuff[4] = '\n';
  173. return 5;
  174. }
  175. uint8_t Protocol::EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff) {
  176. txbuff[0] = (uint8_t)msg.code;
  177. txbuff[1] = msg.value + '0';
  178. txbuff[2] = ' ';
  179. txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted;
  180. txbuff[4] = findaValue + '0';
  181. txbuff[5] = '\n';
  182. return 6;
  183. }
  184. uint8_t Protocol::EncodeResponseVersion(const RequestMsg &msg, uint8_t value, uint8_t *txbuff) {
  185. txbuff[0] = (uint8_t)msg.code;
  186. txbuff[1] = msg.value + '0';
  187. txbuff[2] = ' ';
  188. txbuff[3] = (uint8_t)ResponseMsgParamCodes::Accepted;
  189. uint8_t *dst = txbuff + 4;
  190. if (value < 10) {
  191. *dst++ = value + '0';
  192. } else if (value < 100) {
  193. *dst++ = value / 10 + '0';
  194. *dst++ = value % 10 + '0';
  195. } else {
  196. *dst++ = value / 100 + '0';
  197. *dst++ = (value / 10) % 10 + '0';
  198. *dst++ = value % 10 + '0';
  199. }
  200. *dst = '\n';
  201. return dst - txbuff + 1;
  202. }
  203. uint8_t Protocol::EncodeResponseQueryOperation(const RequestMsg &msg, ResponseMsgParamCodes code, uint16_t value, uint8_t *txbuff) {
  204. txbuff[0] = (uint8_t)msg.code;
  205. txbuff[1] = msg.value + '0';
  206. txbuff[2] = ' ';
  207. txbuff[3] = (uint8_t)code;
  208. uint8_t *dst = txbuff + 4;
  209. if (code != ResponseMsgParamCodes::Finished) {
  210. if (value < 10) {
  211. *dst++ = value + '0';
  212. } else if (value < 100) {
  213. *dst++ = value / 10 + '0';
  214. *dst++ = value % 10 + '0';
  215. } else if (value < 1000) {
  216. *dst++ = value / 100 + '0';
  217. *dst++ = (value / 10) % 10 + '0';
  218. *dst++ = value % 10 + '0';
  219. } else if (value < 10000) {
  220. *dst++ = value / 1000 + '0';
  221. *dst++ = (value / 100) % 10 + '0';
  222. *dst++ = (value / 10) % 10 + '0';
  223. *dst++ = value % 10 + '0';
  224. } else {
  225. *dst++ = value / 10000 + '0';
  226. *dst++ = (value / 1000) % 10 + '0';
  227. *dst++ = (value / 100) % 10 + '0';
  228. *dst++ = (value / 10) % 10 + '0';
  229. *dst++ = value % 10 + '0';
  230. }
  231. }
  232. *dst = '\n';
  233. return dst - txbuff + 1;
  234. }
  235. } // namespace protocol
  236. } // namespace modules