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