diff options
Diffstat (limited to 'drivers/avr/serial.c')
| -rw-r--r-- | drivers/avr/serial.c | 82 |
1 files changed, 24 insertions, 58 deletions
diff --git a/drivers/avr/serial.c b/drivers/avr/serial.c index 3647bee0d..9a7345a53 100644 --- a/drivers/avr/serial.c +++ b/drivers/avr/serial.c | |||
| @@ -224,15 +224,8 @@ | |||
| 224 | # define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) | 224 | # define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2) |
| 225 | 225 | ||
| 226 | # define SLAVE_INT_WIDTH_US 1 | 226 | # define SLAVE_INT_WIDTH_US 1 |
| 227 | # ifndef SERIAL_USE_MULTI_TRANSACTION | 227 | # define SLAVE_INT_ACK_WIDTH_UNIT 2 |
| 228 | # define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY | 228 | # define SLAVE_INT_ACK_WIDTH 4 |
| 229 | # else | ||
| 230 | # define SLAVE_INT_ACK_WIDTH_UNIT 2 | ||
| 231 | # define SLAVE_INT_ACK_WIDTH 4 | ||
| 232 | # endif | ||
| 233 | |||
| 234 | static SSTD_t *Transaction_table = NULL; | ||
| 235 | static uint8_t Transaction_table_size = 0; | ||
| 236 | 229 | ||
| 237 | inline static void serial_delay(void) ALWAYS_INLINE; | 230 | inline static void serial_delay(void) ALWAYS_INLINE; |
| 238 | inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } | 231 | inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); } |
| @@ -259,16 +252,12 @@ inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); } | |||
| 259 | inline static void serial_high(void) ALWAYS_INLINE; | 252 | inline static void serial_high(void) ALWAYS_INLINE; |
| 260 | inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } | 253 | inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); } |
| 261 | 254 | ||
| 262 | void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) { | 255 | void soft_serial_initiator_init(void) { |
| 263 | Transaction_table = sstd_table; | ||
| 264 | Transaction_table_size = (uint8_t)sstd_table_size; | ||
| 265 | serial_output(); | 256 | serial_output(); |
| 266 | serial_high(); | 257 | serial_high(); |
| 267 | } | 258 | } |
| 268 | 259 | ||
| 269 | void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) { | 260 | void soft_serial_target_init(void) { |
| 270 | Transaction_table = sstd_table; | ||
| 271 | Transaction_table_size = (uint8_t)sstd_table_size; | ||
| 272 | serial_input_with_pullup(); | 261 | serial_input_with_pullup(); |
| 273 | 262 | ||
| 274 | // Enable INT0-INT7 | 263 | // Enable INT0-INT7 |
| @@ -395,19 +384,14 @@ static inline uint8_t nibble_bits_count(uint8_t bits) { | |||
| 395 | 384 | ||
| 396 | // interrupt handle to be used by the target device | 385 | // interrupt handle to be used by the target device |
| 397 | ISR(SERIAL_PIN_INTERRUPT) { | 386 | ISR(SERIAL_PIN_INTERRUPT) { |
| 398 | # ifndef SERIAL_USE_MULTI_TRANSACTION | ||
| 399 | serial_low(); | ||
| 400 | serial_output(); | ||
| 401 | SSTD_t *trans = Transaction_table; | ||
| 402 | # else | ||
| 403 | // recive transaction table index | 387 | // recive transaction table index |
| 404 | uint8_t tid, bits; | 388 | uint8_t tid, bits; |
| 405 | uint8_t pecount = 0; | 389 | uint8_t pecount = 0; |
| 406 | sync_recv(); | 390 | sync_recv(); |
| 407 | bits = serial_read_chunk(&pecount, 7); | 391 | bits = serial_read_chunk(&pecount, 8); |
| 408 | tid = bits >> 3; | 392 | tid = bits >> 3; |
| 409 | bits = (bits & 7) != nibble_bits_count(tid); | 393 | bits = (bits & 7) != (nibble_bits_count(tid) & 7); |
| 410 | if (bits || pecount > 0 || tid > Transaction_table_size) { | 394 | if (bits || pecount > 0 || tid > NUM_TOTAL_TRANSACTIONS) { |
| 411 | return; | 395 | return; |
| 412 | } | 396 | } |
| 413 | serial_delay_half1(); | 397 | serial_delay_half1(); |
| @@ -415,18 +399,22 @@ ISR(SERIAL_PIN_INTERRUPT) { | |||
| 415 | serial_high(); // response step1 low->high | 399 | serial_high(); // response step1 low->high |
| 416 | serial_output(); | 400 | serial_output(); |
| 417 | _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); | 401 | _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT * SLAVE_INT_ACK_WIDTH); |
| 418 | SSTD_t *trans = &Transaction_table[tid]; | 402 | split_transaction_desc_t *trans = &split_transaction_table[tid]; |
| 419 | serial_low(); // response step2 ack high->low | 403 | serial_low(); // response step2 ack high->low |
| 420 | # endif | 404 | |
| 405 | // If the transaction has a callback, we can execute it now | ||
| 406 | if (trans->slave_callback) { | ||
| 407 | trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans)); | ||
| 408 | } | ||
| 421 | 409 | ||
| 422 | // target send phase | 410 | // target send phase |
| 423 | if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size); | 411 | if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size); |
| 424 | // target switch to input | 412 | // target switch to input |
| 425 | change_sender2reciver(); | 413 | change_sender2reciver(); |
| 426 | 414 | ||
| 427 | // target recive phase | 415 | // target recive phase |
| 428 | if (trans->initiator2target_buffer_size > 0) { | 416 | if (trans->initiator2target_buffer_size > 0) { |
| 429 | if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size)) { | 417 | if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) { |
| 430 | *trans->status = TRANSACTION_ACCEPTED; | 418 | *trans->status = TRANSACTION_ACCEPTED; |
| 431 | } else { | 419 | } else { |
| 432 | *trans->status = TRANSACTION_DATA_ERROR; | 420 | *trans->status = TRANSACTION_DATA_ERROR; |
| @@ -448,14 +436,12 @@ ISR(SERIAL_PIN_INTERRUPT) { | |||
| 448 | // TRANSACTION_NO_RESPONSE | 436 | // TRANSACTION_NO_RESPONSE |
| 449 | // TRANSACTION_DATA_ERROR | 437 | // TRANSACTION_DATA_ERROR |
| 450 | // this code is very time dependent, so we need to disable interrupts | 438 | // this code is very time dependent, so we need to disable interrupts |
| 451 | # ifndef SERIAL_USE_MULTI_TRANSACTION | ||
| 452 | int soft_serial_transaction(void) { | ||
| 453 | SSTD_t *trans = Transaction_table; | ||
| 454 | # else | ||
| 455 | int soft_serial_transaction(int sstd_index) { | 439 | int soft_serial_transaction(int sstd_index) { |
| 456 | if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR; | 440 | if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR; |
| 457 | SSTD_t *trans = &Transaction_table[sstd_index]; | 441 | split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; |
| 458 | # endif | 442 | |
| 443 | if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered | ||
| 444 | |||
| 459 | cli(); | 445 | cli(); |
| 460 | 446 | ||
| 461 | // signal to the target that we want to start a transaction | 447 | // signal to the target that we want to start a transaction |
| @@ -463,27 +449,11 @@ int soft_serial_transaction(int sstd_index) { | |||
| 463 | serial_low(); | 449 | serial_low(); |
| 464 | _delay_us(SLAVE_INT_WIDTH_US); | 450 | _delay_us(SLAVE_INT_WIDTH_US); |
| 465 | 451 | ||
| 466 | # ifndef SERIAL_USE_MULTI_TRANSACTION | ||
| 467 | // wait for the target response | ||
| 468 | serial_input_with_pullup(); | ||
| 469 | _delay_us(SLAVE_INT_RESPONSE_TIME); | ||
| 470 | |||
| 471 | // check if the target is present | ||
| 472 | if (serial_read_pin()) { | ||
| 473 | // target failed to pull the line low, assume not present | ||
| 474 | serial_output(); | ||
| 475 | serial_high(); | ||
| 476 | *trans->status = TRANSACTION_NO_RESPONSE; | ||
| 477 | sei(); | ||
| 478 | return TRANSACTION_NO_RESPONSE; | ||
| 479 | } | ||
| 480 | |||
| 481 | # else | ||
| 482 | // send transaction table index | 452 | // send transaction table index |
| 483 | int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); | 453 | int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index)); |
| 484 | sync_send(); | 454 | sync_send(); |
| 485 | _delay_sub_us(TID_SEND_ADJUST); | 455 | _delay_sub_us(TID_SEND_ADJUST); |
| 486 | serial_write_chunk(tid, 7); | 456 | serial_write_chunk(tid, 8); |
| 487 | serial_delay_half1(); | 457 | serial_delay_half1(); |
| 488 | 458 | ||
| 489 | // wait for the target response (step1 low->high) | 459 | // wait for the target response (step1 low->high) |
| @@ -504,12 +474,11 @@ int soft_serial_transaction(int sstd_index) { | |||
| 504 | } | 474 | } |
| 505 | _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); | 475 | _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT); |
| 506 | } | 476 | } |
| 507 | # endif | ||
| 508 | 477 | ||
| 509 | // initiator recive phase | 478 | // initiator recive phase |
| 510 | // if the target is present syncronize with it | 479 | // if the target is present syncronize with it |
| 511 | if (trans->target2initiator_buffer_size > 0) { | 480 | if (trans->target2initiator_buffer_size > 0) { |
| 512 | if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size)) { | 481 | if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) { |
| 513 | serial_output(); | 482 | serial_output(); |
| 514 | serial_high(); | 483 | serial_high(); |
| 515 | *trans->status = TRANSACTION_DATA_ERROR; | 484 | *trans->status = TRANSACTION_DATA_ERROR; |
| @@ -523,7 +492,7 @@ int soft_serial_transaction(int sstd_index) { | |||
| 523 | 492 | ||
| 524 | // initiator send phase | 493 | // initiator send phase |
| 525 | if (trans->initiator2target_buffer_size > 0) { | 494 | if (trans->initiator2target_buffer_size > 0) { |
| 526 | serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size); | 495 | serial_send_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size); |
| 527 | } | 496 | } |
| 528 | 497 | ||
| 529 | // always, release the line when not in use | 498 | // always, release the line when not in use |
| @@ -534,9 +503,8 @@ int soft_serial_transaction(int sstd_index) { | |||
| 534 | return TRANSACTION_END; | 503 | return TRANSACTION_END; |
| 535 | } | 504 | } |
| 536 | 505 | ||
| 537 | # ifdef SERIAL_USE_MULTI_TRANSACTION | ||
| 538 | int soft_serial_get_and_clean_status(int sstd_index) { | 506 | int soft_serial_get_and_clean_status(int sstd_index) { |
| 539 | SSTD_t *trans = &Transaction_table[sstd_index]; | 507 | split_transaction_desc_t *trans = &split_transaction_table[sstd_index]; |
| 540 | cli(); | 508 | cli(); |
| 541 | int retval = *trans->status; | 509 | int retval = *trans->status; |
| 542 | *trans->status = 0; | 510 | *trans->status = 0; |
| @@ -544,8 +512,6 @@ int soft_serial_get_and_clean_status(int sstd_index) { | |||
| 544 | sei(); | 512 | sei(); |
| 545 | return retval; | 513 | return retval; |
| 546 | } | 514 | } |
| 547 | # endif | ||
| 548 | |||
| 549 | #endif | 515 | #endif |
| 550 | 516 | ||
| 551 | // Helix serial.c history | 517 | // Helix serial.c history |
