tty.cpp 8.4 KB

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