qmk_firmware

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

helix.c (12917B)


      1 /* Copyright 2023 splitkb.com <support@splitkb.com>
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include "quantum.h"
     18 
     19 // The first four layers gets a name for readability, which is then used in the OLED below.
     20 enum layers {
     21   _DEFAULT,
     22   _LOWER,
     23   _RAISE,
     24   _ADJUST
     25 };
     26 
     27 #ifdef OLED_ENABLE
     28 // NOTE: Most of the OLED code was originally written by Soundmonster for the Corne,
     29 // and has been copied directly from `crkbd/soundmonster/keymap.c`
     30 
     31 oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
     32     return OLED_ROTATION_270;
     33 }
     34 
     35 void render_mod_status_gui_alt(uint8_t modifiers) {
     36     static const char PROGMEM gui_off_1[] = {0x85, 0x86, 0};
     37     static const char PROGMEM gui_off_2[] = {0xa5, 0xa6, 0};
     38     static const char PROGMEM gui_on_1[] = {0x8d, 0x8e, 0};
     39     static const char PROGMEM gui_on_2[] = {0xad, 0xae, 0};
     40 
     41     static const char PROGMEM alt_off_1[] = {0x87, 0x88, 0};
     42     static const char PROGMEM alt_off_2[] = {0xa7, 0xa8, 0};
     43     static const char PROGMEM alt_on_1[] = {0x8f, 0x90, 0};
     44     static const char PROGMEM alt_on_2[] = {0xaf, 0xb0, 0};
     45 
     46     // fillers between the modifier icons bleed into the icon frames
     47     static const char PROGMEM off_off_1[] = {0xc5, 0};
     48     static const char PROGMEM off_off_2[] = {0xc6, 0};
     49     static const char PROGMEM on_off_1[] = {0xc7, 0};
     50     static const char PROGMEM on_off_2[] = {0xc8, 0};
     51     static const char PROGMEM off_on_1[] = {0xc9, 0};
     52     static const char PROGMEM off_on_2[] = {0xca, 0};
     53     static const char PROGMEM on_on_1[] = {0xcb, 0};
     54     static const char PROGMEM on_on_2[] = {0xcc, 0};
     55 
     56     if(modifiers & MOD_MASK_GUI) {
     57         oled_write_P(gui_on_1, false);
     58     } else {
     59         oled_write_P(gui_off_1, false);
     60     }
     61 
     62     if ((modifiers & MOD_MASK_GUI) && (modifiers & MOD_MASK_ALT)) {
     63         oled_write_P(on_on_1, false);
     64     } else if(modifiers & MOD_MASK_GUI) {
     65         oled_write_P(on_off_1, false);
     66     } else if(modifiers & MOD_MASK_ALT) {
     67         oled_write_P(off_on_1, false);
     68     } else {
     69         oled_write_P(off_off_1, false);
     70     }
     71 
     72     if(modifiers & MOD_MASK_ALT) {
     73         oled_write_P(alt_on_1, false);
     74     } else {
     75         oled_write_P(alt_off_1, false);
     76     }
     77 
     78     if(modifiers & MOD_MASK_GUI) {
     79         oled_write_P(gui_on_2, false);
     80     } else {
     81         oled_write_P(gui_off_2, false);
     82     }
     83 
     84     if ((modifiers & MOD_MASK_GUI) && (modifiers & MOD_MASK_ALT)) {
     85         oled_write_P(on_on_2, false);
     86     } else if(modifiers & MOD_MASK_GUI) {
     87         oled_write_P(on_off_2, false);
     88     } else if(modifiers & MOD_MASK_ALT) {
     89         oled_write_P(off_on_2, false);
     90     } else {
     91         oled_write_P(off_off_2, false);
     92     }
     93 
     94     if(modifiers & MOD_MASK_ALT) {
     95         oled_write_P(alt_on_2, false);
     96     } else {
     97         oled_write_P(alt_off_2, false);
     98     }
     99 }
    100 
    101 void render_mod_status_ctrl_shift(uint8_t modifiers) {
    102     static const char PROGMEM ctrl_off_1[] = {0x89, 0x8a, 0};
    103     static const char PROGMEM ctrl_off_2[] = {0xa9, 0xaa, 0};
    104     static const char PROGMEM ctrl_on_1[] = {0x91, 0x92, 0};
    105     static const char PROGMEM ctrl_on_2[] = {0xb1, 0xb2, 0};
    106 
    107     static const char PROGMEM shift_off_1[] = {0x8b, 0x8c, 0};
    108     static const char PROGMEM shift_off_2[] = {0xab, 0xac, 0};
    109     static const char PROGMEM shift_on_1[] = {0xcd, 0xce, 0};
    110     static const char PROGMEM shift_on_2[] = {0xcf, 0xd0, 0};
    111 
    112     // fillers between the modifier icons bleed into the icon frames
    113     static const char PROGMEM off_off_1[] = {0xc5, 0};
    114     static const char PROGMEM off_off_2[] = {0xc6, 0};
    115     static const char PROGMEM on_off_1[] = {0xc7, 0};
    116     static const char PROGMEM on_off_2[] = {0xc8, 0};
    117     static const char PROGMEM off_on_1[] = {0xc9, 0};
    118     static const char PROGMEM off_on_2[] = {0xca, 0};
    119     static const char PROGMEM on_on_1[] = {0xcb, 0};
    120     static const char PROGMEM on_on_2[] = {0xcc, 0};
    121 
    122     if(modifiers & MOD_MASK_CTRL) {
    123         oled_write_P(ctrl_on_1, false);
    124     } else {
    125         oled_write_P(ctrl_off_1, false);
    126     }
    127 
    128     if ((modifiers & MOD_MASK_CTRL) && (modifiers & MOD_MASK_SHIFT)) {
    129         oled_write_P(on_on_1, false);
    130     } else if(modifiers & MOD_MASK_CTRL) {
    131         oled_write_P(on_off_1, false);
    132     } else if(modifiers & MOD_MASK_SHIFT) {
    133         oled_write_P(off_on_1, false);
    134     } else {
    135         oled_write_P(off_off_1, false);
    136     }
    137 
    138     if(modifiers & MOD_MASK_SHIFT) {
    139         oled_write_P(shift_on_1, false);
    140     } else {
    141         oled_write_P(shift_off_1, false);
    142     }
    143 
    144     if(modifiers & MOD_MASK_CTRL) {
    145         oled_write_P(ctrl_on_2, false);
    146     } else {
    147         oled_write_P(ctrl_off_2, false);
    148     }
    149 
    150     if ((modifiers & MOD_MASK_CTRL) && (modifiers & MOD_MASK_SHIFT)) {
    151         oled_write_P(on_on_2, false);
    152     } else if(modifiers & MOD_MASK_CTRL) {
    153         oled_write_P(on_off_2, false);
    154     } else if(modifiers & MOD_MASK_SHIFT) {
    155         oled_write_P(off_on_2, false);
    156     } else {
    157         oled_write_P(off_off_2, false);
    158     }
    159 
    160     if(modifiers & MOD_MASK_SHIFT) {
    161         oled_write_P(shift_on_2, false);
    162     } else {
    163         oled_write_P(shift_off_2, false);
    164     }
    165 }
    166 
    167 void render_logo(void) {
    168     static const char PROGMEM aurora_logo[] = {
    169         0x00, 0x00, 0x00, 0xe0, 0x00, 0xf8, 0xc0, 0xf8, 0xe0, 0xc0, 0xfc, 0x00, 0x7e, 0x18, 0x00, 0x80,
    170         0x00, 0x02, 0x80, 0xf0, 0x00, 0xc0, 0x80, 0xf8, 0xc0, 0xe0, 0x70, 0x60, 0x3c, 0x38, 0x3c, 0x1c,
    171         0x00, 0x3f, 0x0c, 0x0f, 0x1f, 0x03, 0x07, 0x01, 0xc3, 0x00, 0xe0, 0x80, 0x00, 0xe0, 0x80, 0xf8,
    172         0x80, 0xc0, 0xf7, 0xc7, 0x6f, 0x7b, 0x39, 0x30, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xc0, 0xc2, 0xe0,
    173         0x00, 0x40, 0x38, 0x30, 0x38, 0x1e, 0x18, 0x1e, 0x0f, 0x0c, 0x07, 0x07, 0x07, 0x03, 0x03, 0x21,
    174         0x21, 0x31, 0x30, 0x18, 0x18, 0x1c, 0x08, 0x0c, 0x0e, 0x07, 0x06, 0x07, 0x03, 0xc3, 0x03, 0x01,
    175         0x4c, 0xcc, 0xc2, 0xc2, 0x41, 0x49, 0x09, 0x2b, 0x2a, 0x6a, 0x6e, 0x24, 0x24, 0x04, 0x92, 0x92,
    176         0xb1, 0xf1, 0xf1, 0xf2, 0xe6, 0xa4, 0xa4, 0x04, 0x04, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28
    177     };
    178     oled_write_raw_P(aurora_logo, sizeof(aurora_logo));
    179     oled_set_cursor(0, 4);
    180 }
    181 
    182 void render_logo_text(void) {
    183     oled_write_P(PSTR("helix"), false);
    184 }
    185 
    186 void render_kb_LED_state(void) {
    187     // Host Keyboard LED Status
    188     led_t led_state = host_keyboard_led_state();
    189     oled_write_P(led_state.num_lock ? PSTR("N ") : PSTR("  "), false);
    190     oled_write_P(led_state.caps_lock ? PSTR("C ") : PSTR("  "), false);
    191     oled_write_P(led_state.scroll_lock ? PSTR("S ") : PSTR("  "), false);
    192 }
    193 
    194 void render_layer_state(void) {
    195     static const char PROGMEM default_layer[] = {
    196         0x20, 0x94, 0x95, 0x96, 0x20,
    197         0x20, 0xb4, 0xb5, 0xb6, 0x20,
    198         0x20, 0xd4, 0xd5, 0xd6, 0x20, 0};
    199     static const char PROGMEM raise_layer[] = {
    200         0x20, 0x97, 0x98, 0x99, 0x20,
    201         0x20, 0xb7, 0xb8, 0xb9, 0x20,
    202         0x20, 0xd7, 0xd8, 0xd9, 0x20, 0};
    203     static const char PROGMEM lower_layer[] = {
    204         0x20, 0x9a, 0x9b, 0x9c, 0x20,
    205         0x20, 0xba, 0xbb, 0xbc, 0x20,
    206         0x20, 0xda, 0xdb, 0xdc, 0x20, 0};
    207     static const char PROGMEM adjust_layer[] = {
    208         0x20, 0x9d, 0x9e, 0x9f, 0x20,
    209         0x20, 0xbd, 0xbe, 0xbf, 0x20,
    210         0x20, 0xdd, 0xde, 0xdf, 0x20, 0};
    211 
    212     switch (get_highest_layer(layer_state | default_layer_state)) {
    213         case _LOWER:
    214             oled_write_P(lower_layer, false);
    215             break;
    216         case _RAISE:
    217             oled_write_P(raise_layer, false);
    218             break;
    219         case _ADJUST:
    220             oled_write_P(adjust_layer, false);
    221             break;
    222         default:
    223             oled_write_P(default_layer, false);
    224     }
    225 }
    226 
    227 
    228 bool oled_task_kb(void) {
    229     if (!oled_task_user()) {
    230         return false;
    231     }
    232     if (is_keyboard_master()) {
    233         // Renders the current keyboard state (layers and mods)
    234         render_logo();
    235         render_logo_text();
    236         oled_advance_page(false);
    237         render_layer_state();
    238         oled_advance_page(false);
    239         render_mod_status_gui_alt(get_mods()|get_oneshot_mods());
    240         render_mod_status_ctrl_shift(get_mods()|get_oneshot_mods());
    241         render_kb_LED_state();
    242     } else {
    243         // clang-format off
    244         static const char PROGMEM aurora_art[] = {
    245             0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x08, 0x00, 0x00,
    246             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
    247             0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40,
    248             0xe0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x80,
    249             0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x00, 0xf0, 0x00, 0x00, 0xc0,
    250             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
    251             0x81, 0x00, 0xc0, 0x00, 0xfe, 0x00, 0xfc, 0x00, 0xff, 0x20, 0xff, 0xf0, 0x0f, 0xf0, 0x00, 0xff,
    252             0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xf8, 0x00, 0x00, 0xf8,
    253             0xff, 0x10, 0xff, 0x84, 0xff, 0x60, 0xff, 0x36, 0xff, 0x0f, 0xff, 0x3f, 0x00, 0x5f, 0x00, 0x05,
    254             0x80, 0x00, 0x80, 0x00, 0xc0, 0x38, 0x00, 0xec, 0xf0, 0x00, 0xfb, 0x80, 0xff, 0xf0, 0xff, 0xef,
    255             0xff, 0xe8, 0xff, 0x03, 0xff, 0x0c, 0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 0x00, 0xf8, 0x00, 0x80,
    256             0xff, 0x20, 0xff, 0xd0, 0xff, 0xe0, 0xfe, 0xf8, 0xff, 0xfc, 0xff, 0xff, 0x0f, 0xff, 0x01, 0x3f,
    257             0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x03, 0x00, 0xfe, 0x80, 0xfe, 0x00, 0xc0, 0xff, 0xc4, 0xfb,
    258             0xff, 0xfe, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x07, 0xff, 0x03, 0x3f, 0x00, 0x0f, 0xc0, 0x00,
    259             0x00, 0x00, 0xb8, 0x00, 0xff, 0x40, 0xbe, 0xf0, 0xff, 0xf1, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
    260             0x1f, 0xff, 0x67, 0x00, 0xef, 0x00, 0x1f, 0x00, 0x00, 0x07, 0x00, 0x00, 0xe0, 0x00, 0xff, 0xf0,
    261             0xff, 0x88, 0xff, 0xc4, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0x7f, 0x0f, 0xff,
    262             0x00, 0x07, 0xfe, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xc0, 0x3f, 0xf8, 0xe7, 0xff,
    263             0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0x3f, 0x01, 0xff, 0x0b, 0x00, 0xff, 0x00, 0x00, 0x05,
    264             0x00, 0x00, 0x00, 0xe0, 0x00, 0xf8, 0x60, 0x80, 0xfe, 0xe3, 0xfc, 0xff, 0x1e, 0xff, 0xff, 0x23,
    265             0xff, 0x09, 0xff, 0x20, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x40, 0x00, 0xc0, 0x00, 0xfc,
    266             0xe0, 0xfc, 0xf0, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0x0f, 0xff, 0x07, 0x1f, 0x00, 0x01, 0x0f, 0x00,
    267             0x0f, 0x00, 0x81, 0x70, 0x0c, 0xf0, 0x80, 0x00, 0x00, 0xe4, 0xf8, 0xe6, 0x70, 0x3f, 0xcf, 0xff,
    268             0x1f, 0xff, 0x48, 0xff, 0x0f, 0x00, 0x07, 0x00, 0x00, 0x43, 0x60, 0xf8, 0xf0, 0xfe, 0x38, 0xfe,
    269             0x00, 0xfc, 0x03, 0x00, 0xc8, 0x72, 0xcf, 0xfc, 0x00, 0x03, 0x0f, 0x01, 0xe0, 0x1c, 0xe0, 0x03,
    270             0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x06, 0xf9, 0x00, 0x03, 0x00, 0x07,
    271             0xff, 0x00, 0x10, 0x12, 0xc9, 0xf0, 0xcf, 0xb4, 0x7f, 0x80, 0xe0, 0x1e, 0x01, 0x40, 0x65, 0x5e,
    272             0xe0, 0x00, 0x00, 0xf0, 0x0c, 0xf0, 0x00, 0x80, 0x7e, 0x01, 0x80, 0x93, 0xfc, 0xc0, 0x00, 0x00,
    273             0x00, 0x00, 0x00, 0x00, 0x89, 0x18, 0x2c, 0x46, 0x00, 0x07, 0x21, 0x10, 0x10, 0x80, 0x09, 0x13,
    274             0x31, 0xbf, 0xff, 0x00, 0x08, 0x1a, 0xf7, 0x0f, 0x00, 0x00, 0x44, 0x45, 0x34, 0xbf, 0xb8, 0x00,
    275             0x10, 0xf0, 0x08, 0xf4, 0x18, 0x11, 0xfc, 0x18, 0xfb, 0x0e, 0x10, 0xf8, 0x04, 0xf8, 0x10, 0x20,
    276             0x18, 0x09, 0xff, 0x0c, 0xea, 0x1f, 0x28, 0x60, 0x30, 0xf8, 0x20, 0xc0, 0x42, 0x33, 0x21, 0x00
    277         };
    278         // clang-format on
    279         oled_write_raw_P(aurora_art, sizeof(aurora_art));
    280     }
    281     return false;
    282 }
    283 #endif
    284 
    285 #ifdef ENCODER_ENABLE
    286 bool encoder_update_kb(uint8_t index, bool clockwise) {
    287     if (!encoder_update_user(index, clockwise)) {
    288         return false;
    289     }
    290     // 0 is left-half encoder,
    291     // 1 is right-half encoder
    292     if (index == 0) {
    293         // Volume control
    294         if (clockwise) {
    295             tap_code(KC_VOLU);
    296         } else {
    297             tap_code(KC_VOLD);
    298         }
    299     } else if (index == 1) {
    300         // Page up/Page down
    301         if (clockwise) {
    302             tap_code(KC_PGDN);
    303         } else {
    304             tap_code(KC_PGUP);
    305         }
    306     }
    307     return true;
    308 }
    309 #endif