voyager.c (9133B)
1 // Copyright 2023 ZSA Technology Labs, Inc <@zsa> 2 // Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 #include "voyager.h" 6 7 keyboard_config_t keyboard_config; 8 9 bool mcp23018_leds[2] = {0, 0}; 10 bool is_launching = false; 11 12 #if defined(DEFERRED_EXEC_ENABLE) 13 # if defined(DYNAMIC_MACRO_ENABLE) 14 deferred_token dynamic_macro_token = INVALID_DEFERRED_TOKEN; 15 static uint32_t dynamic_macro_led(uint32_t trigger_time, void *cb_arg) { 16 static bool led_state = true; 17 if (!is_launching) { 18 led_state = !led_state; 19 STATUS_LED_3(led_state); 20 } 21 return 100; 22 } 23 24 bool dynamic_macro_record_start_kb(int8_t direction) { 25 if (!dynamic_macro_record_start_user(direction)) { 26 return false; 27 } 28 if (dynamic_macro_token == INVALID_DEFERRED_TOKEN) { 29 STATUS_LED_3(true); 30 dynamic_macro_token = defer_exec(100, dynamic_macro_led, NULL); 31 } 32 return true; 33 } 34 35 bool dynamic_macro_record_end_kb(int8_t direction) { 36 if (!dynamic_macro_record_end_user(direction)) { 37 return false; 38 } 39 if (cancel_deferred_exec(dynamic_macro_token)) { 40 dynamic_macro_token = INVALID_DEFERRED_TOKEN; 41 STATUS_LED_3(false); 42 } 43 return true; 44 } 45 # endif 46 47 static uint32_t startup_exec(uint32_t trigger_time, void *cb_arg) { 48 static uint8_t startup_loop = 0; 49 50 switch (startup_loop++) { 51 case 0: 52 STATUS_LED_1(true); 53 STATUS_LED_2(false); 54 STATUS_LED_3(false); 55 STATUS_LED_4(false); 56 break; 57 case 1: 58 STATUS_LED_2(true); 59 break; 60 case 2: 61 STATUS_LED_3(true); 62 break; 63 case 3: 64 STATUS_LED_4(true); 65 break; 66 case 4: 67 STATUS_LED_1(false); 68 break; 69 case 5: 70 STATUS_LED_2(false); 71 break; 72 case 6: 73 STATUS_LED_3(false); 74 break; 75 case 7: 76 STATUS_LED_4(false); 77 break; 78 case 8: 79 is_launching = false; 80 layer_state_set_kb(layer_state); 81 return 0; 82 } 83 return 250; 84 } 85 #endif 86 87 void keyboard_pre_init_kb(void) { 88 // Initialize Reset pins 89 gpio_set_pin_input(A8); 90 gpio_set_pin_output(A9); 91 gpio_write_pin_low(A9); 92 93 gpio_set_pin_output(B5); 94 gpio_set_pin_output(B4); 95 gpio_set_pin_output(B3); 96 97 gpio_write_pin_low(B5); 98 gpio_write_pin_low(B4); 99 gpio_write_pin_low(B3); 100 101 keyboard_pre_init_user(); 102 } 103 104 #if !defined(VOYAGER_USER_LEDS) 105 layer_state_t layer_state_set_kb(layer_state_t state) { 106 state = layer_state_set_user(state); 107 if (is_launching || !keyboard_config.led_level) return state; 108 109 uint8_t layer = get_highest_layer(state); 110 111 STATUS_LED_1(layer & (1 << 0)); 112 STATUS_LED_2(layer & (1 << 1)); 113 STATUS_LED_3(layer & (1 << 2)); 114 115 # if !defined(CAPS_LOCK_STATUS) 116 STATUS_LED_4(layer & (1 << 3)); 117 # endif 118 return state; 119 } 120 #endif 121 122 #ifdef RGB_MATRIX_ENABLE 123 // clang-format off 124 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[RGB_MATRIX_LED_COUNT] = { 125 /* Refer to IS31 manual for these locations 126 * driver 127 * | R location 128 * | | G location 129 * | | | B location 130 * | | | | */ 131 {0, C2_2, C1_2, C4_3}, 132 {0, C2_3, C1_3, C3_3}, 133 {0, C2_4, C1_4, C3_4}, 134 {0, C2_5, C1_5, C3_5}, 135 {0, C2_6, C1_6, C3_6}, 136 {0, C2_7, C1_7, C3_7}, 137 {0, C2_8, C1_8, C3_8}, 138 {0, C8_1, C7_1, C9_1}, 139 {0, C8_2, C7_2, C9_2}, 140 {0, C8_3, C7_3, C9_3}, 141 {0, C8_4, C7_4, C9_4}, 142 {0, C8_5, C7_5, C9_5}, 143 {0, C8_6, C7_6, C9_6}, 144 {0, C2_10, C1_10, C4_11}, 145 {0, C2_11, C1_11, C3_11}, 146 {0, C2_12, C1_12, C3_12}, 147 {0, C2_13, C1_13, C3_13}, 148 {0, C2_14, C1_14, C3_14}, 149 {0, C2_15, C1_15, C3_15}, 150 {0, C2_16, C1_16, C3_16}, 151 {0, C8_9, C7_9, C9_9}, 152 {0, C8_10, C7_10, C9_10}, 153 {0, C8_11, C7_11, C9_11}, 154 {0, C8_12, C7_12, C9_12}, 155 {0, C8_13, C7_13, C9_13}, 156 {0, C8_14, C7_14, C9_14}, 157 158 {1, C2_7, C1_7, C3_7}, 159 {1, C2_6, C1_6, C3_6}, 160 {1, C2_5, C1_5, C3_5}, 161 {1, C2_4, C1_4, C3_4}, 162 {1, C2_3, C1_3, C3_3}, 163 {1, C2_2, C1_2, C4_3}, 164 165 {1, C8_5, C7_5, C9_5}, 166 {1, C8_4, C7_4, C9_4}, 167 {1, C8_3, C7_3, C9_3}, 168 {1, C8_2, C7_2, C9_2}, 169 {1, C8_1, C7_1, C9_1}, 170 {1, C2_8, C1_8, C3_8}, 171 172 {1, C2_14, C1_14, C3_14}, 173 {1, C2_13, C1_13, C3_13}, 174 {1, C2_12, C1_12, C3_12}, 175 {1, C2_11, C1_11, C3_11}, 176 {1, C2_10, C1_10, C4_11}, 177 {1, C8_6, C7_6, C9_6}, 178 179 {1, C8_12, C7_12, C9_12}, 180 {1, C8_11, C7_11, C9_11}, 181 {1, C8_10, C7_10, C9_10}, 182 {1, C8_9, C7_9, C9_9}, 183 {1, C2_16, C1_16, C3_16}, 184 {1, C2_15, C1_15, C3_15}, 185 186 {1, C8_14, C7_14, C9_14}, 187 {1, C8_13, C7_13, C9_13}, 188 }; 189 // clang-format on 190 #endif 191 192 #ifdef SWAP_HANDS_ENABLE 193 // swap-hands action needs a matrix to define the swap 194 // clang-format off 195 const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { 196 /* Left hand, matrix positions */ 197 {{6,6}, {5,6}, {4,6}, {3,6}, {2,6}, {1,6},{0,6}}, 198 {{6,7}, {5,7}, {4,7}, {3,7}, {2,7}, {1,7},{0,7}}, 199 {{6,8}, {5,8}, {4,8}, {3,8}, {2,8}, {1,8},{0,8}}, 200 {{6,9}, {5,9}, {4,9}, {3,9}, {2,9}, {1,9},{0,9}}, 201 {{6,10},{5,10},{4,10},{3,10},{2,10},{1,10},{0,10}}, 202 {{6,11},{5,11},{4,11},{3,11},{2,11},{1,11},{0,11}}, 203 /* Right hand, matrix positions */ 204 {{6,0}, {5,0}, {4,0}, {3,0}, {2,0}, {1,0},{0,0}}, 205 {{6,1}, {5,1}, {4,1}, {3,1}, {2,1}, {1,1},{0,1}}, 206 {{6,2}, {5,2}, {4,2}, {3,2}, {2,2}, {1,2},{0,2}}, 207 {{6,3}, {5,3}, {4,3}, {3,3}, {2,3}, {1,3},{0,3}}, 208 {{6,4}, {5,4}, {4,4}, {3,4}, {2,4}, {1,4},{0,4}}, 209 {{6,5}, {5,5}, {4,5}, {3,5}, {2,5}, {1,5},{0,5}}, 210 }; 211 // clang-format on 212 #endif 213 214 #ifdef CAPS_LOCK_STATUS 215 bool led_update_kb(led_t led_state) { 216 bool res = led_update_user(led_state); 217 if (res) { 218 STATUS_LED_4(led_state.caps_lock); 219 } 220 return res; 221 } 222 #endif 223 224 bool process_record_kb(uint16_t keycode, keyrecord_t *record) { 225 if (!process_record_user(keycode, record)) { 226 return false; 227 } 228 switch (keycode) { 229 #if !defined(VOYAGER_USER_LEDS) 230 case LED_LEVEL: 231 if (record->event.pressed) { 232 keyboard_config.led_level ^= 1; 233 eeconfig_update_kb(keyboard_config.raw); 234 if (keyboard_config.led_level) { 235 layer_state_set_kb(layer_state); 236 } else { 237 STATUS_LED_1(false); 238 STATUS_LED_2(false); 239 STATUS_LED_3(false); 240 STATUS_LED_4(false); 241 } 242 } 243 break; 244 #endif 245 #ifdef RGB_MATRIX_ENABLE 246 case TOGGLE_LAYER_COLOR: 247 if (record->event.pressed) { 248 keyboard_config.disable_layer_led ^= 1; 249 if (keyboard_config.disable_layer_led) rgb_matrix_set_color_all(0, 0, 0); 250 } 251 break; 252 case QK_RGB_MATRIX_TOGGLE: 253 if (record->event.pressed) { 254 switch (rgb_matrix_get_flags()) { 255 case LED_FLAG_ALL: { 256 rgb_matrix_set_flags(LED_FLAG_NONE); 257 rgb_matrix_set_color_all(0, 0, 0); 258 } break; 259 default: { 260 rgb_matrix_set_flags(LED_FLAG_ALL); 261 } break; 262 } 263 } 264 return false; 265 #endif 266 } 267 return true; 268 } 269 270 void keyboard_post_init_kb(void) { 271 #ifdef RGB_MATRIX_ENABLE 272 rgb_matrix_enable_noeeprom(); 273 #endif 274 275 keyboard_config.raw = eeconfig_read_kb(); 276 277 if (!keyboard_config.led_level && !keyboard_config.led_level_res) { 278 keyboard_config.led_level = true; 279 keyboard_config.led_level_res = 0b11; 280 eeconfig_update_kb(keyboard_config.raw); 281 } 282 #if defined(DEFERRED_EXEC_ENABLE) 283 is_launching = true; 284 defer_exec(500, startup_exec, NULL); 285 #endif 286 keyboard_post_init_user(); 287 } 288 289 void eeconfig_init_kb(void) { // EEPROM is getting reset! 290 keyboard_config.raw = 0; 291 keyboard_config.led_level = true; 292 keyboard_config.led_level_res = 0b11; 293 eeconfig_update_kb(keyboard_config.raw); 294 eeconfig_init_user(); 295 } 296 297 __attribute__((weak)) void bootloader_jump(void) { 298 // The ignition bootloader is checking for a high signal on A8 for 100ms when powering on the board. 299 // Setting both A8 and A9 high will charge the capacitor quickly. 300 // Setting A9 low before reset will cause the capacitor to discharge 301 // thus making the bootloder unlikely to trigger twice between power cycles. 302 gpio_set_pin_output_push_pull(A9); 303 gpio_set_pin_output_push_pull(A8); 304 gpio_write_pin_high(A9); 305 gpio_write_pin_high(A8); 306 wait_ms(500); 307 gpio_write_pin_low(A9); 308 309 NVIC_SystemReset(); 310 } 311 312 __attribute__((weak)) void mcu_reset(void) { 313 gpio_set_pin_output_push_pull(A9); 314 gpio_set_pin_output_push_pull(A8); 315 gpio_write_pin_low(A8); 316 gpio_write_pin_low(A9); 317 318 NVIC_SystemReset(); 319 }