diff options
Diffstat (limited to 'quantum/split_common/transport.c')
| -rw-r--r-- | quantum/split_common/transport.c | 184 |
1 files changed, 110 insertions, 74 deletions
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index ab055ee65..7ea1a9cec 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c | |||
| @@ -25,36 +25,23 @@ extern backlight_config_t backlight_config; | |||
| 25 | # include "i2c_master.h" | 25 | # include "i2c_master.h" |
| 26 | # include "i2c_slave.h" | 26 | # include "i2c_slave.h" |
| 27 | 27 | ||
| 28 | typedef struct __attribute__ ((__packed__)) { | 28 | typedef struct _I2C_slave_buffer_t { |
| 29 | #ifdef BACKLIGHT_ENABLE | 29 | matrix_row_t smatrix[ROWS_PER_HAND]; |
| 30 | uint8_t backlight_level; | 30 | uint8_t backlight_level; |
| 31 | #endif | 31 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) |
| 32 | #ifdef RGBLIGHT_ENABLE | 32 | rgblight_syncinfo_t rgblight_sync; |
| 33 | uint32_t rgb_settings; | ||
| 34 | #endif | 33 | #endif |
| 35 | #ifdef ENCODER_ENABLE | 34 | #ifdef ENCODER_ENABLE |
| 36 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | 35 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; |
| 37 | #endif | ||
| 38 | // Keep matrix last, we are only using this for it's offset | ||
| 39 | uint8_t matrix_start[0]; | ||
| 40 | } transport_values_t; | ||
| 41 | |||
| 42 | __attribute__ ((unused)) | ||
| 43 | static transport_values_t transport_values; | ||
| 44 | |||
| 45 | #ifdef BACKLIGHT_ENABLE | ||
| 46 | # define I2C_BACKLIT_START (uint8_t)offsetof(transport_values_t, backlight_level) | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #ifdef RGBLIGHT_ENABLE | ||
| 50 | # define I2C_RGB_START (uint8_t)offsetof(transport_values_t, rgb_settings) | ||
| 51 | #endif | 36 | #endif |
| 37 | } I2C_slave_buffer_t; | ||
| 52 | 38 | ||
| 53 | #ifdef ENCODER_ENABLE | 39 | static I2C_slave_buffer_t * const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; |
| 54 | # define I2C_ENCODER_START (uint8_t)offsetof(transport_values_t, encoder_state) | ||
| 55 | #endif | ||
| 56 | 40 | ||
| 57 | #define I2C_KEYMAP_START (uint8_t)offsetof(transport_values_t, matrix_start) | 41 | # define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) |
| 42 | # define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) | ||
| 43 | # define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix) | ||
| 44 | # define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) | ||
| 58 | 45 | ||
| 59 | # define TIMEOUT 100 | 46 | # define TIMEOUT 100 |
| 60 | 47 | ||
| @@ -64,30 +51,32 @@ static transport_values_t transport_values; | |||
| 64 | 51 | ||
| 65 | // Get rows from other half over i2c | 52 | // Get rows from other half over i2c |
| 66 | bool transport_master(matrix_row_t matrix[]) { | 53 | bool transport_master(matrix_row_t matrix[]) { |
| 67 | i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t), TIMEOUT); | 54 | i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, sizeof(i2c_buffer->smatrix), TIMEOUT); |
| 68 | 55 | ||
| 69 | // write backlight info | 56 | // write backlight info |
| 70 | # ifdef BACKLIGHT_ENABLE | 57 | # ifdef BACKLIGHT_ENABLE |
| 71 | uint8_t level = get_backlight_level(); | 58 | uint8_t level = get_backlight_level(); |
| 72 | if (level != transport_values.backlight_level) { | 59 | if (level != i2c_buffer->backlight_level) { |
| 73 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { | 60 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) { |
| 74 | transport_values.backlight_level = level; | 61 | i2c_buffer->backlight_level = level; |
| 75 | } | 62 | } |
| 76 | } | 63 | } |
| 77 | # endif | 64 | # endif |
| 78 | 65 | ||
| 79 | # ifdef RGBLIGHT_ENABLE | 66 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) |
| 80 | uint32_t rgb = rgblight_read_dword(); | 67 | if (rgblight_get_change_flags()) { |
| 81 | if (rgb != transport_values.rgb_settings) { | 68 | rgblight_syncinfo_t rgblight_sync; |
| 82 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgb, sizeof(rgb), TIMEOUT) >= 0) { | 69 | rgblight_get_syncinfo(&rgblight_sync); |
| 83 | transport_values.rgb_settings = rgb; | 70 | if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, |
| 71 | (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) { | ||
| 72 | rgblight_clear_change_flags(); | ||
| 84 | } | 73 | } |
| 85 | } | 74 | } |
| 86 | # endif | 75 | # endif |
| 87 | 76 | ||
| 88 | # ifdef ENCODER_ENABLE | 77 | # ifdef ENCODER_ENABLE |
| 89 | i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)transport_values.encoder_state, sizeof(transport_values.encoder_state), TIMEOUT); | 78 | i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(I2C_slave_buffer_t.encoder_state), TIMEOUT); |
| 90 | encoder_update_raw(&transport_values.encoder_state[0]); | 79 | encoder_update_raw(i2c_buffer->encoder_state); |
| 91 | # endif | 80 | # endif |
| 92 | 81 | ||
| 93 | return true; | 82 | return true; |
| @@ -95,21 +84,23 @@ bool transport_master(matrix_row_t matrix[]) { | |||
| 95 | 84 | ||
| 96 | void transport_slave(matrix_row_t matrix[]) { | 85 | void transport_slave(matrix_row_t matrix[]) { |
| 97 | // Copy matrix to I2C buffer | 86 | // Copy matrix to I2C buffer |
| 98 | memcpy((void*)(i2c_slave_reg + I2C_KEYMAP_START), (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t) ); | 87 | memcpy((void*)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); |
| 99 | 88 | ||
| 100 | // Read Backlight Info | 89 | // Read Backlight Info |
| 101 | # ifdef BACKLIGHT_ENABLE | 90 | # ifdef BACKLIGHT_ENABLE |
| 102 | backlight_set(i2c_slave_reg[I2C_BACKLIT_START]); | 91 | backlight_set(i2c_buffer->backlight_level); |
| 103 | # endif | 92 | # endif |
| 104 | 93 | ||
| 105 | # ifdef RGBLIGHT_ENABLE | 94 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) |
| 106 | uint32_t rgb = *(uint32_t *)(i2c_slave_reg + I2C_RGB_START); | ||
| 107 | // Update the RGB with the new data | 95 | // Update the RGB with the new data |
| 108 | rgblight_update_dword(rgb); | 96 | if (i2c_buffer->rgblight_sync.status.change_flags != 0) { |
| 97 | rgblight_update_sync(&i2c_buffer->rgblight_sync, false); | ||
| 98 | i2c_buffer->rgblight_sync.status.change_flags = 0; | ||
| 99 | } | ||
| 109 | # endif | 100 | # endif |
| 110 | 101 | ||
| 111 | # ifdef ENCODER_ENABLE | 102 | # ifdef ENCODER_ENABLE |
| 112 | encoder_state_raw((uint8_t*)(i2c_slave_reg + I2C_ENCODER_START)); | 103 | encoder_state_raw(i2c_buffer->encoder_state); |
| 113 | # endif | 104 | # endif |
| 114 | } | 105 | } |
| 115 | 106 | ||
| @@ -121,53 +112,109 @@ void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); } | |||
| 121 | 112 | ||
| 122 | # include "serial.h" | 113 | # include "serial.h" |
| 123 | 114 | ||
| 124 | typedef struct __attribute__ ((__packed__)) { | 115 | typedef struct _Serial_s2m_buffer_t { |
| 116 | // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack | ||
| 117 | matrix_row_t smatrix[ROWS_PER_HAND]; | ||
| 118 | |||
| 125 | # ifdef ENCODER_ENABLE | 119 | # ifdef ENCODER_ENABLE |
| 126 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; | 120 | uint8_t encoder_state[NUMBER_OF_ENCODERS]; |
| 127 | # endif | 121 | # endif |
| 128 | // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack | 122 | |
| 129 | matrix_row_t smatrix[ROWS_PER_HAND]; | ||
| 130 | } Serial_s2m_buffer_t; | 123 | } Serial_s2m_buffer_t; |
| 131 | 124 | ||
| 132 | typedef struct __attribute__ ((__packed__)) { | 125 | typedef struct _Serial_m2s_buffer_t { |
| 133 | # ifdef BACKLIGHT_ENABLE | 126 | # ifdef BACKLIGHT_ENABLE |
| 134 | uint8_t backlight_level; | 127 | uint8_t backlight_level; |
| 135 | # endif | 128 | # endif |
| 136 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) | ||
| 137 | rgblight_config_t rgblight_config; // not yet use | ||
| 138 | // | ||
| 139 | // When MCUs on both sides drive their respective RGB LED chains, | ||
| 140 | // it is necessary to synchronize, so it is necessary to communicate RGB | ||
| 141 | // information. In that case, define RGBLED_SPLIT with info on the number | ||
| 142 | // of LEDs on each half. | ||
| 143 | // | ||
| 144 | // Otherwise, if the master side MCU drives both sides RGB LED chains, | ||
| 145 | // there is no need to communicate. | ||
| 146 | # endif | ||
| 147 | } Serial_m2s_buffer_t; | 129 | } Serial_m2s_buffer_t; |
| 148 | 130 | ||
| 131 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 132 | // When MCUs on both sides drive their respective RGB LED chains, | ||
| 133 | // it is necessary to synchronize, so it is necessary to communicate RGB | ||
| 134 | // information. In that case, define RGBLIGHT_SPLIT with info on the number | ||
| 135 | // of LEDs on each half. | ||
| 136 | // | ||
| 137 | // Otherwise, if the master side MCU drives both sides RGB LED chains, | ||
| 138 | // there is no need to communicate. | ||
| 139 | |||
| 140 | typedef struct _Serial_rgblight_t { | ||
| 141 | rgblight_syncinfo_t rgblight_sync; | ||
| 142 | } Serial_rgblight_t; | ||
| 143 | |||
| 144 | volatile Serial_rgblight_t serial_rgblight = {}; | ||
| 145 | uint8_t volatile status_rgblight = 0; | ||
| 146 | #endif | ||
| 147 | |||
| 149 | volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; | 148 | volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; |
| 150 | volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; | 149 | volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; |
| 151 | uint8_t volatile status0 = 0; | 150 | uint8_t volatile status0 = 0; |
| 152 | 151 | ||
| 152 | enum serial_transaction_id { | ||
| 153 | GET_SLAVE_MATRIX = 0, | ||
| 154 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 155 | PUT_RGBLIGHT, | ||
| 156 | #endif | ||
| 157 | }; | ||
| 158 | |||
| 153 | SSTD_t transactions[] = { | 159 | SSTD_t transactions[] = { |
| 154 | { | 160 | [GET_SLAVE_MATRIX] = { |
| 155 | (uint8_t *)&status0, | 161 | (uint8_t *)&status0, |
| 156 | sizeof(serial_m2s_buffer), | 162 | sizeof(serial_m2s_buffer), |
| 157 | (uint8_t *)&serial_m2s_buffer, | 163 | (uint8_t *)&serial_m2s_buffer, |
| 158 | sizeof(serial_s2m_buffer), | 164 | sizeof(serial_s2m_buffer), |
| 159 | (uint8_t *)&serial_s2m_buffer, | 165 | (uint8_t *)&serial_s2m_buffer, |
| 160 | }, | 166 | }, |
| 167 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 168 | [PUT_RGBLIGHT] = { | ||
| 169 | (uint8_t *)&status_rgblight, | ||
| 170 | sizeof(serial_rgblight), | ||
| 171 | (uint8_t *)&serial_rgblight, | ||
| 172 | 0, NULL // no slave to master transfer | ||
| 173 | }, | ||
| 174 | #endif | ||
| 161 | }; | 175 | }; |
| 162 | 176 | ||
| 163 | void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } | 177 | void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } |
| 164 | 178 | ||
| 165 | void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } | 179 | void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } |
| 166 | 180 | ||
| 181 | #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) | ||
| 182 | |||
| 183 | // rgblight synchronization information communication. | ||
| 184 | |||
| 185 | void transport_rgblight_master(void) { | ||
| 186 | if (rgblight_get_change_flags()) { | ||
| 187 | rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync); | ||
| 188 | if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) { | ||
| 189 | rgblight_clear_change_flags(); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | void transport_rgblight_slave(void) { | ||
| 195 | if (status_rgblight == TRANSACTION_ACCEPTED) { | ||
| 196 | rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, | ||
| 197 | false); | ||
| 198 | status_rgblight = TRANSACTION_END; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | #else | ||
| 203 | #define transport_rgblight_master() | ||
| 204 | #define transport_rgblight_slave() | ||
| 205 | #endif | ||
| 206 | |||
| 167 | bool transport_master(matrix_row_t matrix[]) { | 207 | bool transport_master(matrix_row_t matrix[]) { |
| 168 | if (soft_serial_transaction()) { | 208 | #ifndef SERIAL_USE_MULTI_TRANSACTION |
| 209 | if (soft_serial_transaction() != TRANSACTION_END) { | ||
| 169 | return false; | 210 | return false; |
| 170 | } | 211 | } |
| 212 | #else | ||
| 213 | transport_rgblight_master(); | ||
| 214 | if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) { | ||
| 215 | return false; | ||
| 216 | } | ||
| 217 | #endif | ||
| 171 | 218 | ||
| 172 | // TODO: if MATRIX_COLS > 8 change to unpack() | 219 | // TODO: if MATRIX_COLS > 8 change to unpack() |
| 173 | for (int i = 0; i < ROWS_PER_HAND; ++i) { | 220 | for (int i = 0; i < ROWS_PER_HAND; ++i) { |
| @@ -179,23 +226,15 @@ bool transport_master(matrix_row_t matrix[]) { | |||
| 179 | serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0; | 226 | serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0; |
| 180 | # endif | 227 | # endif |
| 181 | 228 | ||
| 182 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) | ||
| 183 | static rgblight_config_t prev_rgb = {~0}; | ||
| 184 | uint32_t rgb = rgblight_read_dword(); | ||
| 185 | if (rgb != prev_rgb.raw) { | ||
| 186 | serial_m2s_buffer.rgblight_config.raw = rgb; | ||
| 187 | prev_rgb.raw = rgb; | ||
| 188 | } | ||
| 189 | # endif | ||
| 190 | |||
| 191 | # ifdef ENCODER_ENABLE | 229 | # ifdef ENCODER_ENABLE |
| 192 | encoder_update_raw((uint8_t*)&serial_s2m_buffer.encoder_state); | 230 | encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state); |
| 193 | # endif | 231 | # endif |
| 194 | 232 | ||
| 195 | return true; | 233 | return true; |
| 196 | } | 234 | } |
| 197 | 235 | ||
| 198 | void transport_slave(matrix_row_t matrix[]) { | 236 | void transport_slave(matrix_row_t matrix[]) { |
| 237 | transport_rgblight_slave(); | ||
| 199 | // TODO: if MATRIX_COLS > 8 change to pack() | 238 | // TODO: if MATRIX_COLS > 8 change to pack() |
| 200 | for (int i = 0; i < ROWS_PER_HAND; ++i) { | 239 | for (int i = 0; i < ROWS_PER_HAND; ++i) { |
| 201 | serial_s2m_buffer.smatrix[i] = matrix[i]; | 240 | serial_s2m_buffer.smatrix[i] = matrix[i]; |
| @@ -203,14 +242,11 @@ void transport_slave(matrix_row_t matrix[]) { | |||
| 203 | # ifdef BACKLIGHT_ENABLE | 242 | # ifdef BACKLIGHT_ENABLE |
| 204 | backlight_set(serial_m2s_buffer.backlight_level); | 243 | backlight_set(serial_m2s_buffer.backlight_level); |
| 205 | # endif | 244 | # endif |
| 206 | # if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT) | ||
| 207 | // Update RGB config with the new data | ||
| 208 | rgblight_update_dword(serial_m2s_buffer.rgblight_config.raw); | ||
| 209 | # endif | ||
| 210 | 245 | ||
| 211 | # ifdef ENCODER_ENABLE | 246 | # ifdef ENCODER_ENABLE |
| 212 | encoder_state_raw((uint8_t*)&serial_s2m_buffer.encoder_state); | 247 | encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state); |
| 213 | # endif | 248 | # endif |
| 249 | |||
| 214 | } | 250 | } |
| 215 | 251 | ||
| 216 | #endif | 252 | #endif |
