aboutsummaryrefslogtreecommitdiff
path: root/quantum/split_common/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/split_common/transport.c')
-rw-r--r--quantum/split_common/transport.c184
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
28typedef struct __attribute__ ((__packed__)) { 28typedef 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))
43static 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 39static 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
66bool transport_master(matrix_row_t matrix[]) { 53bool 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
96void transport_slave(matrix_row_t matrix[]) { 85void 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
124typedef struct __attribute__ ((__packed__)) { 115typedef 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
132typedef struct __attribute__ ((__packed__)) { 125typedef 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
140typedef struct _Serial_rgblight_t {
141 rgblight_syncinfo_t rgblight_sync;
142} Serial_rgblight_t;
143
144volatile Serial_rgblight_t serial_rgblight = {};
145uint8_t volatile status_rgblight = 0;
146#endif
147
149volatile Serial_s2m_buffer_t serial_s2m_buffer = {}; 148volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
150volatile Serial_m2s_buffer_t serial_m2s_buffer = {}; 149volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
151uint8_t volatile status0 = 0; 150uint8_t volatile status0 = 0;
152 151
152enum serial_transaction_id {
153 GET_SLAVE_MATRIX = 0,
154#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
155 PUT_RGBLIGHT,
156#endif
157};
158
153SSTD_t transactions[] = { 159SSTD_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
163void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); } 177void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
164 178
165void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); } 179void 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
185void 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
194void 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
167bool transport_master(matrix_row_t matrix[]) { 207bool 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
198void transport_slave(matrix_row_t matrix[]) { 236void 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