qmk_firmware

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

rgb_ring.c (14052B)


      1 /**
      2  * @file rgb_ring.c
      3  * @author astro
      4  *
      5  * This program is free software: you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation, either version 2 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "rgb_ring.h"
     20 
     21 #include <stdint.h>
     22 #include <stdbool.h>
     23 #include <string.h>
     24 #include "quantum.h"
     25 #include "rgblight.h"
     26 #include "timer.h"
     27 #include "action.h"
     28 #include "drivers/led/issi/is31fl3731.h"
     29 #include "i2c_master.h"
     30 
     31 
     32 #ifndef RGBLIGHT_ENABLE
     33 #error "MUST enable rgblight"
     34 #endif
     35 // rgb ring leds setting
     36 
     37 const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
     38 /* Refer to IS31 manual for these locations
     39  *   driver
     40  *   |  R location
     41  *   |  |       G location
     42  *   |  |       |       B location
     43  *   |  |       |       | */
     44     {0, C1_1,   C3_2,   C4_2},
     45     {0, C1_2,   C2_2,   C4_3},
     46     {0, C1_3,   C2_3,   C3_3},
     47     {0, C1_4,   C2_4,   C3_4},
     48     {0, C1_5,   C2_5,   C3_5},
     49     {0, C1_6,   C2_6,   C3_6},
     50     {0, C1_7,   C2_7,   C3_7},
     51     {0, C1_8,   C2_8,   C3_8},
     52 
     53     {0, C9_1,   C8_1,   C7_1},
     54     {0, C9_2,   C8_2,   C7_2},
     55     {0, C9_3,   C8_3,   C7_3},
     56     {0, C9_4,   C8_4,   C7_4},
     57     {0, C9_5,   C8_5,   C7_5},
     58     {0, C9_6,   C8_6,   C7_6},
     59     {0, C9_7,   C8_7,   C6_6},
     60     {0, C9_8,   C7_7,   C6_7},
     61 
     62     {0, C1_9,   C3_10,  C4_10},
     63     {0, C1_10,  C2_10,  C4_11},
     64     {0, C1_11,  C2_11,  C3_11},
     65     {0, C1_12,  C2_12,  C3_12},
     66 };
     67 
     68 #define RING_OUTER_BEGIN    0
     69 #define RING_OUTER_END      15
     70 #define RING_OUTER_SIZE     (RING_OUTER_END + 1 - RING_OUTER_BEGIN)
     71 
     72 #define RING_INNER_BEGIN    16
     73 #define RING_INNER_END      19
     74 #define RING_INNER_SIZE     (RING_INNER_END + 1 - RING_INNER_BEGIN)
     75 
     76 #define SPEED_MAX           100
     77 #define SPEED_STEP          10
     78 
     79 typedef enum {
     80     RING_STATE_INIT,
     81     RING_STATE_QMK,
     82     RING_STATE_CUSTOM,
     83 } RING_STATE;
     84 
     85 typedef enum {
     86     RING_EFFECT_1,
     87     RING_EFFECT_2,
     88     RING_EFFECT_3,
     89     RING_EFFECT_4,
     90     RING_EFFECT_5,
     91     RING_EFFECT_6,
     92     RING_EFFECT_MAX
     93 } RING_EFFECT;
     94 
     95 typedef struct {
     96     uint8_t state;
     97     uint8_t effect;
     98     uint8_t speed;
     99     uint8_t outer_index;
    100     uint8_t inner_index;
    101     uint8_t effect_count;
    102     uint8_t led_begin;
    103     uint8_t led_end;
    104     bool    led_forward;
    105     bool    led_clear;
    106 } rgb_ring_t;
    107 
    108 static rgb_ring_t rgb_ring = {
    109     .state          = RING_STATE_INIT,
    110     .effect         = RING_EFFECT_1,
    111     .speed          = 10,
    112     .outer_index    = 0,
    113     .inner_index    = 0,
    114     .effect_count   = 0,
    115     .led_begin      = RING_OUTER_BEGIN,
    116     .led_end        = RING_OUTER_END,
    117     .led_forward    = true,
    118     .led_clear      = false,
    119 };
    120 
    121 static void rgb_ring_reset(void)
    122 {
    123     rgb_ring.effect_count   = 0;
    124     rgb_ring.led_begin      = RING_OUTER_BEGIN;
    125     rgb_ring.led_end        = RING_OUTER_END;
    126     rgb_ring.led_forward    = true;
    127     rgb_ring.led_clear      = false;
    128 }
    129 
    130 extern animation_status_t animation_status;
    131 extern rgblight_config_t rgblight_config;
    132 
    133 #define EFFECT_TEST_INTERVAL    50
    134 #define EFFECT_TEST_COUNT       5
    135 #define EFFECT_TEST_HUE_STEP    85
    136 #define EFFECT_TEST_VAL_STEP    17
    137 static void testing_mode(void)
    138 {
    139     if (timer_elapsed(animation_status.last_timer) > EFFECT_TEST_INTERVAL) {
    140         hsv_t h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
    141         rgb_t c = hsv_to_rgb(h);
    142         //is31fl3731_set_color_all(c.r, c.g, c.b);
    143         is31fl3731_set_color_all(0, 0, 0);
    144         is31fl3731_set_color(rgb_ring.outer_index+RING_OUTER_BEGIN, c.r, c.g, c.b);
    145         h.v = EFFECT_TEST_VAL_STEP*rgb_ring.outer_index;
    146         c = hsv_to_rgb(h);
    147         for (uint8_t i = RING_INNER_BEGIN; i <= RING_INNER_END; i++) {
    148             is31fl3731_set_color(i, c.r, c.g, c.b);
    149         }
    150         rgb_ring.outer_index = (rgb_ring.outer_index + 1) % RING_OUTER_SIZE;
    151         //rgb_ring.inner_index = (rgb_ring.inner_index + 1) % RING_INNER_SIZE;
    152 
    153         if (rgb_ring.outer_index == RING_OUTER_BEGIN) {
    154             rgblight_config.hue += EFFECT_TEST_HUE_STEP;
    155             rgb_ring.effect_count++;
    156         }
    157         animation_status.last_timer = timer_read();
    158     }
    159     if (rgb_ring.effect_count > EFFECT_TEST_COUNT) {
    160         rgb_ring_reset();
    161         rgb_ring.state = RING_STATE_QMK;
    162         rgblight_set();
    163     }
    164 }
    165 
    166 static bool need_update(uint32_t max_interval)
    167 {
    168     uint32_t interval = timer_elapsed(animation_status.last_timer);
    169     return (interval*rgb_ring.speed) > max_interval;
    170 }
    171 
    172 static void update_effect(uint32_t max_count)
    173 {
    174     if (rgb_ring.effect_count > max_count) {
    175         rgb_ring_reset();
    176         rgb_ring.effect = (rgb_ring.effect + 1) % RING_EFFECT_MAX;
    177     }
    178 }
    179 
    180 #define EFFECT_1_INTERVAL  1000
    181 #define EFFECT_1_COUNT     64
    182 #define EFFECT_1_HUE_STEP  15
    183 
    184 static void ring_effect_no_1(void)
    185 {
    186     if (need_update(EFFECT_1_INTERVAL)) {
    187         hsv_t h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
    188         for (uint8_t i = RING_OUTER_BEGIN; i <= RING_OUTER_END; i++) {
    189             rgb_t c = hsv_to_rgb(h);
    190             is31fl3731_set_color(i, c.r, c.g, c.b);
    191         }
    192         rgblight_config.hue += EFFECT_1_HUE_STEP;
    193         rgb_ring.effect_count++;
    194         animation_status.last_timer = timer_read();
    195     }
    196 
    197     update_effect(EFFECT_1_COUNT);
    198 }
    199 
    200 #define EFFECT_2_INTERVAL  1000
    201 #define EFFECT_2_COUNT     64
    202 #define EFFECT_2_HUE_STEP  15
    203 
    204 static void ring_effect_no_2(void)
    205 {
    206     if (need_update(EFFECT_2_INTERVAL)) {
    207         is31fl3731_set_color_all(0, 0, 0);
    208         hsv_t h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
    209         rgb_t c = hsv_to_rgb(h);
    210 
    211         is31fl3731_set_color(rgb_ring.led_begin, c.r, c.g, c.b);
    212         is31fl3731_set_color(rgb_ring.led_end, c.r, c.g, c.b);
    213 
    214         rgb_ring.led_begin = (rgb_ring.led_begin + 1) % RING_OUTER_SIZE;
    215         rgb_ring.led_end = (rgb_ring.led_end + RING_OUTER_SIZE - 1) % RING_OUTER_SIZE;
    216 
    217         rgblight_config.hue += EFFECT_2_HUE_STEP;
    218         rgb_ring.effect_count++;
    219         animation_status.last_timer = timer_read();
    220     }
    221 
    222     update_effect(EFFECT_2_COUNT);
    223 }
    224 
    225 #define EFFECT_3_INTERVAL  1000
    226 #define EFFECT_3_COUNT     64
    227 #define EFFECT_3_HUE_STEP  15
    228 
    229 static void ring_effect_no_3(void)
    230 {
    231     if (rgb_ring.effect_count == 0) {
    232         is31fl3731_set_color_all(0, 0, 0);
    233     }
    234 
    235     if (need_update(EFFECT_3_INTERVAL)) {
    236         hsv_t h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
    237 
    238         if (rgb_ring.led_clear) {
    239             is31fl3731_set_color(rgb_ring.led_begin, 0, 0, 0);
    240             is31fl3731_set_color(rgb_ring.led_end, 0, 0, 0);
    241         } else {
    242             rgb_t c = hsv_to_rgb(h);
    243             is31fl3731_set_color(rgb_ring.led_begin, c.r, c.g, c.b);
    244             is31fl3731_set_color(rgb_ring.led_end, c.r, c.g, c.b);
    245         }
    246 
    247         rgb_ring.led_begin = (rgb_ring.led_begin + 1) % RING_OUTER_SIZE;
    248         if (rgb_ring.led_begin == rgb_ring.led_end) {
    249             if (rgb_ring.led_forward) {
    250                 rgb_ring.led_begin = RING_OUTER_BEGIN;
    251                 rgb_ring.led_end = RING_OUTER_END+1;
    252             } else {
    253                 rgb_ring.led_begin = RING_OUTER_BEGIN + RING_OUTER_SIZE/2;
    254                 rgb_ring.led_end = RING_OUTER_END+1 - RING_OUTER_SIZE/2;
    255             }
    256 
    257             if (!rgb_ring.led_clear) {
    258                 rgb_ring.led_forward = !rgb_ring.led_forward;
    259             }
    260 
    261             rgb_ring.led_clear = !rgb_ring.led_clear;
    262         }
    263 
    264         rgb_ring.led_end = (rgb_ring.led_end + RING_OUTER_SIZE - 1) % RING_OUTER_SIZE;
    265 
    266         rgblight_config.hue += EFFECT_3_HUE_STEP;
    267         rgb_ring.effect_count++;
    268         animation_status.last_timer = timer_read();
    269     }
    270 
    271     update_effect(EFFECT_3_COUNT);
    272 }
    273 
    274 #define EFFECT_4_INTERVAL  1000
    275 #define EFFECT_4_COUNT     64
    276 #define EFFECT_4_STEP      3
    277 static void ring_effect_no_4(void)
    278 {
    279     if (need_update(EFFECT_4_INTERVAL)) {
    280         is31fl3731_set_color_all(0, 0, 0);
    281         hsv_t h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
    282         rgb_t c = hsv_to_rgb(h);
    283 
    284         is31fl3731_set_color(rgb_ring.led_begin, c.r, c.g, c.b);
    285         is31fl3731_set_color(rgb_ring.led_end, c.r, c.g, c.b);
    286 
    287         rgb_ring.led_begin = (rgb_ring.led_begin + EFFECT_4_STEP) % RING_OUTER_SIZE;
    288         rgb_ring.led_end = (rgb_ring.led_end + RING_OUTER_SIZE - EFFECT_4_STEP) % RING_OUTER_SIZE;
    289 
    290         rgblight_config.hue += EFFECT_1_HUE_STEP;
    291         rgb_ring.effect_count++;
    292         animation_status.last_timer = timer_read();
    293     }
    294 
    295     update_effect(EFFECT_4_COUNT);
    296 }
    297 
    298 #define EFFECT_5_INTERVAL  1000
    299 #define EFFECT_5_COUNT     64
    300 #define EFFECT_5_HUE_STEP  16
    301 static void ring_effect_no_5(void)
    302 {
    303     if (need_update(EFFECT_5_INTERVAL)) {
    304         is31fl3731_set_color_all(0, 0, 0);
    305         for (uint8_t i = RING_INNER_BEGIN; i <= RING_INNER_END; i++) {
    306             hsv_t h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
    307             rgb_t c = hsv_to_rgb(h);
    308             is31fl3731_set_color(i, c.r, c.g, c.b);
    309         }
    310         for (uint8_t i = RING_OUTER_BEGIN; i <= RING_OUTER_END; i++) {
    311             hsv_t h = {rgblight_config.hue+EFFECT_5_HUE_STEP, rgblight_config.sat, rgblight_config.val};
    312             rgb_t c = hsv_to_rgb(h);
    313             is31fl3731_set_color(i, c.r, c.g, c.b);
    314         }
    315         rgblight_config.hue += EFFECT_5_HUE_STEP;
    316         rgb_ring.effect_count++;
    317         animation_status.last_timer = timer_read();
    318     }
    319 
    320     update_effect(EFFECT_5_COUNT);
    321 }
    322 
    323 #define EFFECT_6_INTERVAL  1000
    324 #define EFFECT_6_COUNT     64
    325 #define EFFECT_I_HUE_STEP  10
    326 #define EFFECT_O_HUE_STEP  10
    327 static void ring_effect_no_6(void)
    328 {
    329     if (need_update(EFFECT_6_INTERVAL)) {
    330         is31fl3731_set_color_all(0, 0, 0);
    331         for (uint8_t i = RING_INNER_BEGIN; i <= RING_INNER_END; i++) {
    332             hsv_t h = {rgblight_config.hue+i*EFFECT_I_HUE_STEP, rgblight_config.sat, rgblight_config.val};
    333             rgb_t c = hsv_to_rgb(h);
    334             is31fl3731_set_color(i, c.r, c.g, c.b);
    335         }
    336         for (uint8_t i = RING_OUTER_BEGIN; i <= RING_OUTER_END; i++) {
    337             hsv_t h = {rgblight_config.hue+i*EFFECT_O_HUE_STEP, rgblight_config.sat, rgblight_config.val};
    338             rgb_t c = hsv_to_rgb(h);
    339             is31fl3731_set_color(i, c.r, c.g, c.b);
    340         }
    341         rgblight_config.hue += EFFECT_I_HUE_STEP;
    342         rgb_ring.effect_count++;
    343         animation_status.last_timer = timer_read();
    344     }
    345 
    346     update_effect(EFFECT_6_COUNT);
    347 }
    348 
    349 typedef void(*effect_fun)(void);
    350 static effect_fun effect_funcs[RING_EFFECT_MAX] = {
    351     ring_effect_no_1,
    352     ring_effect_no_2,
    353     ring_effect_no_3,
    354     ring_effect_no_4,
    355     ring_effect_no_5,
    356     ring_effect_no_6,
    357 };
    358 
    359 static void custom_effects(void)
    360 {
    361     effect_funcs[rgb_ring.effect]();
    362 }
    363 
    364 void flush_custom(void) {
    365     if (rgb_ring.state != RING_STATE_QMK) {
    366         return;
    367     }
    368 
    369     is31fl3731_flush();
    370 }
    371 
    372 const rgblight_driver_t rgblight_driver = {
    373     .init          = is31fl3731_init_drivers,
    374     .set_color     = is31fl3731_set_color,
    375     .set_color_all = is31fl3731_set_color_all,
    376     .flush         = flush_custom,
    377 };
    378 
    379 
    380 void rgb_ring_task(void)
    381 {
    382     switch (rgb_ring.state) {
    383         case RING_STATE_INIT: // testing mode
    384             testing_mode();
    385             break;
    386         case RING_STATE_QMK: // qmk effects
    387             //rgblight_task();
    388             break;
    389         case RING_STATE_CUSTOM: // custom effects
    390             custom_effects();
    391             break;
    392         default:
    393             break;
    394     };
    395 }
    396 
    397 bool process_record_kb(uint16_t keycode, keyrecord_t *record)
    398 {
    399     if (record->event.pressed) {
    400         switch(keycode) {
    401             case QK_UNDERGLOW_MODE_NEXT:
    402                 if (rgb_ring.state == RING_STATE_INIT) {
    403                     // in testing mode, do nothing
    404                     return false;
    405                 } else if (rgb_ring.state == RING_STATE_CUSTOM) {
    406                     // switch to qmk mode
    407                     rgblight_config.mode = 1;
    408                     rgb_ring.state = RING_STATE_QMK;
    409                     rgblight_mode(rgblight_config.mode);
    410                     return false;
    411                 } else {
    412                     // in qmk mode, switch to custom mode?
    413                     if (rgblight_config.mode >= RGBLIGHT_MODES) {
    414                         rgb_ring.state = RING_STATE_CUSTOM;
    415                         return false;
    416                     }
    417                 }
    418                 break;
    419             case QK_UNDERGLOW_MODE_PREVIOUS:
    420                 if (rgb_ring.state == RING_STATE_INIT) {
    421                     // in testing mode, do nothing
    422                     return false;
    423                 } else if (rgb_ring.state == RING_STATE_CUSTOM) {
    424                     // switch to qmk mode
    425                     rgblight_config.mode = RGBLIGHT_MODES;
    426                     rgb_ring.state = RING_STATE_QMK;
    427                     rgblight_mode(rgblight_config.mode);
    428                     return false;
    429                 } else {
    430                     // in qmk mode, switch to custom mode?
    431                     if (rgblight_config.mode <= 1) {
    432                         rgb_ring.state = RING_STATE_CUSTOM;
    433                         return false;
    434                     }
    435                 }
    436                 break;
    437             case KC_F24:
    438                 if (rgb_ring.state == RING_STATE_QMK) {
    439                     rgb_ring.state = RING_STATE_CUSTOM;
    440                     rgb_ring_reset();
    441                     return false;
    442                 } else if (rgb_ring.state == RING_STATE_CUSTOM) {
    443                     rgb_ring.state = RING_STATE_QMK;
    444                     return false;
    445                 }
    446                 break;
    447             default:
    448                 break;
    449         }
    450     }
    451     return process_record_user(keycode, record);
    452 }