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.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