serial.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /*
  2. * WARNING: be careful changing this code, it is very timing dependent
  3. *
  4. * 2018-10-28 checked
  5. * avr-gcc 4.9.2
  6. * avr-gcc 5.4.0
  7. * avr-gcc 7.3.0
  8. */
  9. #ifndef F_CPU
  10. #define F_CPU 16000000
  11. #endif
  12. #include <avr/io.h>
  13. #include <avr/interrupt.h>
  14. #include <util/delay.h>
  15. #include <stddef.h>
  16. #include <stdbool.h>
  17. #include "serial.h"
  18. //#include <pro_micro.h>
  19. #ifdef SOFT_SERIAL_PIN
  20. #ifdef __AVR_ATmega32U4__
  21. // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial.
  22. #ifdef USE_I2C
  23. #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1
  24. #error Using ATmega32U4 I2C, so can not use PD0, PD1
  25. #endif
  26. #endif
  27. #if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3
  28. #define SERIAL_PIN_DDR DDRD
  29. #define SERIAL_PIN_PORT PORTD
  30. #define SERIAL_PIN_INPUT PIND
  31. #if SOFT_SERIAL_PIN == D0
  32. #define SERIAL_PIN_MASK _BV(PD0)
  33. #define EIMSK_BIT _BV(INT0)
  34. #define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01)))
  35. #define SERIAL_PIN_INTERRUPT INT0_vect
  36. #elif SOFT_SERIAL_PIN == D1
  37. #define SERIAL_PIN_MASK _BV(PD1)
  38. #define EIMSK_BIT _BV(INT1)
  39. #define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11)))
  40. #define SERIAL_PIN_INTERRUPT INT1_vect
  41. #elif SOFT_SERIAL_PIN == D2
  42. #define SERIAL_PIN_MASK _BV(PD2)
  43. #define EIMSK_BIT _BV(INT2)
  44. #define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21)))
  45. #define SERIAL_PIN_INTERRUPT INT2_vect
  46. #elif SOFT_SERIAL_PIN == D3
  47. #define SERIAL_PIN_MASK _BV(PD3)
  48. #define EIMSK_BIT _BV(INT3)
  49. #define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31)))
  50. #define SERIAL_PIN_INTERRUPT INT3_vect
  51. #endif
  52. #elif SOFT_SERIAL_PIN == E6
  53. #define SERIAL_PIN_DDR DDRE
  54. #define SERIAL_PIN_PORT PORTE
  55. #define SERIAL_PIN_INPUT PINE
  56. #define SERIAL_PIN_MASK _BV(PE6)
  57. #define EIMSK_BIT _BV(INT6)
  58. #define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
  59. #define SERIAL_PIN_INTERRUPT INT6_vect
  60. #else
  61. #error invalid SOFT_SERIAL_PIN value
  62. #endif
  63. #else
  64. #error serial.c now support ATmega32U4 only
  65. #endif
  66. #ifndef SERIAL_USE_MULTI_TRANSACTION
  67. /* --- USE Simple API (OLD API, compatible with let's split serial.c) */
  68. #if SERIAL_SLAVE_BUFFER_LENGTH > 0
  69. uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
  70. #endif
  71. #if SERIAL_MASTER_BUFFER_LENGTH > 0
  72. uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
  73. #endif
  74. uint8_t volatile status0 = 0;
  75. SSTD_t transactions[] = {
  76. { (uint8_t *)&status0,
  77. #if SERIAL_MASTER_BUFFER_LENGTH > 0
  78. sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer,
  79. #else
  80. 0, (uint8_t *)NULL,
  81. #endif
  82. #if SERIAL_SLAVE_BUFFER_LENGTH > 0
  83. sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
  84. #else
  85. 0, (uint8_t *)NULL,
  86. #endif
  87. }
  88. };
  89. void serial_master_init(void)
  90. { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
  91. void serial_slave_init(void)
  92. { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
  93. // 0 => no error
  94. // 1 => slave did not respond
  95. // 2 => checksum error
  96. int serial_update_buffers()
  97. {
  98. int result;
  99. result = soft_serial_transaction();
  100. return result;
  101. }
  102. #endif // Simple API (OLD API, compatible with let's split serial.c)
  103. #define ALWAYS_INLINE __attribute__((always_inline))
  104. #define NO_INLINE __attribute__((noinline))
  105. #define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
  106. // parity check
  107. #define ODD_PARITY 1
  108. #define EVEN_PARITY 0
  109. #define PARITY EVEN_PARITY
  110. #ifdef SERIAL_DELAY
  111. // custom setup in config.h
  112. // #define TID_SEND_ADJUST 2
  113. // #define SERIAL_DELAY 6 // micro sec
  114. // #define READ_WRITE_START_ADJUST 30 // cycles
  115. // #define READ_WRITE_WIDTH_ADJUST 8 // cycles
  116. #else
  117. // ============ Standard setups ============
  118. #ifndef SELECT_SOFT_SERIAL_SPEED
  119. #define SELECT_SOFT_SERIAL_SPEED 1
  120. // 0: about 189kbps
  121. // 1: about 137kbps (default)
  122. // 2: about 75kbps
  123. // 3: about 39kbps
  124. // 4: about 26kbps
  125. // 5: about 20kbps
  126. #endif
  127. #if __GNUC__ < 6
  128. #define TID_SEND_ADJUST 14
  129. #else
  130. #define TID_SEND_ADJUST 2
  131. #endif
  132. #if SELECT_SOFT_SERIAL_SPEED == 0
  133. // Very High speed
  134. #define SERIAL_DELAY 4 // micro sec
  135. #if __GNUC__ < 6
  136. #define READ_WRITE_START_ADJUST 33 // cycles
  137. #define READ_WRITE_WIDTH_ADJUST 3 // cycles
  138. #else
  139. #define READ_WRITE_START_ADJUST 34 // cycles
  140. #define READ_WRITE_WIDTH_ADJUST 7 // cycles
  141. #endif
  142. #elif SELECT_SOFT_SERIAL_SPEED == 1
  143. // High speed
  144. #define SERIAL_DELAY 6 // micro sec
  145. #if __GNUC__ < 6
  146. #define READ_WRITE_START_ADJUST 30 // cycles
  147. #define READ_WRITE_WIDTH_ADJUST 3 // cycles
  148. #else
  149. #define READ_WRITE_START_ADJUST 33 // cycles
  150. #define READ_WRITE_WIDTH_ADJUST 7 // cycles
  151. #endif
  152. #elif SELECT_SOFT_SERIAL_SPEED == 2
  153. // Middle speed
  154. #define SERIAL_DELAY 12 // micro sec
  155. #define READ_WRITE_START_ADJUST 30 // cycles
  156. #if __GNUC__ < 6
  157. #define READ_WRITE_WIDTH_ADJUST 3 // cycles
  158. #else
  159. #define READ_WRITE_WIDTH_ADJUST 7 // cycles
  160. #endif
  161. #elif SELECT_SOFT_SERIAL_SPEED == 3
  162. // Low speed
  163. #define SERIAL_DELAY 24 // micro sec
  164. #define READ_WRITE_START_ADJUST 30 // cycles
  165. #if __GNUC__ < 6
  166. #define READ_WRITE_WIDTH_ADJUST 3 // cycles
  167. #else
  168. #define READ_WRITE_WIDTH_ADJUST 7 // cycles
  169. #endif
  170. #elif SELECT_SOFT_SERIAL_SPEED == 4
  171. // Very Low speed
  172. #define SERIAL_DELAY 36 // micro sec
  173. #define READ_WRITE_START_ADJUST 30 // cycles
  174. #if __GNUC__ < 6
  175. #define READ_WRITE_WIDTH_ADJUST 3 // cycles
  176. #else
  177. #define READ_WRITE_WIDTH_ADJUST 7 // cycles
  178. #endif
  179. #elif SELECT_SOFT_SERIAL_SPEED == 5
  180. // Ultra Low speed
  181. #define SERIAL_DELAY 48 // micro sec
  182. #define READ_WRITE_START_ADJUST 30 // cycles
  183. #if __GNUC__ < 6
  184. #define READ_WRITE_WIDTH_ADJUST 3 // cycles
  185. #else
  186. #define READ_WRITE_WIDTH_ADJUST 7 // cycles
  187. #endif
  188. #else
  189. #error invalid SELECT_SOFT_SERIAL_SPEED value
  190. #endif /* SELECT_SOFT_SERIAL_SPEED */
  191. #endif /* SERIAL_DELAY */
  192. #define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2)
  193. #define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2)
  194. #define SLAVE_INT_WIDTH_US 1
  195. #ifndef SERIAL_USE_MULTI_TRANSACTION
  196. #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
  197. #else
  198. #define SLAVE_INT_ACK_WIDTH_UNIT 2
  199. #define SLAVE_INT_ACK_WIDTH 4
  200. #endif
  201. static SSTD_t *Transaction_table = NULL;
  202. static uint8_t Transaction_table_size = 0;
  203. inline static void serial_delay(void) ALWAYS_INLINE;
  204. inline static
  205. void serial_delay(void) {
  206. _delay_us(SERIAL_DELAY);
  207. }
  208. inline static void serial_delay_half1(void) ALWAYS_INLINE;
  209. inline static
  210. void serial_delay_half1(void) {
  211. _delay_us(SERIAL_DELAY_HALF1);
  212. }
  213. inline static void serial_delay_half2(void) ALWAYS_INLINE;
  214. inline static
  215. void serial_delay_half2(void) {
  216. _delay_us(SERIAL_DELAY_HALF2);
  217. }
  218. inline static void serial_output(void) ALWAYS_INLINE;
  219. inline static
  220. void serial_output(void) {
  221. SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
  222. }
  223. // make the serial pin an input with pull-up resistor
  224. inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
  225. inline static
  226. void serial_input_with_pullup(void) {
  227. SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
  228. SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
  229. }
  230. inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
  231. inline static
  232. uint8_t serial_read_pin(void) {
  233. return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
  234. }
  235. inline static void serial_low(void) ALWAYS_INLINE;
  236. inline static
  237. void serial_low(void) {
  238. SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
  239. }
  240. inline static void serial_high(void) ALWAYS_INLINE;
  241. inline static
  242. void serial_high(void) {
  243. SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
  244. }
  245. void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size)
  246. {
  247. Transaction_table = sstd_table;
  248. Transaction_table_size = (uint8_t)sstd_table_size;
  249. serial_output();
  250. serial_high();
  251. }
  252. void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size)
  253. {
  254. Transaction_table = sstd_table;
  255. Transaction_table_size = (uint8_t)sstd_table_size;
  256. serial_input_with_pullup();
  257. // Enable INT0-INT3,INT6
  258. EIMSK |= EIMSK_BIT;
  259. #if SERIAL_PIN_MASK == _BV(PE6)
  260. // Trigger on falling edge of INT6
  261. EICRB &= EICRx_BIT;
  262. #else
  263. // Trigger on falling edge of INT0-INT3
  264. EICRA &= EICRx_BIT;
  265. #endif
  266. }
  267. // Used by the sender to synchronize timing with the reciver.
  268. static void sync_recv(void) NO_INLINE;
  269. static
  270. void sync_recv(void) {
  271. for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) {
  272. }
  273. // This shouldn't hang if the target disconnects because the
  274. // serial line will float to high if the target does disconnect.
  275. while (!serial_read_pin());
  276. }
  277. // Used by the reciver to send a synchronization signal to the sender.
  278. static void sync_send(void) NO_INLINE;
  279. static
  280. void sync_send(void) {
  281. serial_low();
  282. serial_delay();
  283. serial_high();
  284. }
  285. // Reads a byte from the serial line
  286. static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE;
  287. static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
  288. uint8_t byte, i, p, pb;
  289. _delay_sub_us(READ_WRITE_START_ADJUST);
  290. for( i = 0, byte = 0, p = PARITY; i < bit; i++ ) {
  291. serial_delay_half1(); // read the middle of pulses
  292. if( serial_read_pin() ) {
  293. byte = (byte << 1) | 1; p ^= 1;
  294. } else {
  295. byte = (byte << 1) | 0; p ^= 0;
  296. }
  297. _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
  298. serial_delay_half2();
  299. }
  300. /* recive parity bit */
  301. serial_delay_half1(); // read the middle of pulses
  302. pb = serial_read_pin();
  303. _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
  304. serial_delay_half2();
  305. *pterrcount += (p != pb)? 1 : 0;
  306. return byte;
  307. }
  308. // Sends a byte with MSB ordering
  309. void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE;
  310. void serial_write_chunk(uint8_t data, uint8_t bit) {
  311. uint8_t b, p;
  312. for( p = PARITY, b = 1<<(bit-1); b ; b >>= 1) {
  313. if(data & b) {
  314. serial_high(); p ^= 1;
  315. } else {
  316. serial_low(); p ^= 0;
  317. }
  318. serial_delay();
  319. }
  320. /* send parity bit */
  321. if(p & 1) { serial_high(); }
  322. else { serial_low(); }
  323. serial_delay();
  324. serial_low(); // sync_send() / senc_recv() need raise edge
  325. }
  326. static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
  327. static
  328. void serial_send_packet(uint8_t *buffer, uint8_t size) {
  329. for (uint8_t i = 0; i < size; ++i) {
  330. uint8_t data;
  331. data = buffer[i];
  332. sync_send();
  333. serial_write_chunk(data,8);
  334. }
  335. }
  336. static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
  337. static
  338. uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
  339. uint8_t pecount = 0;
  340. for (uint8_t i = 0; i < size; ++i) {
  341. uint8_t data;
  342. sync_recv();
  343. data = serial_read_chunk(&pecount, 8);
  344. buffer[i] = data;
  345. }
  346. return pecount == 0;
  347. }
  348. inline static
  349. void change_sender2reciver(void) {
  350. sync_send(); //0
  351. serial_delay_half1(); //1
  352. serial_low(); //2
  353. serial_input_with_pullup(); //2
  354. serial_delay_half1(); //3
  355. }
  356. inline static
  357. void change_reciver2sender(void) {
  358. sync_recv(); //0
  359. serial_delay(); //1
  360. serial_low(); //3
  361. serial_output(); //3
  362. serial_delay_half1(); //4
  363. }
  364. static inline uint8_t nibble_bits_count(uint8_t bits)
  365. {
  366. bits = (bits & 0x5) + (bits >> 1 & 0x5);
  367. bits = (bits & 0x3) + (bits >> 2 & 0x3);
  368. return bits;
  369. }
  370. // interrupt handle to be used by the target device
  371. ISR(SERIAL_PIN_INTERRUPT) {
  372. #ifndef SERIAL_USE_MULTI_TRANSACTION
  373. serial_low();
  374. serial_output();
  375. SSTD_t *trans = Transaction_table;
  376. #else
  377. // recive transaction table index
  378. uint8_t tid, bits;
  379. uint8_t pecount = 0;
  380. sync_recv();
  381. bits = serial_read_chunk(&pecount,7);
  382. tid = bits>>3;
  383. bits = (bits&7) != nibble_bits_count(tid);
  384. if( bits || pecount> 0 || tid > Transaction_table_size ) {
  385. return;
  386. }
  387. serial_delay_half1();
  388. serial_high(); // response step1 low->high
  389. serial_output();
  390. _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH);
  391. SSTD_t *trans = &Transaction_table[tid];
  392. serial_low(); // response step2 ack high->low
  393. #endif
  394. // target send phase
  395. if( trans->target2initiator_buffer_size > 0 )
  396. serial_send_packet((uint8_t *)trans->target2initiator_buffer,
  397. trans->target2initiator_buffer_size);
  398. // target switch to input
  399. change_sender2reciver();
  400. // target recive phase
  401. if( trans->initiator2target_buffer_size > 0 ) {
  402. if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer,
  403. trans->initiator2target_buffer_size) ) {
  404. *trans->status = TRANSACTION_ACCEPTED;
  405. } else {
  406. *trans->status = TRANSACTION_DATA_ERROR;
  407. }
  408. } else {
  409. *trans->status = TRANSACTION_ACCEPTED;
  410. }
  411. sync_recv(); //weit initiator output to high
  412. }
  413. /////////
  414. // start transaction by initiator
  415. //
  416. // int soft_serial_transaction(int sstd_index)
  417. //
  418. // Returns:
  419. // TRANSACTION_END
  420. // TRANSACTION_NO_RESPONSE
  421. // TRANSACTION_DATA_ERROR
  422. // this code is very time dependent, so we need to disable interrupts
  423. #ifndef SERIAL_USE_MULTI_TRANSACTION
  424. int soft_serial_transaction(void) {
  425. SSTD_t *trans = Transaction_table;
  426. #else
  427. int soft_serial_transaction(int sstd_index) {
  428. if( sstd_index > Transaction_table_size )
  429. return TRANSACTION_TYPE_ERROR;
  430. SSTD_t *trans = &Transaction_table[sstd_index];
  431. #endif
  432. cli();
  433. // signal to the target that we want to start a transaction
  434. serial_output();
  435. serial_low();
  436. _delay_us(SLAVE_INT_WIDTH_US);
  437. #ifndef SERIAL_USE_MULTI_TRANSACTION
  438. // wait for the target response
  439. serial_input_with_pullup();
  440. _delay_us(SLAVE_INT_RESPONSE_TIME);
  441. // check if the target is present
  442. if (serial_read_pin()) {
  443. // target failed to pull the line low, assume not present
  444. serial_output();
  445. serial_high();
  446. *trans->status = TRANSACTION_NO_RESPONSE;
  447. sei();
  448. return TRANSACTION_NO_RESPONSE;
  449. }
  450. #else
  451. // send transaction table index
  452. int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index));
  453. sync_send();
  454. _delay_sub_us(TID_SEND_ADJUST);
  455. serial_write_chunk(tid, 7);
  456. serial_delay_half1();
  457. // wait for the target response (step1 low->high)
  458. serial_input_with_pullup();
  459. while( !serial_read_pin() ) {
  460. _delay_sub_us(2);
  461. }
  462. // check if the target is present (step2 high->low)
  463. for( int i = 0; serial_read_pin(); i++ ) {
  464. if (i > SLAVE_INT_ACK_WIDTH + 1) {
  465. // slave failed to pull the line low, assume not present
  466. serial_output();
  467. serial_high();
  468. *trans->status = TRANSACTION_NO_RESPONSE;
  469. sei();
  470. return TRANSACTION_NO_RESPONSE;
  471. }
  472. _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
  473. }
  474. #endif
  475. // initiator recive phase
  476. // if the target is present syncronize with it
  477. if( trans->target2initiator_buffer_size > 0 ) {
  478. if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer,
  479. trans->target2initiator_buffer_size) ) {
  480. serial_output();
  481. serial_high();
  482. *trans->status = TRANSACTION_DATA_ERROR;
  483. sei();
  484. return TRANSACTION_DATA_ERROR;
  485. }
  486. }
  487. // initiator switch to output
  488. change_reciver2sender();
  489. // initiator send phase
  490. if( trans->initiator2target_buffer_size > 0 ) {
  491. serial_send_packet((uint8_t *)trans->initiator2target_buffer,
  492. trans->initiator2target_buffer_size);
  493. }
  494. // always, release the line when not in use
  495. sync_send();
  496. *trans->status = TRANSACTION_END;
  497. sei();
  498. return TRANSACTION_END;
  499. }
  500. #ifdef SERIAL_USE_MULTI_TRANSACTION
  501. int soft_serial_get_and_clean_status(int sstd_index) {
  502. SSTD_t *trans = &Transaction_table[sstd_index];
  503. cli();
  504. int retval = *trans->status;
  505. *trans->status = 0;;
  506. sei();
  507. return retval;
  508. }
  509. #endif
  510. #endif
  511. // Helix serial.c history
  512. // 2018-1-29 fork from let's split (#2308)
  513. // 2018-6-28 bug fix master to slave comm (#3255)
  514. // 2018-8-11 improvements (#3608)
  515. // 2018-10-21 fix serial and RGB animation conflict (#4191)