forked from mirror/qmk_firmware
serial.c: multiple types of transaction support
Add 4 bits transaction-type field at packet top. Select Transaction Descriptor Table entry by transaction-type.
This commit is contained in:
@@ -8,8 +8,7 @@
|
||||
#define SERIAL_PIN_MASK _BV(PD2)
|
||||
#define SERIAL_PIN_INTERRUPT INT2_vect
|
||||
|
||||
#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
|
||||
#define SERIAL_MASTER_BUFFER_LENGTH 1
|
||||
#define SERIAL_USE_SIMPLE_TRANSACTION
|
||||
|
||||
//// #error rev1/keymaps/OLED_sample serial config
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#define SERIAL_PIN_MASK _BV(PD0)
|
||||
#define SERIAL_PIN_INTERRUPT INT0_vect
|
||||
|
||||
#define SERIAL_USE_SIMPLE_TRANSACTION
|
||||
|
||||
/// #error rev1 serial config
|
||||
|
||||
#endif /* SOFT_SERIAL_CONFIG_H */
|
||||
|
||||
@@ -10,8 +10,6 @@ uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
|
||||
uint8_t volatile status0 = 0;
|
||||
|
||||
SSTD_t transactions[] = {
|
||||
|
||||
#define WHOLE_MATRIX_EXCHANGE 0
|
||||
{ (uint8_t *)&status0,
|
||||
sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer,
|
||||
sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
|
||||
@@ -33,6 +31,6 @@ void serial_slave_init(void)
|
||||
// 2 => checksum error
|
||||
int serial_update_buffers(int master_update)
|
||||
{
|
||||
return soft_serial_transaction(WHOLE_MATRIX_EXCHANGE);
|
||||
return soft_serial_transaction();
|
||||
}
|
||||
#endif /* USE_SERIAL */
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#define SERIAL_PIN_MASK _BV(PD2)
|
||||
#define SERIAL_PIN_INTERRUPT INT2_vect
|
||||
|
||||
// if you need more program area, use this macro
|
||||
// #define SERIAL_USE_SIMPLE_TRANSACTION
|
||||
|
||||
//// #error rev2 serial config
|
||||
|
||||
#endif /* SOFT_SERIAL_CONFIG_H */
|
||||
|
||||
@@ -9,14 +9,22 @@ uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
|
||||
uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
|
||||
uint8_t volatile status0 = 0;
|
||||
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
SSTD_t transactions[] = {
|
||||
{ (uint8_t *)&status0,
|
||||
sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer,
|
||||
sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
|
||||
}
|
||||
};
|
||||
#else
|
||||
SSTD_t transactions[] = {
|
||||
|
||||
#define WHOLE_MATRIX_EXCHANGE 0
|
||||
{ (uint8_t *)&status0,
|
||||
sizeof(serial_master_buffer), (uint8_t *)serial_master_buffer,
|
||||
sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void serial_master_init(void)
|
||||
{
|
||||
@@ -33,6 +41,10 @@ void serial_slave_init(void)
|
||||
// 2 => checksum error
|
||||
int serial_update_buffers(int master_update)
|
||||
{
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
return soft_serial_transaction();
|
||||
#else
|
||||
return soft_serial_transaction(WHOLE_MATRIX_EXCHANGE);
|
||||
#endif
|
||||
}
|
||||
#endif /* USE_SERIAL */
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
|
||||
|
||||
// Serial pulse period in microseconds.
|
||||
#define TID_SEND_ADJUST 14
|
||||
|
||||
#define SELECT_SERIAL_SPEED 1
|
||||
#if SELECT_SERIAL_SPEED == 0
|
||||
// Very High speed
|
||||
@@ -55,8 +57,13 @@
|
||||
#define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2)
|
||||
#define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2)
|
||||
|
||||
#define SLAVE_INT_WIDTH 1
|
||||
#define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
|
||||
#define SLAVE_INT_WIDTH_US 1
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
#define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
|
||||
#else
|
||||
#define SLAVE_INT_ACK_WIDTH_UNIT 2
|
||||
#define SLAVE_INT_ACK_WIDTH 4
|
||||
#endif
|
||||
|
||||
static SSTD_t *Transaction_table = NULL;
|
||||
|
||||
@@ -272,10 +279,31 @@ void change_reciver2sender(void) {
|
||||
// interrupt handle to be used by the target device
|
||||
ISR(SERIAL_PIN_INTERRUPT) {
|
||||
debug_output_mode(); debug_input_mode(); // indicate intterupt entry
|
||||
debug_recvsample(); debug_recvsample(); // indicate intterupt entry
|
||||
debug_sync_start(); debug_sync_end(); // indicate intterupt entry
|
||||
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
serial_low();
|
||||
serial_output();
|
||||
SSTD_t *trans = Transaction_table;
|
||||
#else
|
||||
// recive transaction table index
|
||||
uint8_t tid;
|
||||
uint8_t pecount = 0;
|
||||
sync_recv();
|
||||
debug_bytewidth_start();
|
||||
tid = serial_read_chunk(&pecount,4);
|
||||
debug_bytewidth_end();
|
||||
if(pecount> 0)
|
||||
return;
|
||||
serial_delay_half1();
|
||||
|
||||
serial_high(); // response step1 low->high
|
||||
serial_output();
|
||||
_delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH);
|
||||
SSTD_t *trans = &Transaction_table[tid];
|
||||
serial_low(); // response step2 ack high->low
|
||||
#endif
|
||||
|
||||
// target send phase
|
||||
if( trans->target2initiator_buffer_size > 0 )
|
||||
@@ -288,10 +316,10 @@ ISR(SERIAL_PIN_INTERRUPT) {
|
||||
if( trans->initiator2target_buffer_size > 0 ) {
|
||||
if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer,
|
||||
trans->initiator2target_buffer_size) ) {
|
||||
*trans->status = RECIVE_ACCEPTED;
|
||||
*trans->status = TRANSACTION_ACCEPTED;
|
||||
} else {
|
||||
debug_parity_on();
|
||||
*trans->status = RECIVE_DATA_ERROR;
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
debug_parity_off();
|
||||
}
|
||||
}
|
||||
@@ -309,16 +337,22 @@ ISR(SERIAL_PIN_INTERRUPT) {
|
||||
// TRANSACTION_END
|
||||
// TRANSACTION_NO_RESPONSE
|
||||
// TRANSACTION_DATA_ERROR
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
int soft_serial_transaction(void) {
|
||||
SSTD_t *trans = Transaction_table;
|
||||
#else
|
||||
int soft_serial_transaction(int sstd_index) {
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
SSTD_t *trans = &Transaction_table[sstd_index];
|
||||
#endif
|
||||
cli();
|
||||
|
||||
// signal to the target that we want to start a transaction
|
||||
serial_output();
|
||||
serial_low();
|
||||
_delay_us(SLAVE_INT_WIDTH);
|
||||
_delay_us(SLAVE_INT_WIDTH_US);
|
||||
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
// wait for the target response
|
||||
serial_input_with_pullup();
|
||||
_delay_us(SLAVE_INT_RESPONSE_TIME);
|
||||
@@ -328,10 +362,44 @@ int soft_serial_transaction(int sstd_index) {
|
||||
// target failed to pull the line low, assume not present
|
||||
serial_output();
|
||||
serial_high();
|
||||
*trans->status = TRANSACTION_NO_RESPONSE;
|
||||
sei();
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
}
|
||||
|
||||
#else
|
||||
// send transaction table index
|
||||
sync_send();
|
||||
debug_bytewidth_start();
|
||||
_delay_sub_us(TID_SEND_ADJUST);
|
||||
serial_write_chunk(sstd_index, 4);
|
||||
debug_bytewidth_end();
|
||||
serial_delay_half1();
|
||||
|
||||
// wait for the target response (step1 low->high)
|
||||
serial_input_with_pullup();
|
||||
while( !serial_read_pin() ) {
|
||||
_delay_sub_us(2);
|
||||
debug_output_mode(); debug_input_mode(); // indicate check pin timeing
|
||||
}
|
||||
|
||||
// check if the target is present (step2 high->low)
|
||||
debug_output_mode(); _delay_sub_us(1); debug_input_mode(); // indicate check pin timeing
|
||||
for( int i = 0; serial_read_pin(); i++ ) {
|
||||
if (i > SLAVE_INT_ACK_WIDTH + 1) {
|
||||
// slave failed to pull the line low, assume not present
|
||||
serial_output();
|
||||
serial_high();
|
||||
*trans->status = TRANSACTION_NO_RESPONSE;
|
||||
sei();
|
||||
return TRANSACTION_NO_RESPONSE;
|
||||
}
|
||||
debug_output_mode();
|
||||
_delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
|
||||
debug_input_mode(); // indicate check pin timeing
|
||||
}
|
||||
#endif
|
||||
|
||||
// initiator recive phase
|
||||
// if the target is present syncronize with it
|
||||
if( trans->target2initiator_buffer_size > 0 ) {
|
||||
@@ -341,6 +409,7 @@ int soft_serial_transaction(int sstd_index) {
|
||||
serial_output();
|
||||
serial_high();
|
||||
debug_parity_off();
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
sei();
|
||||
return TRANSACTION_DATA_ERROR;
|
||||
}
|
||||
@@ -359,8 +428,20 @@ int soft_serial_transaction(int sstd_index) {
|
||||
sync_send();
|
||||
debug_input_mode(); debug_output_mode(); // indicate intterupt exit
|
||||
|
||||
*trans->status = TRANSACTION_END;
|
||||
sei();
|
||||
return TRANSACTION_END;
|
||||
}
|
||||
|
||||
#ifndef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
int soft_serial_get_and_clean_status(int sstd_index) {
|
||||
SSTD_t *trans = &Transaction_table[sstd_index];
|
||||
cli();
|
||||
int retval = *trans->status;
|
||||
*trans->status = 0;;
|
||||
sei();
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,15 +29,27 @@ void soft_serial_target_init(SSTD_t *sstd_table);
|
||||
|
||||
// initiator resullt
|
||||
#define TRANSACTION_END 0
|
||||
#define TRANSACTION_NO_RESPONSE 1
|
||||
#define TRANSACTION_DATA_ERROR 2
|
||||
#define TRANSACTION_NO_RESPONSE 0x1
|
||||
#define TRANSACTION_DATA_ERROR 0x2
|
||||
#ifdef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
int soft_serial_transaction(void);
|
||||
#else
|
||||
int soft_serial_transaction(int sstd_index);
|
||||
#endif
|
||||
|
||||
// target status
|
||||
#define RECIVE_ACCEPTED 1
|
||||
#define RECIVE_DATA_ERROR 2
|
||||
int soft_serial_get_and_clean_target_status(int sstd_index);
|
||||
|
||||
// *SSTD_t.status has
|
||||
// initiator:
|
||||
// TRANSACTION_END
|
||||
// or TRANSACTION_NO_RESPONSE
|
||||
// or TRANSACTION_DATA_ERROR
|
||||
// target:
|
||||
// TRANSACTION_DATA_ERROR
|
||||
// or TRANSACTION_ACCEPTED
|
||||
#define TRANSACTION_ACCEPTED 0x4
|
||||
#ifndef SERIAL_USE_SIMPLE_TRANSACTION
|
||||
int soft_serial_get_and_clean_status(int sstd_index);
|
||||
#endif
|
||||
|
||||
|
||||
// debug flags
|
||||
|
||||
Reference in New Issue
Block a user