rgblight.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. /* Copyright 2016-2017 Yang Liu
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <math.h>
  17. #include <string.h>
  18. #ifdef __AVR__
  19. #include <avr/eeprom.h>
  20. #include <avr/interrupt.h>
  21. #endif
  22. #ifdef STM32_EEPROM_ENABLE
  23. #include "hal.h"
  24. #include "eeprom.h"
  25. #include "eeprom_stm32.h"
  26. #endif
  27. #include "wait.h"
  28. #include "progmem.h"
  29. #include "timer.h"
  30. #include "rgblight.h"
  31. #include "color.h"
  32. #include "debug.h"
  33. #include "led_tables.h"
  34. #include "lib/lib8tion/lib8tion.h"
  35. #ifdef VELOCIKEY_ENABLE
  36. #include "velocikey.h"
  37. #endif
  38. #ifdef RGBLIGHT_SPLIT
  39. /* for split keyboard */
  40. #define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE
  41. #define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS
  42. #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE|RGBLIGHT_STATUS_CHANGE_HSVS)
  43. #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER
  44. #define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK
  45. #else
  46. #define RGBLIGHT_SPLIT_SET_CHANGE_MODE
  47. #define RGBLIGHT_SPLIT_SET_CHANGE_HSVS
  48. #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS
  49. #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE
  50. #define RGBLIGHT_SPLIT_ANIMATION_TICK
  51. #endif
  52. #define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
  53. #define _RGBM_SINGLE_DYNAMIC(sym)
  54. #define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
  55. #define _RGBM_MULTI_DYNAMIC(sym)
  56. #define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_ ## sym,
  57. #define _RGBM_TMP_DYNAMIC(sym, msym)
  58. static uint8_t static_effect_table [] = {
  59. #include "rgblight_modes.h"
  60. };
  61. #define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
  62. #define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
  63. #define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
  64. #define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
  65. #define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_ ## msym,
  66. #define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_ ## msym,
  67. static uint8_t mode_base_table [] = {
  68. 0, // RGBLIGHT_MODE_zero
  69. #include "rgblight_modes.h"
  70. };
  71. static inline int is_static_effect(uint8_t mode) {
  72. return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL;
  73. }
  74. #ifdef RGBLIGHT_LED_MAP
  75. const uint8_t led_map[] PROGMEM = RGBLIGHT_LED_MAP;
  76. #endif
  77. #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
  78. __attribute__ ((weak))
  79. const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64};
  80. #endif
  81. rgblight_config_t rgblight_config;
  82. rgblight_status_t rgblight_status = { .timer_enabled = false };
  83. bool is_rgblight_initialized = false;
  84. #ifdef RGBLIGHT_USE_TIMER
  85. animation_status_t animation_status = {};
  86. #endif
  87. #ifndef LED_ARRAY
  88. LED_TYPE led[RGBLED_NUM];
  89. #define LED_ARRAY led
  90. #endif
  91. static uint8_t clipping_start_pos = 0;
  92. static uint8_t clipping_num_leds = RGBLED_NUM;
  93. static uint8_t effect_start_pos = 0;
  94. static uint8_t effect_end_pos = RGBLED_NUM;
  95. static uint8_t effect_num_leds = RGBLED_NUM;
  96. void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) {
  97. clipping_start_pos = start_pos;
  98. clipping_num_leds = num_leds;
  99. }
  100. void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) {
  101. if (start_pos >= RGBLED_NUM) return;
  102. if (start_pos + num_leds > RGBLED_NUM) return;
  103. effect_start_pos = start_pos;
  104. effect_end_pos = start_pos + num_leds;
  105. effect_num_leds = num_leds;
  106. }
  107. void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
  108. HSV hsv = { hue, sat, val };
  109. RGB rgb = hsv_to_rgb(hsv);
  110. setrgb(rgb.r, rgb.g, rgb.b, led1);
  111. }
  112. void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
  113. sethsv_raw( hue, sat,
  114. val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val,
  115. led1);
  116. }
  117. void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
  118. (*led1).r = r;
  119. (*led1).g = g;
  120. (*led1).b = b;
  121. }
  122. void rgblight_check_config(void) {
  123. /* Add some out of bound checks for RGB light config */
  124. if (rgblight_config.mode < RGBLIGHT_MODE_STATIC_LIGHT) {
  125. rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
  126. }
  127. else if (rgblight_config.mode > RGBLIGHT_MODES) {
  128. rgblight_config.mode = RGBLIGHT_MODES;
  129. }
  130. if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) {
  131. rgblight_config.val = RGBLIGHT_LIMIT_VAL;
  132. }
  133. }
  134. uint32_t eeconfig_read_rgblight(void) {
  135. #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
  136. return eeprom_read_dword(EECONFIG_RGBLIGHT);
  137. #else
  138. return 0;
  139. #endif
  140. }
  141. void eeconfig_update_rgblight(uint32_t val) {
  142. #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE)
  143. rgblight_check_config();
  144. eeprom_update_dword(EECONFIG_RGBLIGHT, val);
  145. #endif
  146. }
  147. void eeconfig_update_rgblight_default(void) {
  148. //dprintf("eeconfig_update_rgblight_default\n");
  149. rgblight_config.enable = 1;
  150. rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
  151. rgblight_config.hue = 0;
  152. rgblight_config.sat = UINT8_MAX;
  153. rgblight_config.val = RGBLIGHT_LIMIT_VAL;
  154. rgblight_config.speed = 0;
  155. RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
  156. eeconfig_update_rgblight(rgblight_config.raw);
  157. }
  158. void eeconfig_debug_rgblight(void) {
  159. dprintf("rgblight_config eprom\n");
  160. dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
  161. dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
  162. dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
  163. dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
  164. dprintf("rgblight_config.val = %d\n", rgblight_config.val);
  165. dprintf("rgblight_config.speed = %d\n", rgblight_config.speed);
  166. }
  167. void rgblight_init(void) {
  168. /* if already initialized, don't do it again.
  169. If you must do it again, extern this and set to false, first.
  170. This is a dirty, dirty hack until proper hooks can be added for keyboard startup. */
  171. if (is_rgblight_initialized) { return; }
  172. debug_enable = 1; // Debug ON!
  173. dprintf("rgblight_init called.\n");
  174. dprintf("rgblight_init start!\n");
  175. if (!eeconfig_is_enabled()) {
  176. dprintf("rgblight_init eeconfig is not enabled.\n");
  177. eeconfig_init();
  178. eeconfig_update_rgblight_default();
  179. }
  180. rgblight_config.raw = eeconfig_read_rgblight();
  181. RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
  182. if (!rgblight_config.mode) {
  183. dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
  184. eeconfig_update_rgblight_default();
  185. rgblight_config.raw = eeconfig_read_rgblight();
  186. }
  187. rgblight_check_config();
  188. eeconfig_debug_rgblight(); // display current eeprom values
  189. #ifdef RGBLIGHT_USE_TIMER
  190. rgblight_timer_init(); // setup the timer
  191. #endif
  192. if (rgblight_config.enable) {
  193. rgblight_mode_noeeprom(rgblight_config.mode);
  194. }
  195. is_rgblight_initialized = true;
  196. }
  197. uint32_t rgblight_read_dword(void) {
  198. return rgblight_config.raw;
  199. }
  200. void rgblight_update_dword(uint32_t dword) {
  201. RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
  202. rgblight_config.raw = dword;
  203. if (rgblight_config.enable)
  204. rgblight_mode_noeeprom(rgblight_config.mode);
  205. else {
  206. #ifdef RGBLIGHT_USE_TIMER
  207. rgblight_timer_disable();
  208. #endif
  209. rgblight_set();
  210. }
  211. }
  212. void rgblight_increase(void) {
  213. uint8_t mode = 0;
  214. if (rgblight_config.mode < RGBLIGHT_MODES) {
  215. mode = rgblight_config.mode + 1;
  216. }
  217. rgblight_mode(mode);
  218. }
  219. void rgblight_decrease(void) {
  220. uint8_t mode = 0;
  221. // Mode will never be < 1. If it ever is, eeprom needs to be initialized.
  222. if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) {
  223. mode = rgblight_config.mode - 1;
  224. }
  225. rgblight_mode(mode);
  226. }
  227. void rgblight_step_helper(bool write_to_eeprom) {
  228. uint8_t mode = 0;
  229. mode = rgblight_config.mode + 1;
  230. if (mode > RGBLIGHT_MODES) {
  231. mode = 1;
  232. }
  233. rgblight_mode_eeprom_helper(mode, write_to_eeprom);
  234. }
  235. void rgblight_step_noeeprom(void) {
  236. rgblight_step_helper(false);
  237. }
  238. void rgblight_step(void) {
  239. rgblight_step_helper(true);
  240. }
  241. void rgblight_step_reverse_helper(bool write_to_eeprom) {
  242. uint8_t mode = 0;
  243. mode = rgblight_config.mode - 1;
  244. if (mode < 1) {
  245. mode = RGBLIGHT_MODES;
  246. }
  247. rgblight_mode_eeprom_helper(mode, write_to_eeprom);
  248. }
  249. void rgblight_step_reverse_noeeprom(void) {
  250. rgblight_step_reverse_helper(false);
  251. }
  252. void rgblight_step_reverse(void) {
  253. rgblight_step_reverse_helper(true);
  254. }
  255. uint8_t rgblight_get_mode(void) {
  256. if (!rgblight_config.enable) {
  257. return false;
  258. }
  259. return rgblight_config.mode;
  260. }
  261. void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
  262. if (!rgblight_config.enable) {
  263. return;
  264. }
  265. if (mode < RGBLIGHT_MODE_STATIC_LIGHT) {
  266. rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
  267. } else if (mode > RGBLIGHT_MODES) {
  268. rgblight_config.mode = RGBLIGHT_MODES;
  269. } else {
  270. rgblight_config.mode = mode;
  271. }
  272. RGBLIGHT_SPLIT_SET_CHANGE_MODE;
  273. if (write_to_eeprom) {
  274. eeconfig_update_rgblight(rgblight_config.raw);
  275. xprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode);
  276. } else {
  277. xprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
  278. }
  279. if( is_static_effect(rgblight_config.mode) ) {
  280. #ifdef RGBLIGHT_USE_TIMER
  281. rgblight_timer_disable();
  282. #endif
  283. } else {
  284. #ifdef RGBLIGHT_USE_TIMER
  285. rgblight_timer_enable();
  286. #endif
  287. }
  288. #ifdef RGBLIGHT_USE_TIMER
  289. animation_status.restart = true;
  290. #endif
  291. rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
  292. }
  293. void rgblight_mode(uint8_t mode) {
  294. rgblight_mode_eeprom_helper(mode, true);
  295. }
  296. void rgblight_mode_noeeprom(uint8_t mode) {
  297. rgblight_mode_eeprom_helper(mode, false);
  298. }
  299. void rgblight_toggle(void) {
  300. xprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
  301. if (rgblight_config.enable) {
  302. rgblight_disable();
  303. }
  304. else {
  305. rgblight_enable();
  306. }
  307. }
  308. void rgblight_toggle_noeeprom(void) {
  309. xprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable);
  310. if (rgblight_config.enable) {
  311. rgblight_disable_noeeprom();
  312. }
  313. else {
  314. rgblight_enable_noeeprom();
  315. }
  316. }
  317. void rgblight_enable(void) {
  318. rgblight_config.enable = 1;
  319. // No need to update EEPROM here. rgblight_mode() will do that, actually
  320. //eeconfig_update_rgblight(rgblight_config.raw);
  321. xprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
  322. rgblight_mode(rgblight_config.mode);
  323. }
  324. void rgblight_enable_noeeprom(void) {
  325. rgblight_config.enable = 1;
  326. xprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
  327. rgblight_mode_noeeprom(rgblight_config.mode);
  328. }
  329. void rgblight_disable(void) {
  330. rgblight_config.enable = 0;
  331. eeconfig_update_rgblight(rgblight_config.raw);
  332. xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
  333. #ifdef RGBLIGHT_USE_TIMER
  334. rgblight_timer_disable();
  335. #endif
  336. RGBLIGHT_SPLIT_SET_CHANGE_MODE;
  337. wait_ms(50);
  338. rgblight_set();
  339. }
  340. void rgblight_disable_noeeprom(void) {
  341. rgblight_config.enable = 0;
  342. xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
  343. #ifdef RGBLIGHT_USE_TIMER
  344. rgblight_timer_disable();
  345. #endif
  346. RGBLIGHT_SPLIT_SET_CHANGE_MODE;
  347. wait_ms(50);
  348. rgblight_set();
  349. }
  350. void rgblight_increase_hue_helper(bool write_to_eeprom) {
  351. uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP;
  352. rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
  353. }
  354. void rgblight_increase_hue_noeeprom(void) {
  355. rgblight_increase_hue_helper(false);
  356. }
  357. void rgblight_increase_hue(void) {
  358. rgblight_increase_hue_helper(true);
  359. }
  360. void rgblight_decrease_hue_helper(bool write_to_eeprom) {
  361. uint8_t hue = rgblight_config.hue - RGBLIGHT_HUE_STEP;
  362. rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
  363. }
  364. void rgblight_decrease_hue_noeeprom(void) {
  365. rgblight_decrease_hue_helper(false);
  366. }
  367. void rgblight_decrease_hue(void) {
  368. rgblight_decrease_hue_helper(true);
  369. }
  370. void rgblight_increase_sat_helper(bool write_to_eeprom) {
  371. uint8_t sat = qadd8(rgblight_config.sat, RGBLIGHT_SAT_STEP);
  372. rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
  373. }
  374. void rgblight_increase_sat_noeeprom(void) {
  375. rgblight_increase_sat_helper(false);
  376. }
  377. void rgblight_increase_sat(void) {
  378. rgblight_increase_sat_helper(true);
  379. }
  380. void rgblight_decrease_sat_helper(bool write_to_eeprom) {
  381. uint8_t sat = qsub8(rgblight_config.sat, RGBLIGHT_SAT_STEP);
  382. rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
  383. }
  384. void rgblight_decrease_sat_noeeprom(void) {
  385. rgblight_decrease_sat_helper(false);
  386. }
  387. void rgblight_decrease_sat(void) {
  388. rgblight_decrease_sat_helper(true);
  389. }
  390. void rgblight_increase_val_helper(bool write_to_eeprom) {
  391. uint8_t val = qadd8(rgblight_config.val, RGBLIGHT_VAL_STEP);
  392. rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
  393. }
  394. void rgblight_increase_val_noeeprom(void) {
  395. rgblight_increase_val_helper(false);
  396. }
  397. void rgblight_increase_val(void) {
  398. rgblight_increase_val_helper(true);
  399. }
  400. void rgblight_decrease_val_helper(bool write_to_eeprom) {
  401. uint8_t val = qsub8(rgblight_config.val, RGBLIGHT_VAL_STEP);
  402. rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
  403. }
  404. void rgblight_decrease_val_noeeprom(void) {
  405. rgblight_decrease_val_helper(false);
  406. }
  407. void rgblight_decrease_val(void) {
  408. rgblight_decrease_val_helper(true);
  409. }
  410. void rgblight_increase_speed(void) {
  411. if (rgblight_config.speed < 3)
  412. rgblight_config.speed++;
  413. //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?
  414. eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
  415. }
  416. void rgblight_decrease_speed(void) {
  417. if (rgblight_config.speed > 0)
  418. rgblight_config.speed--;
  419. //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED??
  420. eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this
  421. }
  422. void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) {
  423. if (rgblight_config.enable) {
  424. LED_TYPE tmp_led;
  425. sethsv(hue, sat, val, &tmp_led);
  426. // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
  427. rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
  428. }
  429. }
  430. void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
  431. if (rgblight_config.enable) {
  432. rgblight_status.base_mode = mode_base_table[rgblight_config.mode];
  433. if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
  434. // same static color
  435. LED_TYPE tmp_led;
  436. sethsv(hue, sat, val, &tmp_led);
  437. rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
  438. } else {
  439. // all LEDs in same color
  440. if ( 1 == 0 ) { //dummy
  441. }
  442. #ifdef RGBLIGHT_EFFECT_BREATHING
  443. else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING ) {
  444. // breathing mode, ignore the change of val, use in memory value instead
  445. val = rgblight_config.val;
  446. }
  447. #endif
  448. #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
  449. else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
  450. // rainbow mood, ignore the change of hue
  451. hue = rgblight_config.hue;
  452. }
  453. #endif
  454. #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
  455. else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
  456. // rainbow swirl, ignore the change of hue
  457. hue = rgblight_config.hue;
  458. }
  459. #endif
  460. #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
  461. else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) {
  462. // static gradient
  463. uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
  464. bool direction = (delta % 2) == 0;
  465. #ifdef __AVR__
  466. // probably due to how pgm_read_word is defined for ARM, but the ARM compiler really hates this line
  467. uint8_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]);
  468. #else
  469. uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2];
  470. #endif
  471. for (uint8_t i = 0; i < effect_num_leds; i++) {
  472. uint8_t _hue = ((uint16_t)i * (uint16_t)range) / effect_num_leds;
  473. if (direction) {
  474. _hue = hue + _hue;
  475. } else {
  476. _hue = hue - _hue;
  477. }
  478. dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
  479. sethsv(_hue, sat, val, (LED_TYPE *)&led[i + effect_start_pos]);
  480. }
  481. rgblight_set();
  482. }
  483. #endif
  484. }
  485. #ifdef RGBLIGHT_SPLIT
  486. if( rgblight_config.hue != hue ||
  487. rgblight_config.sat != sat ||
  488. rgblight_config.val != val ) {
  489. RGBLIGHT_SPLIT_SET_CHANGE_HSVS;
  490. }
  491. #endif
  492. rgblight_config.hue = hue;
  493. rgblight_config.sat = sat;
  494. rgblight_config.val = val;
  495. if (write_to_eeprom) {
  496. eeconfig_update_rgblight(rgblight_config.raw);
  497. xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
  498. } else {
  499. xprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
  500. }
  501. }
  502. }
  503. void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val) {
  504. rgblight_sethsv_eeprom_helper(hue, sat, val, true);
  505. }
  506. void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val) {
  507. rgblight_sethsv_eeprom_helper(hue, sat, val, false);
  508. }
  509. uint8_t rgblight_get_hue(void) {
  510. return rgblight_config.hue;
  511. }
  512. uint8_t rgblight_get_sat(void) {
  513. return rgblight_config.sat;
  514. }
  515. uint8_t rgblight_get_val(void) {
  516. return rgblight_config.val;
  517. }
  518. void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
  519. if (!rgblight_config.enable) { return; }
  520. for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
  521. led[i].r = r;
  522. led[i].g = g;
  523. led[i].b = b;
  524. }
  525. rgblight_set();
  526. }
  527. void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) {
  528. if (!rgblight_config.enable || index >= RGBLED_NUM) { return; }
  529. led[index].r = r;
  530. led[index].g = g;
  531. led[index].b = b;
  532. rgblight_set();
  533. }
  534. void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
  535. if (!rgblight_config.enable) { return; }
  536. LED_TYPE tmp_led;
  537. sethsv(hue, sat, val, &tmp_led);
  538. rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
  539. }
  540. #if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) \
  541. || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT)
  542. static uint8_t get_interval_time(const uint8_t* default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
  543. return
  544. #ifdef VELOCIKEY_ENABLE
  545. velocikey_enabled() ? velocikey_match_speed(velocikey_min, velocikey_max) :
  546. #endif
  547. pgm_read_byte(default_interval_address);
  548. }
  549. #endif
  550. void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) {
  551. if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) { return; }
  552. for (uint8_t i = start; i < end; i++) {
  553. led[i].r = r;
  554. led[i].g = g;
  555. led[i].b = b;
  556. }
  557. rgblight_set();
  558. wait_ms(1);
  559. }
  560. void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) {
  561. if (!rgblight_config.enable) { return; }
  562. LED_TYPE tmp_led;
  563. sethsv(hue, sat, val, &tmp_led);
  564. rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end);
  565. }
  566. #ifndef RGBLIGHT_SPLIT
  567. void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) {
  568. rgblight_setrgb_range(r, g, b, 0 , (uint8_t) RGBLED_NUM/2);
  569. }
  570. void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) {
  571. rgblight_setrgb_range(r, g, b, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
  572. }
  573. void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) {
  574. rgblight_sethsv_range(hue, sat, val, 0, (uint8_t) RGBLED_NUM/2);
  575. }
  576. void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) {
  577. rgblight_sethsv_range(hue, sat, val, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM);
  578. }
  579. #endif // ifndef RGBLIGHT_SPLIT
  580. #ifndef RGBLIGHT_CUSTOM_DRIVER
  581. void rgblight_set(void) {
  582. LED_TYPE *start_led;
  583. uint16_t num_leds = clipping_num_leds;
  584. if (!rgblight_config.enable) {
  585. for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
  586. led[i].r = 0;
  587. led[i].g = 0;
  588. led[i].b = 0;
  589. }
  590. }
  591. #ifdef RGBLIGHT_LED_MAP
  592. LED_TYPE led0[RGBLED_NUM];
  593. for(uint8_t i = 0; i < RGBLED_NUM; i++) {
  594. led0[i] = led[pgm_read_byte(&led_map[i])];
  595. }
  596. start_led = led0 + clipping_start_pos;
  597. #else
  598. start_led = led + clipping_start_pos;
  599. #endif
  600. #ifdef RGBW
  601. ws2812_setleds_rgbw(start_led, num_leds);
  602. #else
  603. ws2812_setleds(start_led, num_leds);
  604. #endif
  605. }
  606. #endif
  607. #ifdef RGBLIGHT_SPLIT
  608. /* for split keyboard master side */
  609. uint8_t rgblight_get_change_flags(void) {
  610. return rgblight_status.change_flags;
  611. }
  612. void rgblight_clear_change_flags(void) {
  613. rgblight_status.change_flags = 0;
  614. }
  615. void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) {
  616. syncinfo->config = rgblight_config;
  617. syncinfo->status = rgblight_status;
  618. }
  619. /* for split keyboard slave side */
  620. void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
  621. if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) {
  622. if (syncinfo->config.enable) {
  623. rgblight_config.enable = 1; // == rgblight_enable_noeeprom();
  624. rgblight_mode_eeprom_helper(syncinfo->config.mode, write_to_eeprom);
  625. } else {
  626. rgblight_disable_noeeprom();
  627. }
  628. }
  629. if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_HSVS) {
  630. rgblight_sethsv_eeprom_helper(syncinfo->config.hue, syncinfo->config.sat, syncinfo->config.val, write_to_eeprom);
  631. // rgblight_config.speed = config->speed; // NEED???
  632. }
  633. #ifdef RGBLIGHT_USE_TIMER
  634. if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_TIMER) {
  635. if (syncinfo->status.timer_enabled) {
  636. rgblight_timer_enable();
  637. } else {
  638. rgblight_timer_disable();
  639. }
  640. }
  641. #ifndef RGBLIGHT_SPLIT_NO_ANIMATION_SYNC
  642. if (syncinfo->status.change_flags & RGBLIGHT_STATUS_ANIMATION_TICK) {
  643. animation_status.restart = true;
  644. }
  645. #endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
  646. #endif /* RGBLIGHT_USE_TIMER */
  647. }
  648. #endif /* RGBLIGHT_SPLIT */
  649. #ifdef RGBLIGHT_USE_TIMER
  650. typedef void (*effect_func_t)(animation_status_t *anim);
  651. // Animation timer -- use system timer (AVR Timer0)
  652. void rgblight_timer_init(void) {
  653. // OLD!!!! Animation timer -- AVR Timer3
  654. // static uint8_t rgblight_timer_is_init = 0;
  655. // if (rgblight_timer_is_init) {
  656. // return;
  657. // }
  658. // rgblight_timer_is_init = 1;
  659. // /* Timer 3 setup */
  660. // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
  661. // | _BV(CS30); // Clock selelct: clk/1
  662. // /* Set TOP value */
  663. // uint8_t sreg = SREG;
  664. // cli();
  665. // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
  666. // OCR3AL = RGBLED_TIMER_TOP & 0xff;
  667. // SREG = sreg;
  668. rgblight_status.timer_enabled = false;
  669. RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
  670. }
  671. void rgblight_timer_enable(void) {
  672. if( !is_static_effect(rgblight_config.mode) ) {
  673. rgblight_status.timer_enabled = true;
  674. }
  675. animation_status.last_timer = timer_read();
  676. RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
  677. dprintf("rgblight timer enabled.\n");
  678. }
  679. void rgblight_timer_disable(void) {
  680. rgblight_status.timer_enabled = false;
  681. RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
  682. dprintf("rgblight timer disable.\n");
  683. }
  684. void rgblight_timer_toggle(void) {
  685. dprintf("rgblight timer toggle.\n");
  686. if(rgblight_status.timer_enabled) {
  687. rgblight_timer_disable();
  688. } else {
  689. rgblight_timer_enable();
  690. }
  691. }
  692. void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
  693. rgblight_enable();
  694. rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
  695. rgblight_setrgb(r, g, b);
  696. }
  697. static void rgblight_effect_dummy(animation_status_t *anim) {
  698. // do nothing
  699. /********
  700. dprintf("rgblight_task() what happened?\n");
  701. dprintf("is_static_effect %d\n", is_static_effect(rgblight_config.mode));
  702. dprintf("mode = %d, base_mode = %d, timer_enabled %d, ",
  703. rgblight_config.mode, rgblight_status.base_mode,
  704. rgblight_status.timer_enabled);
  705. dprintf("last_timer = %d\n",anim->last_timer);
  706. **/
  707. }
  708. void rgblight_task(void) {
  709. if (rgblight_status.timer_enabled) {
  710. effect_func_t effect_func = rgblight_effect_dummy;
  711. uint16_t interval_time = 2000; // dummy interval
  712. uint8_t delta = rgblight_config.mode - rgblight_status.base_mode;
  713. animation_status.delta = delta;
  714. // static light mode, do nothing here
  715. if ( 1 == 0 ) { //dummy
  716. }
  717. #ifdef RGBLIGHT_EFFECT_BREATHING
  718. else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) {
  719. // breathing mode
  720. interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[delta], 1, 100);
  721. effect_func = rgblight_effect_breathing;
  722. }
  723. #endif
  724. #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
  725. else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) {
  726. // rainbow mood mode
  727. interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[delta], 5, 100);
  728. effect_func = rgblight_effect_rainbow_mood;
  729. }
  730. #endif
  731. #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
  732. else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) {
  733. // rainbow swirl mode
  734. interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[delta / 2], 1, 100);
  735. effect_func = rgblight_effect_rainbow_swirl;
  736. }
  737. #endif
  738. #ifdef RGBLIGHT_EFFECT_SNAKE
  739. else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) {
  740. // snake mode
  741. interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[delta / 2], 1, 200);
  742. effect_func = rgblight_effect_snake;
  743. }
  744. #endif
  745. #ifdef RGBLIGHT_EFFECT_KNIGHT
  746. else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) {
  747. // knight mode
  748. interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100);
  749. effect_func = rgblight_effect_knight;
  750. }
  751. #endif
  752. #ifdef RGBLIGHT_EFFECT_CHRISTMAS
  753. else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) {
  754. // christmas mode
  755. interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL;
  756. effect_func = (effect_func_t)rgblight_effect_christmas;
  757. }
  758. #endif
  759. #ifdef RGBLIGHT_EFFECT_RGB_TEST
  760. else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) {
  761. // RGB test mode
  762. interval_time = pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0]);
  763. effect_func = (effect_func_t)rgblight_effect_rgbtest;
  764. }
  765. #endif
  766. #ifdef RGBLIGHT_EFFECT_ALTERNATING
  767. else if (rgblight_status.base_mode == RGBLIGHT_MODE_ALTERNATING){
  768. interval_time = 500;
  769. effect_func = (effect_func_t)rgblight_effect_alternating;
  770. }
  771. #endif
  772. if (animation_status.restart) {
  773. animation_status.restart = false;
  774. animation_status.last_timer = timer_read() - interval_time - 1;
  775. animation_status.pos16 = 0; // restart signal to local each effect
  776. }
  777. if (timer_elapsed(animation_status.last_timer) >= interval_time) {
  778. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  779. static uint16_t report_last_timer = 0;
  780. static bool tick_flag = false;
  781. uint16_t oldpos16;
  782. if (tick_flag) {
  783. tick_flag = false;
  784. //dprintf("rgblight animation tick\n");
  785. if (timer_elapsed(report_last_timer) >= 30000) {
  786. report_last_timer = timer_read();
  787. dprintf("rgblight animation tick report to slave\n");
  788. RGBLIGHT_SPLIT_ANIMATION_TICK;
  789. }
  790. }
  791. oldpos16 = animation_status.pos16;
  792. //dprintf("call effect function\n");
  793. #endif
  794. animation_status.last_timer += interval_time;
  795. effect_func(&animation_status);
  796. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  797. //dprintf("pos16, oldpos16 = %d %d\n",
  798. // animation_status.pos16,oldpos16);
  799. if (animation_status.pos16 == 0 && oldpos16 != 0) {
  800. //dprintf("flag on\n");
  801. tick_flag = true;
  802. }
  803. #endif
  804. }
  805. }
  806. }
  807. #endif /* RGBLIGHT_USE_TIMER */
  808. // Effects
  809. #ifdef RGBLIGHT_EFFECT_BREATHING
  810. #ifndef RGBLIGHT_EFFECT_BREATHE_CENTER
  811. #ifndef RGBLIGHT_BREATHE_TABLE_SIZE
  812. #define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256 or 128 or 64
  813. #endif
  814. #include <rgblight_breathe_table.h>
  815. #endif
  816. __attribute__ ((weak))
  817. const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
  818. void rgblight_effect_breathing(animation_status_t *anim) {
  819. float val;
  820. // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
  821. #ifdef RGBLIGHT_EFFECT_BREATHE_TABLE
  822. val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]);
  823. #else
  824. val = (exp(sin((anim->pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E));
  825. #endif
  826. rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
  827. anim->pos = (anim->pos + 1);
  828. }
  829. #endif
  830. #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
  831. __attribute__ ((weak))
  832. const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
  833. void rgblight_effect_rainbow_mood(animation_status_t *anim) {
  834. rgblight_sethsv_noeeprom_old(anim->current_hue, rgblight_config.sat, rgblight_config.val);
  835. anim->current_hue++;
  836. }
  837. #endif
  838. #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
  839. #ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE
  840. #define RGBLIGHT_RAINBOW_SWIRL_RANGE 255
  841. #endif
  842. __attribute__ ((weak))
  843. const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
  844. void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
  845. uint8_t hue;
  846. uint8_t i;
  847. for (i = 0; i < effect_num_leds; i++) {
  848. hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / effect_num_leds * i + anim->current_hue);
  849. sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]);
  850. }
  851. rgblight_set();
  852. if (anim->delta % 2) {
  853. anim->current_hue++;
  854. } else {
  855. anim->current_hue--;
  856. }
  857. }
  858. #endif
  859. #ifdef RGBLIGHT_EFFECT_SNAKE
  860. __attribute__ ((weak))
  861. const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
  862. void rgblight_effect_snake(animation_status_t *anim) {
  863. static uint8_t pos = 0;
  864. uint8_t i, j;
  865. int8_t k;
  866. int8_t increment = 1;
  867. if (anim->delta % 2) {
  868. increment = -1;
  869. }
  870. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  871. if (anim->pos == 0) { // restart signal
  872. if (increment == 1) {
  873. pos = effect_num_leds - 1;
  874. } else {
  875. pos = 0;
  876. }
  877. anim->pos = 1;
  878. }
  879. #endif
  880. for (i = 0; i < effect_num_leds; i++) {
  881. LED_TYPE *ledp = led + i + effect_start_pos;
  882. ledp->r = 0;
  883. ledp->g = 0;
  884. ledp->b = 0;
  885. for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) {
  886. k = pos + j * increment;
  887. if (k < 0) {
  888. k = k + effect_num_leds;
  889. }
  890. if (i == k) {
  891. sethsv(rgblight_config.hue, rgblight_config.sat,
  892. (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH),
  893. ledp);
  894. }
  895. }
  896. }
  897. rgblight_set();
  898. if (increment == 1) {
  899. if (pos - 1 < 0) {
  900. pos = effect_num_leds - 1;
  901. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  902. anim->pos = 0;
  903. #endif
  904. } else {
  905. pos -= 1;
  906. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  907. anim->pos = 1;
  908. #endif
  909. }
  910. } else {
  911. pos = (pos + 1) % effect_num_leds;
  912. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  913. anim->pos = pos;
  914. #endif
  915. }
  916. }
  917. #endif
  918. #ifdef RGBLIGHT_EFFECT_KNIGHT
  919. __attribute__ ((weak))
  920. const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
  921. void rgblight_effect_knight(animation_status_t *anim) {
  922. static int8_t low_bound = 0;
  923. static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
  924. static int8_t increment = 1;
  925. uint8_t i, cur;
  926. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  927. if (anim->pos == 0) { // restart signal
  928. anim->pos = 1;
  929. low_bound = 0;
  930. high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1;
  931. increment = 1;
  932. }
  933. #endif
  934. // Set all the LEDs to 0
  935. for (i = effect_start_pos; i < effect_end_pos; i++) {
  936. led[i].r = 0;
  937. led[i].g = 0;
  938. led[i].b = 0;
  939. }
  940. // Determine which LEDs should be lit up
  941. for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
  942. cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % effect_num_leds + effect_start_pos;
  943. if (i >= low_bound && i <= high_bound) {
  944. sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
  945. } else {
  946. led[cur].r = 0;
  947. led[cur].g = 0;
  948. led[cur].b = 0;
  949. }
  950. }
  951. rgblight_set();
  952. // Move from low_bound to high_bound changing the direction we increment each
  953. // time a boundary is hit.
  954. low_bound += increment;
  955. high_bound += increment;
  956. if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) {
  957. increment = -increment;
  958. #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
  959. if (increment == 1) {
  960. anim->pos = 0;
  961. }
  962. #endif
  963. }
  964. }
  965. #endif
  966. #ifdef RGBLIGHT_EFFECT_CHRISTMAS
  967. void rgblight_effect_christmas(animation_status_t *anim) {
  968. uint8_t hue;
  969. uint8_t i;
  970. anim->current_offset = (anim->current_offset + 1) % 2;
  971. for (i = 0; i < effect_num_leds; i++) {
  972. hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 85;
  973. sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]);
  974. }
  975. rgblight_set();
  976. }
  977. #endif
  978. #ifdef RGBLIGHT_EFFECT_RGB_TEST
  979. __attribute__ ((weak))
  980. const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
  981. void rgblight_effect_rgbtest(animation_status_t *anim) {
  982. static uint8_t maxval = 0;
  983. uint8_t g; uint8_t r; uint8_t b;
  984. if( maxval == 0 ) {
  985. LED_TYPE tmp_led;
  986. sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led);
  987. maxval = tmp_led.r;
  988. }
  989. g = r = b = 0;
  990. switch( anim->pos ) {
  991. case 0: r = maxval; break;
  992. case 1: g = maxval; break;
  993. case 2: b = maxval; break;
  994. }
  995. rgblight_setrgb(r, g, b);
  996. anim->pos = (anim->pos + 1) % 3;
  997. }
  998. #endif
  999. #ifdef RGBLIGHT_EFFECT_ALTERNATING
  1000. void rgblight_effect_alternating(animation_status_t *anim) {
  1001. for (int i = 0; i < effect_num_leds; i++) {
  1002. LED_TYPE *ledp = led + i + effect_start_pos;
  1003. if (i<effect_num_leds/2 && anim->pos) {
  1004. sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
  1005. } else if (i>=effect_num_leds/2 && !anim->pos) {
  1006. sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
  1007. } else {
  1008. sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp);
  1009. }
  1010. }
  1011. rgblight_set();
  1012. anim->pos = (anim->pos + 1) % 2;
  1013. }
  1014. #endif