You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

590 lines
16 KiB

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