summaryrefslogtreecommitdiff
path: root/quantum/split_common/transport.c
blob: 8d408f6fdc6b0344bffdb7e19e798d86bfb0635a (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
#include <string.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

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

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

#  define I2C_BACKLIT_START 0x00
// Need 4 bytes for RGB (32 bit)
#  define I2C_RGB_START 0x01
#  define I2C_KEYMAP_START 0x05

#  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
  static uint8_t prev_level = ~0;
  uint8_t        level      = get_backlight_level();
  if (level != prev_level) {
    if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
      prev_level = level;
    }
  }
#  endif

#  ifdef RGBLIGHT_ENABLE
  static uint32_t prev_rgb = ~0;
  uint32_t        rgb      = rgblight_read_dword();
  if (rgb != prev_rgb) {
    if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgb, sizeof(rgb), TIMEOUT) >= 0) {
      prev_rgb = rgb;
    }
  }
#  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
}

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 _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(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

  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
}

#endif