qmk_firmware

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

satisfaction_core.c (9904B)


      1 // Copyright 2023 Andrew Kannan
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 
      4 #include "satisfaction_core.h"
      5 #include "print.h"
      6 #include "debug.h"
      7 #include "matrix.h"
      8 #include "quantum.h"
      9 #include "encoder.h"
     10 
     11 #include <ch.h>
     12 #include <hal.h>
     13 
     14 #include "timer.h"
     15 
     16 #include "raw_hid.h"
     17 #include "dynamic_keymap.h"
     18 #include "eeprom.h"
     19 #include "version.h" // for QMK_BUILDDATE used in EEPROM magic
     20 
     21 /* Artificial delay added to get media keys to work in the encoder*/
     22 #define MEDIA_KEY_DELAY 10
     23 
     24 volatile uint8_t led_numlock = false;
     25 volatile uint8_t led_capslock = false;
     26 volatile uint8_t led_scrolllock = false;
     27 
     28 uint8_t layer;
     29 
     30 bool clock_set_mode = false;
     31 uint8_t oled_mode = OLED_DEFAULT;
     32 bool oled_repaint_requested = false;
     33 bool oled_wakeup_requested = false;
     34 uint32_t oled_sleep_timer;
     35 
     36 uint8_t encoder_value = 32;
     37 uint8_t encoder_mode = ENC_MODE_VOLUME;
     38 uint8_t enabled_encoder_modes = 0x1F;
     39 
     40 RTCDateTime last_timespec;
     41 uint16_t last_minute = 0;
     42 
     43 uint8_t time_config_idx = 0;
     44 int8_t hour_config = 0;
     45 int16_t minute_config = 0;
     46 int8_t year_config = 0;
     47 int8_t month_config = 0;
     48 int8_t day_config = 0;
     49 uint8_t previous_encoder_mode = 0;
     50 
     51 void board_init(void) {
     52   SYSCFG->CFGR1 |= SYSCFG_CFGR1_I2C1_DMA_RMP;
     53   SYSCFG->CFGR1 &= ~(SYSCFG_CFGR1_SPI2_DMA_RMP);
     54 }
     55 
     56 uint32_t read_custom_config(void *data, uint32_t offset, uint32_t length) {
     57 #ifdef VIA_ENABLE
     58     return via_read_custom_config(data, offset, length);
     59 #else
     60     return eeconfig_read_kb_datablock(data, offset, length);
     61 #endif
     62 }
     63 
     64 uint32_t write_custom_config(const void *data, uint32_t offset, uint32_t length) {
     65 #ifdef VIA_ENABLE
     66     return via_update_custom_config(data, offset, length);
     67 #else
     68     return eeconfig_update_kb_datablock(data, offset, length);
     69 #endif
     70 }
     71 
     72 void keyboard_post_init_kb(void) {
     73       /*
     74         This is a workaround to some really weird behavior
     75         Without this code, the OLED will turn on, but not when you initially plug the keyboard in.
     76         You have to manually trigger a user reset to get the OLED to initialize properly
     77         I'm not sure what the root cause is at this time, but this workaround fixes it.
     78     */
     79     #ifdef OLED_ENABLE
     80     if(!is_oled_on()){
     81         wait_ms(3000);
     82         oled_init(OLED_ROTATION_0);
     83     }
     84     #endif
     85 
     86     keyboard_post_init_user();
     87 }
     88 
     89 #ifdef VIA_ENABLE
     90 void custom_set_value(uint8_t *data) {
     91     uint8_t *value_id = &(data[0]);
     92     uint8_t *value_data = &(data[1]);
     93 
     94     switch ( *value_id ) {
     95         case id_oled_default_mode:
     96         {
     97             write_custom_config(&value_data[0], EEPROM_DEFAULT_OLED_OFFSET, 1);
     98             break;
     99         }
    100         case id_oled_mode:
    101         {
    102             oled_mode = value_data[0];
    103             oled_request_wakeup();
    104             break;
    105         }
    106         case id_encoder_modes:
    107         {
    108             uint8_t index = value_data[0];
    109             uint8_t enable = value_data[1];
    110             enabled_encoder_modes = (enabled_encoder_modes & ~(1<<index)) | (enable<<index);
    111             write_custom_config(&enabled_encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
    112             break;
    113         }
    114         case id_encoder_custom:
    115         {
    116             uint8_t custom_encoder_idx = value_data[0];
    117             uint8_t encoder_behavior = value_data[1];
    118             uint16_t keycode = (value_data[2] << 8) | value_data[3];
    119             set_custom_encoder_config(custom_encoder_idx, encoder_behavior, keycode);
    120             break;
    121         }
    122     }
    123 }
    124 
    125 void custom_get_value(uint8_t *data) {
    126     uint8_t *value_id = &(data[0]);
    127     uint8_t *value_data = &(data[1]);
    128 
    129     switch ( *value_id ) {
    130         case id_oled_default_mode:
    131         {
    132             uint8_t default_oled;
    133             read_custom_config(&default_oled, EEPROM_DEFAULT_OLED_OFFSET, 1);
    134             value_data[0] = default_oled;
    135             break;
    136         }
    137         case id_oled_mode:
    138         {
    139             value_data[0] = oled_mode;
    140             break;
    141         }
    142         case id_encoder_modes:
    143         {
    144             uint8_t index = value_data[0];
    145             value_data[1] = (enabled_encoder_modes & (1<<index)) ? 1 : 0;
    146             break;
    147         }
    148         case id_encoder_custom:
    149         {
    150             uint8_t custom_encoder_idx = value_data[0];
    151             uint8_t encoder_behavior = value_data[1];
    152             uint16_t keycode = retrieve_custom_encoder_config(custom_encoder_idx, encoder_behavior);
    153             value_data[2] = keycode >> 8;
    154             value_data[3] = keycode & 0xFF;
    155             break;
    156         }
    157     }
    158 }
    159 
    160 void via_custom_value_command_kb(uint8_t *data, uint8_t length) {
    161     uint8_t *command_id        = &(data[0]);
    162     uint8_t *channel_id        = &(data[1]);
    163     uint8_t *value_id_and_data = &(data[2]);
    164 
    165     if ( *channel_id == id_custom_channel ) {
    166         switch ( *command_id )
    167         {
    168             case id_custom_set_value:
    169             {
    170                 custom_set_value(value_id_and_data);
    171                 break;
    172             }
    173             case id_custom_get_value:
    174             {
    175                 custom_get_value(value_id_and_data);
    176                 break;
    177             }
    178             case id_custom_save:
    179             {
    180                 // values are saved in custom_set_value()
    181                 break;
    182             }
    183             default:
    184             {
    185                 // Unhandled message.
    186                 *command_id = id_unhandled;
    187                 break;
    188             }
    189         }
    190         return;
    191     }
    192 
    193     *command_id = id_unhandled;
    194 
    195     // DO NOT call raw_hid_send(data,length) here, let caller do this
    196 }
    197 #endif
    198 
    199 void read_host_led_state(void) {
    200   led_t led_state = host_keyboard_led_state();
    201   if (led_state.num_lock)    {
    202     if (led_numlock == false){
    203     led_numlock = true;}
    204     } else {
    205     if (led_numlock == true){
    206     led_numlock = false;}
    207     }
    208   if (led_state.caps_lock)   {
    209     if (led_capslock == false){
    210     led_capslock = true;}
    211     } else {
    212     if (led_capslock == true){
    213     led_capslock = false;}
    214     }
    215   if (led_state.scroll_lock) {
    216     if (led_scrolllock == false){
    217     led_scrolllock = true;}
    218     } else {
    219     if (led_scrolllock == true){
    220     led_scrolllock = false;}
    221     }
    222 }
    223 
    224 layer_state_t layer_state_set_kb(layer_state_t state) {
    225   state = layer_state_set_user(state);
    226   layer = get_highest_layer(state);
    227   oled_request_wakeup();
    228   return state;
    229 }
    230 
    231 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
    232   oled_request_wakeup();
    233   switch (keycode) {
    234     case OLED_TOGG:
    235       if(!clock_set_mode){
    236         if (record->event.pressed) {
    237           oled_mode = (oled_mode + 1) % _NUM_OLED_MODES;
    238         }
    239       }
    240       return false;
    241     case CLOCK_SET:
    242       if (record->event.pressed) {
    243         if(clock_set_mode){
    244           pre_encoder_mode_change();
    245           clock_set_mode = false;
    246           encoder_mode = previous_encoder_mode;
    247           post_encoder_mode_change();
    248 
    249         }else{
    250           previous_encoder_mode = encoder_mode;
    251           pre_encoder_mode_change();
    252           clock_set_mode = true;
    253           encoder_mode = ENC_MODE_CLOCK_SET;
    254           post_encoder_mode_change();
    255         }
    256       }
    257       return false;
    258     case ENC_PRESS:
    259       if (record->event.pressed) {
    260         uint16_t mapped_code = handle_encoder_press();
    261         uint16_t held_keycode_timer = timer_read();
    262         if(mapped_code != 0){
    263           register_code16(mapped_code);
    264           while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
    265           unregister_code16(mapped_code);
    266         }
    267       } else {
    268         // Do something else when release
    269       }
    270       return false;
    271     default:
    272       break;
    273   }
    274 
    275   return process_record_user(keycode, record);
    276 }
    277 
    278 
    279 bool encoder_update_kb(uint8_t index, bool clockwise) {
    280     if (!encoder_update_user(index, clockwise)) return false;
    281     oled_request_wakeup();
    282   encoder_value = (encoder_value + (clockwise ? 1 : -1)) % 64;
    283   if (index == 0) {
    284     if (layer == 0){
    285       uint16_t mapped_code = 0;
    286       if (clockwise) {
    287         mapped_code = handle_encoder_clockwise();
    288       } else {
    289         mapped_code = handle_encoder_ccw();
    290       }
    291       uint16_t held_keycode_timer = timer_read();
    292       if(mapped_code != 0){
    293         register_code16(mapped_code);
    294         while (timer_elapsed(held_keycode_timer) < MEDIA_KEY_DELAY){ /* no-op */ }
    295         unregister_code16(mapped_code);
    296       }
    297     } else {
    298       if(clockwise){
    299         change_encoder_mode(false);
    300       } else {
    301         change_encoder_mode(true);
    302       }
    303     }
    304   }
    305   return true;
    306 }
    307 
    308 void custom_config_reset(void){
    309   for(int i = 0; i < VIA_EEPROM_CUSTOM_CONFIG_SIZE; ++i) {
    310     uint8_t dummy = 0;
    311     write_custom_config(&dummy, i, 1);
    312   }
    313 
    314   uint8_t encoder_modes = 0x1F;
    315   write_custom_config(&encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
    316 }
    317 
    318 void custom_config_load(void){
    319 #ifdef DYNAMIC_KEYMAP_ENABLE
    320   read_custom_config(&oled_mode, EEPROM_DEFAULT_OLED_OFFSET, 1);
    321   read_custom_config(&enabled_encoder_modes, EEPROM_ENABLED_ENCODER_MODES_OFFSET, 1);
    322 #endif
    323 }
    324 
    325 // Called from via_init() if VIA_ENABLE
    326 // Called from matrix_init_kb() if not VIA_ENABLE
    327 void satisfaction_core_init(void)
    328 {
    329   // This checks both an EEPROM reset (from bootmagic lite, keycodes)
    330   // and also firmware build date (from via_eeprom_is_valid())
    331   if (eeconfig_is_enabled()) {
    332     custom_config_load();
    333   } else	{
    334 #ifdef DYNAMIC_KEYMAP_ENABLE
    335     // Reset the custom stuff
    336     custom_config_reset();
    337 #endif
    338     // DO NOT set EEPROM valid here, let caller do this
    339   }
    340 }
    341 
    342 void matrix_init_kb(void)
    343 {
    344 #ifndef VIA_ENABLE
    345   satisfaction_core_init();
    346 #endif // VIA_ENABLE
    347 
    348   rtcGetTime(&RTCD1, &last_timespec);
    349   matrix_init_user();
    350   oled_request_wakeup();
    351 }
    352 
    353 #ifdef VIA_ENABLE
    354 void via_init_kb(void) {
    355     satisfaction_core_init();
    356 }
    357 #endif // VIA_ENABLE
    358 
    359 void housekeeping_task_kb(void) {
    360   rtcGetTime(&RTCD1, &last_timespec);
    361   uint16_t minutes_since_midnight = last_timespec.millisecond / 1000 / 60;
    362 
    363   if (minutes_since_midnight != last_minute){
    364     last_minute = minutes_since_midnight;
    365     oled_request_repaint();
    366   }
    367 }