qmk_firmware

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

700e.c (10766B)


      1 /**
      2  * @file 700e.c
      3  *
      4     Copyright 2022 astro
      5 
      6     This program is free software: you can redistribute it and/or modify
      7     it under the terms of the GNU General Public License as published by
      8     the Free Software Foundation, either version 2 of the License, or
      9     (at your option) any later version.
     10 
     11     This program is distributed in the hope that it will be useful,
     12     but WITHOUT ANY WARRANTY; without even the implied warranty of
     13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14     GNU General Public License for more details.
     15 
     16     You should have received a copy of the GNU General Public License
     17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18  */
     19 
     20 #include "quantum.h"
     21 
     22 #ifdef RGBLIGHT_ENABLE
     23 #    include "i2c_master.h"
     24 #    include "drivers/led/issi/is31fl3731.h"
     25 #    include "ws2812.h"
     26 
     27 enum {
     28     SELF_TESTING,
     29     CAPS_ALERT,
     30     NORMAL,
     31 };
     32 
     33 enum {
     34     ST_STAGE_1,
     35     ST_STAGE_2,
     36     ST_STAGE_3,
     37 };
     38 
     39 // alert state update interval
     40 #define ALERT_INTERVAL      500
     41 // self testing state update interval
     42 #define ST_INTERVAL         100
     43 // self testing start index
     44 #define ST_DEFAULT_INDEX    15
     45 // self testing stage delay
     46 #define ST_STAGE_DELAY      10
     47 // self testing stage cycle count
     48 #define ST_STAGE_COUNT      4
     49 // self testing stage end duration
     50 #define ST_END_DURATION     10
     51 
     52 // led index
     53 #define ST_LEFT_BEGIN       0
     54 #ifdef IS31FL3731_I2C_ADDRESS_2
     55 #define ST_LEFT_SIZE        4
     56 #else
     57 #define ST_LEFT_SIZE        2
     58 #endif
     59 #define ST_LEFT_END         (ST_LEFT_BEGIN+ST_LEFT_SIZE-1)
     60 #ifdef IS31FL3731_I2C_ADDRESS_2
     61 #define ST_RIGHT_BEGIN      60
     62 #else
     63 #define ST_RIGHT_BEGIN      30
     64 #endif
     65 #ifdef IS31FL3731_I2C_ADDRESS_2
     66 #define ST_RIGHT_SIZE       4
     67 #else
     68 #define ST_RIGHT_SIZE       2
     69 #endif
     70 #define ST_RIGHT_END        (ST_RIGHT_BEGIN+ST_RIGHT_SIZE-1)
     71 
     72 
     73 typedef struct {
     74     uint8_t state;
     75     uint8_t testing;
     76     bool    alert;
     77     uint8_t index;
     78     uint8_t delay;
     79     uint8_t count;
     80     bool    dir;
     81     uint8_t duration;
     82     uint16_t ticks;
     83 } rgb_state_t;
     84 
     85 static rgb_state_t rgb_state = {
     86     .state = //NORMAL,
     87     SELF_TESTING,
     88     .testing = ST_STAGE_1,
     89     .ticks = 0,
     90     .alert = false,
     91     .index = ST_DEFAULT_INDEX,
     92     .delay = ST_STAGE_DELAY,
     93     .count = ST_STAGE_COUNT,
     94     .dir = true,
     95     .duration = ST_END_DURATION,
     96 };
     97 
     98 static void update_ticks(void)
     99 {
    100     rgb_state.ticks = timer_read();
    101 }
    102 
    103 static void self_testing(void)
    104 {
    105     if (timer_elapsed(rgb_state.ticks) < ST_INTERVAL) return;
    106     hsv_t hsv = rgblight_get_hsv();
    107 
    108     rgb_t led = hsv_to_rgb(hsv);
    109     switch(rgb_state.testing) {
    110         case ST_STAGE_1:
    111             if (rgb_state.index !=0 ) {
    112                 is31fl3731_set_color_all(0, 0, 0);
    113             }
    114 
    115             if (rgb_state.index >= ST_LEFT_END) {
    116                 for (int i = rgb_state.index - 1; i < IS31FL3731_LED_COUNT - rgb_state.index + 1; i++) {
    117                     is31fl3731_set_color(i, led.r, led.g, led.b);
    118                 }
    119                 if (rgb_state.index == ST_LEFT_END) {
    120                     rgb_state.index = ST_LEFT_BEGIN;
    121                 } else {
    122                     rgb_state.index -= ST_LEFT_SIZE;
    123                 }
    124             } else{
    125                 if (rgb_state.delay > 0) {
    126                     rgb_state.delay--;
    127                 } else {
    128                     // move to stage 2
    129                     rgb_state.index = ST_LEFT_BEGIN+ST_LEFT_SIZE;
    130                     rgb_state.testing = ST_STAGE_2;
    131                 }
    132             }
    133         break;
    134         case ST_STAGE_2: {
    135             // clear all
    136             is31fl3731_set_color_all(0, 0, 0);
    137             int i = 0;
    138             // light left and right
    139             for (i = 0; i < ST_LEFT_SIZE; i++) {
    140                 is31fl3731_set_color(ST_LEFT_BEGIN+i, led.r, led.g, led.b);
    141             }
    142             for (i = 0; i < ST_RIGHT_SIZE; i++) {
    143                 is31fl3731_set_color(ST_RIGHT_BEGIN+i, led.r, led.g, led.b);
    144 
    145             }
    146             if (rgb_state.dir) {
    147                 // left to right
    148                 for (int i = rgb_state.index; i < rgb_state.index+ST_LEFT_SIZE+ST_RIGHT_SIZE; i++) {
    149                     is31fl3731_set_color(i, led.r, led.g, led.b);
    150                 }
    151                 rgb_state.index += ST_LEFT_SIZE+ST_RIGHT_SIZE;
    152                 if (rgb_state.index == ST_RIGHT_BEGIN) {
    153                     rgb_state.dir = !rgb_state.dir;
    154                     rgb_state.count--;
    155                 }
    156             } else {
    157                 // right to left
    158                 for (int i = rgb_state.index - ST_RIGHT_SIZE; i < rgb_state.index; i++) {
    159                     is31fl3731_set_color(i, led.r, led.g, led.b);
    160                 }
    161                 rgb_state.index -= ST_LEFT_SIZE + ST_RIGHT_SIZE;
    162                 if (rgb_state.index == ST_LEFT_BEGIN+ST_LEFT_SIZE) {
    163                     rgb_state.dir = !rgb_state.dir;
    164                     rgb_state.count--;
    165                 }
    166             }
    167 
    168             if (rgb_state.count == 0) {
    169                 // move to stage 3
    170                 rgb_state.testing = ST_STAGE_3;
    171                 rgb_state.index = 0;
    172                 rgb_state.delay = ST_STAGE_DELAY;
    173                 rgb_state.duration = ST_END_DURATION;
    174             }
    175         }
    176         break;
    177         case ST_STAGE_3:
    178             if (rgb_state.index != IS31FL3731_LED_COUNT/2) {
    179                 is31fl3731_set_color_all(0, 0, 0);
    180             }
    181 
    182             // light left and right
    183 
    184             if (rgb_state.index == IS31FL3731_LED_COUNT/2) {
    185                 if (rgb_state.duration) {
    186                     rgb_state.duration--;
    187                 } else {
    188                     if (host_keyboard_led_state().caps_lock) {
    189                         rgb_state.state = CAPS_ALERT;
    190                     } else {
    191                         rgb_state.state = NORMAL;
    192                         rgblight_set();
    193                     }
    194                 }
    195             } else {
    196                 // left
    197                 for (int i = 0; i < rgb_state.index+1; i++) {
    198                     is31fl3731_set_color(i, led.r, led.g, led.b);
    199                 }
    200                 // right
    201                 for (int i = ST_RIGHT_END; i > ST_RIGHT_END - rgb_state.index - 1; i--) {
    202                     is31fl3731_set_color(i, led.r, led.g, led.b);
    203                 }
    204                 rgb_state.index ++;
    205             }
    206         break;
    207     }
    208 
    209     update_ticks();
    210 }
    211 
    212 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
    213     /* Refer to IS31 manual for these locations
    214      *   driver
    215      *   |  R location
    216      *   |  |       G location
    217      *   |  |       |       B location
    218      *   |  |       |       | */
    219     // left CA
    220     {0, C1_1, C3_2, C4_2},
    221     {0, C1_2, C2_2, C4_3},
    222     {0, C1_3, C2_3, C3_3},
    223     {0, C1_4, C2_4, C3_4},
    224     {0, C1_5, C2_5, C3_5},
    225     {0, C1_6, C2_6, C3_6},
    226     {0, C1_7, C2_7, C3_7},
    227     {0, C1_8, C2_8, C3_8},
    228 
    229     {0, C9_1, C8_1, C7_1},
    230     {0, C9_2, C8_2, C7_2},
    231     {0, C9_3, C8_3, C7_3},
    232     {0, C9_4, C8_4, C7_4},
    233     {0, C9_5, C8_5, C7_5},
    234     {0, C9_6, C8_6, C7_6},
    235     {0, C9_7, C8_7, C6_6},
    236     {0, C9_8, C7_7, C6_7},
    237     // left CB
    238     {0, C1_9, C3_10, C4_10},
    239     {0, C1_10, C2_10, C4_11},
    240     {0, C1_11, C2_11, C3_11},
    241     {0, C1_12, C2_12, C3_12},
    242     {0, C1_13, C2_13, C3_13},
    243     {0, C1_14, C2_14, C3_14},
    244     {0, C1_15, C2_15, C3_15},
    245     {0, C1_16, C2_16, C3_16},
    246 
    247     {0, C9_9, C8_9, C7_9},
    248     {0, C9_10, C8_10, C7_10},
    249     {0, C9_11, C8_11, C7_11},
    250     {0, C9_12, C8_12, C7_12},
    251     {0, C9_13, C8_13, C7_13},
    252     {0, C9_14, C8_14, C7_14},
    253     {0, C9_15, C8_15, C6_14},
    254     {0, C9_16, C7_15, C6_15},
    255 
    256     // right CA
    257     {1, C1_1, C3_2, C4_2},
    258     {1, C1_2, C2_2, C4_3},
    259     {1, C1_3, C2_3, C3_3},
    260     {1, C1_4, C2_4, C3_4},
    261     {1, C1_5, C2_5, C3_5},
    262     {1, C1_6, C2_6, C3_6},
    263     {1, C1_7, C2_7, C3_7},
    264     {1, C1_8, C2_8, C3_8},
    265 
    266     {1, C9_1, C8_1, C7_1},
    267     {1, C9_2, C8_2, C7_2},
    268     {1, C9_3, C8_3, C7_3},
    269     {1, C9_4, C8_4, C7_4},
    270     {1, C9_5, C8_5, C7_5},
    271     {1, C9_6, C8_6, C7_6},
    272     {1, C9_7, C8_7, C6_6},
    273     {1, C9_8, C7_7, C6_7},
    274     // right CB
    275     {1, C1_9, C3_10, C4_10},
    276     {1, C1_10, C2_10, C4_11},
    277     {1, C1_11, C2_11, C3_11},
    278     {1, C1_12, C2_12, C3_12},
    279     {1, C1_13, C2_13, C3_13},
    280     {1, C1_14, C2_14, C3_14},
    281     {1, C1_15, C2_15, C3_15},
    282     {1, C1_16, C2_16, C3_16},
    283 
    284     {1, C9_9, C8_9, C7_9},
    285     {1, C9_10, C8_10, C7_10},
    286     {1, C9_11, C8_11, C7_11},
    287     {1, C9_12, C8_12, C7_12},
    288     {1, C9_13, C8_13, C7_13},
    289     {1, C9_14, C8_14, C7_14},
    290     {1, C9_15, C8_15, C6_14},
    291     {1, C9_16, C7_15, C6_15},
    292 };
    293 
    294 void matrix_init_kb(void)
    295 {
    296     gpio_set_pin_output(LED_CAPS_LOCK_PIN);
    297     gpio_write_pin_low(LED_CAPS_LOCK_PIN);
    298 
    299 
    300     update_ticks();
    301     matrix_init_user();
    302 }
    303 
    304 #define ALERM_LED_R     0xFF
    305 #define ALERM_LED_G     0xA5
    306 #define ALERM_LED_B     0x00
    307 //golden 0xFF, 0xD9, 0x00
    308 
    309 void housekeeping_task_kb(void)
    310 {
    311     if (rgb_state.state == SELF_TESTING) {
    312         self_testing();
    313     } else if (rgb_state.state == CAPS_ALERT) {
    314         if (rgb_state.alert) {
    315             is31fl3731_set_color_all(ALERM_LED_R, ALERM_LED_G, ALERM_LED_B);
    316             ws2812_set_color_all(ALERM_LED_G, ALERM_LED_R, ALERM_LED_B);
    317         } else {
    318             is31fl3731_set_color_all(0, 0, 0);
    319             ws2812_set_color_all(0, 0, 0);
    320         }
    321 
    322         if (timer_elapsed(rgb_state.ticks) > ALERT_INTERVAL) {
    323             rgb_state.alert = !rgb_state.alert;
    324             update_ticks();
    325         }
    326     }
    327 
    328     is31fl3731_flush();
    329     ws2812_flush();
    330 }
    331 
    332 void init_custom(void) {
    333     is31fl3731_init_drivers();
    334     ws2812_init();
    335 }
    336 
    337 void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
    338     if (index < IS31FL3731_LED_COUNT) {
    339         is31fl3731_set_color(index, red, green, blue);
    340     } else if (index < IS31FL3731_LED_COUNT + WS2812_LED_COUNT) {
    341         ws2812_set_color(index - IS31FL3731_LED_COUNT, green, red, blue);
    342     }
    343 }
    344 
    345 void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
    346     for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
    347         set_color_custom(i, red, green, blue);
    348     }
    349 }
    350 
    351 void flush_custom(void) {
    352     if (rgb_state.state != NORMAL) return;
    353 
    354     is31fl3731_flush();
    355     ws2812_flush();
    356 }
    357 
    358 const rgblight_driver_t rgblight_driver = {
    359     .init          = init_custom,
    360     .set_color     = set_color_custom,
    361     .set_color_all = set_color_all_custom,
    362     .flush         = flush_custom,
    363 };
    364 
    365 bool led_update_kb(led_t led_state)
    366 {
    367     bool res = led_update_user(led_state);
    368     if (res) {
    369         gpio_write_pin(LED_CAPS_LOCK_PIN, led_state.caps_lock);
    370 
    371         if (rgb_state.state != SELF_TESTING) {
    372             if (led_state.caps_lock) {
    373                 rgb_state.state = CAPS_ALERT;
    374                 update_ticks();
    375             } else {
    376                 rgb_state.state = NORMAL;
    377                 rgblight_set();
    378             }
    379         }
    380     }
    381     return res;
    382 }
    383 
    384 #endif