qmk_firmware

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

rev1.c (8366B)


      1 // Copyright 2024 splitkb.com (support@splitkb.com)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #include "rev1.h"
      5 #include "spi_master.h"
      6 #include "myriad.h"
      7 
      8 bool is_oled_enabled = true;
      9 
     10 //// HW init
     11 
     12 // Make sure all external hardware is
     13 // in a known-good state on powerup
     14 void keyboard_pre_init_kb(void) {
     15     /// SPI Chip Select pins for various hardware
     16     // Matrix CS
     17     gpio_set_pin_output(GP13);
     18     gpio_write_pin_high(GP13);
     19     // Myriad Module CS
     20     gpio_set_pin_output(GP9);
     21     gpio_write_pin_high(GP9);
     22 
     23     gpio_set_pin_output(ELORA_CC1_PIN);
     24     gpio_write_pin_low(ELORA_CC1_PIN);
     25 
     26     gpio_set_pin_output(ELORA_CC2_PIN);
     27     gpio_write_pin_low(ELORA_CC2_PIN);
     28 
     29     // We have to get the SPI interface working quite early,
     30     // So make sure it is available well before we need it
     31     spi_init();
     32     
     33     keyboard_pre_init_user();
     34 }
     35 
     36 //// Encoder functionality
     37 
     38 // The encoders are hooked in to the same shift registers as the switch matrix, so we can just piggyback on that.
     39 
     40 // Clone of a variant in quantum/matrix_common.c, but matrix-agnostic
     41 bool mat_is_on(matrix_row_t mat[], uint8_t row, uint8_t col) {
     42     return (mat[row] & ((matrix_row_t)1 << col));
     43 }
     44 
     45 uint8_t encoder_read_pads_from(uint8_t index, bool pad_b, matrix_row_t mat[]) {
     46     // First two matrix rows:
     47     //
     48     // Pin  A   B   C   D   E   F   G   H
     49     // Left: 
     50     //   { __, __, __, __, __, __, A1, B1 },
     51     //   { A3, B3, A2, B2, __, __, __, __ }
     52     // Right:
     53     //   { A1, B1, __, __, __, __, __, __ },
     54     //   { __, __, __, __, A2, B2, A3, B3 }
     55     //
     56     // See also rev1.h
     57 
     58     bool pad_value = false;
     59 
     60     if (is_keyboard_left()) {
     61         if (index == 0) {
     62             pad_value = pad_b ? mat_is_on(mat, 0, 7) : mat_is_on(mat, 0, 6); // B1, A1 
     63         } else if (index == 1) {
     64             pad_value = pad_b ? mat_is_on(mat, 1, 3) : mat_is_on(mat, 1, 2); // B2, A2
     65         } else if (index == 2) {
     66             pad_value = pad_b ? mat_is_on(mat, 1, 1) : mat_is_on(mat, 1, 0); // B3, A3
     67         }
     68     } else {
     69         if (index == 0) {
     70             pad_value = pad_b ? mat_is_on(mat, 0, 1) : mat_is_on(mat, 0, 0); // B1, A1
     71         } else if (index == 1) {
     72             pad_value = pad_b ? mat_is_on(mat, 1, 5) : mat_is_on(mat, 1, 4); // B2, A2
     73         } else if (index == 2) {
     74             pad_value = pad_b ? mat_is_on(mat, 1, 7) : mat_is_on(mat, 1, 6); // B3, A3
     75         }
     76     }
     77 
     78     return pad_value ? 1 : 0;
     79 }
     80 
     81 void encoder_quadrature_init_pin(uint8_t index, bool pad_b) {
     82     // At this point the first matrix scan hasn't happened yet,
     83     // so we can't use raw_matrix to initialize our encoder state
     84     // as it contains all zeroes - so we have to do our own first scan
     85     // The pins for myriad are initialized in myriad.c
     86 
     87     matrix_row_t mat[MATRIX_ROWS];
     88 
     89     encoder_read_pads_from(index, pad_b, mat);
     90 }
     91 
     92 extern matrix_row_t raw_matrix[MATRIX_ROWS]; // From quantum/matrix_common.c
     93 
     94 uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b) {
     95     // The matrix code already keeps the raw matrix up-to-date,
     96     // so we only have to read the values from it
     97     if(index <= 2) {
     98         return encoder_read_pads_from(index, pad_b, raw_matrix);
     99     } else {
    100         #ifdef MYRIAD_ENABLE
    101             return myriad_hook_encoder(index, pad_b);
    102         #endif
    103         return 0;
    104     }
    105     return 0;
    106 }
    107 
    108 //// Default functionality
    109 
    110 #ifdef OLED_ENABLE
    111 oled_rotation_t oled_init_kb(oled_rotation_t rotation) {
    112     if (is_keyboard_left()) {
    113         return OLED_ROTATION_270;
    114     } else {
    115         return OLED_ROTATION_90;
    116     }
    117 }
    118 
    119 bool oled_task_kb(void) {
    120     if (!oled_task_user()) {
    121         return false;
    122     }
    123 
    124     if (!is_oled_enabled) {
    125         oled_off();
    126         return false;
    127     } else  {
    128         oled_on();
    129     }
    130 
    131     if (is_keyboard_master()) {
    132         oled_write_P(PSTR("Elora rev1\n\n"), false);
    133 
    134         // Keyboard Layer Status
    135         // Ideally we'd print the layer name, but no way to know that for sure
    136         // Fallback option: just print the layer number
    137         uint8_t layer = get_highest_layer(layer_state | default_layer_state);
    138         oled_write_P(PSTR("Layer: "), false);
    139         oled_write(get_u8_str(layer, ' '), false);
    140 
    141         // Keyboard LED Status
    142         led_t led_state = host_keyboard_led_state();
    143         oled_write_P(led_state.num_lock ? PSTR(" NUM") : PSTR("    "), false);
    144         oled_write_P(led_state.caps_lock ? PSTR("CAP") : PSTR("   "), false);
    145         oled_write_P(led_state.scroll_lock ? PSTR("SCR") : PSTR("   "), false);
    146 
    147         // QMK Logo
    148         // clang-format off
    149         static const char PROGMEM qmk_logo[] = {
    150             0x81,0x82,0x83,0x84,0x0a,
    151             0xa1,0xa2,0xa3,0xa4,0x85,0x86,0x87,0x88,0x89,0x0a,
    152             0xc1,0xc2,0xc3,0xc4,0xa5,0xa6,0xa7,0xa8,0xa9,0x0a,
    153             0x8a,0x8b,0x8c,0x8d,0xc5,0xc6,0xc7,0xc8,0xc9,0x0a,
    154             0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0x00
    155         };
    156         // clang-format on
    157         oled_set_cursor(0, oled_max_lines()-5);
    158         oled_write_P(qmk_logo, false);
    159     } else {
    160         // Elora sigil
    161         // clang-format off
    162         static const char PROGMEM elora_logo[] = {
    163             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128,128,192,224,224,240,248,120, 56, 60,188,158,158,222,206,207,207,207,239,239,239,239,239,239,207,207,207,206,222,158,158,188, 60, 56,120,248,240,224,224,192,128,128,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,192,224,248,252,126, 31,143,199,227,243,249,124, 60, 30, 31, 15,  7,  7,  3,  3,  3,131,193,225,241,249,253,255,255,255,255,127, 63, 31, 15,  7,  7,  7,143,223,254,252,252,249,243,227,199,143, 31,126,252,248,224,192,  0,  0,  0,  0,  0,
    164             0,192,240,254,255, 63,  7,227,248,252,127, 31, 15,  3,  1,  0,  0,  0,128,192,224,240,248,252,254,255,255,255,127, 63, 31, 15,  7,  3,  1,128,192,224,240,248,252,254,255,255,255,255,127, 63, 31, 15,  7, 15, 31,255,252,248,227,  7, 63,255,254,240,192,  0,252,255,255,255,  1,224,255,255,255,  7,  0,  0,  0,  0,  0,  0,  0,  0, 31, 31, 31, 31, 31, 15,  7,  3,  1,  0,  0,  0,240,248,252,254,255,255,255,255,127, 63, 31, 15,  7,  3,  1,128,192,224,240,248,252,254,255,255,255,255,255,255,224,  1,255,255,255,252,
    165             63,255,255,255,128,  7,255,255,255,224,  0,  0,  0,  0,  0,  0,  0,  0,  0,128,192,224,240,248,248,248,248,248,248,  0,  3,  3,  3,  3,  3,  3,  1,128,192,224,240,248,252,254,255,255,255,127, 63, 31, 15,  7,  3,  1,224,255,255,255,  7,128,255,255,255, 63,  0,  3, 15,127,255,252,224,199, 31, 63,254,248,240,192,128,  0,  0,  0,  0, 31, 31, 31, 31, 31, 31, 15,  7,  3,  1,  0,  0,  0,  0,  0,  0, 62, 63, 63, 63, 63, 63, 31, 15,  7,  3,  1,  0,  0,  0,128,192,240,248,254, 63, 31,199,224,252,255,127, 15,  3,  0, 
    166             0,  0,  0,  0,  0,  3,  7, 31, 63,126,248,241,227,199,207,159, 62, 60,120,248,240,224,224,192,192,192,192,128,128,128,128,128,128,128,128,128,128,192,192,192,192,224,224,240,248,120, 60, 62,159,207,199,227,241,248,126, 63, 31,  7,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  3,  7,  7, 15, 31, 30, 28, 60, 61,121,121,123,115,243,243,243,247,247,247,247,247,247,243,243,243,115,123,121,121, 61, 60, 28, 30, 31, 15,  7,  7,  3,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    167         };
    168         // clang-format on
    169         oled_set_cursor(0, (oled_max_lines()/2)-4); // logo is 8 lines high, so center vertically
    170         oled_write_raw_P(elora_logo, sizeof(elora_logo));
    171     }
    172 
    173     return false;
    174 }
    175 
    176 void housekeeping_task_kb(void) {
    177     is_oled_enabled = last_input_activity_elapsed() < 60000;
    178 }
    179 #endif
    180 
    181 #ifdef ENCODER_ENABLE
    182 bool encoder_update_kb(uint8_t index, bool clockwise) {
    183     if (!encoder_update_user(index, clockwise)) {
    184         return false;
    185     }
    186 
    187     if (index == 0 || index == 1 || index == 2) {
    188         // Left side
    189         // Arrow keys
    190         if (clockwise) {
    191             tap_code(KC_RIGHT);
    192         } else {
    193             tap_code(KC_LEFT);
    194         }
    195     } else if (index == 4 || index == 5 || index == 6) {
    196         // Right side
    197         // Page up/Page down
    198         if (clockwise) {
    199             tap_code(KC_PGDN);
    200         } else {
    201             tap_code(KC_PGUP);
    202         }
    203     } else if (index == 3 || index == 7) {
    204         // Myriad
    205         // Volume control
    206         if (clockwise) {
    207             tap_code(KC_VOLU);
    208         } else {
    209             tap_code(KC_VOLD);
    210         }
    211     }
    212     return true;
    213 }
    214 #endif