summaryrefslogtreecommitdiffstats
path: root/quantum/split_common/transport.c
blob: 95738530ecf433555964a5a04590db2f9676f64d (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
217
218
219
220
221
222
223
224

#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

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

#include "i2c.h"

#ifndef SLAVE_I2C_ADDRESS
#  define SLAVE_I2C_ADDRESS           0x32
#endif

#if (MATRIX_COLS > 8)
#  error "Currently only supports 8 COLS"
#endif

// Get rows from other half over i2c
bool transport_master(matrix_row_t matrix[]) {
  int err = 0;

  // write backlight info
#ifdef BACKLIGHT_ENABLE
  if (BACKLIT_DIRTY) {
    err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
    if (err) { goto i2c_error; }

    // Backlight location
    err = i2c_master_write(I2C_BACKLIT_START);
    if (err) { goto i2c_error; }

    // Write backlight
    i2c_master_write(get_backlight_level());

    BACKLIT_DIRTY = false;
  }
#endif

  err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
  if (err) { goto i2c_error; }

  // start of matrix stored at I2C_KEYMAP_START
  err = i2c_master_write(I2C_KEYMAP_START);
  if (err) { goto i2c_error; }

  // Start read
  err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
  if (err) { goto i2c_error; }

  if (!err) {
    int i;
    for (i = 0; i < ROWS_PER_HAND-1; ++i) {
      matrix[i] = i2c_master_read(I2C_ACK);
    }
    matrix[i] = i2c_master_read(I2C_NACK);
    i2c_master_stop();
  } else {
i2c_error: // the cable is disconnceted, or something else went wrong
    i2c_reset_state();
    return false;
  }

#ifdef RGBLIGHT_ENABLE
  if (RGB_DIRTY) {
    err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
    if (err) { goto i2c_error; }

    // RGB Location
    err = i2c_master_write(I2C_RGB_START);
    if (err) { goto i2c_error; }

    uint32_t dword = eeconfig_read_rgblight();

    // Write RGB
    err = i2c_master_write_data(&dword, 4);
    if (err) { goto i2c_error; }

    RGB_DIRTY = false;
    i2c_master_stop();
  }
#endif

  return true;
}

void transport_slave(matrix_row_t matrix[]) {

  for (int i = 0; i < ROWS_PER_HAND; ++i)
  {
    i2c_slave_buffer[I2C_KEYMAP_START + i] = matrix[i];
  }
  // Read Backlight Info
  #ifdef BACKLIGHT_ENABLE
  if (BACKLIT_DIRTY)
  {
    backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
    BACKLIT_DIRTY = false;
  }
  #endif
  #ifdef RGBLIGHT_ENABLE
  if (RGB_DIRTY)
  {
    // Disable interupts (RGB data is big)
    cli();
    // Create new DWORD for RGB data
    uint32_t dword;

    // Fill the new DWORD with the data that was sent over
    uint8_t * dword_dat = (uint8_t *)(&dword);
    for (int i = 0; i < 4; i++)
    {
      dword_dat[i] = i2c_slave_buffer[I2C_RGB_START + i];
    }

    // Update the RGB now with the new data and set RGB_DIRTY to false
    rgblight_update_dword(dword);
    RGB_DIRTY = false;
    // Re-enable interupts now that RGB is set
    sei();
  }
  #endif
}

void transport_master_init(void) {
  i2c_master_init();
}

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

#else // USE_SERIAL

#include "serial.h"

typedef struct _Serial_s2m_buffer_t {
  // 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 _Serial_m2s_buffer_t {
#ifdef BACKLIGHT_ENABLE
    uint8_t backlight_level;
#endif
#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_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 the RGBLIGHT_SPLIT macro.
    //
    // 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];
  }

  #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
    // Code to send RGB over serial goes here (not implemented yet)
  #endif

  #ifdef BACKLIGHT_ENABLE
    // Write backlight level for slave to read
    serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
  #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(RGBLIGHT_SPLIT)
  // Add serial implementation for RGB here
  #endif

}

#endif