qmk_firmware

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

mschwingen.c (6532B)


      1 /*
      2  * Copyright 2020 Michael Schwingen
      3 
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 #include <util/delay.h>
     18 #include "mschwingen.h"
     19 #include "uart.h"
     20 #include "print.h"
     21 #include "sendchar.h"
     22 #include "sleep_led.h"
     23 
     24 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
     25 #include "ws2812.h"
     26 #endif
     27 
     28 #ifdef UART_DEBUG
     29 #    undef sendchar
     30 static int8_t capture_sendchar(uint8_t c) {
     31     //  sendchar(c);
     32     uart_write(c);
     33     return 0;
     34 }
     35 #endif
     36 
     37 static uint16_t blink_cycle_timer;
     38 static bool     blink_state = false;
     39 static uint8_t  isRecording = 0;
     40 
     41 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
     42 #    if RGBLIGHT_LED_COUNT < 3
     43 #        error we need at least 3 RGB LEDs!
     44 #    endif
     45 
     46 #    define BRIGHT 32
     47 #    define DIM 6
     48 
     49 static led_t   led_state;
     50 static uint8_t layer;
     51 static uint8_t default_layer;
     52 #endif
     53 
     54 // we need our own sleep_led_* implementation to get callbacks on USB
     55 // suspend/resume in order to completely turn off WS2812 LEDs
     56 static bool suspend_active = false;
     57 void sleep_led_init(void) {}
     58 
     59 void sleep_led_toggle(void) {}
     60 
     61 void sleep_led_disable(void) {
     62     suspend_active = false;
     63     gpio_write_pin_high(MODELM_STATUS_LED);
     64 }
     65 
     66 void sleep_led_enable(void) {
     67     suspend_active = true;
     68     gpio_write_pin_low(MODELM_STATUS_LED);
     69 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
     70     ws2812_set_color_all(0, 0, 0);
     71     ws2812_flush();
     72 #endif
     73 }
     74 
     75 void keyboard_pre_init_kb(void) {
     76 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
     77     ws2812_init();
     78     ws2812_flush();
     79 #else
     80     /* Set status LEDs pins to output and Low (on) */
     81     gpio_set_pin_output(MODELM_LED_CAPSLOCK);
     82     gpio_set_pin_output(MODELM_LED_SCROLLOCK);
     83     gpio_set_pin_output(MODELM_LED_NUMLOCK);
     84     gpio_write_pin_low(MODELM_LED_CAPSLOCK);
     85     gpio_write_pin_low(MODELM_LED_SCROLLOCK);
     86     gpio_write_pin_low(MODELM_LED_NUMLOCK);
     87 #endif
     88     gpio_set_pin_output(MODELM_STATUS_LED);
     89     gpio_write_pin_high(MODELM_STATUS_LED);
     90     _delay_ms(50);
     91 #ifdef UART_DEBUG
     92     uart_init(115200);
     93     print_set_sendchar(capture_sendchar);
     94     uprintf("\r\nHello world!\r\n");
     95 #endif
     96 
     97     gpio_set_pin_output(SR_LOAD_PIN);
     98     gpio_set_pin_output(SR_CLK_PIN);
     99     gpio_set_pin_output(SR_DOUT_PIN);  // MOSI - unused
    100     gpio_write_pin_low(SR_CLK_PIN);
    101 
    102     keyboard_pre_init_user();
    103 }
    104 
    105 #ifdef KEYBOARD_ibm_model_m_mschwingen_led_ws2812
    106 static void led_update_rgb(void) {
    107     if (isRecording && blink_state) {
    108         ws2812_set_color(0, BRIGHT, BRIGHT, BRIGHT);
    109     } else {
    110         switch (default_layer) {
    111             case 0:
    112                 if (led_state.num_lock) {
    113                     ws2812_set_color(0, 0, 0, BRIGHT);
    114                 } else {
    115                     ws2812_set_color(0, 0, 0, DIM);
    116                 }
    117                 break;
    118             case 1:
    119                 if (led_state.num_lock) {
    120                     ws2812_set_color(0, 0, BRIGHT, 0);
    121                 } else {
    122                     ws2812_set_color(0, 0, 0, 0);
    123                 }
    124                 break;
    125         }
    126     }
    127 
    128     if (led_state.caps_lock) {
    129         ws2812_set_color(1, 0, BRIGHT, 0);
    130     } else {
    131         ws2812_set_color(1, 0, 0, 0);
    132     }
    133 
    134     switch (layer) {
    135         case 0:
    136         case 1:
    137         default:
    138             if (led_state.scroll_lock) {
    139                 ws2812_set_color(2, 0, BRIGHT, 0);
    140             } else {
    141                 ws2812_set_color(2, 0, 0, 0);
    142             }
    143             break;
    144         case 2:
    145             if (led_state.scroll_lock) {
    146                 ws2812_set_color(2, BRIGHT, 0, 0);
    147             } else {
    148                 ws2812_set_color(2, DIM, 0, 0);
    149             }
    150             break;
    151         case 3:
    152             if (led_state.scroll_lock) {
    153                 ws2812_set_color(2, 0, BRIGHT, BRIGHT);
    154             } else {
    155                 ws2812_set_color(2, 0, DIM, DIM);
    156             }
    157             break;
    158     }
    159     if (!suspend_active) {
    160         ws2812_flush();
    161     }
    162 }
    163 
    164 bool led_update_kb(led_t state) {
    165     dprintf("LED Update: %d %d %d", led_state.num_lock, led_state.caps_lock, led_state.scroll_lock);
    166     led_state = state;
    167     led_update_rgb();
    168 
    169     return true;
    170 }
    171 
    172 void update_layer_leds(void) {
    173     static uint8_t old_layer         = 255;
    174     static uint8_t old_default_layer = 255;
    175 
    176     layer         = get_highest_layer(layer_state);
    177     default_layer = get_highest_layer(default_layer_state);
    178 
    179     if (isRecording && timer_elapsed(blink_cycle_timer) > 150) {
    180         blink_state       = !blink_state;
    181         blink_cycle_timer = timer_read();
    182         old_layer         = 255;  // fallthrough next check
    183     }
    184 
    185     if (layer == old_layer && default_layer == old_default_layer) {
    186 	return;
    187     }
    188     old_layer         = layer;
    189     old_default_layer = default_layer;
    190     dprintf("Layer change: %d %d", default_layer, layer);
    191     led_update_rgb();
    192 }
    193 
    194 /*****************************************************************************/
    195 #else  // classic LEDs on GPIO
    196 bool led_update_kb(led_t led_state) {
    197     dprintf("LED Update: %d %d %d", led_state.num_lock, led_state.caps_lock, led_state.scroll_lock);
    198 
    199     if (led_update_user(led_state)) {
    200         if (!isRecording) gpio_write_pin(MODELM_LED_NUMLOCK, !led_state.num_lock);
    201         gpio_write_pin(MODELM_LED_CAPSLOCK, !led_state.caps_lock);
    202         gpio_write_pin(MODELM_LED_SCROLLOCK, !led_state.scroll_lock);
    203     }
    204     return true;
    205 }
    206 
    207 void update_layer_leds(void) {
    208     if (isRecording && timer_elapsed(blink_cycle_timer) > 150) {
    209         blink_state = !blink_state;
    210         blink_cycle_timer = timer_read();
    211         gpio_write_pin(MODELM_LED_NUMLOCK, blink_state);
    212     }
    213 }
    214 
    215 #endif
    216 
    217 bool dynamic_macro_record_start_kb(int8_t direction) {
    218     if (!dynamic_macro_record_start_user(direction)) {
    219         return false;
    220     }
    221     isRecording++;
    222     blink_cycle_timer = timer_read();
    223     return true;
    224 }
    225 
    226 bool dynamic_macro_record_end_kb(int8_t direction) {
    227     if (!dynamic_macro_record_end_user(direction)) {
    228         return false;
    229     }
    230     if (isRecording) isRecording--;
    231     return true;
    232 }