qmk_firmware

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

n6.c (10707B)


      1 /**
      2  * @file n6.c
      3  *
      4     Copyright 2021 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 extern rgblight_config_t rgblight_config;
     73 
     74 typedef struct {
     75     uint8_t state;
     76     uint8_t testing;
     77     bool    alert;
     78     uint8_t index;
     79     uint8_t delay;
     80     uint8_t count;
     81     bool    dir;
     82     uint8_t duration;
     83     uint16_t ticks;
     84 } rgb_state_t;
     85 
     86 static rgb_state_t rgb_state = {
     87     .state = //NORMAL,
     88     SELF_TESTING,
     89     .testing = ST_STAGE_1,
     90     .ticks = 0,
     91     .alert = false,
     92     .index = ST_DEFAULT_INDEX,
     93     .delay = ST_STAGE_DELAY,
     94     .count = ST_STAGE_COUNT,
     95     .dir = true,
     96     .duration = ST_END_DURATION,
     97 };
     98 
     99 static void update_ticks(void)
    100 {
    101     rgb_state.ticks = timer_read();
    102 }
    103 
    104 static void self_testing(void)
    105 {
    106     if (timer_elapsed(rgb_state.ticks) < ST_INTERVAL) return;
    107     hsv_t hsv;
    108     hsv.h = rgblight_config.hue;
    109     hsv.s = rgblight_config.sat;
    110     hsv.v = rgblight_config.val;
    111 
    112     rgb_t led = hsv_to_rgb(hsv);
    113     switch(rgb_state.testing) {
    114         case ST_STAGE_1:
    115             if (rgb_state.index !=0 ) {
    116                 is31fl3731_set_color_all(0, 0, 0);
    117             }
    118 
    119             if (rgb_state.index >= ST_LEFT_END) {
    120                 for (int i = rgb_state.index - 1; i < IS31FL3731_LED_COUNT - rgb_state.index + 1; i++) {
    121                     is31fl3731_set_color(i, led.r, led.g, led.b);
    122                 }
    123                 if (rgb_state.index == ST_LEFT_END) {
    124                     rgb_state.index = ST_LEFT_BEGIN;
    125                 } else {
    126                     rgb_state.index -= ST_LEFT_SIZE;
    127                 }
    128             } else{
    129                 if (rgb_state.delay > 0) {
    130                     rgb_state.delay--;
    131                 } else {
    132                     // move to stage 2
    133                     rgb_state.index = ST_LEFT_BEGIN+ST_LEFT_SIZE;
    134                     rgb_state.testing = ST_STAGE_2;
    135                 }
    136             }
    137         break;
    138         case ST_STAGE_2: {
    139             // clear all
    140             is31fl3731_set_color_all(0, 0, 0);
    141             int i = 0;
    142             // light left and right
    143             for (i = 0; i < ST_LEFT_SIZE; i++) {
    144                 is31fl3731_set_color(ST_LEFT_BEGIN+i, led.r, led.g, led.b);
    145             }
    146             for (i = 0; i < ST_RIGHT_SIZE; i++) {
    147                 is31fl3731_set_color(ST_RIGHT_BEGIN+i, led.r, led.g, led.b);
    148 
    149             }
    150             if (rgb_state.dir) {
    151                 // left to right
    152                 for (int i = rgb_state.index; i < rgb_state.index+ST_LEFT_SIZE+ST_RIGHT_SIZE; i++) {
    153                     is31fl3731_set_color(i, led.r, led.g, led.b);
    154                 }
    155                 rgb_state.index += ST_LEFT_SIZE+ST_RIGHT_SIZE;
    156                 if (rgb_state.index == ST_RIGHT_BEGIN) {
    157                     rgb_state.dir = !rgb_state.dir;
    158                     rgb_state.count--;
    159                 }
    160             } else {
    161                 // right to left
    162                 for (int i = rgb_state.index - ST_RIGHT_SIZE; i < rgb_state.index; i++) {
    163                     is31fl3731_set_color(i, led.r, led.g, led.b);
    164                 }
    165                 rgb_state.index -= ST_LEFT_SIZE + ST_RIGHT_SIZE;
    166                 if (rgb_state.index == ST_LEFT_BEGIN+ST_LEFT_SIZE) {
    167                     rgb_state.dir = !rgb_state.dir;
    168                     rgb_state.count--;
    169                 }
    170             }
    171 
    172             if (rgb_state.count == 0) {
    173                 // move to stage 3
    174                 rgb_state.testing = ST_STAGE_3;
    175                 rgb_state.index = 0;
    176                 rgb_state.delay = ST_STAGE_DELAY;
    177                 rgb_state.duration = ST_END_DURATION;
    178             }
    179         }
    180         break;
    181         case ST_STAGE_3:
    182             if (rgb_state.index != IS31FL3731_LED_COUNT/2) {
    183                 is31fl3731_set_color_all(0, 0, 0);
    184             }
    185 
    186             // light left and right
    187 
    188             if (rgb_state.index == IS31FL3731_LED_COUNT/2) {
    189                 if (rgb_state.duration) {
    190                     rgb_state.duration--;
    191                 } else {
    192                     if (host_keyboard_led_state().caps_lock) {
    193                         rgb_state.state = CAPS_ALERT;
    194                     } else {
    195                         rgb_state.state = NORMAL;
    196                         rgblight_set();
    197                     }
    198                 }
    199             } else {
    200                 // left
    201                 for (int i = 0; i < rgb_state.index+1; i++) {
    202                     is31fl3731_set_color(i, led.r, led.g, led.b);
    203                 }
    204                 // right
    205                 for (int i = ST_RIGHT_END; i > ST_RIGHT_END - rgb_state.index - 1; i--) {
    206                     is31fl3731_set_color(i, led.r, led.g, led.b);
    207                 }
    208                 rgb_state.index ++;
    209             }
    210         break;
    211     }
    212 
    213     update_ticks();
    214 }
    215 
    216 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
    217     /* Refer to IS31 manual for these locations
    218      *   driver
    219      *   |  R location
    220      *   |  |       G location
    221      *   |  |       |       B location
    222      *   |  |       |       | */
    223     // left CA
    224     {0, C1_1, C3_2, C4_2},
    225     {0, C1_2, C2_2, C4_3},
    226     {0, C1_3, C2_3, C3_3},
    227     {0, C1_4, C2_4, C3_4},
    228     {0, C1_5, C2_5, C3_5},
    229     {0, C1_6, C2_6, C3_6},
    230     {0, C1_7, C2_7, C3_7},
    231     {0, C1_8, C2_8, C3_8},
    232 
    233     {0, C9_1, C8_1, C7_1},
    234     {0, C9_2, C8_2, C7_2},
    235     {0, C9_3, C8_3, C7_3},
    236     {0, C9_4, C8_4, C7_4},
    237     {0, C9_5, C8_5, C7_5},
    238     {0, C9_6, C8_6, C7_6},
    239     {0, C9_7, C8_7, C6_6},
    240     {0, C9_8, C7_7, C6_7},
    241     // left CB
    242     {0, C1_9, C3_10, C4_10},
    243     {0, C1_10, C2_10, C4_11},
    244     {0, C1_11, C2_11, C3_11},
    245     {0, C1_12, C2_12, C3_12},
    246     {0, C1_13, C2_13, C3_13},
    247     {0, C1_14, C2_14, C3_14},
    248     {0, C1_15, C2_15, C3_15},
    249     {0, C1_16, C2_16, C3_16},
    250 
    251     {0, C9_9, C8_9, C7_9},
    252     {0, C9_10, C8_10, C7_10},
    253     {0, C9_11, C8_11, C7_11},
    254     {0, C9_12, C8_12, C7_12},
    255     {0, C9_13, C8_13, C7_13},
    256     {0, C9_14, C8_14, C7_14},
    257     {0, C9_15, C8_15, C6_14},
    258     {0, C9_16, C7_15, C6_15},
    259 
    260     // right CA
    261     {1, C1_1, C3_2, C4_2},
    262     {1, C1_2, C2_2, C4_3},
    263     {1, C1_3, C2_3, C3_3},
    264     {1, C1_4, C2_4, C3_4},
    265     {1, C1_5, C2_5, C3_5},
    266     {1, C1_6, C2_6, C3_6},
    267     {1, C1_7, C2_7, C3_7},
    268     {1, C1_8, C2_8, C3_8},
    269 
    270     {1, C9_1, C8_1, C7_1},
    271     {1, C9_2, C8_2, C7_2},
    272     {1, C9_3, C8_3, C7_3},
    273     {1, C9_4, C8_4, C7_4},
    274     {1, C9_5, C8_5, C7_5},
    275     {1, C9_6, C8_6, C7_6},
    276     {1, C9_7, C8_7, C6_6},
    277     {1, C9_8, C7_7, C6_7},
    278     // right CB
    279     {1, C1_9, C3_10, C4_10},
    280     {1, C1_10, C2_10, C4_11},
    281     {1, C1_11, C2_11, C3_11},
    282     {1, C1_12, C2_12, C3_12},
    283     {1, C1_13, C2_13, C3_13},
    284     {1, C1_14, C2_14, C3_14},
    285     {1, C1_15, C2_15, C3_15},
    286     {1, C1_16, C2_16, C3_16},
    287 
    288     {1, C9_9, C8_9, C7_9},
    289     {1, C9_10, C8_10, C7_10},
    290     {1, C9_11, C8_11, C7_11},
    291     {1, C9_12, C8_12, C7_12},
    292     {1, C9_13, C8_13, C7_13},
    293     {1, C9_14, C8_14, C7_14},
    294     {1, C9_15, C8_15, C6_14},
    295     {1, C9_16, C7_15, C6_15},
    296 };
    297 
    298 void matrix_init_kb(void)
    299 {
    300     gpio_set_pin_output(LED_CAPS_LOCK_PIN);
    301     gpio_write_pin_low(LED_CAPS_LOCK_PIN);
    302 
    303     update_ticks();
    304     matrix_init_user();
    305 }
    306 
    307 void housekeeping_task_kb(void)
    308 {
    309     if (rgb_state.state == SELF_TESTING) {
    310         self_testing();
    311     } else if (rgb_state.state == CAPS_ALERT) {
    312         if (rgb_state.alert) {
    313             is31fl3731_set_color_all(0xFF, 0xA5, 0x00);
    314             ws2812_set_color_all(0xFF, 0xA5, 0x00);
    315         } else {
    316             is31fl3731_set_color_all(0, 0, 0);
    317             ws2812_set_color_all(0, 0, 0);
    318         }
    319 
    320         if (timer_elapsed(rgb_state.ticks) > ALERT_INTERVAL) {
    321             rgb_state.alert = !rgb_state.alert;
    322             update_ticks();
    323         }
    324     }
    325 
    326     is31fl3731_flush();
    327 }
    328 
    329 void init_custom(void) {
    330     is31fl3731_init_drivers();
    331     ws2812_init();
    332 }
    333 
    334 void set_color_custom(int index, uint8_t red, uint8_t green, uint8_t blue) {
    335     if (index < IS31FL3731_LED_COUNT) {
    336         is31fl3731_set_color(index, red, green, blue);
    337     } else if (index < IS31FL3731_LED_COUNT + WS2812_LED_COUNT) {
    338         ws2812_set_color(index - IS31FL3731_LED_COUNT, red, green, blue);
    339     }
    340 }
    341 
    342 void set_color_all_custom(uint8_t red, uint8_t green, uint8_t blue) {
    343     for (int i = 0; i < RGBLIGHT_LED_COUNT; i++) {
    344         set_color_custom(i, red, green, blue);
    345     }
    346 }
    347 
    348 void flush_custom(void) {
    349     if (rgb_state.state != NORMAL) return;
    350 
    351     is31fl3731_flush();
    352     ws2812_flush();
    353 }
    354 
    355 const rgblight_driver_t rgblight_driver = {
    356     .init          = init_custom,
    357     .set_color     = set_color_custom,
    358     .set_color_all = set_color_all_custom,
    359     .flush         = flush_custom,
    360 };
    361 
    362 bool led_update_kb(led_t led_state)
    363 {
    364     bool res = led_update_user(led_state);
    365     if (res) {
    366         gpio_write_pin(LED_CAPS_LOCK_PIN, led_state.caps_lock);
    367 
    368         if (rgb_state.state != SELF_TESTING) {
    369             if (led_state.caps_lock) {
    370                 rgb_state.state = CAPS_ALERT;
    371                 update_ticks();
    372             } else {
    373                 rgb_state.state = NORMAL;
    374                 rgblight_set();
    375             }
    376         }
    377     }
    378     return res;
    379 }
    380 
    381 #endif