tty.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #define BAUD_RATE 115200
  2. #include "tty.h"
  3. #include "config.h"
  4. #include "fw.h"
  5. #include "rom/crc.h"
  6. #include <USB.h>
  7. #include <HardwareSerial.h>
  8. #define SOH '\001'
  9. #define STX '\002'
  10. #define ETX '\003'
  11. #define EOT '\004'
  12. #define ENQ '\005'
  13. #define ACK '\006'
  14. #define XON '\021' // DC1
  15. #define WRST '\022' // DC2 - window = 0
  16. #define XOFF '\023' // DC3
  17. #define WGO '\024' // DC4 - window + 256 bytes
  18. #define NAK '\025'
  19. #define SYN '\026'
  20. #define ETB '\027' // Not in upload mode
  21. #define CAN '\030'
  22. #define EM '\031' // Packet offset too high
  23. #define FS '\034'
  24. #define GS '\035'
  25. #define RS '\036'
  26. #define US '\037'
  27. #define WGO_CHUNK 256
  28. #define STREAMBUF_SIZE 8192
  29. static char enq_str[] = "\026\035MAX80 v0\004\r\n";
  30. static const char fwupload_start[] =
  31. "\034\001: /// MAX80 FW UPLOAD ~@~ $\035\r\n";
  32. void TTY::reset()
  33. {
  34. rx.rlen = 0;
  35. rx.state = rx_state::normal;
  36. }
  37. TTY::TTY(Stream &port)
  38. {
  39. _port = &port;
  40. rx_sbuf = NULL;
  41. win_sem = xSemaphoreCreateMutexStatic(&win_sem_ss);
  42. reset();
  43. }
  44. TTY::~TTY()
  45. {
  46. if (rx_sbuf)
  47. vStreamBufferDelete(rx_sbuf);
  48. }
  49. void TTY::_update_window(bool rst)
  50. {
  51. xSemaphoreTake(win_sem, portMAX_DELAY);
  52. if (rst) {
  53. port().write(WRST);
  54. tx_window = 0;
  55. }
  56. while (xStreamBufferSpacesAvailable(rx_sbuf) >= tx_window + WGO_CHUNK) {
  57. tx_window += WGO_CHUNK;
  58. port().write(WGO); // Space for one more window
  59. }
  60. xSemaphoreGive(win_sem);
  61. }
  62. int TTY::rxdata(void *buf, size_t len)
  63. {
  64. if (!rx_sbuf)
  65. return 0;
  66. size_t rcv = xStreamBufferReceive(rx_sbuf, buf, len, portMAX_DELAY);
  67. _update_window(false);
  68. return rcv;
  69. }
  70. int TTY::rxdata(token_t me, void *buf, size_t len)
  71. {
  72. TTY *tty = (TTY *)me;
  73. return tty->rxdata(buf, len);
  74. }
  75. void TTY::_upload_begin()
  76. {
  77. if (rx_sbuf)
  78. xStreamBufferReset(rx_sbuf);
  79. else
  80. rx_sbuf = xStreamBufferCreate(STREAMBUF_SIZE, 1);
  81. if (!rx_sbuf)
  82. goto nak;
  83. if (firmware_update_start((read_func_t)TTY::rxdata, (token_t)this))
  84. goto nak;
  85. // Respond with WRST + n*WGO
  86. _update_window(true);
  87. rx.state = rx_state::hdr;
  88. return;
  89. nak:
  90. port().write(NAK);
  91. rx.state = rx_state::normal;
  92. return;
  93. }
  94. void TTY::_onerr()
  95. {
  96. if (rx.state != rx_state::normal)
  97. _update_window(true);
  98. }
  99. // Change this to be a buffer...
  100. void TTY::_onrx()
  101. {
  102. int byte;
  103. int len;
  104. while (1) {
  105. int byte = port().read();
  106. if (byte == -1)
  107. break; // No more data
  108. switch (rx.state) {
  109. case rx_state::normal:
  110. if (byte == fwupload_start[rx.rlen]) {
  111. if (!fwupload_start[++rx.rlen])
  112. _upload_begin();
  113. } else {
  114. rx.rlen = 0;
  115. switch (byte) {
  116. case ENQ:
  117. port().write(enq_str);
  118. byte = ETB;
  119. break;
  120. case ETX:
  121. case EOT:
  122. case CAN:
  123. byte = ETB; // Not in file upload state
  124. break;
  125. default:
  126. // Normal echo
  127. break;
  128. }
  129. }
  130. break;
  131. case rx_state::hdr:
  132. if (rx.rlen > 0 || byte == STX) {
  133. rx.hdr_raw[rx.rlen++] = byte;
  134. byte = -1;
  135. if (rx.rlen == sizeof rx.hdr) {
  136. // Start of data packet
  137. rx.state = rx_state::data;
  138. rx.rlen = 0;
  139. }
  140. } else {
  141. switch (byte) {
  142. case ETX:
  143. case EOT:
  144. case CAN:
  145. reset();
  146. byte = CAN;
  147. break;
  148. case ENQ:
  149. byte = SYN; // In file upload state
  150. break;
  151. default:
  152. // Normal echo
  153. break;
  154. }
  155. }
  156. break;
  157. case rx_state::data:
  158. rx_data[rx.rlen++] = byte;
  159. byte = -1;
  160. // rx.hdr.len = packet data len - 1
  161. if (rx.rlen > rx.hdr.len) {
  162. int have = rx.rlen;
  163. uint32_t crc = ~crc32_le(0, rx_data, have);
  164. if (crc != rx.hdr.crc) {
  165. byte = NAK;
  166. } else if (rx.hdr.offs > rx.last_ack) {
  167. byte = EM;
  168. } else {
  169. int sent = 0;
  170. tx_window -= rx.rlen;
  171. if (rx.hdr.offs + rx.rlen <= rx.last_ack) {
  172. have = 0;
  173. } else {
  174. uint32_t skip = rx.last_ack - rx.hdr.offs;
  175. have -= skip;
  176. sent = xStreamBufferSend(rx_sbuf, rx_data+skip, have, 0);
  177. rx.last_ack += sent;
  178. }
  179. if (sent == have)
  180. byte = ACK;
  181. else
  182. _update_window(true);
  183. rx.state = rx_state::hdr;
  184. rx.rlen = 0;
  185. }
  186. }
  187. break;
  188. }
  189. if (byte >= 0)
  190. port().write(byte);
  191. }
  192. }
  193. void TTY::_onconnect()
  194. {
  195. port().write(XON);
  196. }
  197. void TTY::_onbreak()
  198. {
  199. reset();
  200. }
  201. void TTY::_ondisconnect()
  202. {
  203. reset();
  204. }
  205. static TTY *uart_tty, *usb_tty;
  206. void TTY::usb_onevent(void *arg, esp_event_base_t event_base,
  207. int32_t event_id, void *event_data)
  208. {
  209. switch (event_id) {
  210. case ARDUINO_USB_CDC_CONNECTED_EVENT:
  211. case ARDUINO_USB_CDC_LINE_STATE_EVENT:
  212. usb_tty->_onconnect();
  213. break;
  214. case ARDUINO_USB_CDC_DISCONNECTED_EVENT:
  215. usb_tty->_ondisconnect();
  216. break;
  217. case ARDUINO_USB_CDC_RX_EVENT:
  218. usb_tty->_onrx();
  219. break;
  220. case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT:
  221. usb_tty->_onerr();
  222. break;
  223. default:
  224. // Do nothing
  225. break;
  226. }
  227. }
  228. void TTY::uart_onrx(void)
  229. {
  230. uart_tty->_onrx();
  231. }
  232. void TTY::uart_onerr(hardwareSerial_error_t err)
  233. {
  234. switch (err) {
  235. case UART_BREAK_ERROR:
  236. uart_tty->_onbreak();
  237. break;
  238. default:
  239. uart_tty->_onerr();
  240. break;
  241. }
  242. }
  243. void TTY::init()
  244. {
  245. enq_str[sizeof(enq_str)-5] += max80_board_version;
  246. uart_tty = new TTY(Serial0);
  247. Serial0.begin(BAUD_RATE);
  248. Serial0.onReceive(uart_onrx, false);
  249. Serial0.onReceiveError(uart_onerr);
  250. usb_tty = new TTY(Serial);
  251. Serial.onEvent(usb_onevent);
  252. }
  253. void TTY::ping()
  254. {
  255. }