serial.c: multiple types of transaction support

Add 4 bits transaction-type field at packet top.
Select Transaction Descriptor Table entry by transaction-type.
pull/3608/head
mtei 7 years ago
parent 7da9081fb1
commit 2b4f7d3400

@ -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

Loading…
Cancel
Save