qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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 }