aboutsummaryrefslogtreecommitdiff
path: root/keyboards/ergodox_infinity/ergodox_infinity.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/ergodox_infinity/ergodox_infinity.c')
-rw-r--r--keyboards/ergodox_infinity/ergodox_infinity.c302
1 files changed, 240 insertions, 62 deletions
diff --git a/keyboards/ergodox_infinity/ergodox_infinity.c b/keyboards/ergodox_infinity/ergodox_infinity.c
index 97b628470..da8ea311a 100644
--- a/keyboards/ergodox_infinity/ergodox_infinity.c
+++ b/keyboards/ergodox_infinity/ergodox_infinity.c
@@ -1,20 +1,45 @@
1#include QMK_KEYBOARD_H 1#include QMK_KEYBOARD_H
2#include <ch.h> 2#include <ch.h>
3#include <hal.h> 3#include <hal.h>
4#include <string.h>
5#include "eeconfig.h"
4#include "serial_link/system/serial_link.h" 6#include "serial_link/system/serial_link.h"
5#ifdef VISUALIZER_ENABLE 7#ifdef VISUALIZER_ENABLE
6#include "lcd_backlight.h" 8# include "lcd_backlight.h"
7#endif 9#endif
8 10
9#ifdef WPM_ENABLE 11#if (defined(LED_MATRIX_ENABLE) || defined(WPM_ENABLE))
10# include "serial_link/protocol/transport.h" 12# include "serial_link/protocol/transport.h"
11# include "wpm.h" 13
14# ifdef LED_MATRIX_ENABLE
15MASTER_TO_ALL_SLAVES_OBJECT(led_matrix, led_eeconfig_t);
16MASTER_TO_ALL_SLAVES_OBJECT(led_suspend_state, bool);
17static led_eeconfig_t last_sent_led_matrix;
18static uint16_t led_matrix_sent_timer = 0;
19
20void send_led_suspend_state(void) {
21 if (is_serial_link_master()) {
22 *begin_write_led_suspend_state() = led_matrix_get_suspend_state();
23 end_write_led_suspend_state();
24 }
25}
26# endif
12 27
28# ifdef WPM_ENABLE
29# include "wpm.h"
13MASTER_TO_ALL_SLAVES_OBJECT(current_wpm, uint8_t); 30MASTER_TO_ALL_SLAVES_OBJECT(current_wpm, uint8_t);
14static remote_object_t* remote_objects[] = { 31static uint8_t last_sent_wpm = 0;
32# endif
33
34static remote_object_t *remote_objects[] = {
35# ifdef LED_MATRIX_ENABLE
36 REMOTE_OBJECT(led_matrix),
37 REMOTE_OBJECT(led_suspend_state),
38# endif
39# ifdef WPM_ENABLE
15 REMOTE_OBJECT(current_wpm), 40 REMOTE_OBJECT(current_wpm),
41# endif
16}; 42};
17static uint8_t last_sent_wpm = 0;
18#endif 43#endif
19 44
20void init_serial_link_hal(void) { 45void init_serial_link_hal(void) {
@@ -52,7 +77,7 @@ void init_serial_link_hal(void) {
52void lcd_backlight_hal_init(void) { 77void lcd_backlight_hal_init(void) {
53 // Setup Backlight 78 // Setup Backlight
54 SIM->SCGC6 |= SIM_SCGC6_FTM0; 79 SIM->SCGC6 |= SIM_SCGC6_FTM0;
55 FTM0->CNT = 0; // Reset counter 80 FTM0->CNT = 0; // Reset counter
56 81
57 // PWM Period 82 // PWM Period
58 // 16-bit maximum 83 // 16-bit maximum
@@ -60,25 +85,25 @@ void lcd_backlight_hal_init(void) {
60 85
61 // Set FTM to PWM output - Edge Aligned, Low-true pulses 86 // Set FTM to PWM output - Edge Aligned, Low-true pulses
62#define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0) 87#define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0)
63 CHANNEL_RED.CnSC = CNSC_MODE; 88 CHANNEL_RED.CnSC = CNSC_MODE;
64 CHANNEL_GREEN.CnSC = CNSC_MODE; 89 CHANNEL_GREEN.CnSC = CNSC_MODE;
65 CHANNEL_BLUE.CnSC = CNSC_MODE; 90 CHANNEL_BLUE.CnSC = CNSC_MODE;
66 91
67 // System clock, /w prescalar setting 92 // System clock, /w prescalar setting
68 FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE); 93 FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE);
69 94
70 CHANNEL_RED.CnV = 0; 95 CHANNEL_RED.CnV = 0;
71 CHANNEL_GREEN.CnV = 0; 96 CHANNEL_GREEN.CnV = 0;
72 CHANNEL_BLUE.CnV = 0; 97 CHANNEL_BLUE.CnV = 0;
73 98
74 RGB_PORT_GPIO->PDDR |= (1 << RED_PIN); 99 RGB_PORT_GPIO->PDDR |= (1 << RED_PIN);
75 RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN); 100 RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN);
76 RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN); 101 RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN);
77 102
78#define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4) 103#define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4)
79 RGB_PORT->PCR[RED_PIN] = RGB_MODE; 104 RGB_PORT->PCR[RED_PIN] = RGB_MODE;
80 RGB_PORT->PCR[GREEN_PIN] = RGB_MODE; 105 RGB_PORT->PCR[GREEN_PIN] = RGB_MODE;
81 RGB_PORT->PCR[BLUE_PIN] = RGB_MODE; 106 RGB_PORT->PCR[BLUE_PIN] = RGB_MODE;
82} 107}
83 108
84static uint16_t cie_lightness(uint16_t v) { 109static uint16_t cie_lightness(uint16_t v) {
@@ -89,12 +114,11 @@ static uint16_t cie_lightness(uint16_t v) {
89 // Y = (L* / 902.3) if L* <= 8 114 // Y = (L* / 902.3) if L* <= 8
90 // Y = ((L* + 16) / 116)^3 if L* > 8 115 // Y = ((L* + 16) / 116)^3 if L* > 8
91 116
92 float l = 100.0f * (v / 65535.0f); 117 float l = 100.0f * (v / 65535.0f);
93 float y = 0.0f; 118 float y = 0.0f;
94 if (l <= 8.0f) { 119 if (l <= 8.0f) {
95 y = l / 902.3; 120 y = l / 902.3;
96 } 121 } else {
97 else {
98 y = ((l + 16.0f) / 116.0f); 122 y = ((l + 16.0f) / 116.0f);
99 y = y * y * y; 123 y = y * y * y;
100 if (y > 1.0f) { 124 if (y > 1.0f) {
@@ -105,31 +129,48 @@ static uint16_t cie_lightness(uint16_t v) {
105} 129}
106 130
107void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) { 131void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) {
108 CHANNEL_RED.CnV = cie_lightness(r); 132 CHANNEL_RED.CnV = cie_lightness(r);
109 CHANNEL_GREEN.CnV = cie_lightness(g); 133 CHANNEL_GREEN.CnV = cie_lightness(g);
110 CHANNEL_BLUE.CnV = cie_lightness(b); 134 CHANNEL_BLUE.CnV = cie_lightness(b);
111} 135}
112 136
113__attribute__ ((weak)) 137__attribute__ ((weak)) void matrix_init_user(void) {}
114void matrix_init_user(void) { 138
115} 139__attribute__ ((weak)) void matrix_scan_user(void) {}
116 140
117__attribute__ ((weak))
118void matrix_scan_user(void) {
119}
120 141
142void keyboard_pre_init_kb() {
143#ifdef LED_MATRIX_ENABLE
144 // Turn on LED controller
145 setPinOutput(B16);
146 writePinHigh(B16);
147#endif
148 keyboard_pre_init_user();
149}
121 150
122void matrix_init_kb(void) { 151void matrix_init_kb(void) {
123 // put your keyboard start-up code here 152 // put your keyboard start-up code here
124 // runs once when the firmware starts up 153 // runs once when the firmware starts up
125 154
155#ifdef LED_MATRIX_ENABLE
156 /*
157 * Since K20x is stuck with a 32 byte EEPROM (see tmk_core/common/chibios/eeprom_teensy.c),
158 * and neither led_matrix_eeconfig.speed or .flags fit in this boundary, just force their values to default on boot.
159 */
160# if !defined(LED_MATRIX_STARTUP_SPD)
161# define LED_MATRIX_STARTUP_SPD UINT8_MAX / 2
162# endif
163 led_matrix_set_speed(LED_MATRIX_STARTUP_SPD);
164 led_matrix_set_flags(LED_FLAG_ALL);
165#endif
166
126 matrix_init_user(); 167 matrix_init_user();
127 // The backlight always has to be initialized, otherwise it will stay lit 168 // The backlight always has to be initialized, otherwise it will stay lit
128#ifndef VISUALIZER_ENABLE 169#ifndef VISUALIZER_ENABLE
129 lcd_backlight_hal_init(); 170 lcd_backlight_hal_init();
130#endif 171#endif
131#ifdef WPM_ENABLE 172#if (defined(LED_MATRIX_ENABLE) || defined(WPM_ENABLE))
132 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*)); 173 add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t *));
133#endif 174#endif
134} 175}
135 176
@@ -137,6 +178,30 @@ void matrix_scan_kb(void) {
137 // put your looping keyboard code here 178 // put your looping keyboard code here
138 // runs every cycle (a lot) 179 // runs every cycle (a lot)
139 180
181#ifdef LED_MATRIX_ENABLE
182 if (is_serial_link_master()) {
183 if (!led_matrix_get_suspend_state()) {
184 if (timer_elapsed(led_matrix_sent_timer) >= 5000 || memcmp((void *)&last_sent_led_matrix, (void *)&led_matrix_eeconfig, sizeof(last_sent_led_matrix))) {
185 led_matrix_sent_timer = timer_read();
186 memcpy((void *)&last_sent_led_matrix, (void *)&led_matrix_eeconfig, sizeof(last_sent_led_matrix));
187 *begin_write_led_matrix() = last_sent_led_matrix;
188 end_write_led_matrix();
189 }
190 }
191 } else if (is_serial_link_connected()) {
192 bool *new_led_suspend_state = read_led_suspend_state();
193 if (new_led_suspend_state) {
194 led_matrix_set_suspend_state(*new_led_suspend_state);
195 }
196 if (!led_matrix_get_suspend_state()) {
197 led_eeconfig_t *new_led_matrix = read_led_matrix();
198 if (new_led_matrix) {
199 memcpy((void *)&led_matrix_eeconfig, (void *)new_led_matrix, sizeof(last_sent_led_matrix));
200 }
201 }
202 }
203#endif
204
140#ifdef WPM_ENABLE 205#ifdef WPM_ENABLE
141 if (is_serial_link_master()) { 206 if (is_serial_link_master()) {
142 uint8_t current_wpm = get_current_wpm(); 207 uint8_t current_wpm = get_current_wpm();
@@ -146,67 +211,68 @@ void matrix_scan_kb(void) {
146 last_sent_wpm = current_wpm; 211 last_sent_wpm = current_wpm;
147 } 212 }
148 } else if (is_serial_link_connected()) { 213 } else if (is_serial_link_connected()) {
149 uint8_t* new_wpm = read_current_wpm(); 214 uint8_t *new_wpm = read_current_wpm();
150 if (new_wpm) { 215 if (new_wpm) {
151 set_current_wpm(*new_wpm); 216 set_current_wpm(*new_wpm);
152 } 217 }
153 } 218 }
154#endif 219#endif
220
155 matrix_scan_user(); 221 matrix_scan_user();
156} 222}
157 223
158bool is_keyboard_master(void) { 224bool is_keyboard_master(void) { return is_serial_link_master(); }
159 return is_serial_link_master();
160}
161 225
162__attribute__ ((weak)) 226bool is_keyboard_left(void) {
163void ergodox_board_led_on(void){ 227#if defined(EE_HANDS)
228 return eeconfig_read_handedness();
229#elif defined(MASTER_IS_ON_RIGHT)
230 return !is_keyboard_master();
231#else
232 return is_keyboard_master();
233#endif
164} 234}
165 235
166__attribute__ ((weak)) 236__attribute__ ((weak)) void ergodox_board_led_on(void) {}
167void ergodox_right_led_1_on(void){
168}
169 237
170__attribute__ ((weak)) 238__attribute__ ((weak)) void ergodox_right_led_1_on(void) {}
171void ergodox_right_led_2_on(void){
172}
173 239
174__attribute__ ((weak)) 240__attribute__ ((weak)) void ergodox_right_led_2_on(void) {}
175void ergodox_right_led_3_on(void){
176}
177 241
178__attribute__ ((weak)) 242__attribute__ ((weak)) void ergodox_right_led_3_on(void) {}
179void ergodox_board_led_off(void){
180}
181 243
182__attribute__ ((weak)) 244__attribute__ ((weak)) void ergodox_board_led_off(void) {}
183void ergodox_right_led_1_off(void){
184}
185 245
186__attribute__ ((weak)) 246__attribute__ ((weak)) void ergodox_right_led_1_off(void) {}
187void ergodox_right_led_2_off(void){
188}
189 247
190__attribute__ ((weak)) 248__attribute__ ((weak)) void ergodox_right_led_2_off(void) {}
191void ergodox_right_led_3_off(void){
192}
193 249
194__attribute__ ((weak)) 250__attribute__ ((weak)) void ergodox_right_led_3_off(void) {}
195void ergodox_right_led_1_set(uint8_t n) {
196}
197 251
198__attribute__ ((weak)) 252__attribute__ ((weak)) void ergodox_right_led_1_set(uint8_t n) {}
199void ergodox_right_led_2_set(uint8_t n) { 253
254__attribute__ ((weak)) void ergodox_right_led_2_set(uint8_t n) {}
255
256__attribute__ ((weak)) void ergodox_right_led_3_set(uint8_t n) {}
257
258void suspend_power_down_kb(void) {
259#ifdef LED_MATRIX_ENABLE
260 send_led_suspend_state();
261#endif
262 suspend_power_down_user();
200} 263}
201 264
202__attribute__ ((weak)) 265void suspend_wakeup_init_kb(void) {
203void ergodox_right_led_3_set(uint8_t n) { 266#ifdef LED_MATRIX_ENABLE
267 send_led_suspend_state();
268#endif
269 suspend_wakeup_init_user();
204} 270}
205 271
206#ifdef SWAP_HANDS_ENABLE 272#ifdef SWAP_HANDS_ENABLE
207__attribute__ ((weak)) 273__attribute__ ((weak))
208const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { 274const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
209 {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}}, 275 {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}},
210 {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}}, 276 {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}},
211 {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}}, 277 {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}},
212 {{0, 12}, {1, 12}, {2, 12}, {3, 12}, {4, 12}}, 278 {{0, 12}, {1, 12}, {2, 12}, {3, 12}, {4, 12}},
@@ -226,3 +292,115 @@ const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
226 {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}}, 292 {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}},
227}; 293};
228#endif 294#endif
295
296#ifdef LED_MATRIX_ENABLE
297const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
298// The numbers in the comments are the led numbers DXX on the PCB
299/* Refer to IS31 manual for these locations
300 * driver
301 * | LED address
302 * | | */
303// Left half
304// 45 44 43 42 41 40 39
305 { 0, C2_2 }, { 0, C1_2 }, { 0, C5_1 }, { 0, C4_1 }, { 0, C3_1 }, { 0, C2_1 }, { 0, C1_1 },
306// 52 51 50 49 48 47 46
307 { 0, C4_3 }, { 0, C3_3 }, { 0, C2_3 }, { 0, C1_3 }, { 0, C5_2 }, { 0, C4_2 }, { 0, C3_2 },
308// 58 57 56 55 54 53
309 { 0, C5_4 }, { 0, C4_4 }, { 0, C3_4 }, { 0, C2_4 }, { 0, C1_4 }, { 0, C5_3 },
310// 67 66 65 64 63 62 61
311 { 0, C4_6 }, { 0, C3_6 }, { 0, C2_6 }, { 0, C1_6 }, { 0, C5_5 }, { 0, C4_5 }, { 0, C3_5 },
312// 76 75 74 73 72
313 { 0, C4_8 }, { 0, C3_8 }, { 0, C2_8 }, { 0, C1_8 }, { 0, C4_7 },
314// 60 59
315 { 0, C2_5 }, { 0, C1_5 },
316// 68
317 { 0, C5_6 },
318// 71 70 69
319 { 0, C3_7 }, { 0, C2_7 }, { 0, C1_7 },
320// Right half (mirrored)
321// Due to how LED_MATRIX_SPLIT is implemented, only the first half of g_is31_leds is actually used.
322// Luckily, the right half has the same LED pinouts, just mirrored.
323// 45 44 43 42 41 40 39
324 { 0, C2_2 }, { 0, C1_2 }, { 0, C5_1 }, { 0, C4_1 }, { 0, C3_1 }, { 0, C2_1 }, { 0, C1_1 },
325// 52 51 50 49 48 47 46
326 { 0, C4_3 }, { 0, C3_3 }, { 0, C2_3 }, { 0, C1_3 }, { 0, C5_2 }, { 0, C4_2 }, { 0, C3_2 },
327// 58 57 56 55 54 53
328 { 0, C5_4 }, { 0, C4_4 }, { 0, C3_4 }, { 0, C2_4 }, { 0, C1_4 }, { 0, C5_3 },
329// 67 66 65 64 63 62 61
330 { 0, C4_6 }, { 0, C3_6 }, { 0, C2_6 }, { 0, C1_6 }, { 0, C5_5 }, { 0, C4_5 }, { 0, C3_5 },
331// 76 75 74 73 72
332 { 0, C4_8 }, { 0, C3_8 }, { 0, C2_8 }, { 0, C1_8 }, { 0, C4_7 },
333// 60 59
334 { 0, C2_5 }, { 0, C1_5 },
335// 68
336 { 0, C5_6 },
337// 71 70 69
338 { 0, C3_7 }, { 0, C2_7 }, { 0, C1_7 },
339};
340
341led_config_t g_led_config = {
342 {
343 // Key Matrix to LED Index
344 // Left half
345 { NO_LED, NO_LED, NO_LED, 33, 34 },
346 { NO_LED, NO_LED, NO_LED, 32, 37 },
347 { 6, 13, NO_LED, 26, 36 },
348 { 5, 12, 19, 25, 35 },
349 { 4, 11, 18, 24, 31 },
350 { 3, 10, 17, 23, 30 },
351 { 2, 9, 16, 22, 29 },
352 { 1, 8, 15, 21, 28 },
353 { 0, 7, 14, 20, 27 },
354 // Right half
355 { NO_LED, NO_LED, NO_LED, 71, 72 },
356 { NO_LED, NO_LED, NO_LED, 70, 75 },
357 { 44, 51, NO_LED, 64, 74 },
358 { 43, 50, 57, 63, 73 },
359 { 42, 49, 56, 62, 69 },
360 { 41, 48, 55, 61, 68 },
361 { 40, 47, 54, 60, 67 },
362 { 39, 46, 53, 59, 66 },
363 { 38, 45, 52, 58, 65 },
364 }, {
365 // LED Index to Physical Position (assumes a reasonable gap between halves)
366 // Left half
367 { 0, 3 }, { 15, 3 }, { 27, 1 }, { 39, 0 }, { 51, 1 }, { 63, 2 }, { 75, 2 },
368 { 0, 13 }, { 15, 13 }, { 27, 11 }, { 39, 10 }, { 51, 11 }, { 63, 12 }, { 78, 17 },
369 { 0, 23 }, { 15, 23 }, { 27, 21 }, { 39, 20 }, { 51, 21 }, { 63, 22 },
370 { 0, 33 }, { 15, 33 }, { 27, 31 }, { 39, 30 }, { 51, 31 }, { 63, 32 }, { 78, 32 },
371 { 4, 43 }, { 15, 43 }, { 27, 41 }, { 39, 40 }, { 51, 41 },
372 { 89, 41 }, { 100, 46 },
373 { 95, 55 },
374 { 72, 54 }, { 83, 59 }, { 90, 64 },
375 // Right half (mirrored)
376 { 224, 3 }, { 209, 3 }, { 197, 1 }, { 185, 0 }, { 173, 1 }, { 161, 2 }, { 149, 2 },
377 { 224, 13 }, { 209, 13 }, { 197, 11 }, { 185, 10 }, { 173, 11 }, { 161, 12 }, { 146, 17 },
378 { 224, 23 }, { 209, 23 }, { 197, 21 }, { 185, 20 }, { 173, 21 }, { 161, 22 },
379 { 224, 33 }, { 209, 33 }, { 197, 31 }, { 185, 30 }, { 173, 31 }, { 161, 32 }, { 146, 32 },
380 { 220, 43 }, { 209, 43 }, { 197, 41 }, { 185, 40 }, { 173, 41 },
381 { 135, 41 }, { 124, 46 },
382 { 129, 55 },
383 { 152, 54 }, { 141, 59 }, { 134, 64 },
384 }, {
385 // LED Index to Flag
386 // Left half
387 1, 4, 4, 4, 4, 4, 1,
388 1, 4, 4, 4, 4, 4, 1,
389 1, 4, 4, 4, 4, 4,
390 1, 4, 4, 4, 4, 4, 1,
391 1, 1, 1, 1, 1,
392 1, 1,
393 1,
394 1, 1, 1,
395 // Right half (mirrored)
396 1, 4, 4, 4, 4, 4, 1,
397 1, 4, 4, 4, 4, 4, 1,
398 1, 4, 4, 4, 4, 4,
399 1, 4, 4, 4, 4, 4, 1,
400 1, 1, 1, 1, 1,
401 1, 1,
402 1,
403 1, 1, 1,
404 }
405};
406#endif