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.

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