]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/split_common/transport.c
ab055ee6566c3d04bce439a51744329824752f9d
[qmk_firmware.git] / quantum / split_common / transport.c
1 #include <string.h>
2 #include <stddef.h>
3
4 #include "config.h"
5 #include "matrix.h"
6 #include "quantum.h"
7
8 #define ROWS_PER_HAND (MATRIX_ROWS / 2)
9
10 #ifdef RGBLIGHT_ENABLE
11 #  include "rgblight.h"
12 #endif
13
14 #ifdef BACKLIGHT_ENABLE
15 #  include "backlight.h"
16 extern backlight_config_t backlight_config;
17 #endif
18
19 #ifdef ENCODER_ENABLE
20 #  include "encoder.h"
21 #endif
22
23 #if defined(USE_I2C) || defined(EH)
24
25 #  include "i2c_master.h"
26 #  include "i2c_slave.h"
27
28 typedef struct __attribute__ ((__packed__)) {
29 #ifdef BACKLIGHT_ENABLE
30   uint8_t backlight_level;
31 #endif
32 #ifdef RGBLIGHT_ENABLE
33   uint32_t rgb_settings;
34 #endif
35 #ifdef ENCODER_ENABLE
36   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
52
53 #ifdef ENCODER_ENABLE
54 #  define I2C_ENCODER_START (uint8_t)offsetof(transport_values_t, encoder_state)
55 #endif
56
57 #define I2C_KEYMAP_START (uint8_t)offsetof(transport_values_t, matrix_start)
58
59 #  define TIMEOUT 100
60
61 #  ifndef SLAVE_I2C_ADDRESS
62 #    define SLAVE_I2C_ADDRESS 0x32
63 #  endif
64
65 // Get rows from other half over i2c
66 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);
68
69   // write backlight info
70 #  ifdef BACKLIGHT_ENABLE
71   uint8_t level = get_backlight_level();
72   if (level != transport_values.backlight_level) {
73     if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
74       transport_values.backlight_level = level;
75     }
76   }
77 #  endif
78
79 #  ifdef RGBLIGHT_ENABLE
80   uint32_t rgb = rgblight_read_dword();
81   if (rgb != transport_values.rgb_settings) {
82     if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgb, sizeof(rgb), TIMEOUT) >= 0) {
83       transport_values.rgb_settings = rgb;
84     }
85   }
86 #  endif
87
88 #  ifdef ENCODER_ENABLE
89   i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)transport_values.encoder_state, sizeof(transport_values.encoder_state), TIMEOUT);
90   encoder_update_raw(&transport_values.encoder_state[0]);
91 #  endif
92
93   return true;
94 }
95
96 void transport_slave(matrix_row_t matrix[]) {
97   // Copy matrix to I2C buffer
98   memcpy((void*)(i2c_slave_reg + I2C_KEYMAP_START), (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t) );
99
100 // Read Backlight Info
101 #  ifdef BACKLIGHT_ENABLE
102   backlight_set(i2c_slave_reg[I2C_BACKLIT_START]);
103 #  endif
104
105 #  ifdef RGBLIGHT_ENABLE
106   uint32_t rgb = *(uint32_t *)(i2c_slave_reg + I2C_RGB_START);
107   // Update the RGB with the new data
108   rgblight_update_dword(rgb);
109 #  endif
110
111 #  ifdef ENCODER_ENABLE
112   encoder_state_raw((uint8_t*)(i2c_slave_reg + I2C_ENCODER_START));
113 #  endif
114 }
115
116 void transport_master_init(void) { i2c_init(); }
117
118 void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
119
120 #else  // USE_SERIAL
121
122 #  include "serial.h"
123
124 typedef struct __attribute__ ((__packed__)) {
125 #  ifdef ENCODER_ENABLE
126   uint8_t encoder_state[NUMBER_OF_ENCODERS];
127 #  endif
128   // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
129   matrix_row_t smatrix[ROWS_PER_HAND];
130 } Serial_s2m_buffer_t;
131
132 typedef struct __attribute__ ((__packed__)) {
133 #  ifdef BACKLIGHT_ENABLE
134   uint8_t           backlight_level;
135 #  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;
148
149 volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
150 volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
151 uint8_t volatile status0                       = 0;
152
153 SSTD_t transactions[] = {
154     {
155         (uint8_t *)&status0,
156         sizeof(serial_m2s_buffer),
157         (uint8_t *)&serial_m2s_buffer,
158         sizeof(serial_s2m_buffer),
159         (uint8_t *)&serial_s2m_buffer,
160     },
161 };
162
163 void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
164
165 void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
166
167 bool transport_master(matrix_row_t matrix[]) {
168   if (soft_serial_transaction()) {
169     return false;
170   }
171
172   // TODO:  if MATRIX_COLS > 8 change to unpack()
173   for (int i = 0; i < ROWS_PER_HAND; ++i) {
174     matrix[i] = serial_s2m_buffer.smatrix[i];
175   }
176
177 #  ifdef BACKLIGHT_ENABLE
178   // Write backlight level for slave to read
179   serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
180 #  endif
181
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
192   encoder_update_raw((uint8_t*)&serial_s2m_buffer.encoder_state);
193 #  endif
194
195   return true;
196 }
197
198 void transport_slave(matrix_row_t matrix[]) {
199   // TODO: if MATRIX_COLS > 8 change to pack()
200   for (int i = 0; i < ROWS_PER_HAND; ++i) {
201     serial_s2m_buffer.smatrix[i] = matrix[i];
202   }
203 #  ifdef BACKLIGHT_ENABLE
204   backlight_set(serial_m2s_buffer.backlight_level);
205 #  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
211 #  ifdef ENCODER_ENABLE
212   encoder_state_raw((uint8_t*)&serial_s2m_buffer.encoder_state);
213 #  endif
214 }
215
216 #endif