ergodox_ez.c (12367B)
1 /* 2 Copyright 2012 Jun Wako <wakojun@gmail.com> 3 Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com> 4 Copyright 2015 ZSA Technology Labs Inc (@zsa) 5 Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna) 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "ergodox_ez.h" 22 23 extern inline void ergodox_board_led_on(void); 24 extern inline void ergodox_right_led_1_on(void); 25 extern inline void ergodox_right_led_2_on(void); 26 extern inline void ergodox_right_led_3_on(void); 27 28 extern inline void ergodox_board_led_off(void); 29 extern inline void ergodox_right_led_1_off(void); 30 extern inline void ergodox_right_led_2_off(void); 31 extern inline void ergodox_right_led_3_off(void); 32 33 extern inline void ergodox_led_all_on(void); 34 extern inline void ergodox_led_all_off(void); 35 36 extern inline void ergodox_right_led_1_set(uint8_t n); 37 extern inline void ergodox_right_led_2_set(uint8_t n); 38 extern inline void ergodox_right_led_3_set(uint8_t n); 39 extern inline void ergodox_right_led_set(uint8_t led, uint8_t n); 40 41 extern inline void ergodox_led_all_set(uint8_t n); 42 43 keyboard_config_t keyboard_config; 44 45 bool i2c_initialized = 0; 46 i2c_status_t mcp23018_status = 0x20; 47 48 void matrix_init_kb(void) { 49 // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md") 50 TCCR1A = 0b10101001; // set and configure fast PWM 51 TCCR1B = 0b00001001; // set and configure fast PWM 52 53 // (tied to Vcc for hardware convenience) 54 gpio_set_pin_input(B4); // set B(4) as input, internal pull-up disabled 55 56 // unused pins - C7, D4, D5, E6 57 // set as input with internal pull-up enabled 58 gpio_set_pin_input_high(C7); 59 gpio_set_pin_input_high(D4); 60 gpio_set_pin_input_high(D5); 61 gpio_set_pin_input_high(E6); 62 63 keyboard_config.raw = eeconfig_read_kb(); 64 ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4); 65 #ifdef RGB_MATRIX_ENABLE 66 if (keyboard_config.rgb_matrix_enable) { 67 rgb_matrix_set_flags(LED_FLAG_ALL); 68 } else { 69 rgb_matrix_set_flags(LED_FLAG_NONE); 70 } 71 #endif 72 73 ergodox_blink_all_leds(); 74 75 matrix_init_user(); 76 } 77 78 void ergodox_blink_all_leds(void) { 79 ergodox_led_all_off(); 80 ergodox_led_all_set(LED_BRIGHTNESS_DEFAULT); 81 ergodox_right_led_1_on(); 82 _delay_ms(50); 83 ergodox_right_led_2_on(); 84 _delay_ms(50); 85 ergodox_right_led_3_on(); 86 _delay_ms(50); 87 #ifdef LEFT_LEDS 88 ergodox_left_led_1_on(); 89 _delay_ms(50); 90 if (!mcp23018_status) { 91 mcp23018_status = ergodox_left_leds_update(); 92 } 93 ergodox_left_led_2_on(); 94 _delay_ms(50); 95 if (!mcp23018_status) { 96 mcp23018_status = ergodox_left_leds_update(); 97 } 98 ergodox_left_led_3_on(); 99 _delay_ms(50); 100 if (!mcp23018_status) { 101 mcp23018_status = ergodox_left_leds_update(); 102 } 103 #endif 104 ergodox_right_led_1_off(); 105 _delay_ms(50); 106 ergodox_right_led_2_off(); 107 _delay_ms(50); 108 ergodox_right_led_3_off(); 109 #ifdef LEFT_LEDS 110 _delay_ms(50); 111 ergodox_left_led_1_off(); 112 if (!mcp23018_status) { 113 mcp23018_status = ergodox_left_leds_update(); 114 } 115 _delay_ms(50); 116 ergodox_left_led_2_off(); 117 if (!mcp23018_status) { 118 mcp23018_status = ergodox_left_leds_update(); 119 } 120 _delay_ms(50); 121 ergodox_left_led_3_off(); 122 if (!mcp23018_status) { 123 mcp23018_status = ergodox_left_leds_update(); 124 } 125 #endif 126 127 // ergodox_led_all_on(); 128 //_delay_ms(333); 129 ergodox_led_all_off(); 130 } 131 132 uint8_t init_mcp23018(void) { 133 mcp23018_status = 0x20; 134 135 // I2C subsystem 136 137 // uint8_t sreg_prev; 138 // sreg_prev=SREG; 139 // cli(); 140 141 if (i2c_initialized == 0) { 142 i2c_init(); // on pins D(1,0) 143 i2c_initialized = true; 144 _delay_ms(1000); 145 } 146 // i2c_init(); // on pins D(1,0) 147 // _delay_ms(1000); 148 149 // set pin direction 150 // - unused : input : 1 151 // - input : input : 1 152 // - driving : output : 0 153 uint8_t data[] = {0b00000000, 0b00111111}; 154 mcp23018_status = i2c_write_register(I2C_ADDR, IODIRA, data, 2, ERGODOX_EZ_I2C_TIMEOUT); 155 156 if (!mcp23018_status) { 157 // set pull-up 158 // - unused : on : 1 159 // - input : on : 1 160 // - driving : off : 0 161 mcp23018_status = i2c_write_register(I2C_ADDR, GPPUA, data, 2, ERGODOX_EZ_I2C_TIMEOUT); 162 } 163 164 #ifdef LEFT_LEDS 165 if (!mcp23018_status) mcp23018_status = ergodox_left_leds_update(); 166 #endif // LEFT_LEDS 167 168 // SREG=sreg_prev; 169 170 return mcp23018_status; 171 } 172 173 #ifdef LEFT_LEDS 174 uint8_t ergodox_left_leds_update(void) { 175 if (mcp23018_status) { // if there was an error 176 return mcp23018_status; 177 } 178 # define LEFT_LED_1_SHIFT 7 // in MCP23018 port B 179 # define LEFT_LED_2_SHIFT 6 // in MCP23018 port B 180 # define LEFT_LED_3_SHIFT 7 // in MCP23018 port A 181 182 // set logical value (doesn't matter on inputs) 183 // - unused : hi-Z : 1 184 // - input : hi-Z : 1 185 // - driving : hi-Z : 1 186 uint8_t data[2]; 187 data[0] = 0b11111111 & ~(ergodox_left_led_3 << LEFT_LED_3_SHIFT); 188 data[1] = 0b11111111 & ~(ergodox_left_led_2 << LEFT_LED_2_SHIFT) & ~(ergodox_left_led_1 << LEFT_LED_1_SHIFT); 189 mcp23018_status = i2c_write_register(I2C_ADDR, OLATA, data, 2, ERGODOX_EZ_I2C_TIMEOUT); 190 191 return mcp23018_status; 192 } 193 #endif 194 195 #ifdef SWAP_HANDS_ENABLE 196 __attribute__((weak)) 197 // swap-hands action needs a matrix to define the swap 198 const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { 199 /* Left hand, matrix positions */ 200 {{0, 13}, {1, 13}, {2, 13}, {3, 13}, {4, 13}, {5, 13}}, 201 {{0, 12}, {1, 12}, {2, 12}, {3, 12}, {4, 12}, {5, 12}}, 202 {{0, 11}, {1, 11}, {2, 11}, {3, 11}, {4, 11}, {5, 11}}, 203 {{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}, {5, 10}}, 204 {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}, {5, 9}}, 205 {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}, {5, 8}}, 206 {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}}, 207 /* Right hand, matrix positions */ 208 {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}}, 209 {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}}, 210 {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}}, 211 {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}}, 212 {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}}, 213 {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}, 214 {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}}, 215 }; 216 #endif 217 218 #ifdef RGB_MATRIX_ENABLE 219 // clang-format off 220 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = { 221 /* driver 222 * | R location 223 * | | G location 224 * | | | B location 225 * | | | | */ 226 {0, C3_1, C2_1, C4_1}, // LED1 on right 227 {0, C6_1, C5_1, C7_1}, // LED2 228 {0, C4_2, C3_2, C5_2}, // LED3 229 {0, C7_2, C6_2, C8_2}, // LED4 230 {0, C2_3, C1_3, C3_3}, // LED5 231 {0, C5_3, C4_3, C6_3}, // LED6 232 {0, C8_3, C7_3, C9_3}, // LED7 233 {0, C2_4, C1_4, C3_4}, // LED8 234 {0, C6_4, C5_4, C7_4}, // LED9 235 {0, C2_5, C1_5, C3_5}, // LED10 236 {0, C7_5, C6_5, C8_5}, // LED11 237 {0, C2_6, C1_6, C3_6}, // LED12 238 {0, C5_6, C4_6, C6_6}, // LED13 239 {0, C8_6, C7_6, C9_6}, // LED14 240 {0, C2_7, C1_7, C3_7}, // LED15 241 {0, C5_7, C4_7, C6_7}, // LED16 242 {0, C2_8, C1_8, C3_8}, // LED17 243 {0, C5_8, C4_8, C6_8}, // LED18 244 245 {0, C3_9, C2_9, C4_9}, // LED19 246 {0, C6_9, C5_9, C7_9}, // LED20 247 {0, C4_10, C3_10, C5_10}, // LED21 248 {0, C7_10, C6_10, C8_10}, // LED22 249 {0, C2_11, C1_11, C3_11}, // LED23 250 {0, C5_11, C4_11, C6_11}, // LED24 251 252 {1, C3_1, C2_1, C4_1}, // LED1 on left 253 {1, C6_1, C5_1, C7_1}, // LED2 254 {1, C4_2, C3_2, C5_2}, // LED3 255 {1, C7_2, C6_2, C8_2}, // LED4 256 {1, C2_3, C1_3, C3_3}, // LED5 257 {1, C5_3, C4_3, C6_3}, // LED6 258 {1, C8_3, C7_3, C9_3}, // LED7 259 {1, C2_4, C1_4, C3_4}, // LED8 260 {1, C6_4, C5_4, C7_4}, // LED9 261 {1, C2_5, C1_5, C3_5}, // LED10 262 {1, C7_5, C6_5, C8_5}, // LED11 263 {1, C2_6, C1_6, C3_6}, // LED12 264 {1, C5_6, C4_6, C6_6}, // LED13 265 {1, C8_6, C7_6, C9_6}, // LED14 266 {1, C2_7, C1_7, C3_7}, // LED15 267 {1, C5_7, C4_7, C6_7}, // LED16 268 {1, C2_8, C1_8, C3_8}, // LED17 269 {1, C5_8, C4_8, C6_8}, // LED18 270 271 {1, C3_9, C2_9, C4_9}, // LED19 272 {1, C6_9, C5_9, C7_9}, // LED20 273 {1, C4_10, C3_10, C5_10}, // LED21 274 {1, C7_10, C6_10, C8_10}, // LED22 275 {1, C2_11, C1_11, C3_11}, // LED23 276 {1, C5_11, C4_11, C6_11} // LED24 277 }; 278 // clang-format on 279 280 # ifdef ORYX_CONFIGURATOR 281 void keyboard_post_init_kb(void) { 282 rgb_matrix_enable_noeeprom(); 283 keyboard_post_init_user(); 284 } 285 # endif 286 #endif 287 288 #ifdef ORYX_CONFIGURATOR 289 bool process_record_kb(uint16_t keycode, keyrecord_t *record) { 290 switch (keycode) { 291 case LED_LEVEL: 292 if (record->event.pressed) { 293 keyboard_config.led_level++; 294 if (keyboard_config.led_level > 4) { 295 keyboard_config.led_level = 0; 296 } 297 ergodox_led_all_set((uint8_t)keyboard_config.led_level * 255 / 4); 298 eeconfig_update_kb(keyboard_config.raw); 299 layer_state_set_kb(layer_state); 300 } 301 break; 302 # ifdef RGB_MATRIX_ENABLE 303 case TOGGLE_LAYER_COLOR: 304 if (record->event.pressed) { 305 keyboard_config.disable_layer_led ^= 1; 306 if (keyboard_config.disable_layer_led) rgb_matrix_set_color_all(0, 0, 0); 307 eeconfig_update_kb(keyboard_config.raw); 308 } 309 break; 310 case QK_RGB_MATRIX_TOGGLE: 311 if (record->event.pressed) { 312 switch (rgb_matrix_get_flags()) { 313 case LED_FLAG_ALL: { 314 rgb_matrix_set_flags(LED_FLAG_NONE); 315 keyboard_config.rgb_matrix_enable = false; 316 rgb_matrix_set_color_all(0, 0, 0); 317 } break; 318 default: { 319 rgb_matrix_set_flags(LED_FLAG_ALL); 320 keyboard_config.rgb_matrix_enable = true; 321 } break; 322 } 323 eeconfig_update_kb(keyboard_config.raw); 324 } 325 return false; 326 # endif 327 } 328 return process_record_user(keycode, record); 329 } 330 #endif 331 332 void eeconfig_init_kb(void) { // EEPROM is getting reset! 333 keyboard_config.raw = 0; 334 keyboard_config.led_level = 4; 335 keyboard_config.rgb_matrix_enable = true; 336 eeconfig_update_kb(keyboard_config.raw); 337 eeconfig_init_user(); 338 } 339 340 #ifdef ORYX_ENABLE 341 static uint16_t loops = 0; 342 static bool is_on = false; 343 #endif 344 345 #ifdef DYNAMIC_MACRO_ENABLE 346 static bool is_dynamic_recording = false; 347 static uint16_t dynamic_loop_timer; 348 349 bool dynamic_macro_record_start_kb(int8_t direction) { 350 if (!dynamic_macro_record_start_user(direction)) { 351 return false; 352 } 353 is_dynamic_recording = true; 354 dynamic_loop_timer = timer_read(); 355 ergodox_right_led_1_on(); 356 return true; 357 } 358 359 bool dynamic_macro_record_end_kb(int8_t direction) { 360 if (!dynamic_macro_record_end_user(direction)) { 361 return false; 362 } 363 is_dynamic_recording = false; 364 layer_state_set_user(layer_state); 365 return true; 366 } 367 #endif 368 369 void matrix_scan_kb(void) { 370 #ifdef DYNAMIC_MACRO_ENABLE 371 if (is_dynamic_recording) { 372 ergodox_right_led_1_off(); 373 // if (timer_elapsed(dynamic_loop_timer) > 5) 374 { 375 static uint8_t counter; 376 counter++; 377 if (counter > 100) ergodox_right_led_1_on(); 378 dynamic_loop_timer = timer_read(); 379 } 380 } 381 #endif 382 383 #ifdef CAPS_LOCK_STATUS 384 led_t led_state = host_keyboard_led_state(); 385 if(led_state.caps_lock) { 386 ergodox_right_led_3_on(); 387 } 388 else { 389 uint8_t layer = get_highest_layer(layer_state); 390 if(layer != 1) { 391 ergodox_right_led_3_off(); 392 } 393 } 394 #endif 395 396 matrix_scan_user(); 397 }