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