summaryrefslogtreecommitdiffstats
path: root/quantum/split_common/transport.c
blob: ab055ee6566c3d04bce439a51744329824752f9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#include <string.h>
#include <stddef.h>

#include "config.h"
#include "matrix.h"
#include "quantum.h"

#define ROWS_PER_HAND (MATRIX_ROWS / 2)

#ifdef RGBLIGHT_ENABLE
#  include "rgblight.h"
#endif

#ifdef BACKLIGHT_ENABLE
#  include "backlight.h"
extern backlight_config_t backlight_config;
#endif

#ifdef ENCODER_ENABLE
#  include "encoder.h"
#endif

#if defined(USE_I2C) || defined(EH)

#  include "i2c_master.h"
#  include "i2c_slave.h"

typedef struct __attribute__ ((__packed__)) {
#ifdef BACKLIGHT_ENABLE
  uint8_t backlight_level;
#endif
#ifdef RGBLIGHT_ENABLE
  uint32_t rgb_settings;
#endif
#ifdef ENCODER_ENABLE
  uint8_t encoder_state[NUMBER_OF_ENCODERS];
#endif
  // Keep matrix last, we are only using this for it's offset
  uint8_t matrix_start[0];
} transport_values_t;

__attribute__ ((unused))
static transport_values_t transport_values;

#ifdef BACKLIGHT_ENABLE
#  define I2C_BACKLIT_START (uint8_t)offsetof(transport_values_t, backlight_level)
#endif

#ifdef RGBLIGHT_ENABLE
#  define I2C_RGB_START (uint8_t)offsetof(transport_values_t, rgb_settings)
#endif

#ifdef ENCODER_ENABLE
#  define I2C_ENCODER_START (uint8_t)offsetof(transport_values_t, encoder_state)
#endif

#define I2C_KEYMAP_START (uint8_t)offsetof(transport_values_t, matrix_start)

#  define TIMEOUT 100

#  ifndef SLAVE_I2C_ADDRESS
#    define SLAVE_I2C_ADDRESS 0x32
#  endif

// Get rows from other half over i2c
bool transport_master(matrix_row_t matrix[]) {
  i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_START, (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t), TIMEOUT);

  // write backlight info
#  ifdef BACKLIGHT_ENABLE
  uint8_t level = get_backlight_level();
  if (level != transport_values.backlight_level) {
    if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
      transport_values.backlight_level = level;
    }
  }
#  endif

#  ifdef RGBLIGHT_ENABLE
  uint32_t rgb = rgblight_read_dword();
  if (rgb != transport_values.rgb_settings) {
    if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgb, sizeof(rgb), TIMEOUT) >= 0) {
      transport_values.rgb_settings = rgb;
    }
  }
#  endif

#  ifdef ENCODER_ENABLE
  i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)transport_values.encoder_state, sizeof(transport_values.encoder_state), TIMEOUT);
  encoder_update_raw(&transport_values.encoder_state[0]);
#  endif

  return true;
}

void transport_slave(matrix_row_t matrix[]) {
  // Copy matrix to I2C buffer
  memcpy((void*)(i2c_slave_reg + I2C_KEYMAP_START), (void *)matrix, ROWS_PER_HAND * sizeof(matrix_row_t) );

// Read Backlight Info
#  ifdef BACKLIGHT_ENABLE
  backlight_set(i2c_slave_reg[I2C_BACKLIT_START]);
#  endif

#  ifdef RGBLIGHT_ENABLE
  uint32_t rgb = *(uint32_t *)(i2c_slave_reg + I2C_RGB_START);
  // Update the RGB with the new data
  rgblight_update_dword(rgb);
#  endif

#  ifdef ENCODER_ENABLE
  encoder_state_raw((uint8_t*)(i2c_slave_reg + I2C_ENCODER_START));
#  endif
}

void transport_master_init(void) { i2c_init(); }

void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }

#else  // USE_SERIAL

#  include "serial.h"

typedef struct __attribute__ ((__packed__)) {
#  ifdef ENCODER_ENABLE
  uint8_t encoder_state[NUMBER_OF_ENCODERS];
#  endif
  // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
  matrix_row_t smatrix[ROWS_PER_HAND];
} Serial_s2m_buffer_t;

typedef struct __attribute__ ((__packed__)) {
#  ifdef BACKLIGHT_ENABLE
  uint8_t           backlight_level;
#  endif
#  if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
  rgblight_config_t rgblight_config;  // not yet use
  //
  // When MCUs on both sides drive their respective RGB LED chains,
  // it is necessary to synchronize, so it is necessary to communicate RGB
  // information. In that case, define RGBLED_SPLIT with info on the number
  // of LEDs on each half.
  //
  // Otherwise, if the master side MCU drives both sides RGB LED chains,
  // there is no need to communicate.
#  endif
} Serial_m2s_buffer_t;

volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
uint8_t volatile status0                       = 0;

SSTD_t transactions[] = {
    {
        (uint8_t *)&status0,
        sizeof(serial_m2s_buffer),
        (uint8_t *)&serial_m2s_buffer,
        sizeof(serial_s2m_buffer),
        (uint8_t *)&serial_s2m_buffer,
    },
};

void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }

void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }

bool transport_master(matrix_row_t matrix[]) {
  if (soft_serial_transaction()) {
    return false;
  }

  // TODO:  if MATRIX_COLS > 8 change to unpack()
  for (int i = 0; i < ROWS_PER_HAND; ++i) {
    matrix[i] = serial_s2m_buffer.smatrix[i];
  }

#  ifdef BACKLIGHT_ENABLE
  // Write backlight level for slave to read
  serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
#  endif

#  if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
  static rgblight_config_t prev_rgb = {~0};
  uint32_t rgb = rgblight_read_dword();
  if (rgb != prev_rgb.raw) {
    serial_m2s_buffer.rgblight_config.raw = rgb;
    prev_rgb.raw = rgb;
  }
#  endif

#  ifdef ENCODER_ENABLE
  encoder_update_raw((uint8_t*)&serial_s2m_buffer.encoder_state);
#  endif

  return true;
}

void transport_slave(matrix_row_t matrix[]) {
  // TODO: if MATRIX_COLS > 8 change to pack()
  for (int i = 0; i < ROWS_PER_HAND; ++i) {
    serial_s2m_buffer.smatrix[i] = matrix[i];
  }
#  ifdef BACKLIGHT_ENABLE
  backlight_set(serial_m2s_buffer.backlight_level);
#  endif
#  if defined(RGBLIGHT_ENABLE) && defined(RGBLED_SPLIT)
  // Update RGB config with the new data
  rgblight_update_dword(serial_m2s_buffer.rgblight_config.raw);
#  endif

#  ifdef ENCODER_ENABLE
  encoder_state_raw((uint8_t*)&serial_s2m_buffer.encoder_state);
#  endif
}

#endif