tty.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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 2048
  29. #define BUF_SLACK (STREAMBUF_SIZE >> 1)
  30. static char enq_str[] = "\026\035MAX80 v0\004\r\n";
  31. static const char fwupload_start[] =
  32. "\034\001: /// MAX80 FW UPLOAD ~@~ $\r\n\035";
  33. void TTY::reset()
  34. {
  35. rx.rlen = 0;
  36. rx.state = rx_state::normal;
  37. rx.b64_bits = 0;
  38. }
  39. TTY::TTY(Stream &port)
  40. {
  41. _port = &port;
  42. rx_sbuf = true ? xStreamBufferCreate(STREAMBUF_SIZE, 1) : NULL;
  43. reset();
  44. }
  45. TTY::~TTY()
  46. {
  47. if (rx_sbuf)
  48. vStreamBufferDelete(rx_sbuf);
  49. }
  50. int TTY::rxdata(void *buf, size_t len)
  51. {
  52. printf("[TTY] rxdata(%zu) ", len);
  53. if (!rx_sbuf)
  54. return 0;
  55. int rcv = 0;
  56. while (!rcv) {
  57. if (tx_credits_reset) {
  58. // Drain input before WRST
  59. rcv = xStreamBufferReceive(rx_sbuf, buf, len, 0);
  60. if (rcv)
  61. break;
  62. if (port().write(WRST)) {
  63. tx_credits_reset = false;
  64. tx_credits = STREAMBUF_SIZE - BUF_SLACK;
  65. } else {
  66. // Uhm... wait one tick and then try again to sent WRST?
  67. rcv = xStreamBufferReceive(rx_sbuf, buf, len, 1);
  68. }
  69. } else {
  70. while (tx_credits >= WGO_CHUNK && port().write(WGO))
  71. tx_credits -= WGO_CHUNK;
  72. rcv = xStreamBufferReceive(rx_sbuf, buf, len, 1);
  73. tx_credits += rcv;
  74. }
  75. }
  76. printf("got %d\n", rcv);
  77. return rcv;
  78. }
  79. int TTY::rxdata(token_t me, void *buf, size_t len)
  80. {
  81. TTY *tty = (TTY *)me;
  82. return tty->rxdata(buf, len);
  83. }
  84. void TTY::_upload_begin()
  85. {
  86. printf("[TTY] _upload_begin\n");
  87. if (rx_sbuf)
  88. xStreamBufferReset(rx_sbuf);
  89. else
  90. rx_sbuf = xStreamBufferCreate(STREAMBUF_SIZE, 1);
  91. printf("[TTY] rx_sbuf = %p\n", rx_sbuf);
  92. if (!rx_sbuf)
  93. goto can;
  94. port().write(RS);
  95. tx_credits_reset = true;
  96. rx.state = rx_state::stxwait;
  97. rx.last_ack = 0;
  98. rx.rlen = 0;
  99. rx.b64_bits = 0;
  100. printf("[TTY] firmware_update_start()\n");
  101. if (firmware_update_start(TTY::rxdata, (token_t)this, true))
  102. goto can;
  103. return;
  104. can:
  105. port().write(CAN);
  106. rx.state = rx_state::normal;
  107. return;
  108. }
  109. void TTY::_onerr()
  110. {
  111. if (rx.state != rx_state::normal) {
  112. port().write(NAK);
  113. }
  114. }
  115. static int filter_echo(int byte)
  116. {
  117. if (byte >= ' ' && byte < 127)
  118. return byte;
  119. if (byte == '\t' || byte == '\r' || byte == '\n')
  120. return byte;
  121. return -1;
  122. }
  123. // Decode a base64 data byte (using simple offset-63)
  124. // Call with -1 or any invalid value to invalidate the input buffer
  125. int TTY::_decode_data(int input)
  126. {
  127. unsigned int buf = rx.b64_buf;
  128. unsigned int inval = input - '?';
  129. if (inval > 63) {
  130. rx.b64_bits = 0;
  131. return -2; // Invalid input
  132. }
  133. rx.b64_buf = buf = (buf << 6) + inval;
  134. rx.b64_bits += 6;
  135. if (rx.b64_bits >= 8) {
  136. rx.b64_bits -= 8;
  137. return (uint8_t)(buf >> rx.b64_bits);
  138. } else {
  139. return -1;
  140. }
  141. }
  142. // Change this to be a buffer...
  143. void TTY::_onrx()
  144. {
  145. int byte, data;
  146. while ((byte = port().read()) >= 0) {
  147. switch (rx.state) {
  148. case rx_state::normal:
  149. if (rx.rlen < sizeof fwupload_start &&
  150. byte == fwupload_start[rx.rlen]) {
  151. if (!fwupload_start[++rx.rlen]) {
  152. _upload_begin();
  153. byte = -1;
  154. }
  155. } else {
  156. rx.rlen = 0;
  157. switch (byte) {
  158. case ENQ:
  159. port().write(enq_str);
  160. byte = ETB;
  161. break;
  162. case ETX:
  163. case EOT:
  164. case CAN:
  165. byte = ETB; // Not in file upload state
  166. break;
  167. default:
  168. // Echo if printable
  169. byte = filter_echo(byte);
  170. break;
  171. }
  172. }
  173. break;
  174. case rx_state::stxwait:
  175. switch (byte) {
  176. case STX:
  177. rx.rlen = 0;
  178. rx.hdr_raw[rx.rlen++] = byte;
  179. rx.b64_bits = 0;
  180. rx.state = rx_state::hdr;
  181. byte = -1;
  182. break;
  183. case ETX:
  184. case CAN:
  185. printf("[UPLD] Received <%02X> waiting for STX\n", byte);
  186. reset();
  187. byte = CAN;
  188. break;
  189. case ENQ:
  190. rx.rlen = 0;
  191. byte = GS; // In upload wait for STX state
  192. break;
  193. case SYN:
  194. rx.rlen = 0;
  195. tx_credits_reset = true; // Request to resync credits
  196. byte = -1;
  197. break;
  198. case EOT:
  199. // Upload complete, no more data
  200. byte = ETB;
  201. break;
  202. default:
  203. byte = -1; // No echo
  204. break;
  205. }
  206. break;
  207. case rx_state::hdr:
  208. data = _decode_data(byte);
  209. byte = -1;
  210. if (data < -1) {
  211. rx.state = rx_state::stxwait;
  212. rx.rlen = 0;
  213. tx_credits_reset = true;
  214. byte = US; // Framing error
  215. } else if (data == -1) {
  216. // Nothing to do
  217. } else if (rx.rlen >= sizeof rx.hdr_raw) {
  218. // ERROR THIS SHOULD NEVER HAPPEN
  219. printf("[UPLD] Header buffer overrun!!!\n");
  220. reset();
  221. byte = CAN;
  222. } else {
  223. rx.hdr_raw[rx.rlen++] = data;
  224. if (rx.rlen == sizeof rx.hdr) {
  225. // Start of data packet
  226. printf("[UPLD] Start packet hdr %d length %d offset %d last_ack %d\n",
  227. rx.rlen, rx.hdr.len+1, rx.hdr.offs, rx.last_ack);
  228. rx.state = rx_state::data;
  229. rx.rlen = 0;
  230. }
  231. }
  232. break;
  233. case rx_state::data:
  234. data = _decode_data(byte);
  235. byte = -1;
  236. if (data < -1) {
  237. rx.state = rx_state::stxwait;
  238. rx.rlen = 0;
  239. tx_credits_reset = true;
  240. byte = US; // Framing error
  241. } else if (data == -1) {
  242. // Nothing to do
  243. } else if (rx.rlen >= sizeof rx_data) {
  244. // ERROR THIS SHOULD NEVER HAPPEN
  245. printf("[UPLD] Packet data buffer overrun!!!\n");
  246. reset();
  247. byte = CAN;
  248. } else {
  249. rx_data[rx.rlen++] = data;
  250. // rx.hdr.len = packet data len - 1
  251. if (rx.rlen > rx.hdr.len) {
  252. int have = rx.rlen;
  253. uint32_t crc;
  254. if (have != rx.hdr.len + 1) {
  255. printf("[UPLD] Invalid packet length (should not happen...)\n");
  256. byte = NAK;
  257. } else if ((crc = crc32_le(0, rx_data, have))
  258. != rx.hdr.crc) {
  259. printf("[UPLD] Packet CRC error hdr %08x data %08x\n", rx.hdr.crc, crc);
  260. printf("\"");
  261. for (int i = 0; i < have; i++)
  262. printf("\\x%02x", rx_data[i]);
  263. printf("\"\n");
  264. byte = NAK;
  265. } else if (rx.hdr.offs > rx.last_ack) {
  266. printf("[UPLD] Invalid packet offsets [%d..%d) at %d\n",
  267. rx.hdr.offs, rx.hdr.offs + have, rx.last_ack);
  268. byte = EM;
  269. } else if (rx.hdr.offs + have <= rx.last_ack) {
  270. // Ack and discard packet below current window (transmitter is catching up)
  271. byte = ACK;
  272. } else {
  273. int sent = 0;
  274. uint32_t skip = rx.last_ack - rx.hdr.offs;
  275. have -= skip;
  276. sent = xStreamBufferSend(rx_sbuf, rx_data+skip, have, 0);
  277. rx.last_ack += sent;
  278. if (sent != have) {
  279. printf("[UPLD] Packet underrun, got %d, expected %d\n", sent, have);
  280. byte = NAK;
  281. } else {
  282. printf("[UPLD] %d bytes received OK\n", sent);
  283. byte = ACK;
  284. }
  285. }
  286. if (byte != ACK)
  287. tx_credits_reset = true;
  288. rx.state = rx_state::stxwait;
  289. rx.rlen = 0;
  290. }
  291. }
  292. break;
  293. }
  294. if (byte >= 0)
  295. port().write(byte);
  296. }
  297. }
  298. void TTY::_onconnect()
  299. {
  300. port().write(XON);
  301. }
  302. void TTY::_onbreak()
  303. {
  304. reset();
  305. }
  306. void TTY::_ondisconnect()
  307. {
  308. reset();
  309. }
  310. static TTY *uart_tty, *usb_tty;
  311. void TTY::usb_onevent(void *arg, esp_event_base_t event_base,
  312. int32_t event_id, void *event_data)
  313. {
  314. switch (event_id) {
  315. case ARDUINO_USB_CDC_CONNECTED_EVENT:
  316. case ARDUINO_USB_CDC_LINE_STATE_EVENT:
  317. usb_tty->_onconnect();
  318. break;
  319. case ARDUINO_USB_CDC_DISCONNECTED_EVENT:
  320. usb_tty->_ondisconnect();
  321. break;
  322. case ARDUINO_USB_CDC_RX_EVENT:
  323. usb_tty->_onrx();
  324. break;
  325. case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT:
  326. usb_tty->_onerr();
  327. break;
  328. default:
  329. // Do nothing
  330. break;
  331. }
  332. }
  333. void TTY::uart_onrx(void)
  334. {
  335. uart_tty->_onrx();
  336. }
  337. void TTY::uart_onerr(hardwareSerial_error_t err)
  338. {
  339. switch (err) {
  340. case UART_BREAK_ERROR:
  341. uart_tty->_onbreak();
  342. break;
  343. default:
  344. uart_tty->_onerr();
  345. break;
  346. }
  347. }
  348. void TTY::init()
  349. {
  350. enq_str[sizeof(enq_str)-5] += max80_board_version;
  351. uart_tty = new TTY(Serial0);
  352. Serial0.begin(BAUD_RATE);
  353. Serial0.onReceive(uart_onrx, false);
  354. Serial0.onReceiveError(uart_onerr);
  355. usb_tty = new TTY(Serial);
  356. Serial.onEvent(usb_onevent);
  357. }
  358. void TTY::ping()
  359. {
  360. }