PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Macro/PixelMap/pixel.c

https://gitlab.com/tylert/kiibohd-controller
C | 3622 lines | 2427 code | 547 blank | 648 comment | 392 complexity | bf6c6cde30c2727d60699c61780023d7 MD5 | raw file
Possible License(s): GPL-3.0, MIT, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* Copyright (C) 2015-2019 by Jacob Alexander
  2. *
  3. * This file is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This file 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 Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with this file. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. // ----- Includes -----
  17. // Compiler Includes
  18. #include <Lib/MacroLib.h>
  19. // Project Includes
  20. #include <Lib/storage.h>
  21. #include <cli.h>
  22. #include <layer.h>
  23. #include <trigger.h>
  24. #include <kll_defs.h>
  25. #include <latency.h>
  26. #include <led.h>
  27. #include <print.h>
  28. #include <output_com.h>
  29. // Interconnect module if compiled in
  30. #if defined(ConnectEnabled_define)
  31. #include <connect_scan.h>
  32. #endif
  33. // Local Includes
  34. #include "pixel.h"
  35. // ----- Function Declarations -----
  36. void Pixel_loadConfig();
  37. void Pixel_saveConfig();
  38. void Pixel_printConfig();
  39. void cliFunc_aniAdd ( char* args );
  40. void cliFunc_aniDel ( char* args );
  41. void cliFunc_aniStack ( char* args );
  42. void cliFunc_chanTest ( char* args );
  43. void cliFunc_pixelList ( char* args );
  44. void cliFunc_pixelSCTest( char* args );
  45. void cliFunc_pixelTest ( char* args );
  46. void cliFunc_pixelXYTest( char* args );
  47. void cliFunc_rectDisp ( char* args );
  48. // ----- Enums -----
  49. typedef enum PixelTest {
  50. PixelTest_Off = 0, // Disabled
  51. PixelTest_Chan_Single = 1,
  52. PixelTest_Chan_SingleReverse = 2,
  53. PixelTest_Chan_All = 3, // Enable all positions
  54. PixelTest_Chan_Roll = 4, // Iterate over all positions
  55. PixelTest_Chan_Full = 5, // Turn on all pixels
  56. PixelTest_Chan_Off = 6, // Turn off all pixels
  57. PixelTest_Pixel_Single = 10,
  58. PixelTest_Pixel_SingleReverse = 11,
  59. PixelTest_Pixel_All = 12, // Enable all positions
  60. PixelTest_Pixel_Roll = 13, // Iterate over all positions
  61. PixelTest_Pixel_Full = 14, // Turn on all pixels
  62. PixelTest_Pixel_Off = 15, // Turn off all pixels
  63. PixelTest_Scan_Single = 20,
  64. PixelTest_Scan_SingleReverse = 21,
  65. PixelTest_Scan_All = 22,
  66. PixelTest_Scan_Roll = 23,
  67. PixelTest_XY_Single = 30,
  68. PixelTest_XY_SingleReverse = 31,
  69. PixelTest_XY_All = 32,
  70. PixelTest_XY_Roll = 33,
  71. } PixelTest;
  72. typedef enum PixelFadeControl {
  73. PixelFadeControl_Reset = 0, // Resets fade profile to defaults (arg ignored)
  74. PixelFadeControl_Reset_All = 1, // Resets all fade profiles to defaults (profile, arg ignored)
  75. PixelFadeControl_Brightness_Set = 2, // Sets fade profile to a given brightness
  76. PixelFadeControl_Brightness_Increment = 3, // Increment brightness by given amount
  77. PixelFadeControl_Brightness_Decrement = 4, // Decrement brightness by given amount
  78. PixelFadeControl_Brightness_Default = 5, // Set profile brightness to default
  79. PixelFadeControl_LAST,
  80. } PixelFadeControl;
  81. // ----- Variables -----
  82. typedef struct {
  83. uint8_t index;
  84. uint8_t pos;
  85. } PixelConfigElem;
  86. typedef struct {
  87. PixelConfigElem animations[Pixel_AnimationStackSize];
  88. PixelPeriodConfig fade_periods[4][4];
  89. uint8_t fade_brightness[4];
  90. } PixelConfig;
  91. static PixelConfig settings;
  92. #if Storage_Enable_define == 1
  93. static PixelConfig defaults;
  94. static StorageModule PixelStorage = {
  95. .name = "Pixel Map",
  96. .settings = &settings,
  97. .defaults = &defaults,
  98. .size = sizeof(PixelConfig),
  99. .onLoad = Pixel_loadConfig,
  100. .onSave = Pixel_saveConfig,
  101. .display = Pixel_printConfig
  102. };
  103. #endif
  104. // Macro Module command dictionary
  105. CLIDict_Entry( aniAdd, "Add the given animation id to the stack" );
  106. CLIDict_Entry( aniDel, "Remove the given stack index animation" );
  107. CLIDict_Entry( aniStack, "Displays the animation stack contents" );
  108. CLIDict_Entry( chanTest, "Channel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" );
  109. CLIDict_Entry( pixelList, "Prints out pixel:channel mappings." );
  110. CLIDict_Entry( pixelSCTest, "Scancode pixel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" );
  111. CLIDict_Entry( pixelTest, "Pixel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop, f - full" );
  112. CLIDict_Entry( pixelXYTest, "XY pixel test. No arg - next pixel. # - pixel, r - roll-through. a - all, s - stop" );
  113. CLIDict_Entry( rectDisp, "Show the current output of the MCU pixel buffer." );
  114. CLIDict_Def( pixelCLIDict, "Pixel Module Commands" ) = {
  115. CLIDict_Item( aniAdd ),
  116. CLIDict_Item( aniDel ),
  117. CLIDict_Item( aniStack ),
  118. CLIDict_Item( chanTest ),
  119. CLIDict_Item( pixelList ),
  120. CLIDict_Item( pixelSCTest ),
  121. CLIDict_Item( pixelTest ),
  122. CLIDict_Item( pixelXYTest ),
  123. CLIDict_Item( rectDisp ),
  124. { 0, 0, 0 } // Null entry for dictionary end
  125. };
  126. // Gamma correction
  127. extern const uint8_t gamma_table[];
  128. static uint8_t gamma_enabled;
  129. // Debug states
  130. PixelTest Pixel_testMode;
  131. volatile uint16_t Pixel_testPos = 0;
  132. // Frame State
  133. // Indicates to pixel and output modules current state of the buffer
  134. FrameState Pixel_FrameState;
  135. // Animation Stack
  136. AnimationStack Pixel_AnimationStack;
  137. // Animation Control
  138. AnimationControl Pixel_animationControl;
  139. // Memory Stor for Animation Elements
  140. // Animation elements may be called multiple times, thus memory must be allocated per instance
  141. AnimationStackElement Pixel_AnimationElement_Stor[Pixel_AnimationStackSize];
  142. #if defined(_host_)
  143. uint16_t Pixel_AnimationStack_HostSize = Pixel_AnimationStackSize;
  144. uint8_t Pixel_Buffers_HostLen = Pixel_BuffersLen_KLL;
  145. uint8_t Pixel_MaxChannelPerPixel_Host = Pixel_MaxChannelPerPixel;
  146. uint16_t Pixel_Mapping_HostLen = 128; // TODO Define
  147. uint8_t Pixel_AnimationStackElement_HostSize = sizeof( AnimationStackElement );
  148. #endif
  149. // Pixel Fade Profile Mapping
  150. // Assigned per pixel (rather than channel)
  151. // 0 - Disabled
  152. // 1 - Profile 1 - Keys
  153. // 2 - Profile 2 - Underlighting
  154. // 3 - Profile 3 - Indicator LEDs
  155. // 4 - Profile 4 - Current active layer (defaultmap is excluded)
  156. static uint8_t Pixel_pixel_fade_profile[Pixel_TotalPixels_KLL];
  157. // Pixel Fade Profile Parameters
  158. // TODO (HaaTa): Use KLL to determine number of profiles (currently only 4)
  159. static PixelFadeProfile Pixel_pixel_fade_profile_entries[4];
  160. // Latency Measurement Resource
  161. static uint8_t pixelLatencyResource;
  162. // ----- Function Declarations -----
  163. uint8_t Pixel_animationProcess( AnimationStackElement *elem );
  164. uint8_t Pixel_addAnimation( AnimationStackElement *element, CapabilityState cstate );
  165. uint8_t Pixel_determineLastTriggerScanCode( TriggerMacro *trigger );
  166. void Pixel_pixelSet( PixelElement *elem, uint32_t value );
  167. void Pixel_clearAnimations();
  168. void Pixel_SecondaryProcessing_profile_init();
  169. PixelBuf *Pixel_bufferMap( uint16_t channel );
  170. AnimationStackElement *Pixel_lookupAnimation( uint16_t index, uint16_t prev );
  171. // ----- Capabilities -----
  172. //
  173. void Pixel_GammaControl_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  174. {
  175. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  176. switch ( cstate )
  177. {
  178. case CapabilityState_Initial:
  179. // Only use capability on press
  180. break;
  181. case CapabilityState_Debug:
  182. // Display capability name
  183. print("Pixel_GammaControl_capability(func)");
  184. return;
  185. default:
  186. return;
  187. }
  188. uint8_t arg = *(uint8_t*)(&args[0]);
  189. // Interconnect broadcasting
  190. #if defined(ConnectEnabled_define)
  191. // By default send to the *next* node, which will determine where to go next
  192. extern uint8_t Connect_id; // connect_scan.c
  193. uint8_t addr = Connect_id + 1;
  194. // Send interconnect remote capability packet
  195. // generatedKeymap.h
  196. extern const Capability CapabilitiesList[];
  197. // Broadcast layerStackExact remote capability (0xFF is the broadcast id)
  198. Connect_send_RemoteCapability(
  199. addr,
  200. Pixel_GammaControl_capability_index,
  201. state,
  202. stateType,
  203. CapabilitiesList[ Pixel_GammaControl_capability_index ].argCount,
  204. args
  205. );
  206. #endif
  207. // Decide how to handle function
  208. switch ( arg )
  209. {
  210. case 0: // Disabled
  211. gamma_enabled = 0;
  212. break;
  213. case 1: // Enabled
  214. gamma_enabled = 1;
  215. break;
  216. default: // Toggle
  217. gamma_enabled = !gamma_enabled;
  218. break;
  219. }
  220. }
  221. void Pixel_AnimationIndex_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  222. {
  223. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  224. switch ( cstate )
  225. {
  226. case CapabilityState_Initial:
  227. case CapabilityState_Last:
  228. // Mainly used on press
  229. // Except some configurations may also use release
  230. break;
  231. case CapabilityState_Debug:
  232. // Display capability name
  233. print("Pixel_AnimationIndex_capability(settingindex)");
  234. return;
  235. default:
  236. return;
  237. }
  238. // Interconnect broadcasting
  239. #if defined(ConnectEnabled_define)
  240. // By default send to the *next* node, which will determine where to go next
  241. extern uint8_t Connect_id; // connect_scan.c
  242. uint8_t addr = Connect_id + 1;
  243. // Send interconnect remote capability packet
  244. // generatedKeymap.h
  245. extern const Capability CapabilitiesList[];
  246. // Broadcast layerStackExact remote capability (0xFF is the broadcast id)
  247. Connect_send_RemoteCapability(
  248. addr,
  249. Pixel_AnimationIndex_capability_index,
  250. state,
  251. stateType,
  252. CapabilitiesList[ Pixel_AnimationIndex_capability_index ].argCount,
  253. args
  254. );
  255. #endif
  256. // Lookup animation settings
  257. uint16_t index = *(uint16_t*)(&args[0]);
  258. // Check if a valid setting
  259. if ( index >= Pixel_AnimationSettingsNum_KLL )
  260. {
  261. warn_msg("Invalid AnimationSetting index: ");
  262. printInt16( index );
  263. print( NL );
  264. return;
  265. }
  266. AnimationStackElement element = Pixel_AnimationSettings[ index ];
  267. element.trigger = trigger;
  268. Pixel_addAnimation( &element, cstate );
  269. }
  270. // XXX (HaaTa): It's not recommended to use this capability, use AnimationIndex instead
  271. void Pixel_Animation_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  272. {
  273. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  274. switch ( cstate )
  275. {
  276. case CapabilityState_Initial:
  277. // Only use capability on press
  278. break;
  279. case CapabilityState_Debug:
  280. // Display capability name
  281. print("Pixel_Animation_capability(index,loops,pfunc,framedelay,frameoption,replace)");
  282. return;
  283. default:
  284. return;
  285. }
  286. AnimationStackElement element;
  287. element.trigger = trigger;
  288. element.pos = 0; // TODO (HaaTa) Start at specific frame
  289. element.subpos = 0;
  290. element.index = *(uint16_t*)(&args[0]);
  291. element.loops = *(uint8_t*)(&args[2]);
  292. element.pfunc = *(uint8_t*)(&args[3]);
  293. element.framedelay = *(uint8_t*)(&args[4]);
  294. element.frameoption = *(uint8_t*)(&args[5]);
  295. element.replace = *(uint8_t*)(&args[6]);
  296. Pixel_addAnimation( &element, cstate );
  297. }
  298. // XXX (HaaTa): TODO
  299. void Pixel_Pixel_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  300. {
  301. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  302. switch ( cstate )
  303. {
  304. case CapabilityState_Initial:
  305. // Only use capability on press
  306. break;
  307. case CapabilityState_Debug:
  308. // Display capability name
  309. print("Pixel_Pixel_capability(pixel,chan,value)");
  310. return;
  311. default:
  312. return;
  313. }
  314. /*
  315. PixelChange change = *(PixelChange*)(&args[0]);
  316. uint16_t channel = *(uint16_t*)(&args[1]);
  317. uint32_t value = *(uint32_t*)(&args[3]);
  318. */
  319. // TODO (HaaTa) Apply the channel modification
  320. }
  321. void Pixel_AnimationControl_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  322. {
  323. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  324. switch ( cstate )
  325. {
  326. case CapabilityState_Initial:
  327. // Only use capability on press
  328. break;
  329. case CapabilityState_Debug:
  330. // Display capability name
  331. print("Pixel_AnimationControl_capability(func)");
  332. return;
  333. default:
  334. return;
  335. }
  336. // Interconnect broadcasting
  337. #if defined(ConnectEnabled_define)
  338. // By default send to the *next* node, which will determine where to go next
  339. extern uint8_t Connect_id; // connect_scan.c
  340. uint8_t addr = Connect_id + 1;
  341. // Send interconnect remote capability packet
  342. // generatedKeymap.h
  343. extern const Capability CapabilitiesList[];
  344. // Broadcast layerStackExact remote capability (0xFF is the broadcast id)
  345. Connect_send_RemoteCapability(
  346. addr,
  347. Pixel_AnimationControl_capability_index,
  348. state,
  349. stateType,
  350. CapabilitiesList[ Pixel_AnimationControl_capability_index ].argCount,
  351. args
  352. );
  353. #endif
  354. uint8_t arg = *(uint8_t*)(&args[0]);
  355. // Decide how to handle function
  356. switch ( arg )
  357. {
  358. case 0: // Pause/Resume
  359. // Determine how to handle Pause/Resume
  360. switch ( Pixel_animationControl )
  361. {
  362. case AnimationControl_Forward:
  363. case AnimationControl_ForwardOne:
  364. Pixel_animationControl = AnimationControl_Pause;
  365. break;
  366. case AnimationControl_Pause:
  367. default:
  368. Pixel_animationControl = AnimationControl_Forward;
  369. break;
  370. }
  371. break;
  372. case 1: // Forward one frame
  373. Pixel_animationControl = AnimationControl_ForwardOne;
  374. break;
  375. case 2: // Forward
  376. Pixel_animationControl = AnimationControl_Forward;
  377. break;
  378. case 3: // Stop (clears all animations)
  379. Pixel_animationControl = AnimationControl_Stop;
  380. break;
  381. case 4: // Reset (restarts animations)
  382. Pixel_animationControl = AnimationControl_Reset;
  383. break;
  384. case 5: // Pauses animations and clears display
  385. Pixel_animationControl = AnimationControl_WipePause;
  386. break;
  387. case 6: // Pauses animation
  388. Pixel_animationControl = AnimationControl_Pause;
  389. break;
  390. case 7: // Clears pixels (no pause and no stop)
  391. Pixel_animationControl = AnimationControl_Clear;
  392. break;
  393. }
  394. }
  395. void Pixel_FadeSet_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  396. {
  397. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  398. switch ( cstate )
  399. {
  400. case CapabilityState_Initial:
  401. // Only use capability on press
  402. break;
  403. case CapabilityState_Debug:
  404. // Display capability name
  405. print("Pixel_FadeSet_capability(profile,config,period)");
  406. return;
  407. default:
  408. return;
  409. }
  410. // Interconnect broadcasting
  411. #if defined(ConnectEnabled_define)
  412. // By default send to the *next* node, which will determine where to go next
  413. extern uint8_t Connect_id; // connect_scan.c
  414. uint8_t addr = Connect_id + 1;
  415. // Send interconnect remote capability packet
  416. // generatedKeymap.h
  417. extern const Capability CapabilitiesList[];
  418. // Broadcast layerStackExact remote capability (0xFF is the broadcast id)
  419. Connect_send_RemoteCapability(
  420. addr,
  421. Pixel_FadeSet_capability_index,
  422. state,
  423. stateType,
  424. CapabilitiesList[ Pixel_FadeSet_capability_index ].argCount,
  425. args
  426. );
  427. #endif
  428. // Get arguments
  429. uint8_t profile = *(uint8_t*)(&args[0]);
  430. uint8_t config = *(uint8_t*)(&args[1]);
  431. uint8_t period = *(uint8_t*)(&args[2]);
  432. // Get period configuation
  433. const PixelPeriodConfig *period_config = &Pixel_LED_FadePeriods[period];
  434. // Set period configuration
  435. Pixel_pixel_fade_profile_entries[profile].conf[config].start = period_config->start;
  436. Pixel_pixel_fade_profile_entries[profile].conf[config].end = period_config->end;
  437. // Reset the current period being processed
  438. Pixel_pixel_fade_profile_entries[profile].pos = 0;
  439. Pixel_pixel_fade_profile_entries[profile].period_conf = PixelPeriodIndex_Off_to_On;
  440. }
  441. void Pixel_FadeLayerHighlight_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  442. {
  443. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  444. // Get argument
  445. uint16_t layer = *(uint16_t*)(&args[0]);
  446. switch ( cstate )
  447. {
  448. case CapabilityState_Initial:
  449. // Refresh the fade profiles
  450. Pixel_SecondaryProcessing_profile_init();
  451. // Scan the layer for keys
  452. break;
  453. case CapabilityState_Last:
  454. // Refresh the fade profiles
  455. Pixel_SecondaryProcessing_profile_init();
  456. // If any layers are still active, re-run using top layer
  457. layer = Layer_topActive();
  458. if ( layer > 0 )
  459. {
  460. break;
  461. }
  462. return;
  463. case CapabilityState_Debug:
  464. // Display capability name
  465. print("Pixel_FadeLayerHighlight_capability(layer)");
  466. return;
  467. default:
  468. return;
  469. }
  470. // Interconnect broadcasting
  471. #if defined(ConnectEnabled_define)
  472. // By default send to the *next* node, which will determine where to go next
  473. extern uint8_t Connect_id; // connect_scan.c
  474. uint8_t addr = Connect_id + 1;
  475. // Send interconnect remote capability packet
  476. // generatedKeymap.h
  477. extern const Capability CapabilitiesList[];
  478. // Broadcast layerStackExact remote capability (0xFF is the broadcast id)
  479. Connect_send_RemoteCapability(
  480. addr,
  481. Pixel_FadeLayerHighlight_capability_index,
  482. state,
  483. stateType,
  484. CapabilitiesList[ Pixel_FadeLayerHighlight_capability_index ].argCount,
  485. args
  486. );
  487. #endif
  488. // Ignore if an invalid layer
  489. if ( layer >= LayerNum )
  490. {
  491. return;
  492. }
  493. // Lookup layer
  494. const Layer *layer_map = &LayerIndex[layer];
  495. #if KLL_LED_FadeActiveLayerInvert_define == 1
  496. // Default layer
  497. const Layer *default_map = &LayerIndex[0];
  498. // Add keys not in layer
  499. uint8_t key = 1; // Scan Codes start at 1
  500. for ( ; key <= layer_map->first; key++ )
  501. {
  502. // If we've exceeded the pixel lookup, ignore
  503. if ( key > MaxPixelToScanCode_KLL )
  504. {
  505. return;
  506. }
  507. uint8_t index = key - default_map->first;
  508. // If the first entry in trigger list is a 0, ignore (otherwise, key is in layer)
  509. if ( !Trigger_DetermineScanCodeOnTrigger( default_map, index ) )
  510. {
  511. continue;
  512. }
  513. // Lookup pixel associated with scancode (remember -1 as all pixels and scancodes start at 1, not 0)
  514. uint16_t pixel = Pixel_ScanCodeToPixel[key - 1];
  515. // If pixel is 0, ignore
  516. if ( pixel == 0 )
  517. {
  518. continue;
  519. }
  520. // Set pixel to group #4
  521. Pixel_pixel_fade_profile[pixel - 1] = 4;
  522. }
  523. // Iterate over every key in layer, skipping active keys
  524. for ( ; key <= layer_map->last; key++ )
  525. {
  526. // If we've exceeded the pixel lookup, ignore
  527. if ( key > MaxPixelToScanCode_KLL )
  528. {
  529. return;
  530. }
  531. uint8_t index = key - layer_map->first;
  532. // If the first entry in trigger list is a 0, set as this key is not in the layer
  533. // Ignore otherwise
  534. if ( Trigger_DetermineScanCodeOnTrigger( layer_map, index ) )
  535. {
  536. continue;
  537. }
  538. // If the first entry in trigger list is a 0, ignore (otherwise, key is in layer)
  539. if ( !Trigger_DetermineScanCodeOnTrigger( default_map, index ) )
  540. {
  541. continue;
  542. }
  543. // Lookup pixel associated with scancode (remember -1 as all pixels and scancodes start at 1, not 0)
  544. uint16_t pixel = Pixel_ScanCodeToPixel[key - 1];
  545. // If pixel is 0, ignore
  546. if ( pixel == 0 )
  547. {
  548. continue;
  549. }
  550. // Set pixel to group #4
  551. Pixel_pixel_fade_profile[pixel - 1] = 4;
  552. }
  553. // Add keys not in layer
  554. for ( ; key <= default_map->last; key++ )
  555. {
  556. // If we've exceeded the pixel lookup, ignore
  557. if ( key > MaxPixelToScanCode_KLL )
  558. {
  559. return;
  560. }
  561. uint8_t index = key - default_map->first;
  562. // If the first entry in trigger list is a 0, ignore (otherwise, key is in layer)
  563. if ( !Trigger_DetermineScanCodeOnTrigger( default_map, index ) )
  564. {
  565. continue;
  566. }
  567. // Lookup pixel associated with scancode (remember -1 as all pixels and scancodes start at 1, not 0)
  568. uint16_t pixel = Pixel_ScanCodeToPixel[key - 1];
  569. // If pixel is 0, ignore
  570. if ( pixel == 0 )
  571. {
  572. continue;
  573. }
  574. // Set pixel to group #4
  575. Pixel_pixel_fade_profile[pixel - 1] = 4;
  576. }
  577. #else
  578. // Lookup list of keys in layer
  579. for ( uint8_t key = layer_map->first; key <= layer_map->last; key++ )
  580. {
  581. uint8_t index = key - layer_map->first;
  582. // If the first entry in trigger list is a 0, ignore (otherwise, key is in layer)
  583. if ( !Trigger_DetermineScanCodeOnTrigger( layer_map, index ) )
  584. {
  585. continue;
  586. }
  587. // Lookup pixel associated with scancode (remember -1 as all pixels and scancodes start at 1, not 0)
  588. uint16_t pixel = Pixel_ScanCodeToPixel[key - 1];
  589. // If pixel is 0, ignore
  590. if ( pixel == 0 )
  591. {
  592. continue;
  593. }
  594. // Set pixel to group #4
  595. Pixel_pixel_fade_profile[pixel - 1] = 4;
  596. }
  597. #endif
  598. }
  599. void Pixel_FadeControl_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  600. {
  601. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  602. switch ( cstate )
  603. {
  604. case CapabilityState_Initial:
  605. // Only activate on press event
  606. break;
  607. case CapabilityState_Debug:
  608. // Display capability name
  609. print("Pixel_FadeControl_capability(test)");
  610. return;
  611. default:
  612. return;
  613. }
  614. // Get arguments
  615. uint8_t profile = args[0];
  616. uint8_t command = args[1];
  617. uint8_t arg = args[2];
  618. // Make sure profile is valid
  619. if ( profile >= sizeof(Pixel_pixel_fade_profile_entries) )
  620. {
  621. return;
  622. }
  623. // Process command
  624. uint16_t tmp;
  625. switch ( command )
  626. {
  627. case PixelFadeControl_Reset:
  628. for ( uint8_t config = 0; config < 4; config++ )
  629. {
  630. Pixel_pixel_fade_profile_entries[profile].conf[config] = \
  631. Pixel_LED_FadePeriods[Pixel_LED_FadePeriod_Defaults[profile][config]];
  632. }
  633. Pixel_pixel_fade_profile_entries[profile].pos = 0;
  634. Pixel_pixel_fade_profile_entries[profile].period_conf = PixelPeriodIndex_Off_to_On;
  635. Pixel_pixel_fade_profile_entries[profile].brightness = Pixel_LED_FadeBrightness[profile];
  636. break;
  637. case PixelFadeControl_Reset_All:
  638. // Setup fade defaults
  639. for ( uint8_t pr = 0; pr < 4; pr++ )
  640. {
  641. for ( uint8_t config = 0; config < 4; config++ )
  642. {
  643. Pixel_pixel_fade_profile_entries[pr].conf[config] = \
  644. Pixel_LED_FadePeriods[Pixel_LED_FadePeriod_Defaults[pr][config]];
  645. }
  646. Pixel_pixel_fade_profile_entries[pr].pos = 0;
  647. Pixel_pixel_fade_profile_entries[pr].period_conf = PixelPeriodIndex_Off_to_On;
  648. Pixel_pixel_fade_profile_entries[profile].brightness = Pixel_LED_FadeBrightness[pr];
  649. }
  650. break;
  651. case PixelFadeControl_Brightness_Set:
  652. // Set brightness
  653. Pixel_pixel_fade_profile_entries[profile].brightness = arg;
  654. break;
  655. case PixelFadeControl_Brightness_Increment:
  656. // Increment with no rollover
  657. tmp = Pixel_pixel_fade_profile_entries[profile].brightness;
  658. if ( tmp + arg > 0xFF )
  659. {
  660. Pixel_pixel_fade_profile_entries[profile].brightness = 0xFF;
  661. break;
  662. }
  663. Pixel_pixel_fade_profile_entries[profile].brightness += arg;
  664. break;
  665. case PixelFadeControl_Brightness_Decrement:
  666. // Decrement with no rollover
  667. tmp = Pixel_pixel_fade_profile_entries[profile].brightness;
  668. if ( tmp - arg < 0x00 )
  669. {
  670. Pixel_pixel_fade_profile_entries[profile].brightness = 0x00;
  671. break;
  672. }
  673. Pixel_pixel_fade_profile_entries[profile].brightness -= arg;
  674. break;
  675. case PixelFadeControl_Brightness_Default:
  676. Pixel_pixel_fade_profile_entries[profile].brightness = Pixel_LED_FadeBrightness[profile];
  677. break;
  678. default:
  679. return;
  680. }
  681. }
  682. void Pixel_LEDTest_capability( TriggerMacro *trigger, uint8_t state, uint8_t stateType, uint8_t *args )
  683. {
  684. CapabilityState cstate = KLL_CapabilityState( state, stateType );
  685. switch ( cstate )
  686. {
  687. case CapabilityState_Initial:
  688. // Only activate on press event
  689. break;
  690. case CapabilityState_Debug:
  691. // Display capability name
  692. print("Pixel_LEDTest_capability(test)");
  693. return;
  694. default:
  695. return;
  696. }
  697. // Get arguments
  698. PixelTest test = *(PixelTest*)(&args[0]);
  699. uint16_t index = *(uint16_t*)(&args[1]);
  700. // If index is not set to 0xFFFF, make sure to update the test position
  701. if ( index != 0xFFFF )
  702. {
  703. Pixel_testPos = index;
  704. }
  705. // Set the test mode
  706. Pixel_testMode = test;
  707. }
  708. // ----- Functions -----
  709. // -- Debug Functions --
  710. // Debug info for PixelElement
  711. void Pixel_showPixelElement( PixelElement *elem )
  712. {
  713. print("W:");
  714. printInt8( elem->width );
  715. print(" C:");
  716. printInt8( elem->channels );
  717. print(" I:");
  718. printInt16( elem->indices[0] );
  719. for ( uint8_t c = 1; c < elem->channels; c++ )
  720. {
  721. print(",");
  722. printInt16( elem->indices[c] );
  723. }
  724. }
  725. // -- Utility Functions --
  726. // TODO Support non-8bit channels
  727. uint8_t Pixel_8bitInterpolation( uint8_t start, uint8_t end, uint8_t dist )
  728. {
  729. return (start * (256 - dist) + end * dist) >> 8;
  730. }
  731. void Pixel_pixelInterpolate( PixelElement *elem, uint8_t position, uint8_t intensity )
  732. {
  733. // Toggle each of the channels of the pixel
  734. for ( uint8_t ch = 0; ch < elem->channels; ch++ )
  735. {
  736. uint16_t ch_pos = elem->indices[ch];
  737. PixelBuf *pixbuf = Pixel_bufferMap( ch_pos );
  738. PixelBuf16( pixbuf, ch_pos ) = Pixel_8bitInterpolation( 0, intensity, position * (ch + 1) );
  739. }
  740. }
  741. // -- Animation Stack --
  742. // Locates animation memory slot using default settings for the animation
  743. // Initiates animation to process on the next cycle
  744. // Returns 1 on success, 0 on failure to allocate
  745. uint8_t Pixel_addDefaultAnimation( uint32_t index )
  746. {
  747. if ( index >= Pixel_AnimationSettingsNum_KLL )
  748. {
  749. warn_msg("Invalid AnimationSetting index: ");
  750. printInt32( index );
  751. print( NL );
  752. return 0;
  753. }
  754. return Pixel_addAnimation( (AnimationStackElement*)&Pixel_AnimationSettings[ index ], CapabilityState_None );
  755. }
  756. // Allocates animaton memory slot
  757. // Initiates animation to process on the next cycle
  758. // Returns 1 on success, 0 on failure to allocate
  759. uint8_t Pixel_addAnimation( AnimationStackElement *element, CapabilityState cstate )
  760. {
  761. AnimationStackElement *found;
  762. switch ( element->replace )
  763. {
  764. case AnimationReplaceType_Basic:
  765. case AnimationReplaceType_All:
  766. found = Pixel_lookupAnimation( element->index, 0 );
  767. // If found, modify stack element
  768. if ( found != NULL && ( found->trigger == element->trigger || element->replace == AnimationReplaceType_All ) )
  769. {
  770. found->pos = element->pos;
  771. found->subpos = element->subpos;
  772. found->loops = element->loops;
  773. found->pfunc = element->pfunc;
  774. found->ffunc = element->ffunc;
  775. found->framedelay = element->framedelay;
  776. found->frameoption = element->frameoption;
  777. found->replace = element->replace;
  778. found->state = element->state;
  779. return 0;
  780. }
  781. break;
  782. // Replace on press and release
  783. // Press starts the animation
  784. // Release stops the animation
  785. case AnimationReplaceType_State:
  786. found = Pixel_lookupAnimation( element->index, 0 );
  787. switch ( cstate )
  788. {
  789. // Press
  790. case CapabilityState_Initial:
  791. // If found, modify stack element
  792. if ( found && found->trigger == element->trigger )
  793. {
  794. found->pos = element->pos;
  795. found->subpos = element->subpos;
  796. found->loops = element->loops;
  797. found->pfunc = element->pfunc;
  798. found->ffunc = element->ffunc;
  799. found->framedelay = element->framedelay;
  800. found->frameoption = element->frameoption;
  801. found->replace = element->replace;
  802. found->state = element->state;
  803. return 0;
  804. }
  805. break;
  806. // Release
  807. case CapabilityState_Last:
  808. // Only need to do something if the animation was found (which is stop)
  809. if ( found && found->trigger == element->trigger )
  810. {
  811. found->state = AnimationPlayState_Stop;
  812. }
  813. return 0;
  814. default:
  815. break;
  816. }
  817. break;
  818. // Clear all current animations from stack before adding new animation
  819. case AnimationReplaceType_Clear:
  820. Pixel_clearAnimations();
  821. break;
  822. // Clear all current animations from stack before adding new animation
  823. // Unless it's paused, and if it's paused do a replace if necessary
  824. case AnimationReplaceType_ClearActive:
  825. found = Pixel_lookupAnimation( element->index, 0 );
  826. // If found, modify stack element
  827. if ( found )
  828. {
  829. found->pos = element->pos;
  830. found->subpos = element->subpos;
  831. found->loops = element->loops;
  832. found->pfunc = element->pfunc;
  833. found->ffunc = element->ffunc;
  834. found->framedelay = element->framedelay;
  835. found->frameoption = element->frameoption;
  836. found->replace = element->replace;
  837. found->state = element->state;
  838. return 0;
  839. }
  840. // Iterate through stack, stopping animations that are not paused
  841. // and ignoring the found animation
  842. for ( uint16_t pos = 0; pos < Pixel_AnimationStack.size; pos++ )
  843. {
  844. // Ignore found animation
  845. if ( Pixel_AnimationStack.stack[pos] == found )
  846. {
  847. continue;
  848. }
  849. // Ignore paused animations (single will be paused on the next frame)
  850. if (
  851. ( Pixel_AnimationStack.stack[pos]->state & 0x7F ) == AnimationPlayState_Pause ||
  852. ( Pixel_AnimationStack.stack[pos]->state & 0x7F ) == AnimationPlayState_Single
  853. )
  854. {
  855. continue;
  856. }
  857. // Otherwise stop
  858. Pixel_AnimationStack.stack[pos]->state = AnimationPlayState_Stop;
  859. }
  860. break;
  861. default:
  862. break;
  863. }
  864. // Make sure there is room left on the stack
  865. if ( Pixel_AnimationStack.size >= Pixel_AnimationStackSize )
  866. {
  867. warn_print("Animation stack is full...");
  868. return 0;
  869. }
  870. // Add to animation stack
  871. // Processing is done from bottom to top of the stack
  872. // First find a free memory slot, this is not ordered, so we have to search for it
  873. uint16_t pos = 0;
  874. for ( ; pos < Pixel_AnimationStackSize; pos++ )
  875. {
  876. // Check if memory is unused
  877. if ( Pixel_AnimationElement_Stor[pos].index == 0xFFFF )
  878. {
  879. break;
  880. }
  881. }
  882. // No memory left
  883. // XXX This shouldn't happen
  884. if ( pos >= Pixel_AnimationStackSize )
  885. {
  886. erro_print("Animation Stack memory leak...this is a bug!");
  887. return 0;
  888. }
  889. // Set stack location
  890. Pixel_AnimationStack.stack[Pixel_AnimationStack.size++] = &Pixel_AnimationElement_Stor[pos];
  891. // Copy animation settings
  892. memcpy( &Pixel_AnimationElement_Stor[pos], element, sizeof(AnimationStackElement) );
  893. return 1;
  894. }
  895. // Removes the first index of an animation
  896. // Will be popped from the stack on the next animation processing loop
  897. uint8_t Pixel_delAnimation( uint16_t index, uint8_t finish )
  898. {
  899. // Find animation by index, look for the *first* one
  900. uint16_t pos = 0;
  901. for ( ; pos < Pixel_AnimationStackSize; pos++ )
  902. {
  903. // Check if memory is unused
  904. if ( Pixel_AnimationElement_Stor[pos].index == index )
  905. {
  906. // Let animation finish it's last frame
  907. if ( finish )
  908. {
  909. Pixel_AnimationElement_Stor[pos].loops = 1;
  910. }
  911. else
  912. {
  913. Pixel_AnimationElement_Stor[pos].index = 0xFFFF;
  914. }
  915. return 1;
  916. }
  917. }
  918. return 0;
  919. }
  920. // Cleans/resets animation stack. Removes all running animations.
  921. // NOTE: Does not clear the output buffer
  922. void Pixel_clearAnimations()
  923. {
  924. // Set stack size to 0
  925. Pixel_AnimationStack.size = 0;
  926. // Set indices to max value to indicate un-allocated
  927. for ( uint16_t pos = 0; pos < Pixel_AnimationStackSize; pos++ )
  928. {
  929. Pixel_AnimationElement_Stor[pos].index = 0xFFFF;
  930. }
  931. }
  932. // Clears all pixels
  933. void Pixel_clearPixels()
  934. {
  935. // Update all positions
  936. for ( uint16_t px = 0; px < Pixel_TotalPixels_KLL; px++ )
  937. {
  938. // Unset pixel
  939. Pixel_pixelSet( (PixelElement*)&Pixel_Mapping[ px ], 0 );
  940. }
  941. }
  942. // Animation ID lookup
  943. // - Does lookup from bottom to top
  944. // - Set previous element to look for the next one
  945. // - Set prev to 0 to start from the beginning
  946. // - Returns NULL/0 if not found
  947. AnimationStackElement *Pixel_lookupAnimation( uint16_t index, uint16_t prev )
  948. {
  949. uint16_t pos = prev;
  950. // Look for next instance of index
  951. for ( ; pos < Pixel_AnimationStack.size; pos++ )
  952. {
  953. // Check if index matches
  954. if ( Pixel_AnimationStack.stack[pos]->index == index )
  955. {
  956. return Pixel_AnimationStack.stack[pos];
  957. }
  958. }
  959. // Could not find, return NULL
  960. return NULL;
  961. }
  962. // Iterate over each element in the Animation Stack
  963. // If the animation is complete, do not re-add to the stack
  964. // - The stack is re-built each time.
  965. // - Ignores any stack element indices set to 0xFFFF/-1 (max)
  966. void Pixel_stackProcess()
  967. {
  968. uint16_t pos = 0;
  969. uint16_t size = Pixel_AnimationStack.size;
  970. // We reset the stack size, and rebuild the stack on the fly
  971. Pixel_AnimationStack.size = 0;
  972. // Process each element of the stack
  973. for ( ; pos < size; pos++ )
  974. {
  975. // Lookup animation stack element
  976. AnimationStackElement *elem = Pixel_AnimationStack.stack[pos];
  977. // Ignore animation if index is 0xFFFF (max)
  978. if ( elem->index == 0xFFFF )
  979. {
  980. continue;
  981. }
  982. // Store index, in case we need to send an event
  983. uint16_t cur_index = elem->index;
  984. // Process animation element
  985. if ( Pixel_animationProcess( elem ) )
  986. {
  987. // Re-add animation to stack
  988. Pixel_AnimationStack.stack[Pixel_AnimationStack.size++] = elem;
  989. }
  990. else
  991. {
  992. // Signal that animation finished
  993. Macro_animationState( cur_index, ScheduleType_Done );
  994. }
  995. }
  996. }
  997. // -- Pixel Control --
  998. // PixelBuf lookup
  999. // - Determines which buffer a channel resides in
  1000. PixelBuf *Pixel_bufferMap( uint16_t channel )
  1001. {
  1002. // TODO Generate based on keyboard
  1003. #if ISSI_Chip_31FL3731_define == 1 || ISSI_Chip_31FL3732_define == 1
  1004. if ( channel < 144 ) return &Pixel_Buffers[0];
  1005. else if ( channel < 288 ) return &Pixel_Buffers[1];
  1006. else if ( channel < 432 ) return &Pixel_Buffers[2];
  1007. else if ( channel < 576 ) return &Pixel_Buffers[3];
  1008. #elif ISSI_Chip_31FL3733_define == 1
  1009. if ( channel < 192 ) return &Pixel_Buffers[0];
  1010. else if ( channel < 384 ) return &Pixel_Buffers[1];
  1011. else if ( channel < 576 ) return &Pixel_Buffers[2];
  1012. #else
  1013. if ( channel < 192 ) return &Pixel_Buffers[0];
  1014. else if ( channel < 384 ) return &Pixel_Buffers[1];
  1015. else if ( channel < 576 ) return &Pixel_Buffers[2];
  1016. #endif
  1017. // Invalid channel, return first channel and display error
  1018. erro_msg("Invalid channel: ");
  1019. printHex( channel );
  1020. print( NL );
  1021. return 0;
  1022. }
  1023. // PixelBuf lookup (LED_Buffers)
  1024. // - Determines which buffer a channel resides in
  1025. PixelBuf *LED_bufferMap( uint16_t channel )
  1026. {
  1027. // TODO Generate based on keyboard
  1028. #if ISSI_Chip_31FL3731_define == 1 || ISSI_Chip_31FL3732_define == 1
  1029. if ( channel < 144 ) return &LED_Buffers[0];
  1030. else if ( channel < 288 ) return &LED_Buffers[1];
  1031. else if ( channel < 432 ) return &LED_Buffers[2];
  1032. else if ( channel < 576 ) return &LED_Buffers[3];
  1033. #elif ISSI_Chip_31FL3733_define == 1
  1034. if ( channel < 192 ) return &LED_Buffers[0];
  1035. else if ( channel < 384 ) return &LED_Buffers[1];
  1036. else if ( channel < 576 ) return &LED_Buffers[2];
  1037. #else
  1038. if ( channel < 192 ) return &LED_Buffers[0];
  1039. else if ( channel < 384 ) return &LED_Buffers[1];
  1040. else if ( channel < 576 ) return &LED_Buffers[2];
  1041. #endif
  1042. // Invalid channel, return first channel and display error
  1043. erro_msg("Invalid channel (LED): ");
  1044. printHex( channel );
  1045. print( NL );
  1046. return 0;
  1047. }
  1048. #define PixelChange_Expansion(pixbuf, ch_pos, mod_value, op) \
  1049. /* Lookup buffer to data width mapping */ \
  1050. switch ( pixbuf->width ) \
  1051. { \
  1052. case 8: /* 8 bit mapping */ \
  1053. PixelBuf8( pixbuf, ch_pos ) op (uint8_t)mod_value; break; \
  1054. case 16: /* 16 bit mapping */ \
  1055. PixelBuf16( pixbuf, ch_pos ) op (uint16_t)mod_value; break; \
  1056. case 32: /* 32 bit mapping */ \
  1057. PixelBuf32( pixbuf, ch_pos ) op (uint32_t)mod_value; break; \
  1058. default: \
  1059. warn_print("Invalid width mapping for "#op ); \
  1060. break; \
  1061. }
  1062. // Pixel Evaluation
  1063. // - Iterates over each of the Pixel channels and applies modifications
  1064. void Pixel_pixelEvaluation( PixelModElement *mod, PixelElement *elem )
  1065. {
  1066. // Ignore if no element
  1067. if ( elem == 0 )
  1068. {
  1069. return;
  1070. }
  1071. // Lookup number of channels in pixel
  1072. uint8_t channels = elem->channels;
  1073. // Data position iterator
  1074. uint8_t position_iter = 0;
  1075. // Apply operation to each channel of the pixel
  1076. for ( uint8_t ch = 0; ch < channels; ch++ )
  1077. {
  1078. // Lookup channel position
  1079. uint16_t ch_pos = elem->indices[ch];
  1080. // Determine which buffer we are in
  1081. PixelBuf *pixbuf = Pixel_bufferMap( ch_pos );
  1082. // Invalid channel, stop
  1083. if ( pixbuf == 0 )
  1084. {
  1085. break;
  1086. }
  1087. // Change Type (first 8 bits of each channel of data, see pixel.h for layout)
  1088. PixelChange change = (PixelChange)mod->data[ position_iter++ ];
  1089. // Modification Value
  1090. uint32_t mod_value = 0;
  1091. // Lookup modification value
  1092. switch ( elem->width )
  1093. {
  1094. case 8:
  1095. mod_value = mod->data[ position_iter++ ];
  1096. break;
  1097. case 16:
  1098. mod_value = mod->data[ position_iter + 1 ] |
  1099. ( mod->data[ position_iter + 2 ] << 8 );
  1100. position_iter += 2;
  1101. break;
  1102. case 32:
  1103. mod_value = mod->data[ position_iter + 1 ] |
  1104. ( mod->data[ position_iter + 2 ] << 8 ) |
  1105. ( mod->data[ position_iter + 3 ] << 16 ) |
  1106. ( mod->data[ position_iter + 4 ] << 24 );
  1107. position_iter += 4;
  1108. break;
  1109. default:
  1110. warn_print("Invalid PixelElement width mapping");
  1111. break;
  1112. }
  1113. // Operation
  1114. switch ( change )
  1115. {
  1116. case PixelChange_Set: // =
  1117. PixelChange_Expansion( pixbuf, ch_pos, mod_value, = );
  1118. break;
  1119. case PixelChange_Add: // +
  1120. PixelChange_Expansion( pixbuf, ch_pos, mod_value, += );
  1121. break;
  1122. case PixelChange_Subtract: // -
  1123. PixelChange_Expansion( pixbuf, ch_pos, mod_value, -= );
  1124. break;
  1125. case PixelChange_LeftShift: // <<
  1126. PixelChange_Expansion( pixbuf, ch_pos, mod_value, <<= );
  1127. break;
  1128. case PixelChange_RightShift: // >>
  1129. PixelChange_Expansion( pixbuf, ch_pos, mod_value, >>= );
  1130. break;
  1131. case PixelChange_NoRoll_Add: // +:
  1132. // Lookup buffer to data width mapping
  1133. switch ( pixbuf->width )
  1134. {
  1135. case 8: // 8 bit mapping
  1136. {
  1137. uint8_t prev = PixelBuf8( pixbuf, ch_pos );
  1138. PixelBuf8( pixbuf, ch_pos ) += (uint8_t)mod_value;
  1139. if ( prev > PixelBuf8( pixbuf, ch_pos ) )
  1140. PixelBuf8( pixbuf, ch_pos ) = 0xFF;
  1141. break;
  1142. }
  1143. case 16: // 16 bit mapping
  1144. {
  1145. // TODO Fix for 16 on 8 bit (i.e. early K-Type)
  1146. //uint16_t prev = PixelBuf16( pixbuf, ch_pos );
  1147. PixelBuf16( pixbuf, ch_pos ) += (uint16_t)mod_value;
  1148. /*
  1149. if ( prev > PixelBuf16( pixbuf, ch_pos ) )
  1150. PixelBuf16( pixbuf, ch_pos ) = 0xFFFF;
  1151. */
  1152. if ( 0xFF < PixelBuf16( pixbuf, ch_pos ) )
  1153. PixelBuf16( pixbuf, ch_pos ) = 0xFF;
  1154. break;
  1155. }
  1156. case 32: // 32 bit mapping
  1157. {
  1158. uint32_t prev = PixelBuf32( pixbuf, ch_pos );
  1159. PixelBuf32( pixbuf, ch_pos ) += (uint32_t)mod_value;
  1160. if ( prev > PixelBuf32( pixbuf, ch_pos ) )
  1161. PixelBuf32( pixbuf, ch_pos ) = 0xFFFFFFFF;
  1162. break;
  1163. }
  1164. default:
  1165. warn_print("Invalid width mapping on set");
  1166. break;
  1167. }
  1168. break;
  1169. case PixelChange_NoRoll_Subtract: // -:
  1170. // Lookup buffer to data width mapping
  1171. switch ( pixbuf->width )
  1172. {
  1173. case 8: // 8 bit mapping
  1174. {
  1175. uint8_t prev = PixelBuf8( pixbuf, ch_pos );
  1176. PixelBuf8( pixbuf, ch_pos ) -= (uint8_t)mod_value;
  1177. if ( prev < PixelBuf8( pixbuf, ch_pos ) )
  1178. PixelBuf8( pixbuf, ch_pos ) = 0;
  1179. break;
  1180. }
  1181. case 16: // 16 bit mapping
  1182. {
  1183. uint16_t prev = PixelBuf16( pixbuf, ch_pos );
  1184. PixelBuf16( pixbuf, ch_pos ) -= (uint16_t)mod_value;
  1185. if ( prev < PixelBuf16( pixbuf, ch_pos ) )
  1186. PixelBuf16( pixbuf, ch_pos ) = 0;
  1187. break;
  1188. }
  1189. case 32: // 32 bit mapping
  1190. {
  1191. uint32_t prev = PixelBuf32( pixbuf, ch_pos );
  1192. PixelBuf32( pixbuf, ch_pos ) -= (uint32_t)mod_value;
  1193. if ( prev < PixelBuf32( pixbuf, ch_pos ) )
  1194. PixelBuf32( pixbuf, ch_pos ) = 0;
  1195. break;
  1196. }
  1197. default:
  1198. warn_print("Invalid width mapping on set");
  1199. break;
  1200. }
  1201. break;
  1202. default:
  1203. warn_print("Unimplemented pixel modifier");
  1204. break;
  1205. }
  1206. }
  1207. }
  1208. // -- Fill Algorithms --
  1209. // Fill Algorithm Pixel Lookup
  1210. // - **elem stores a pointer to the PixelElement which can be used to lookup the channel buffer location
  1211. // - Determines which pixel element to work on next
  1212. // - If type:index has more than one pixel, non-0 is returned
  1213. // - The return value signifies the next value to set the prev argument
  1214. // - Once the function returns 0, all pixels have been processed
  1215. uint16_t Pixel_fillPixelLookup(
  1216. PixelModElement *mod,
  1217. PixelElement **elem,
  1218. uint16_t prev,
  1219. AnimationStackElement *stack_elem,
  1220. uint16_t *valid
  1221. )
  1222. {
  1223. // Used to determine next pixel in column or row (fill)
  1224. uint16_t cur = prev;
  1225. uint16_t index = 0;
  1226. // Assume invalid (i.e. do not evaluate pixel unless we are sure it's valid)
  1227. *valid = 0;
  1228. // Default to nothing found
  1229. *elem = 0;
  1230. // Lookup fill algorith
  1231. switch ( mod->type )
  1232. {
  1233. case PixelAddressType_Index:
  1234. // Lookup pixel by absolute index
  1235. *elem = (PixelElement*)&Pixel_Mapping[mod->index] - 1;
  1236. if ( mod->index <= Pixel_TotalPixels_KLL )
  1237. {
  1238. *valid = 1;
  1239. }
  1240. break;
  1241. case PixelAddressType_Rect:
  1242. // Make sure row,column exists
  1243. if ( mod->rect.col >= Pixel_DisplayMapping_Cols_KLL
  1244. && mod->rect.row >= Pixel_DisplayMapping_Rows_KLL )
  1245. {
  1246. erro_msg("Invalid row,column index: ");
  1247. printInt16( mod->rect.row );
  1248. print(",");
  1249. printInt16( mod->rect.col );
  1250. print( NL );
  1251. break;
  1252. }
  1253. // Lookup pixel in rectangle display organization
  1254. *elem = (PixelElement*)&Pixel_Mapping[
  1255. Pixel_DisplayMapping[
  1256. mod->rect.row * Pixel_DisplayMapping_Cols_KLL + mod->rect.col
  1257. ] - 1
  1258. ];
  1259. *valid = 1;
  1260. break;
  1261. case PixelAddressType_ColumnFill:
  1262. // Lookup pixel until either, non-0 index or we reached the last row
  1263. do {
  1264. // Check if we've processed all rows
  1265. if ( cur >= Pixel_DisplayMapping_Rows_KLL )
  1266. {
  1267. return 0;
  1268. }
  1269. // Pixel index
  1270. index = Pixel_DisplayMapping[ cur * Pixel_DisplayMapping_Cols_KLL + mod->rect.col ];
  1271. cur++;
  1272. } while ( index == 0 );
  1273. // Validate index is actually a valid evaluation
  1274. if ( index <= Pixel_TotalPixels_KLL )
  1275. {
  1276. *valid = 1;
  1277. }
  1278. // Lookup pixel, pixels are 1 indexed, hence the -1
  1279. *elem = (PixelElement*)&Pixel_Mapping[ index - 1 ];
  1280. return cur;
  1281. case PixelAddressType_RowFill:
  1282. // Lookup pixel until either, non-0 index or we reached the last column
  1283. do {
  1284. // Check if we've processed all rows
  1285. if ( cur >= Pixel_DisplayMapping_Cols_KLL )
  1286. {
  1287. return 0;
  1288. }
  1289. // Pixel index
  1290. index = Pixel_DisplayMapping[ mod->rect.row * Pixel_DisplayMapping_Cols_KLL + cur ];
  1291. cur++;
  1292. } while ( index == 0 );
  1293. // Validate index is actually a valid evaluation
  1294. if ( index <= Pixel_TotalPixels_KLL )
  1295. {
  1296. *valid = 1;
  1297. }
  1298. // Lookup pixel, pixels are 1 indexed, hence the -1
  1299. *elem = (PixelElement*)&Pixel_Mapping[ index - 1 ];
  1300. return cur;
  1301. case PixelAddressType_ScanCode:
  1302. // Make sure ScanCode exists
  1303. if ( mod->index > MaxScanCode_KLL )
  1304. {
  1305. erro_msg("Invalid ScanCode: ");
  1306. printInt16( mod->index );
  1307. print( NL );
  1308. break;
  1309. }
  1310. *valid = 1;
  1311. // Lookup ScanCode - Indices are 1-indexed in both arrays (hence the -1)
  1312. uint16_t pixel = Pixel_ScanCodeToPixel[ mod->index - 1 ];
  1313. *elem = (PixelElement*)&Pixel_Mapping[ pixel - 1 ];
  1314. break;
  1315. case PixelAddressType_RelativeIndex:
  1316. // TODO
  1317. break;
  1318. case PixelAddressType_RelativeRect:
  1319. {
  1320. // Determine scancode to be relative from
  1321. uint8_t scan_code = Pixel_determineLastTriggerScanCode( stack_elem->trigger );
  1322. // Lookup display position of scancode
  1323. uint16_t position = Pixel_ScanCodeToDisplay[ scan_code - 1 ];
  1324. // Calculate rectangle offset
  1325. position += (int16_t)mod->rect.row * Pixel_DisplayMapping_Cols_KLL + (int16_t)mod->rect.col;
  1326. // Make sure position exists
  1327. if ( position >= Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL )
  1328. {
  1329. break;
  1330. }
  1331. // Lookup pixel, pixels are 1 indexed, hence the -1
  1332. index = Pixel_DisplayMapping[ position ];
  1333. // Validate index is actually a valid evaluation
  1334. if ( index <= Pixel_TotalPixels_KLL && index != 0 )
  1335. {
  1336. *valid = 1;
  1337. *elem = (PixelElement*)&Pixel_Mapping[ index - 1 ];
  1338. }
  1339. break;
  1340. }
  1341. case PixelAddressType_RelativeColumnFill:
  1342. {
  1343. // Determine scancode to be relative from
  1344. uint8_t scan_code = Pixel_determineLastTriggerScanCode( stack_elem->trigger );
  1345. // Lookup display position of scancode
  1346. uint16_t position = Pixel_ScanCodeToDisplay[ scan_code - 1 ];
  1347. // Calculate rectangle offset
  1348. position += (int16_t)mod->rect.col;
  1349. // Make sure column exists
  1350. if ( position >= Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL )
  1351. {
  1352. erro_msg("Invalid position index (relcol): ");
  1353. printInt16( position );
  1354. print( NL );
  1355. break;
  1356. }
  1357. // Determine first row in column
  1358. position %= Pixel_DisplayMapping_Cols_KLL;
  1359. // Lookup pixel until either, non-0 index or we reached the last row
  1360. do {
  1361. // Current position
  1362. uint16_t curpos = cur++ * Pixel_DisplayMapping_Cols_KLL + position;
  1363. // Check if we've gone too far (and finished all rows)
  1364. if ( curpos >= Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL )
  1365. {
  1366. return 0;
  1367. }
  1368. // Pixel index
  1369. index = Pixel_DisplayMapping[ curpos ];
  1370. } while ( index == 0 );
  1371. // Validate index is actually a valid evaluation
  1372. if ( index <= Pixel_TotalPixels_KLL )
  1373. {
  1374. *valid = 1;
  1375. }
  1376. // Lookup pixel, pixels are 1 indexed, hence the -1
  1377. *elem = (PixelElement*)&Pixel_Mapping[ index - 1 ];
  1378. return cur;
  1379. }
  1380. case PixelAddressType_RelativeRowFill:
  1381. {
  1382. // Determine scancode to be relative from
  1383. uint8_t scan_code = Pixel_determineLastTriggerScanCode( stack_elem->trigger );
  1384. // Lookup display position of scancode
  1385. uint16_t position = Pixel_ScanCodeToDisplay[ scan_code - 1 ];
  1386. // Calculate rectangle offset
  1387. position += (int16_t)mod->rect.row * Pixel_DisplayMapping_Rows_KLL;
  1388. // Make sure column exists
  1389. if ( position >= Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL )
  1390. {
  1391. erro_msg("Invalid position index (relrow): ");
  1392. printInt16( position );
  1393. print( NL );
  1394. break;
  1395. }
  1396. // Determine which row we are in
  1397. position /= Pixel_DisplayMapping_Cols_KLL;
  1398. // Lookup pixel until either, non-0 index or we reached the last row
  1399. do {
  1400. // Current position
  1401. uint16_t curpos = cur++ + Pixel_DisplayMapping_Cols_KLL * position;
  1402. // Check if we've gone too far (and finished all rows)
  1403. if ( cur >= Pixel_DisplayMapping_Cols_KLL )
  1404. {
  1405. return 0;
  1406. }
  1407. // Pixel index
  1408. index = Pixel_DisplayMapping[ curpos ];
  1409. } while ( index == 0 );
  1410. // Validate index is actually a valid evaluation
  1411. if ( index <= Pixel_TotalPixels_KLL )
  1412. {
  1413. *valid = 1;
  1414. }
  1415. // Lookup pixel, pixels are 1 indexed, hence the -1
  1416. *elem = (PixelElement*)&Pixel_Mapping[ index - 1 ];
  1417. return cur;
  1418. }
  1419. // Skip
  1420. default:
  1421. break;
  1422. }
  1423. return 0;
  1424. }
  1425. // -- Pixel Tweening --
  1426. uint16_t Pixel_pixelTweenNextPos( PixelElement *elem, PixelElement *prev )
  1427. {
  1428. // No elem found
  1429. // XXX (HaaTa) This is actually a hard problem for relative animations
  1430. // We may not find any element initially, so we don't know anothing to increment the position
  1431. // The best solution may be to just find a relatively nearby pixel and use that info...
  1432. // Or waste enough more flash...
  1433. uint16_t ret = 0;
  1434. #if Pixel_HardCode_ChanWidth_define != 0 && Pixel_HardCode_Channels_define != 0
  1435. // More efficient tweening, as we know the number of channels and width at compile time in all cases.
  1436. ret = (
  1437. ( Pixel_HardCode_ChanWidth_define / 8 + sizeof( PixelChange ) )
  1438. * Pixel_HardCode_Channels_define
  1439. ) + sizeof( PixelModElement );
  1440. #else
  1441. // Determine tweening using nearby pixel definitions
  1442. // First try the next element
  1443. if ( elem != 0 )
  1444. {
  1445. ret = ( ( elem->width / 8 + sizeof( PixelChange ) ) * elem->channels ) + sizeof( PixelModElement );
  1446. return ret;
  1447. }
  1448. // Next try the previous element
  1449. if ( prev != 0 )
  1450. {
  1451. ret = ( ( prev->width / 8 + sizeof( PixelChange ) ) * prev->channels ) + sizeof( PixelModElement );
  1452. return ret;
  1453. }
  1454. // BAD BAD BAD
  1455. // TODO - This is BAD, will break in most cases, except for K-Type like keyboards.
  1456. erro_print("Pixel Tween Bug!");
  1457. ret = ( ( 8 / 8 + sizeof( PixelChange ) ) * 3 ) + sizeof( PixelModElement );
  1458. #endif
  1459. return ret;
  1460. }
  1461. // Standard Pixel Pixel Function (standard lookup, no additonal processing)
  1462. void Pixel_pixelTweenStandard( const uint8_t *frame, AnimationStackElement *stack_elem )
  1463. {
  1464. // Iterate over all of the Pixel Modifier elements of the Animation Frame
  1465. uint16_t pos = 0;
  1466. PixelModElement *mod = (PixelModElement*)&frame[pos];
  1467. while ( mod->type != PixelAddressType_End )
  1468. {
  1469. // Lookup type of pixel, choose fill algorith and query all sub-pixels
  1470. uint16_t next = 0;
  1471. uint16_t valid = 0;
  1472. PixelElement *prev_pixel_elem = 0;
  1473. PixelElement *elem = 0;
  1474. do {
  1475. // Last element
  1476. prev_pixel_elem = elem;
  1477. // Lookup pixel, and check if there are any more pixels left
  1478. next = Pixel_fillPixelLookup( mod, &elem, next, stack_elem, &valid );
  1479. // Apply operation to pixel
  1480. Pixel_pixelEvaluation( mod, elem );
  1481. } while ( next );
  1482. // Determine next position
  1483. pos += Pixel_pixelTweenNextPos( elem, prev_pixel_elem );
  1484. // Lookup next mod element
  1485. mod = (PixelModElement*)&frame[pos];
  1486. }
  1487. }
  1488. // Basic interpolation Pixel Pixel Function
  1489. // TODO - Only works with Colummn and Row fill currently
  1490. void Pixel_pixelTweenInterpolation( const uint8_t *frame, AnimationStackElement *stack_elem )
  1491. {
  1492. // Iterate over all of the Pixel Modifier elements of the Animation Frame
  1493. uint16_t pos = 0;
  1494. PixelModElement *prev = 0;
  1495. PixelModElement *mod = (PixelModElement*)&frame[pos];
  1496. while ( mod->type != PixelAddressType_End )
  1497. {
  1498. // By default, no interpolation
  1499. int32_t start = mod->index;
  1500. int32_t end = mod->index;
  1501. // Calculate interpolation position
  1502. // TODO Depends on addressing type
  1503. // TODO Work with dis-similar PixelModElement address types
  1504. switch ( mod->type )
  1505. {
  1506. case PixelAddressType_ColumnFill:
  1507. // If this is the first pixel, just set start at the same spot
  1508. start = prev != 0 ? prev->rect.col : mod->rect.col;
  1509. end = mod->rect.col;
  1510. break;
  1511. case PixelAddressType_RowFill:
  1512. // If this is the first pixel, just set start at the same spot
  1513. start = prev != 0 ? prev->rect.row : mod->rect.row;
  1514. end = mod->rect.row;
  1515. break;
  1516. case PixelAddressType_Rect:
  1517. // TODO - This is not correct (just a quick and dirty hack)
  1518. if ( prev != 0 )
  1519. {
  1520. // TODO - Diagonal interpolation?
  1521. if ( prev->rect.col != mod->rect.col )
  1522. {
  1523. start = prev->rect.col;
  1524. }
  1525. if ( prev->rect.row != mod->rect.row )
  1526. {
  1527. start = prev->rect.row;
  1528. }
  1529. }
  1530. else
  1531. {
  1532. start = mod->rect.col;
  1533. }
  1534. //end = ( mod->rect.col + mod->rect.row ) / 2;
  1535. end = mod->rect.col;
  1536. break;
  1537. case PixelAddressType_ScanCode:
  1538. // If this is the first pixel, just set start at the same spot
  1539. start = prev != 0 ? prev->index : mod->index;
  1540. end = mod->index;
  1541. break;
  1542. case PixelAddressType_Index:
  1543. // If this is the first pixel, just set start at the same spot
  1544. start = prev != 0 ? prev->index : mod->index;
  1545. end = mod->index;
  1546. break;
  1547. default:
  1548. break;
  1549. }
  1550. // Lookup prev and mod PixelElements
  1551. PixelElement *prev_elem = 0;
  1552. uint16_t valid = 0;
  1553. if ( prev != 0 )
  1554. {
  1555. Pixel_fillPixelLookup( prev, &prev_elem, 0, stack_elem, &valid );
  1556. }
  1557. PixelElement *mod_elem = 0;
  1558. Pixel_fillPixelLookup( mod, &mod_elem, 0, stack_elem, &valid );
  1559. // Data variable for PixelModElement
  1560. // TODO (HaaTa) Allow for smal…

Large files files are truncated, but you can click here to view the full file