fmtx.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Transmit an FM-modulated signal using the USART in SPI master mode.
  3. * As per ABC standard, this signal is transmitted MSB first.
  4. */
  5. #include "usbcas.h"
  6. #define BIT_PATTERN_LEN_LG2 2
  7. #define BITS_PER_PATTERN_BYTE (8 >> BIT_PATTERN_LEN_LG2)
  8. #define PATTERN_BIT_MASK ((1 << BITS_PER_PATTERN_BYTE) - 1)
  9. #include "fmpat.h"
  10. static void fmtx_set_speed(uint8_t divisor);
  11. /* Post-block silent pause, in pattern times */
  12. static unsigned int block_pause(uint8_t blktype, uint8_t divisor)
  13. {
  14. if (blktype == 0) /* data block */
  15. return 362 << BIT_PATTERN_LEN_LG2;
  16. else /* header block */
  17. return (3*362) << BIT_PATTERN_LEN_LG2;
  18. }
  19. /* Triple buffer: one being transmitted, one being received, and one ready. */
  20. static struct cas_block block[3];
  21. #define TX_BUSY 0
  22. #define TX_IDLE (1 << TXC1)
  23. /* Disable the TX ISR */
  24. static inline ATTR_ALWAYS_INLINE void fmtx_disable(void)
  25. {
  26. UCSR1B &= ~(1 << UDRIE1);
  27. }
  28. static uint8_t parity;
  29. /*
  30. * Send stuff if we have anything to send
  31. */
  32. ISR(USART1_UDRE_vect)
  33. {
  34. static uint8_t tx_data, tx_bits;
  35. static struct cas_block *blk = &block[0];
  36. uint8_t pattern;
  37. while (!tx_bits) {
  38. if (!blk->ready || !motor_relay()) {
  39. /* Hold the line for one pattern time, then idle */
  40. UCSR1A = TX_IDLE;
  41. UDR1 = parity;
  42. fmtx_disable(); /* Nothing left to do */
  43. return;
  44. } else if (blk->divisor) {
  45. fmtx_set_speed(blk->divisor);
  46. blk->divisor = 0;
  47. return;
  48. } else if (blk->offset < sizeof blk->data) {
  49. tx_data = ((const uint8_t *)&blk->data)[blk->offset++];
  50. tx_bits = 8;
  51. } else if (blk->pause) {
  52. /* Interblock silence; hold the line */
  53. UCSR1A = TX_IDLE;
  54. UDR1 = parity;
  55. blk->pause--;
  56. return;
  57. } else {
  58. blk->ready = false; /* Free buffer */
  59. blk = blk->next;
  60. }
  61. }
  62. /* Actual data bits available */
  63. pattern = fm_pat[tx_data & PATTERN_BIT_MASK] ^ parity;
  64. tx_data >>= BITS_PER_PATTERN_BYTE;
  65. parity = -((int8_t)pattern < 0);
  66. tx_bits -= BITS_PER_PATTERN_BYTE;
  67. UCSR1A = TX_IDLE;
  68. UDR1 = pattern;
  69. }
  70. /*
  71. * Synchronize transmitter before reconfiguration
  72. */
  73. void fmtx_drain(void)
  74. {
  75. /* Wait until input queue is idle and we have had at least one output */
  76. while ((UCSR1B & (1 << UDRIE1)) || !(UCSR1A & TX_IDLE))
  77. do_usb_tasks();
  78. }
  79. static inline uint16_t divisor_to_ubrr(uint8_t divisor)
  80. {
  81. uint16_t ubrr;
  82. if (!divisor)
  83. divisor = CAS_DIVISOR_ABC80;
  84. #if F_CPU != 16000000
  85. #error "Assuming F_CPU is 16 MHz"
  86. #endif
  87. ubrr = ((uint16_t)divisor << (8-BIT_PATTERN_LEN_LG2))/3 - 1;
  88. if (ubrr > 4095)
  89. ubrr = 4095;
  90. return ubrr;
  91. }
  92. static void fmtx_set_speed(uint8_t divisor)
  93. {
  94. if (!divisor)
  95. divisor = CAS_DIVISOR_ABC80;
  96. parity = 0xff; /* We start out with a high idle */
  97. DDRD |= 0x28; /* PD3 = outdata, PD5 = XCK/TXLED */
  98. PORTD |= 0x28; /* Drive data and clock high while idle */
  99. UCSR1B = 0; /* Disable transmitter and ISR */
  100. /*
  101. * SPI master mode, mode 1, LSB first
  102. * UCPHA doesn't matter, but have UCPOL=1 to that the clock
  103. * is 1 when idle and the TXLED is OFF.
  104. */
  105. UCSR1C = (3 << UMSEL10) | (1 << UDORD1) | (1 << UCPOL1);
  106. /* UBRR must be zero when the transmitter is enabled */
  107. UBRR1 = 0;
  108. /* Enable transmitter, but not receiver and not the ISR (yet) */
  109. UCSR1B = (1 << TXEN1);
  110. /* Configure baud rate */
  111. UBRR1 = divisor_to_ubrr(divisor);
  112. /*
  113. * Enable transmitter ISR (which probably will immediately
  114. * go to idle...)
  115. */
  116. fmtx_enable();
  117. }
  118. static enum rx_state {
  119. rx_amp, /* Waiting for & */
  120. rx_cmd, /* & received */
  121. rx_filename, /* Getting filename */
  122. rx_num, /* Getting numeric arguments */
  123. rx_data, /* Receiving data */
  124. rx_idle = rx_num /* Root state */
  125. } rx_state;
  126. static unsigned int rx_blk_cnt;
  127. static struct cas_block *rx_blk;
  128. void fmtx_init(void)
  129. {
  130. int i;
  131. /* Fill in the invariant part of the block buffers */
  132. memset(block, 0, sizeof block);
  133. block[0].next = &block[1];
  134. block[1].next = &block[2];
  135. block[2].next = &block[0];
  136. rx_blk = &block[0];
  137. rx_state = rx_idle;
  138. for (i = 0; i <= 2; i++) {
  139. memset(block[i].data.sync, 0x16, sizeof block[i].data.sync);
  140. block[i].data.stx = 0x02;
  141. block[i].data.etx = 0x03;
  142. }
  143. fmtx_set_speed(CAS_DIVISOR_ABC80);
  144. }
  145. bool fmtx_full(void)
  146. {
  147. return rx_blk->ready;
  148. }
  149. static void fmtx_wait_for_free_buffer(void)
  150. {
  151. while (rx_blk->ready)
  152. do_usb_tasks();
  153. }
  154. static enum rx_state setup_block(unsigned int blkno)
  155. {
  156. uint8_t blktype;
  157. rx_blk->data.blkno = blkno;
  158. blktype = -(blkno == -1U);
  159. rx_blk->data.blktype = blktype;
  160. rx_blk->pause = block_pause(blktype, rx_blk->divisor);
  161. /* Initialize checksum */
  162. rx_blk->data.csum = 0x03 /* ETX is part of the checksum */
  163. + blktype + (uint8_t)blkno + (uint8_t)(blkno >> 8);
  164. /* Start at beginning of data */
  165. rx_blk->offset = 0;
  166. return rx_data;
  167. }
  168. static uint16_t checksum_range(const uint8_t *data, unsigned int len)
  169. {
  170. uint16_t csum = 0;
  171. while (len--)
  172. csum += *data++;
  173. return csum;
  174. }
  175. #define MAX_ARGS 4
  176. static enum rx_state do_cmd(uint8_t cmd, const uint16_t *arg)
  177. {
  178. switch (cmd) {
  179. case 'U':
  180. /* Firmware update, kick us to boot loader */
  181. /* &U */
  182. go_to_bootloader();
  183. return rx_idle;
  184. case 'R':
  185. /* Set receive baudrate divisor */
  186. /* &R divisor */
  187. fmtx_wait_for_free_buffer();
  188. rx_blk->divisor = arg[0];
  189. return rx_idle;
  190. case 'H':
  191. /* Send header block */
  192. /* &H */
  193. rx_blk_cnt = 1;
  194. return setup_block(-1);
  195. case 'D':
  196. /* Send data block */
  197. /* &D blocknr */
  198. rx_blk_cnt = 1;
  199. return setup_block(arg[0]);
  200. case 'F':
  201. {
  202. /* Send file */
  203. /* &F filename,blocks[,divisor] */
  204. uint8_t divisor = arg[1];
  205. if (divisor == CAS_DIVISOR_ABC80)
  206. divisor = 0;
  207. setup_block(-1);
  208. rx_blk_cnt = arg[0];
  209. rx_blk->divisor = CAS_DIVISOR_ABC80; /* Header always slow */
  210. rx_blk->data.hdr.divisor = divisor;
  211. memset(rx_blk->data.hdr.zero, 0, sizeof rx_blk->data.hdr.zero);
  212. rx_blk->data.hdr.nblocks = rx_blk_cnt;
  213. /* Checksum filename and divisor */
  214. rx_blk->data.csum += checksum_range(rx_blk->data.data, 12);
  215. rx_blk->data.csum += (uint8_t)rx_blk_cnt
  216. + (uint8_t)(rx_blk_cnt >> 8);
  217. rx_blk->ready = true;
  218. rx_blk = rx_blk->next;
  219. if (!rx_blk_cnt)
  220. return rx_idle;
  221. if (divisor) {
  222. fmtx_wait_for_free_buffer();
  223. rx_blk->divisor = divisor;
  224. }
  225. return rx_data;
  226. }
  227. case 'P':
  228. /* Pause (produce silence) */
  229. /* &P byte_times */
  230. if (arg[0]) {
  231. fmtx_wait_for_free_buffer();
  232. rx_blk->pause = arg[0] << BIT_PATTERN_LEN_LG2;
  233. rx_blk->offset = sizeof rx_blk->data; /* No data */
  234. rx_blk->ready = true;
  235. }
  236. return rx_idle;
  237. default:
  238. return rx_idle; /* Unknown/unimplemented command */
  239. }
  240. }
  241. void fmtx_recv_byte(uint8_t byte)
  242. {
  243. static uint8_t cmd; /* Command byte */
  244. static uint8_t ctr; /* State-specific counter */
  245. static uint16_t arg[4];
  246. switch (rx_state) {
  247. case rx_amp:
  248. if (byte == '&')
  249. rx_state = rx_cmd;
  250. break;
  251. case rx_cmd:
  252. ctr = 0;
  253. memset(arg, 0, sizeof arg);
  254. cmd = byte;
  255. if (byte == 'F') {
  256. memset(rx_blk->data.hdr.filename, ' ',
  257. sizeof rx_blk->data.hdr.filename);
  258. rx_state = rx_filename;
  259. } else if (byte > ' ' && byte <= '~')
  260. rx_state = rx_num;
  261. else
  262. rx_state = rx_idle;
  263. break;
  264. case rx_filename:
  265. switch (byte) {
  266. case '\n':
  267. ctr = 0;
  268. rx_state = do_cmd(cmd, arg);
  269. break;
  270. case '.':
  271. memset(rx_blk->data.hdr.filename+8, ' ', 3);
  272. ctr = 8;
  273. break;
  274. case ':':
  275. ctr = 0;
  276. break;
  277. case ',':
  278. rx_state = rx_num;
  279. break;
  280. default:
  281. if (byte <= ' ' || byte > '~' || ctr >= 11)
  282. break;
  283. if (byte & 0x40)
  284. byte &= ~0x20; /* Upper case */
  285. rx_blk->data.hdr.filename[ctr++] = byte;
  286. break;
  287. }
  288. break;
  289. case rx_num:
  290. if (byte == '\n') {
  291. ctr = 0;
  292. rx_state = do_cmd(cmd, arg);
  293. break;
  294. } else if (byte == ',') {
  295. ctr++;
  296. } else if (ctr < MAX_ARGS) {
  297. byte -= '0';
  298. if (byte < 10)
  299. arg[ctr] = arg[ctr]*10 + byte;
  300. }
  301. break;
  302. case rx_data:
  303. rx_blk->data.data[ctr++] = byte;
  304. rx_blk->data.csum += byte;
  305. if (ctr >= 253) {
  306. uint16_t nextblk = rx_blk->data.blkno + 1;
  307. rx_blk->ready = true;
  308. rx_blk = rx_blk->next;
  309. fmtx_enable();
  310. if (--rx_blk_cnt) {
  311. fmtx_wait_for_free_buffer();
  312. setup_block(nextblk);
  313. } else {
  314. rx_state = rx_idle;
  315. }
  316. }
  317. break;
  318. }
  319. }