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
|
@ -74,21 +74,12 @@ static THD_FUNCTION(Thread1, arg) {
|
|||
}
|
||||
}
|
||||
|
||||
static SSTD_t *Transaction_table = NULL;
|
||||
static uint8_t Transaction_table_size = 0;
|
||||
|
||||
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();
|
||||
|
||||
palEnablePadEvent(PAL_PORT(SOFT_SERIAL_PIN), PAL_PAD(SOFT_SERIAL_PIN), PAL_EVENT_MODE_FALLING_EDGE);
|
||||
|
@ -154,16 +145,14 @@ void interrupt_handler(void *arg) {
|
|||
uint8_t checksum_computed = 0;
|
||||
int sstd_index = 0;
|
||||
|
||||
#ifdef SERIAL_USE_MULTI_TRANSACTION
|
||||
sstd_index = serial_read_byte();
|
||||
sync_send();
|
||||
#endif
|
||||
|
||||
SSTD_t *trans = &Transaction_table[sstd_index];
|
||||
split_transaction_desc_t *trans = &split_transaction_table[sstd_index];
|
||||
for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
|
||||
trans->initiator2target_buffer[i] = serial_read_byte();
|
||||
split_trans_initiator2target_buffer(trans)[i] = serial_read_byte();
|
||||
sync_send();
|
||||
checksum_computed += trans->initiator2target_buffer[i];
|
||||
checksum_computed += split_trans_initiator2target_buffer(trans)[i];
|
||||
}
|
||||
checksum_computed ^= 7;
|
||||
uint8_t checksum_received = serial_read_byte();
|
||||
|
@ -172,12 +161,17 @@ void interrupt_handler(void *arg) {
|
|||
// wait for the sync to finish sending
|
||||
serial_delay();
|
||||
|
||||
// Allow any slave processing to occur
|
||||
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));
|
||||
}
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
|
||||
serial_write_byte(trans->target2initiator_buffer[i]);
|
||||
serial_write_byte(split_trans_target2initiator_buffer(trans)[i]);
|
||||
sync_send();
|
||||
serial_delay_half();
|
||||
checksum += trans->target2initiator_buffer[i];
|
||||
checksum += split_trans_target2initiator_buffer(trans)[i];
|
||||
}
|
||||
serial_write_byte(checksum ^ 7);
|
||||
sync_send();
|
||||
|
@ -206,15 +200,10 @@ void interrupt_handler(void *arg) {
|
|||
// 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) {
|
||||
int sstd_index = 0;
|
||||
#else
|
||||
int soft_serial_transaction(int sstd_index) {
|
||||
#endif
|
||||
|
||||
if (sstd_index > Transaction_table_size) return TRANSACTION_TYPE_ERROR;
|
||||
SSTD_t *trans = &Transaction_table[sstd_index];
|
||||
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
|
||||
|
||||
// TODO: remove extra delay between transactions
|
||||
serial_delay();
|
||||
|
@ -244,14 +233,13 @@ int soft_serial_transaction(int sstd_index) {
|
|||
|
||||
uint8_t checksum = 0;
|
||||
// send data to the slave
|
||||
#ifdef SERIAL_USE_MULTI_TRANSACTION
|
||||
serial_write_byte(sstd_index); // first chunk is transaction id
|
||||
sync_recv();
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < trans->initiator2target_buffer_size; ++i) {
|
||||
serial_write_byte(trans->initiator2target_buffer[i]);
|
||||
serial_write_byte(split_trans_initiator2target_buffer(trans)[i]);
|
||||
sync_recv();
|
||||
checksum += trans->initiator2target_buffer[i];
|
||||
checksum += split_trans_initiator2target_buffer(trans)[i];
|
||||
}
|
||||
serial_write_byte(checksum ^ 7);
|
||||
sync_recv();
|
||||
|
@ -262,9 +250,9 @@ int soft_serial_transaction(int sstd_index) {
|
|||
// receive data from the slave
|
||||
uint8_t checksum_computed = 0;
|
||||
for (int i = 0; i < trans->target2initiator_buffer_size; ++i) {
|
||||
trans->target2initiator_buffer[i] = serial_read_byte();
|
||||
split_trans_target2initiator_buffer(trans)[i] = serial_read_byte();
|
||||
sync_recv();
|
||||
checksum_computed += trans->target2initiator_buffer[i];
|
||||
checksum_computed += split_trans_target2initiator_buffer(trans)[i];
|
||||
}
|
||||
checksum_computed ^= 7;
|
||||
uint8_t checksum_received = serial_read_byte();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue