aboutsummaryrefslogtreecommitdiff
path: root/quantum/split_common/transport.c
diff options
context:
space:
mode:
authorJames Churchill <pelrun@gmail.com>2019-01-18 04:08:14 +1000
committerDrashna Jaelre <drashna@live.com>2019-01-17 10:08:14 -0800
commit28929ad0174bdcb38e09f6d272a23b9be6aa430c (patch)
tree3d3568df6a3f7292ccfcedd616cb1bbc8839804c /quantum/split_common/transport.c
parent5fcca9a226b2ab0b1335396e25c37e4b2a261a06 (diff)
downloadqmk_firmware-28929ad0174bdcb38e09f6d272a23b9be6aa430c.tar.gz
qmk_firmware-28929ad0174bdcb38e09f6d272a23b9be6aa430c.zip
Simplify split_common Code significantly (#4772)
* Eliminate separate slave loop Both master and slave run the standard keyboard_task main loop now. * Refactor i2c/serial specific code Simplify some of the preprocessor mess by using common function names. * Fix missing #endif * Move direct pin mapping support from miniaxe to split_common For boards with more pins than sense--sorry, switches. * Reordering and reformatting only * Don't run matrix_scan_quantum on slave side * Clean up the offset/slaveOffset calculations * Cut undebounced matrix size in half * Refactor debouncing * Minor fixups * Split split_common transport and debounce code into their own files Can now be replaced with custom versions per keyboard using CUSTOM_TRANSPORT = yes and CUSTOM_DEBOUNCE = yes * Refactor debounce for non-split keyboards too * Update handwired/xealous to build using new split_common * Fix debounce breaking basic test * Dodgy method to allow a split kb to only include one of i2c/serial SPLIT_TRANSPORT = serial or SPLIT_TRANSPORT = i2c will include only that driver code in the binary. SPLIT_TRANSPORT = custom (or anything else) will include neither, the keyboard must supply it's own code if SPLIT_TRANSPORT is not defined then the original behaviour (include both avr i2c and serial code) is maintained. This could be better but it would require explicitly updating all the existing split keyboards. * Enable LTO to get lets_split/sockets under the line * Add docs for SPLIT_TRANSPORT, CUSTOM_MATRIX, CUSTOM_DEBOUNCE * Remove avr-specific sei() from split matrix_setup Not needed now that slave doesn't have a separate main loop. Both sides (on avr) call sei() in lufa's main() after exiting keyboard_setup(). * Fix QUANTUM_LIB_SRC references and simplify SPLIT_TRANSPORT. * Add comments and fix formatting.
Diffstat (limited to 'quantum/split_common/transport.c')
-rw-r--r--quantum/split_common/transport.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
new file mode 100644
index 000000000..95738530e
--- /dev/null
+++ b/quantum/split_common/transport.c
@@ -0,0 +1,224 @@
1
2#include "config.h"
3#include "matrix.h"
4#include "quantum.h"
5
6#define ROWS_PER_HAND (MATRIX_ROWS/2)
7
8#ifdef RGBLIGHT_ENABLE
9# include "rgblight.h"
10#endif
11
12#ifdef BACKLIGHT_ENABLE
13# include "backlight.h"
14 extern backlight_config_t backlight_config;
15#endif
16
17#if defined(USE_I2C) || defined(EH)
18
19#include "i2c.h"
20
21#ifndef SLAVE_I2C_ADDRESS
22# define SLAVE_I2C_ADDRESS 0x32
23#endif
24
25#if (MATRIX_COLS > 8)
26# error "Currently only supports 8 COLS"
27#endif
28
29// Get rows from other half over i2c
30bool transport_master(matrix_row_t matrix[]) {
31 int err = 0;
32
33 // write backlight info
34#ifdef BACKLIGHT_ENABLE
35 if (BACKLIT_DIRTY) {
36 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
37 if (err) { goto i2c_error; }
38
39 // Backlight location
40 err = i2c_master_write(I2C_BACKLIT_START);
41 if (err) { goto i2c_error; }
42
43 // Write backlight
44 i2c_master_write(get_backlight_level());
45
46 BACKLIT_DIRTY = false;
47 }
48#endif
49
50 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
51 if (err) { goto i2c_error; }
52
53 // start of matrix stored at I2C_KEYMAP_START
54 err = i2c_master_write(I2C_KEYMAP_START);
55 if (err) { goto i2c_error; }
56
57 // Start read
58 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
59 if (err) { goto i2c_error; }
60
61 if (!err) {
62 int i;
63 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
64 matrix[i] = i2c_master_read(I2C_ACK);
65 }
66 matrix[i] = i2c_master_read(I2C_NACK);
67 i2c_master_stop();
68 } else {
69i2c_error: // the cable is disconnceted, or something else went wrong
70 i2c_reset_state();
71 return false;
72 }
73
74#ifdef RGBLIGHT_ENABLE
75 if (RGB_DIRTY) {
76 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
77 if (err) { goto i2c_error; }
78
79 // RGB Location
80 err = i2c_master_write(I2C_RGB_START);
81 if (err) { goto i2c_error; }
82
83 uint32_t dword = eeconfig_read_rgblight();
84
85 // Write RGB
86 err = i2c_master_write_data(&dword, 4);
87 if (err) { goto i2c_error; }
88
89 RGB_DIRTY = false;
90 i2c_master_stop();
91 }
92#endif
93
94 return true;
95}
96
97void transport_slave(matrix_row_t matrix[]) {
98
99 for (int i = 0; i < ROWS_PER_HAND; ++i)
100 {
101 i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[i];
102 }
103 // Read Backlight Info
104 #ifdef BACKLIGHT_ENABLE
105 if (BACKLIT_DIRTY)
106 {
107 backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
108 BACKLIT_DIRTY = false;
109 }
110 #endif
111 #ifdef RGBLIGHT_ENABLE
112 if (RGB_DIRTY)
113 {
114 // Disable interupts (RGB data is big)
115 cli();
116 // Create new DWORD for RGB data
117 uint32_t dword;
118
119 // Fill the new DWORD with the data that was sent over
120 uint8_t * dword_dat = (uint8_t *)(&dword);
121 for (int i = 0; i < 4; i++)
122 {
123 dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i];
124 }
125
126 // Update the RGB now with the new data and set RGB_DIRTY to false
127 rgblight_update_dword(dword);
128 RGB_DIRTY = false;
129 // Re-enable interupts now that RGB is set
130 sei();
131 }
132 #endif
133}
134
135void transport_master_init(void) {
136 i2c_master_init();
137}
138
139void transport_slave_init(void) {
140 i2c_slave_init(SLAVE_I2C_ADDRESS);
141}
142
143#else // USE_SERIAL
144
145#include "serial.h"
146
147typedef struct _Serial_s2m_buffer_t {
148 // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
149 matrix_row_t smatrix[ROWS_PER_HAND];
150} Serial_s2m_buffer_t;
151
152typedef struct _Serial_m2s_buffer_t {
153#ifdef BACKLIGHT_ENABLE
154 uint8_t backlight_level;
155#endif
156#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
157 rgblight_config_t rgblight_config; //not yet use
158 //
159 // When MCUs on both sides drive their respective RGB LED chains,
160 // it is necessary to synchronize, so it is necessary to communicate RGB information.
161 // In that case, define the RGBLIGHT_SPLIT macro.
162 //
163 // Otherwise, if the master side MCU drives both sides RGB LED chains,
164 // there is no need to communicate.
165#endif
166} Serial_m2s_buffer_t;
167
168volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
169volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
170uint8_t volatile status0 = 0;
171
172SSTD_t transactions[] = {
173 { (uint8_t *)&status0,
174 sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
175 sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
176 }
177};
178
179void transport_master_init(void)
180{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
181
182void transport_slave_init(void)
183{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
184
185bool transport_master(matrix_row_t matrix[]) {
186
187 if (soft_serial_transaction()) {
188 return false;
189 }
190
191 // TODO: if MATRIX_COLS > 8 change to unpack()
192 for (int i = 0; i < ROWS_PER_HAND; ++i) {
193 matrix[i] = serial_s2m_buffer.smatrix[i];
194 }
195
196 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
197 // Code to send RGB over serial goes here (not implemented yet)
198 #endif
199
200 #ifdef BACKLIGHT_ENABLE
201 // Write backlight level for slave to read
202 serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
203 #endif
204
205 return true;
206}
207
208void transport_slave(matrix_row_t matrix[]) {
209
210 // TODO: if MATRIX_COLS > 8 change to pack()
211 for (int i = 0; i < ROWS_PER_HAND; ++i)
212 {
213 serial_s2m_buffer.smatrix[i] = matrix[i];
214 }
215 #ifdef BACKLIGHT_ENABLE
216 backlight_set(serial_m2s_buffer.backlight_level);
217 #endif
218 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
219 // Add serial implementation for RGB here
220 #endif
221
222}
223
224#endif