Extensible split data sync (#11930)
* Extensible split data sync capability through transactions. - Split common transport has been split up between the transport layer and data layer. - Split "transactions" model used, with convergence between I2C and serial data definitions. - Slave matrix "generation count" is used to determine if the full slave matrix needs to be retrieved. - Encoders get the same "generation count" treatment. - All other blocks of data are synchronised when a change is detected. - All transmissions have a globally-configurable deadline before a transmission is forced (`FORCED_SYNC_THROTTLE_MS`, default 100ms). - Added atomicity for all core-synced data, preventing partial updates - Added retries to AVR i2c_master's i2c_start, to minimise the number of failed transactions when interrupts are disabled on the slave due to atomicity checks. - Some keyboards have had slight modifications made in order to ensure that they still build due to firmware size restrictions. * Fixup LED_MATRIX compile. * Parameterise ERROR_DISCONNECT_COUNT.
This commit is contained in:
parent
ef92c9ee2c
commit
172e6a7030
29 changed files with 1389 additions and 693 deletions
|
@ -224,15 +224,8 @@
|
|||
# define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY / 2)
|
||||
|
||||
# define SLAVE_INT_WIDTH_US 1
|
||||
# ifndef SERIAL_USE_MULTI_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;
|
||||
static uint8_t Transaction_table_size = 0;
|
||||
# define SLAVE_INT_ACK_WIDTH_UNIT 2
|
||||
# define SLAVE_INT_ACK_WIDTH 4
|
||||
|
||||
inline static void serial_delay(void) ALWAYS_INLINE;
|
||||
inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); }
|
||||
|
@ -259,16 +252,12 @@ inline static void serial_low(void) { writePinLow(SOFT_SERIAL_PIN); }
|
|||
inline static void serial_high(void) ALWAYS_INLINE;
|
||||
inline static void serial_high(void) { writePinHigh(SOFT_SERIAL_PIN); }
|
||||
|
||||
void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size) {
|
||||
Transaction_table = sstd_table;
|
||||
Transaction_table_size = (uint8_t)sstd_table_size;
|
||||
void soft_serial_initiator_init(void) {
|
||||
serial_output();
|
||||
serial_high();
|
||||
}
|
||||
|
||||
void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size) {
|
||||
Transaction_table = sstd_table;
|
||||
Transaction_table_size = (uint8_t)sstd_table_size;
|
||||
void soft_serial_target_init(void) {
|
||||
serial_input_with_pullup();
|
||||
|
||||
// Enable INT0-INT7
|
||||
|
@ -395,19 +384,14 @@ static inline uint8_t nibble_bits_count(uint8_t bits) {
|
|||
|
||||
// interrupt handle to be used by the target device
|
||||
ISR(SERIAL_PIN_INTERRUPT) {
|
||||
# ifndef SERIAL_USE_MULTI_TRANSACTION
|
||||
serial_low();
|
||||
serial_output();
|
||||
SSTD_t *trans = Transaction_table;
|
||||
# else
|
||||
// recive transaction table index
|
||||
uint8_t tid, bits;
|
||||
uint8_t pecount = 0;
|
||||
sync_recv();
|
||||
bits = serial_read_chunk(&pecount, 7);
|
||||
bits = serial_read_chunk(&pecount, 8);
|
||||
tid = bits >> 3;
|
||||
bits = (bits & 7) != nibble_bits_count(tid);
|
||||
if (bits || pecount > 0 || tid > Transaction_table_size) {
|
||||
bits = (bits & 7) != (nibble_bits_count(tid) & 7);
|
||||
if (bits || pecount > 0 || tid > NUM_TOTAL_TRANSACTIONS) {
|
||||
return;
|
||||
}
|
||||
serial_delay_half1();
|
||||
|
@ -415,18 +399,22 @@ ISR(SERIAL_PIN_INTERRUPT) {
|
|||
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];
|
||||
split_transaction_desc_t *trans = &split_transaction_table[tid];
|
||||
serial_low(); // response step2 ack high->low
|
||||
# endif
|
||||
|
||||
// If the transaction has a callback, we can execute it now
|
||||
if (trans->slave_callback) {
|
||||
trans->slave_callback(trans->initiator2target_buffer_size, split_trans_initiator2target_buffer(trans), trans->target2initiator_buffer_size, split_trans_target2initiator_buffer(trans));
|
||||
}
|
||||
|
||||
// target send phase
|
||||
if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size);
|
||||
if (trans->target2initiator_buffer_size > 0) serial_send_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size);
|
||||
// target switch to input
|
||||
change_sender2reciver();
|
||||
|
||||
// target recive phase
|
||||
if (trans->initiator2target_buffer_size > 0) {
|
||||
if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size)) {
|
||||
if (serial_recive_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size)) {
|
||||
*trans->status = TRANSACTION_ACCEPTED;
|
||||
} else {
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
|
@ -448,14 +436,12 @@ ISR(SERIAL_PIN_INTERRUPT) {
|
|||
// TRANSACTION_NO_RESPONSE
|
||||
// TRANSACTION_DATA_ERROR
|
||||
// this code is very time dependent, so we need to disable interrupts
|
||||
# ifndef SERIAL_USE_MULTI_TRANSACTION
|
||||
int soft_serial_transaction(void) {
|
||||
SSTD_t *trans = Transaction_table;
|
||||
# else
|
||||
int soft_serial_transaction(int sstd_index) {
|
||||
if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR;
|
||||
SSTD_t *trans = &Transaction_table[sstd_index];
|
||||
# endif
|
||||
if (sstd_index > NUM_TOTAL_TRANSACTIONS) return TRANSACTION_TYPE_ERROR;
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
|
||||
if (!trans->status) return TRANSACTION_TYPE_ERROR; // not registered
|
||||
|
||||
cli();
|
||||
|
||||
// signal to the target that we want to start a transaction
|
||||
|
@ -463,27 +449,11 @@ int soft_serial_transaction(int sstd_index) {
|
|||
serial_low();
|
||||
_delay_us(SLAVE_INT_WIDTH_US);
|
||||
|
||||
# ifndef SERIAL_USE_MULTI_TRANSACTION
|
||||
// wait for the target response
|
||||
serial_input_with_pullup();
|
||||
_delay_us(SLAVE_INT_RESPONSE_TIME);
|
||||
|
||||
// check if the target is present
|
||||
if (serial_read_pin()) {
|
||||
// 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
|
||||
int tid = (sstd_index << 3) | (7 & nibble_bits_count(sstd_index));
|
||||
sync_send();
|
||||
_delay_sub_us(TID_SEND_ADJUST);
|
||||
serial_write_chunk(tid, 7);
|
||||
serial_write_chunk(tid, 8);
|
||||
serial_delay_half1();
|
||||
|
||||
// wait for the target response (step1 low->high)
|
||||
|
@ -504,12 +474,11 @@ int soft_serial_transaction(int sstd_index) {
|
|||
}
|
||||
_delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
|
||||
}
|
||||
# endif
|
||||
|
||||
// initiator recive phase
|
||||
// if the target is present syncronize with it
|
||||
if (trans->target2initiator_buffer_size > 0) {
|
||||
if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer, trans->target2initiator_buffer_size)) {
|
||||
if (!serial_recive_packet((uint8_t *)split_trans_target2initiator_buffer(trans), trans->target2initiator_buffer_size)) {
|
||||
serial_output();
|
||||
serial_high();
|
||||
*trans->status = TRANSACTION_DATA_ERROR;
|
||||
|
@ -523,7 +492,7 @@ int soft_serial_transaction(int sstd_index) {
|
|||
|
||||
// initiator send phase
|
||||
if (trans->initiator2target_buffer_size > 0) {
|
||||
serial_send_packet((uint8_t *)trans->initiator2target_buffer, trans->initiator2target_buffer_size);
|
||||
serial_send_packet((uint8_t *)split_trans_initiator2target_buffer(trans), trans->initiator2target_buffer_size);
|
||||
}
|
||||
|
||||
// always, release the line when not in use
|
||||
|
@ -534,9 +503,8 @@ int soft_serial_transaction(int sstd_index) {
|
|||
return TRANSACTION_END;
|
||||
}
|
||||
|
||||
# ifdef SERIAL_USE_MULTI_TRANSACTION
|
||||
int soft_serial_get_and_clean_status(int sstd_index) {
|
||||
SSTD_t *trans = &Transaction_table[sstd_index];
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
cli();
|
||||
int retval = *trans->status;
|
||||
*trans->status = 0;
|
||||
|
@ -544,8 +512,6 @@ int soft_serial_get_and_clean_status(int sstd_index) {
|
|||
sei();
|
||||
return retval;
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
// Helix serial.c history
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue