PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

RH_Serial.cpp 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // RH_Serial.cpp
  2. //
  3. // Copyright (C) 2014 Mike McCauley
  4. // $Id: RH_Serial.cpp,v 1.12 2016/04/04 01:40:12 mikem Exp $
  5. #include <RH_Serial.h>
  6. #if (RH_PLATFORM == RH_PLATFORM_STM32F2)
  7. #else
  8. #include <HardwareSerial.h>
  9. #endif
  10. #include <RHCRC.h>
  11. RH_Serial::RH_Serial(HardwareSerial& serial)
  12. :
  13. _serial(serial),
  14. _rxState(RxStateInitialising)
  15. {
  16. }
  17. HardwareSerial& RH_Serial::serial()
  18. {
  19. return _serial;
  20. }
  21. bool RH_Serial::init()
  22. {
  23. if (!RHGenericDriver::init())
  24. return false;
  25. _rxState = RxStateIdle;
  26. return true;
  27. }
  28. // Call this often
  29. bool RH_Serial::available()
  30. {
  31. while (!_rxBufValid &&_serial.available())
  32. handleRx(_serial.read());
  33. return _rxBufValid;
  34. }
  35. void RH_Serial::waitAvailable()
  36. {
  37. #if (RH_PLATFORM == RH_PLATFORM_UNIX)
  38. // Unix version driver in RHutil/HardwareSerial knows how to wait without polling
  39. while (!available())
  40. _serial.waitAvailable();
  41. #else
  42. RHGenericDriver::waitAvailable();
  43. #endif
  44. }
  45. bool RH_Serial::waitAvailableTimeout(uint16_t timeout)
  46. {
  47. #if (RH_PLATFORM == RH_PLATFORM_UNIX)
  48. // Unix version driver in RHutil/HardwareSerial knows how to wait without polling
  49. unsigned long starttime = millis();
  50. while ((millis() - starttime) < timeout)
  51. {
  52. _serial.waitAvailableTimeout(timeout - (millis() - starttime));
  53. if (available())
  54. return true;
  55. YIELD;
  56. }
  57. return false;
  58. #else
  59. return RHGenericDriver::waitAvailableTimeout(timeout);
  60. #endif
  61. }
  62. void RH_Serial::handleRx(uint8_t ch)
  63. {
  64. // State machine for receiving chars
  65. switch(_rxState)
  66. {
  67. case RxStateIdle:
  68. {
  69. if (ch == DLE)
  70. _rxState = RxStateDLE;
  71. }
  72. break;
  73. case RxStateDLE:
  74. {
  75. if (ch == STX)
  76. {
  77. clearRxBuf();
  78. _rxState = RxStateData;
  79. }
  80. else
  81. _rxState = RxStateIdle;
  82. }
  83. break;
  84. case RxStateData:
  85. {
  86. if (ch == DLE)
  87. _rxState = RxStateEscape;
  88. else
  89. appendRxBuf(ch);
  90. }
  91. break;
  92. case RxStateEscape:
  93. {
  94. if (ch == ETX)
  95. {
  96. // add fcs for DLE, ETX
  97. _rxFcs = RHcrc_ccitt_update(_rxFcs, DLE);
  98. _rxFcs = RHcrc_ccitt_update(_rxFcs, ETX);
  99. _rxState = RxStateWaitFCS1; // End frame
  100. }
  101. else if (ch == DLE)
  102. {
  103. appendRxBuf(ch);
  104. _rxState = RxStateData;
  105. }
  106. else
  107. _rxState = RxStateIdle; // Unexpected
  108. }
  109. break;
  110. case RxStateWaitFCS1:
  111. {
  112. _rxRecdFcs = ch << 8;
  113. _rxState = RxStateWaitFCS2;
  114. }
  115. break;
  116. case RxStateWaitFCS2:
  117. {
  118. _rxRecdFcs |= ch;
  119. _rxState = RxStateIdle;
  120. validateRxBuf();
  121. }
  122. break;
  123. default: // Else some compilers complain
  124. break;
  125. }
  126. }
  127. void RH_Serial::clearRxBuf()
  128. {
  129. _rxBufValid = false;
  130. _rxFcs = 0xffff;
  131. _rxBufLen = 0;
  132. }
  133. void RH_Serial::appendRxBuf(uint8_t ch)
  134. {
  135. if (_rxBufLen < RH_SERIAL_MAX_PAYLOAD_LEN)
  136. {
  137. // Normal data, save and add to FCS
  138. _rxBuf[_rxBufLen++] = ch;
  139. _rxFcs = RHcrc_ccitt_update(_rxFcs, ch);
  140. }
  141. // If the buffer overflows, we dont record the trailing data, and the FCS will be wrong,
  142. // causing the message to be dropped when the FCS is received
  143. }
  144. // Check whether the latest received message is complete and uncorrupted
  145. void RH_Serial::validateRxBuf()
  146. {
  147. if (_rxRecdFcs != _rxFcs)
  148. {
  149. _rxBad++;
  150. return;
  151. }
  152. // Extract the 4 headers
  153. _rxHeaderTo = _rxBuf[0];
  154. _rxHeaderFrom = _rxBuf[1];
  155. _rxHeaderId = _rxBuf[2];
  156. _rxHeaderFlags = _rxBuf[3];
  157. if (_promiscuous ||
  158. _rxHeaderTo == _thisAddress ||
  159. _rxHeaderTo == RH_BROADCAST_ADDRESS)
  160. {
  161. _rxGood++;
  162. _rxBufValid = true;
  163. }
  164. }
  165. bool RH_Serial::recv(uint8_t* buf, uint8_t* len)
  166. {
  167. if (!available())
  168. return false;
  169. if (buf && len)
  170. {
  171. // Skip the 4 headers that are at the beginning of the rxBuf
  172. if (*len > _rxBufLen-RH_SERIAL_HEADER_LEN)
  173. *len = _rxBufLen-RH_SERIAL_HEADER_LEN;
  174. memcpy(buf, _rxBuf+RH_SERIAL_HEADER_LEN, *len);
  175. }
  176. clearRxBuf(); // This message accepted and cleared
  177. return true;
  178. }
  179. // Caution: this may block
  180. bool RH_Serial::send(const uint8_t* data, uint8_t len)
  181. {
  182. _txFcs = 0xffff; // Initial value
  183. _serial.write(DLE); // Not in FCS
  184. _serial.write(STX); // Not in FCS
  185. // First the 4 headers
  186. txData(_txHeaderTo);
  187. txData(_txHeaderFrom);
  188. txData(_txHeaderId);
  189. txData(_txHeaderFlags);
  190. // Now the payload
  191. while (len--)
  192. txData(*data++);
  193. // End of message
  194. _serial.write(DLE);
  195. _txFcs = RHcrc_ccitt_update(_txFcs, DLE);
  196. _serial.write(ETX);
  197. _txFcs = RHcrc_ccitt_update(_txFcs, ETX);
  198. // Now send the calculated FCS for this message
  199. _serial.write((_txFcs >> 8) & 0xff);
  200. _serial.write(_txFcs & 0xff);
  201. return true;
  202. }
  203. void RH_Serial::txData(uint8_t ch)
  204. {
  205. if (ch == DLE) // DLE stuffing required?
  206. _serial.write(DLE); // Not in FCS
  207. _serial.write(ch);
  208. _txFcs = RHcrc_ccitt_update(_txFcs, ch);
  209. }
  210. uint8_t RH_Serial::maxMessageLength()
  211. {
  212. return RH_SERIAL_MAX_MESSAGE_LEN;
  213. }