PageRenderTime 68ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  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 smaller bit widths than 8, and sizes larger than 24-bits
  1561. const uint8_t data_max_size = sizeof( PixelModElement ) + ( sizeof( PixelModDataElement ) + 1 ) * 3;
  1562. uint8_t interp_data[ data_max_size ];
  1563. // Make sure mod_elem is pointing to something, if not, this could be a blank
  1564. // In which case continue to the next definition
  1565. if ( mod_elem == 0 )
  1566. {
  1567. goto next;
  1568. }
  1569. #ifndef __clang__
  1570. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  1571. #endif
  1572. PixelElement *prev_pixel_elem = 0;
  1573. #ifndef __clang__
  1574. #pragma GCC diagnostic pop
  1575. #endif
  1576. PixelElement *elem = 0;
  1577. // Prepare tweened PixelModElement
  1578. #if Pixel_HardCode_ChanWidth_define != 0 && Pixel_HardCode_Channels_define != 0
  1579. // More efficient tweening, as we know the number of channels and width at compile time in all cases.
  1580. uint8_t data_size = (
  1581. ( Pixel_HardCode_ChanWidth_define / 8 + sizeof( PixelChange ) )
  1582. * Pixel_HardCode_Channels_define
  1583. ) + sizeof( PixelModElement );
  1584. #else
  1585. uint8_t data_size = prev_elem != 0
  1586. ? sizeof( PixelModElement ) + ( sizeof( PixelModDataElement ) + prev_elem->width / 8 ) * prev_elem->channels
  1587. : sizeof( PixelModElement ) + ( sizeof( PixelModDataElement ) + mod_elem->width / 8 ) * mod_elem->channels;
  1588. #endif
  1589. if ( data_size > data_max_size )
  1590. {
  1591. warn_msg("Bad data size for this frame: ");
  1592. printInt8( data_size );
  1593. print(" instead of ");
  1594. printInt8( data_max_size );
  1595. print(NL);
  1596. data_size = data_max_size;
  1597. }
  1598. PixelModElement *interp_mod = (PixelModElement*)&interp_data;
  1599. memcpy( interp_mod, mod, data_size );
  1600. // Calculate slice mulitplier size
  1601. // TODO Non-8bit
  1602. // XXX Division...
  1603. uint16_t slice = prev != 0 ? 256 / (end - start + 1) : 0;
  1604. // Iterate over tween-pixels
  1605. for ( int32_t cur = 0; cur < end - start + 1; cur++ )
  1606. {
  1607. // Determine where the tween pixel is
  1608. switch ( mod->type )
  1609. {
  1610. case PixelAddressType_ColumnFill:
  1611. interp_mod->rect.col = start + cur;
  1612. // Ignore invalid columns
  1613. if ( interp_mod->rect.col >= Pixel_DisplayMapping_Cols_KLL || interp_mod->rect.col < 0 )
  1614. {
  1615. continue;
  1616. }
  1617. break;
  1618. case PixelAddressType_RowFill:
  1619. interp_mod->rect.row = start + cur;
  1620. // Ignore invalid rows
  1621. if ( interp_mod->rect.row >= Pixel_DisplayMapping_Rows_KLL || interp_mod->rect.row < 0 )
  1622. {
  1623. continue;
  1624. }
  1625. break;
  1626. case PixelAddressType_Rect:
  1627. // TODO - This is not correct (just a quick and dirty hack)
  1628. interp_mod->rect.col = 0;
  1629. interp_mod->rect.row = 0;
  1630. if ( prev != 0 )
  1631. {
  1632. interp_mod->rect.col = prev->rect.col + cur;
  1633. interp_mod->rect.row = 0;
  1634. //interp_mod->rect.row = prev->rect.row + cur;
  1635. }
  1636. break;
  1637. case PixelAddressType_ScanCode:
  1638. interp_mod->index = start + cur;
  1639. // Ignore un-assigned ScanCodes
  1640. if ( Pixel_ScanCodeToDisplay[interp_mod->index - 1] == 0 )
  1641. {
  1642. continue;
  1643. }
  1644. break;
  1645. case PixelAddressType_Index:
  1646. interp_mod->index = start + cur;
  1647. // Ignore unused pixels (this is uncommon)
  1648. if ( Pixel_Mapping[interp_mod->index - 1].width == 0 || Pixel_Mapping[interp_mod->index - 1].channels == 0 )
  1649. {
  1650. continue;
  1651. }
  1652. break;
  1653. default:
  1654. break;
  1655. }
  1656. // Calculate interpolation pixel value
  1657. // Uses prev to current PixelMods as the base
  1658. // TODO Non-8bit
  1659. if ( prev != 0 )
  1660. {
  1661. int32_t distance = slice * cur;
  1662. for ( uint8_t ch = 0; ch < mod_elem->channels; ch++ )
  1663. {
  1664. uint8_t pos = ch * 2 + 1; // TODO Only works with 8 bit channels
  1665. interp_mod->data[pos] = Pixel_8bitInterpolation(
  1666. prev->data[pos],
  1667. mod->data[pos],
  1668. distance
  1669. );
  1670. }
  1671. }
  1672. // Lookup type of pixel, choose fill algorith and query all sub-pixels
  1673. uint16_t next = 0;
  1674. uint16_t valid = 0;
  1675. do {
  1676. // Previous element
  1677. prev_pixel_elem = elem;
  1678. // Lookup pixel, and check if there are any more pixels left
  1679. next = Pixel_fillPixelLookup( interp_mod, &elem, next, stack_elem, &valid );
  1680. // Apply operation to pixel if at a valid location
  1681. if ( valid )
  1682. {
  1683. Pixel_pixelEvaluation( interp_mod, elem );
  1684. }
  1685. } while ( next );
  1686. }
  1687. next:
  1688. // This may have been a valid frame in an invalid position
  1689. // Store it so we can still use it for interpolation purposes
  1690. prev = mod;
  1691. // Determine next position
  1692. #ifndef __clang__
  1693. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  1694. #endif
  1695. pos += Pixel_pixelTweenNextPos( elem, prev_pixel_elem );
  1696. #ifndef __clang__
  1697. #pragma GCC diagnostic pop
  1698. #endif
  1699. // Lookup next mod element
  1700. mod = (PixelModElement*)&frame[pos];
  1701. }
  1702. }
  1703. // -- Frame Tweening --
  1704. // Standard Pixel Frame Function (no additional processing)
  1705. void Pixel_frameTweenStandard( const uint8_t *data, AnimationStackElement *elem )
  1706. {
  1707. // Do nothing during sub-frames, skip
  1708. if ( elem->subpos != 0 )
  1709. {
  1710. // But only if frame strech isn't set
  1711. if ( !( elem->frameoption & PixelFrameOption_FrameStretch ) )
  1712. {
  1713. return;
  1714. }
  1715. }
  1716. // Lookup Pixel Tweening Function
  1717. switch ( elem->pfunc )
  1718. {
  1719. case PixelPixelFunction_PointInterpolation:
  1720. Pixel_pixelTweenInterpolation( data, elem );
  1721. break;
  1722. // Generic, no addition processing necessary
  1723. case PixelPixelFunction_Off:
  1724. case PixelPixelFunction_PointInterpolationKLL:
  1725. Pixel_pixelTweenStandard( data, elem );
  1726. break;
  1727. }
  1728. }
  1729. // Pixel Frame Interpolation Tweening
  1730. // Do averaging between key frames
  1731. void Pixel_frameTweenInterpolation( const uint8_t *data, AnimationStackElement *elem )
  1732. {
  1733. // TODO
  1734. }
  1735. // -- Animation Control --
  1736. // Process the animation stack element
  1737. // - Returns 1 if the animation should be re-added to the stack
  1738. // - Returns 0 if the animation is finished (clean-up memory)
  1739. uint8_t Pixel_animationProcess( AnimationStackElement *elem )
  1740. {
  1741. // Skip if index has been invalidate (unset)
  1742. if ( elem->index == 0xFFFF )
  1743. {
  1744. return 0;
  1745. }
  1746. // Check the play state
  1747. switch ( elem->state & 0x7F )
  1748. {
  1749. // Pause animation (paused animations will take up animation stack memory)
  1750. case AnimationPlayState_Pause:
  1751. return 1;
  1752. // Stopping animation (frees animation from stack memory)
  1753. case AnimationPlayState_Stop:
  1754. // Indicate animation slot is free
  1755. elem->index = 0xFFFF;
  1756. return 0;
  1757. // Single frame of the animation
  1758. // Set to paused afterwards
  1759. case AnimationPlayState_Single:
  1760. elem->state = AnimationPlayState_Pause;
  1761. break;
  1762. // Do nothing
  1763. case AnimationPlayState_Start:
  1764. default:
  1765. break;
  1766. }
  1767. // Lookup animation frame to make sure we have something to do
  1768. // TODO Make sure animation index exists -HaaTa
  1769. const uint8_t *data = Pixel_Animations[elem->index][elem->pos];
  1770. // If there is no frame data, that means we either stop, or restart
  1771. if ( data == 0 )
  1772. {
  1773. // Check if we still have more loops, one signifies stop, 0 is infinite
  1774. if ( elem->loops == 0 || elem->loops-- > 1 )
  1775. {
  1776. elem->pos = 0;
  1777. // Signal that animation is repeating
  1778. Macro_animationState( elem->index, ScheduleType_Repeat );
  1779. return Pixel_animationProcess( elem );
  1780. }
  1781. // Stop animation
  1782. else
  1783. {
  1784. // Indicate animation slot is free
  1785. elem->index = 0xFFFF;
  1786. return 0;
  1787. }
  1788. }
  1789. // Lookup Frame Tweening Function
  1790. switch ( elem->ffunc )
  1791. {
  1792. case PixelFrameFunction_Interpolation:
  1793. Pixel_frameTweenInterpolation( data, elem );
  1794. break;
  1795. // Generic, no additonal processing necessary
  1796. case PixelFrameFunction_Off:
  1797. case PixelFrameFunction_InterpolationKLL:
  1798. Pixel_frameTweenStandard( data, elem );
  1799. break;
  1800. }
  1801. // Increment positions
  1802. // framedelay case
  1803. if ( elem->framedelay > 0 )
  1804. {
  1805. // Roll-over subpos for framedelay
  1806. if ( elem->subpos == elem->framedelay )
  1807. {
  1808. elem->subpos = 0;
  1809. elem->pos++;
  1810. }
  1811. // Increment subposition
  1812. else
  1813. {
  1814. elem->subpos++;
  1815. }
  1816. }
  1817. // Full-speed
  1818. else
  1819. {
  1820. elem->pos++;
  1821. }
  1822. return 1;
  1823. }
  1824. // -- Pixel Control --
  1825. // Debug function, used by cli only XXX
  1826. void Pixel_channelSet( uint16_t channel, uint32_t value )
  1827. {
  1828. // Determine which buffer we are in
  1829. PixelBuf *pixbuf = Pixel_bufferMap( channel );
  1830. // Toggle channel accordingly
  1831. switch ( pixbuf->width )
  1832. {
  1833. // Invalid width, default to 8
  1834. default:
  1835. warn_msg("ChanSet Unknown width: ");
  1836. printInt8( pixbuf->width );
  1837. print(" Ch: ");
  1838. printHex( channel );
  1839. print( NL );
  1840. // Falls through on purpose
  1841. // 0bit width - ignore/blank
  1842. case 0:
  1843. break;
  1844. // 8bit width
  1845. case 8:
  1846. PixelBuf8( pixbuf, channel ) = (uint8_t)value;
  1847. break;
  1848. // 16bit width
  1849. case 16:
  1850. PixelBuf16( pixbuf, channel ) = (uint16_t)value;
  1851. break;
  1852. }
  1853. }
  1854. // Toggle the given channel
  1855. // Debug function, used by cli only XXX
  1856. void Pixel_channelToggle( uint16_t channel )
  1857. {
  1858. // Determine which buffer we are in
  1859. PixelBuf *pixbuf = Pixel_bufferMap( channel );
  1860. // Toggle channel accordingly
  1861. switch ( pixbuf->width )
  1862. {
  1863. // Invalid width, default to 8
  1864. default:
  1865. warn_msg("ChanToggle Unknown width: ");
  1866. printInt8( pixbuf->width );
  1867. print(" Ch: ");
  1868. printHex( channel );
  1869. print( NL );
  1870. // Falls through on purpose
  1871. // 0bit width - ignore/blank
  1872. case 0:
  1873. break;
  1874. // 8bit width
  1875. case 8:
  1876. PixelBuf8( pixbuf, channel ) ^= 128;
  1877. break;
  1878. // 16bit width
  1879. case 16:
  1880. PixelBuf16( pixbuf, channel ) ^= 128;
  1881. break;
  1882. }
  1883. }
  1884. // Set each of the channels to a specific value
  1885. void Pixel_pixelSet( PixelElement *elem, uint32_t value )
  1886. {
  1887. // Set each of the channels of the pixel
  1888. for ( uint8_t ch = 0; ch < elem->channels; ch++ )
  1889. {
  1890. Pixel_channelSet( elem->indices[ch], value );
  1891. }
  1892. }
  1893. // Toggle given pixel element
  1894. // Debug function, used by cli only XXX
  1895. void Pixel_pixelToggle( PixelElement *elem )
  1896. {
  1897. // Toggle each of the channels of the pixel
  1898. for ( uint8_t ch = 0; ch < elem->channels; ch++ )
  1899. {
  1900. Pixel_channelToggle( elem->indices[ch] );
  1901. }
  1902. }
  1903. // -- Secondary Processing --
  1904. void Pixel_SecondaryProcessing_profile_init()
  1905. {
  1906. // TODO (HaaTa): Only 3 profiles for now, may need more groups in the future
  1907. for ( uint8_t group = 0; group < 3; group++ )
  1908. {
  1909. const PixelLEDGroupEntry entry = Pixel_LED_DefaultFadeGroups[group];
  1910. // Iterate over each pixel
  1911. for ( uint16_t pxin = 0; pxin < entry.size; pxin++ )
  1912. {
  1913. // For each pixel in the default settings, apply index
  1914. // 0 specifies disabled, so all groups are +1
  1915. Pixel_pixel_fade_profile[entry.pixels[pxin] - 1] = group + 1;
  1916. }
  1917. }
  1918. }
  1919. void Pixel_SecondaryProcessing_setup()
  1920. {
  1921. // Set default gamma setting
  1922. gamma_enabled = Pixel_gamma_default_define;
  1923. // Disable all fade profiles (active defaults afterwards)
  1924. memset( Pixel_pixel_fade_profile, 0, Pixel_TotalPixels_KLL );
  1925. // Setup each of the default profiles
  1926. Pixel_SecondaryProcessing_profile_init();
  1927. // Setup default profile parameters
  1928. for ( uint8_t pf = 0; pf < 4; pf++ )
  1929. {
  1930. // Each of the periods
  1931. for ( uint8_t pr = 0; pr < 4; pr++ )
  1932. {
  1933. // Set period to profile
  1934. PixelPeriodConfig conf = settings.fade_periods[pf][pr];
  1935. Pixel_pixel_fade_profile_entries[pf].conf[pr] = conf;
  1936. }
  1937. // Reset state
  1938. Pixel_pixel_fade_profile_entries[pf].pos = 0;
  1939. Pixel_pixel_fade_profile_entries[pf].period_conf = PixelPeriodIndex_Off_to_On;
  1940. Pixel_pixel_fade_profile_entries[pf].brightness = settings.fade_brightness[pf];
  1941. }
  1942. }
  1943. // Given a starting value and profile, calculate the resulting brightness
  1944. // The returned value is always equal to or less than val
  1945. static inline uint32_t Pixel_ApplyFadeBrightness( uint8_t brightness, uint32_t val )
  1946. {
  1947. // No need to calculate if brightness is max or 0
  1948. if ( brightness == 255 )
  1949. {
  1950. return val;
  1951. }
  1952. if ( brightness == 0 )
  1953. {
  1954. return 0;
  1955. }
  1956. uint32_t result = (val * brightness) >> 8; // val * brightness / 255
  1957. return result;
  1958. }
  1959. void Pixel_SecondaryProcessing()
  1960. {
  1961. // Copy KLL buffer into LED buffer
  1962. for ( uint8_t buf = 0; buf < Pixel_BuffersLen_KLL; buf++ )
  1963. {
  1964. memcpy(
  1965. LED_Buffers[buf].data,
  1966. Pixel_Buffers[buf].data,
  1967. Pixel_Buffers[buf].size * ( Pixel_Buffers[buf].width >> 3 ) // Size may not be multiples bytes
  1968. );
  1969. }
  1970. // Iterate over each of the pixels, applying the appropriate profile to each one
  1971. for ( uint16_t pxin = 0; pxin < Pixel_TotalPixels_KLL; pxin++ )
  1972. {
  1973. // Select profile
  1974. uint8_t profile_in = Pixel_pixel_fade_profile[pxin];
  1975. // Nothing to do
  1976. if ( profile_in == 0 )
  1977. {
  1978. continue;
  1979. }
  1980. // All profiles start from 1
  1981. PixelFadeProfile *profile = &Pixel_pixel_fade_profile_entries[profile_in - 1];
  1982. PixelPeriodConfig *period = &profile->conf[profile->period_conf];
  1983. // Lookup channels of the pixel
  1984. const PixelElement *elem = &Pixel_Mapping[pxin];
  1985. for ( uint8_t ch = 0; ch < elem->channels; ch++ )
  1986. {
  1987. // Lookup PixelBuf containing the channel
  1988. uint16_t chan = elem->indices[ch];
  1989. PixelBuf *buf = LED_bufferMap( chan );
  1990. // Lookup memory location
  1991. // Then apply fade depending on the current position
  1992. //
  1993. // Percentage calculation using 32-bit integer instead of float
  1994. // This is just a: pos / end * current value of LED
  1995. // Ignores rounding
  1996. // For 8-bit values, the maximum percentage spread must be no greater than 25-bits
  1997. // e.g. 1 << 24
  1998. uint32_t val;
  1999. switch (buf->width)
  2000. {
  2001. // TODO (HaaTa): Handle non-16bit arrays of 8-bit values
  2002. case 16:
  2003. switch ( profile->period_conf )
  2004. {
  2005. // Off -> On
  2006. case PixelPeriodIndex_Off_to_On:
  2007. // On -> Off
  2008. case PixelPeriodIndex_On_to_Off:
  2009. // If start and end are set to 0, ignore
  2010. if ( period->end == 0 && period->start == 0 )
  2011. {
  2012. val = (uint8_t)((uint16_t*)buf->data)[chan - buf->offset];
  2013. val = Pixel_ApplyFadeBrightness(profile->brightness, val);
  2014. if (gamma_enabled) {
  2015. val = gamma_table[val];
  2016. }
  2017. ((uint16_t*)buf->data)[chan - buf->offset] = (uint8_t)val;
  2018. break;
  2019. }
  2020. val = (uint8_t)((uint16_t*)buf->data)[chan - buf->offset];
  2021. val = Pixel_ApplyFadeBrightness(profile->brightness, val);
  2022. if (gamma_enabled) {
  2023. val = gamma_table[val];
  2024. }
  2025. val *= profile->pos;
  2026. val >>= period->end;
  2027. ((uint16_t*)buf->data)[chan - buf->offset] = (uint8_t)val;
  2028. break;
  2029. // On hold time
  2030. case PixelPeriodIndex_On:
  2031. val = (uint8_t)((uint16_t*)buf->data)[chan - buf->offset];
  2032. val = Pixel_ApplyFadeBrightness(profile->brightness, val);
  2033. if (gamma_enabled) {
  2034. val = gamma_table[val];
  2035. }
  2036. ((uint16_t*)buf->data)[chan - buf->offset] = (uint8_t)val;
  2037. break;
  2038. // Off hold time
  2039. case PixelPeriodIndex_Off:
  2040. {
  2041. PixelPeriodConfig *prev = &profile->conf[PixelPeriodIndex_On_to_Off];
  2042. // If the previous config was disabled, do not set to 0
  2043. if ( prev->start == 0 && prev->end == 0 )
  2044. {
  2045. val = (uint8_t)((uint16_t*)buf->data)[chan - buf->offset];
  2046. val = Pixel_ApplyFadeBrightness(profile->brightness, val);
  2047. if (gamma_enabled) {
  2048. val = gamma_table[val];
  2049. }
  2050. ((uint16_t*)buf->data)[chan - buf->offset] = (uint8_t)val;
  2051. break;
  2052. }
  2053. // If the previous On->Off change didn't go to fully off
  2054. // Calculate the value based off the previous config
  2055. val = 0;
  2056. if ( prev->start != 0 )
  2057. {
  2058. val = (uint8_t)((uint16_t*)buf->data)[chan - buf->offset];
  2059. val = Pixel_ApplyFadeBrightness(profile->brightness, val);
  2060. if (gamma_enabled) {
  2061. val = gamma_table[val];
  2062. }
  2063. val *= (1 << prev->start) - 1;
  2064. val >>= prev->end;
  2065. }
  2066. // Set to 0
  2067. ((uint16_t*)buf->data)[chan - buf->offset] = (uint8_t)val;
  2068. break;
  2069. }
  2070. }
  2071. break;
  2072. default:
  2073. erro_print("Unsupported buffer width");
  2074. break;
  2075. }
  2076. }
  2077. }
  2078. // Increment positions of each of the active profiles
  2079. for ( uint8_t proin = 0; proin < 4; proin++ )
  2080. {
  2081. // Lookup profile and current period
  2082. PixelFadeProfile *profile = &Pixel_pixel_fade_profile_entries[proin];
  2083. PixelPeriodConfig *period = &profile->conf[profile->period_conf];
  2084. switch ( profile->period_conf )
  2085. {
  2086. case PixelPeriodIndex_Off_to_On:
  2087. profile->pos++;
  2088. // Check if we need to move onto the next conf
  2089. if ( profile->pos >= (1 << period->end) )
  2090. {
  2091. profile->pos = (1 << profile->conf[PixelPeriodIndex_On].start) - 1;
  2092. profile->period_conf = PixelPeriodIndex_On;
  2093. }
  2094. break;
  2095. case PixelPeriodIndex_On:
  2096. profile->pos++;
  2097. // Check if we need to move onto the next conf
  2098. if ( profile->pos >= (1 << period->end) )
  2099. {
  2100. profile->pos = (1 << profile->conf[PixelPeriodIndex_On_to_Off].end);
  2101. profile->period_conf = PixelPeriodIndex_On_to_Off;
  2102. }
  2103. break;
  2104. case PixelPeriodIndex_On_to_Off:
  2105. profile->pos--;
  2106. // Check if we need to move onto the next conf
  2107. if ( profile->pos == (1 << period->start) - 1 )
  2108. {
  2109. profile->pos = (1 << profile->conf[PixelPeriodIndex_Off].start) - 1;
  2110. profile->period_conf = PixelPeriodIndex_Off;
  2111. }
  2112. break;
  2113. case PixelPeriodIndex_Off:
  2114. profile->pos++;
  2115. // Check if we need to move onto the next conf
  2116. if ( profile->pos >= (1 << period->end) )
  2117. {
  2118. profile->pos = (1 << profile->conf[PixelPeriodIndex_Off_to_On].start) - 1;
  2119. profile->period_conf = PixelPeriodIndex_Off_to_On;
  2120. }
  2121. break;
  2122. }
  2123. }
  2124. }
  2125. // -- General --
  2126. // Looks up the final scancode in a trigger macro
  2127. uint8_t Pixel_determineLastTriggerScanCode( TriggerMacro *trigger )
  2128. {
  2129. // Ignore (set to zero) if unset
  2130. if ( trigger == 0 )
  2131. {
  2132. return 0;
  2133. }
  2134. // Iterate over each TriggerGuide element
  2135. uint8_t curScanCode = 0;
  2136. for ( var_uint_t pos = 0; ; pos += trigger->guide[ pos ] * TriggerGuideSize + 1 )
  2137. {
  2138. // Length of this combo
  2139. uint8_t comboLength = trigger->guide[ pos ] * TriggerGuideSize;
  2140. // Determine scancode, use first TriggerGuide scanCode
  2141. TriggerGuide *guide = (TriggerGuide*)&trigger->guide[ pos + 1 ];
  2142. curScanCode = guide->scanCode;
  2143. // If this combo has zero length, we are at the end
  2144. if ( trigger->guide[ pos + comboLength + 1 ] == 0 )
  2145. {
  2146. return curScanCode;
  2147. }
  2148. }
  2149. }
  2150. // External Animation Control
  2151. void Pixel_setAnimationControl( AnimationControl control )
  2152. {
  2153. Pixel_animationControl = control;
  2154. }
  2155. // Starting Animation setup
  2156. void Pixel_initializeStartAnimations()
  2157. {
  2158. // Animations
  2159. for ( uint8_t pos = 0; pos < Pixel_AnimationStackSize; pos++ )
  2160. {
  2161. uint8_t index = settings.animations[pos].index;
  2162. if (index != 255) {
  2163. AnimationStackElement element = Pixel_AnimationSettings[ index ];
  2164. // Only update state if not already defined
  2165. if ( ( element.state & 0x7F ) == AnimationPlayState_Pause )
  2166. {
  2167. element.state = AnimationPlayState_Start;
  2168. }
  2169. element.pos = settings.animations[pos].pos;
  2170. Pixel_addAnimation( &element, CapabilityState_None );
  2171. }
  2172. }
  2173. }
  2174. // Pixel Procesing Loop
  2175. inline void Pixel_process()
  2176. {
  2177. // Start latency measurement
  2178. Latency_start_time( pixelLatencyResource );
  2179. // Only update frame when ready
  2180. switch( Pixel_FrameState )
  2181. {
  2182. case FrameState_Update:
  2183. case FrameState_Pause:
  2184. break;
  2185. default:
  2186. goto pixel_process_final;
  2187. }
  2188. // Pause animation if set
  2189. switch ( Pixel_animationControl )
  2190. {
  2191. case AnimationControl_Forward: // Ok
  2192. case AnimationControl_ForwardOne: // Ok + 1, then stop
  2193. Pixel_FrameState = FrameState_Update;
  2194. break;
  2195. case AnimationControl_Stop: // Clear animations, then proceed forward
  2196. Pixel_FrameState = FrameState_Update;
  2197. Pixel_clearAnimations();
  2198. Pixel_clearPixels();
  2199. Pixel_animationControl = AnimationControl_Forward;
  2200. break;
  2201. case AnimationControl_Reset: // Clear animations, then restart initial
  2202. Pixel_FrameState = FrameState_Update;
  2203. Pixel_clearAnimations();
  2204. Pixel_clearPixels();
  2205. Pixel_SecondaryProcessing_setup(); // Reset fade and gamma correction
  2206. Pixel_animationControl = AnimationControl_Forward;
  2207. Pixel_initializeStartAnimations();
  2208. break;
  2209. case AnimationControl_WipePause: // Pauses animations, clears the display
  2210. Pixel_animationControl = AnimationControl_Pause; // Update one more time
  2211. Pixel_clearPixels();
  2212. goto pixel_process_done;
  2213. case AnimationControl_Clear: // Clears the display, animations continue
  2214. Pixel_animationControl = AnimationControl_Forward;
  2215. Pixel_FrameState = FrameState_Update;
  2216. Pixel_clearPixels();
  2217. break;
  2218. default: // Pause
  2219. Pixel_FrameState = FrameState_Pause;
  2220. goto pixel_process_final;
  2221. }
  2222. // First check if we are in a test mode
  2223. switch ( Pixel_testMode )
  2224. {
  2225. // Single channel control
  2226. case PixelTest_Chan_Single:
  2227. // Increment channel
  2228. if ( Pixel_testPos >= Pixel_TotalChannels_KLL )
  2229. Pixel_testPos = 0;
  2230. Pixel_testPos++;
  2231. // Toggle channel
  2232. Pixel_channelToggle( Pixel_testPos - 1 );
  2233. // Disable test mode
  2234. Pixel_testMode = PixelTest_Off;
  2235. goto pixel_process_done;
  2236. // Single channel control reverse
  2237. case PixelTest_Chan_SingleReverse:
  2238. // Make sure we don't start as 0
  2239. if ( Pixel_testPos == 0 )
  2240. Pixel_testPos++;
  2241. // Decrement channel
  2242. if ( Pixel_testPos == 1 )
  2243. Pixel_testPos = Pixel_TotalChannels_KLL + 1;
  2244. Pixel_testPos--;
  2245. // Toggle channel
  2246. Pixel_channelToggle( Pixel_testPos - 1 );
  2247. // Disable test mode
  2248. Pixel_testMode = PixelTest_Off;
  2249. goto pixel_process_done;
  2250. // Toggle current position, then increment
  2251. case PixelTest_Chan_Roll:
  2252. // Toggle channel
  2253. Pixel_channelToggle( Pixel_testPos );
  2254. // Increment channel
  2255. Pixel_testPos++;
  2256. if ( Pixel_testPos >= Pixel_TotalChannels_KLL )
  2257. Pixel_testPos = 0;
  2258. goto pixel_process_done;
  2259. // Blink all channels
  2260. case PixelTest_Chan_All:
  2261. // Update all positions
  2262. for ( uint16_t ch = 0; ch < Pixel_TotalChannels_KLL; ch++ )
  2263. {
  2264. // Toggle channel
  2265. Pixel_channelToggle( ch );
  2266. }
  2267. goto pixel_process_done;
  2268. // Enable all channels
  2269. case PixelTest_Chan_Full:
  2270. // Update all positions
  2271. for ( uint16_t ch = 0; ch < Pixel_TotalChannels_KLL; ch++ )
  2272. {
  2273. // Toggle channel
  2274. Pixel_channelSet( ch, 255 );
  2275. }
  2276. goto pixel_process_done;
  2277. // Turn off all channels
  2278. case PixelTest_Chan_Off:
  2279. // Update all positions
  2280. for ( uint16_t ch = 0; ch < Pixel_TotalChannels_KLL; ch++ )
  2281. {
  2282. // Toggle channel
  2283. Pixel_channelSet( ch, 0 );
  2284. }
  2285. goto pixel_process_done;
  2286. // Single pixel control
  2287. case PixelTest_Pixel_Single:
  2288. // Increment channel
  2289. if ( Pixel_testPos >= Pixel_TotalPixels_KLL )
  2290. Pixel_testPos = 0;
  2291. Pixel_testPos++;
  2292. // Toggle channel
  2293. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ Pixel_testPos - 1 ] );
  2294. // Disable test mode
  2295. Pixel_testMode = PixelTest_Off;
  2296. goto pixel_process_done;
  2297. // Single pixel control reverse
  2298. case PixelTest_Pixel_SingleReverse:
  2299. // Make sure we don't start as 0
  2300. if ( Pixel_testPos == 0 )
  2301. Pixel_testPos++;
  2302. // Decrement channel
  2303. if ( Pixel_testPos == 1 )
  2304. Pixel_testPos = Pixel_TotalPixels_KLL + 1;
  2305. Pixel_testPos--;
  2306. // Toggle channel
  2307. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ Pixel_testPos - 1 ] );
  2308. // Disable test mode
  2309. Pixel_testMode = PixelTest_Off;
  2310. goto pixel_process_done;
  2311. // Toggle current position, then increment
  2312. case PixelTest_Pixel_Roll:
  2313. // Toggle pixel
  2314. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ Pixel_testPos ] );
  2315. // Increment pixel
  2316. Pixel_testPos++;
  2317. if ( Pixel_testPos >= Pixel_TotalPixels_KLL )
  2318. Pixel_testPos = 0;
  2319. goto pixel_process_done;
  2320. // Toggle all positions
  2321. case PixelTest_Pixel_All:
  2322. // Update all positions
  2323. for ( uint16_t px = Pixel_testPos; px < Pixel_TotalPixels_KLL; px++ )
  2324. {
  2325. // Toggle pixel
  2326. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ px ] );
  2327. }
  2328. goto pixel_process_done;
  2329. // Enable all positions
  2330. case PixelTest_Pixel_Full:
  2331. // Update all positions
  2332. for ( uint16_t px = 0; px < Pixel_TotalPixels_KLL; px++ )
  2333. {
  2334. // Toggle pixel
  2335. // XXX (only works for 8 bit atm)
  2336. Pixel_pixelSet( (PixelElement*)&Pixel_Mapping[ px ], 255 );
  2337. Pixel_testMode = PixelTest_Off;
  2338. }
  2339. goto pixel_process_done;
  2340. // Disable all positions
  2341. case PixelTest_Pixel_Off:
  2342. // Update all positions
  2343. for ( uint16_t px = 0; px < Pixel_TotalPixels_KLL; px++ )
  2344. {
  2345. // Unset pixel
  2346. Pixel_pixelSet( (PixelElement*)&Pixel_Mapping[ px ], 0 );
  2347. Pixel_testMode = PixelTest_Off;
  2348. }
  2349. goto pixel_process_done;
  2350. // Single scan control
  2351. case PixelTest_Scan_Single:
  2352. {
  2353. // Lookup pixel
  2354. uint16_t pixel = Pixel_ScanCodeToPixel[ Pixel_testPos ];
  2355. // Increment pixel
  2356. Pixel_testPos++;
  2357. if ( Pixel_testPos >= MaxScanCode_KLL )
  2358. Pixel_testPos = 0;
  2359. // Ignore if pixel set to 0
  2360. if ( pixel == 0 )
  2361. {
  2362. goto pixel_process_final;
  2363. }
  2364. // Toggle channel
  2365. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2366. // Disable test mode
  2367. Pixel_testMode = PixelTest_Off;
  2368. goto pixel_process_done;
  2369. }
  2370. // Single scan control reverse
  2371. case PixelTest_Scan_SingleReverse:
  2372. {
  2373. // Lookup pixel
  2374. uint16_t pixel = Pixel_ScanCodeToPixel[ Pixel_testPos ];
  2375. // Increment pixel
  2376. if ( Pixel_testPos == 0 )
  2377. Pixel_testPos = MaxScanCode_KLL;
  2378. Pixel_testPos--;
  2379. // Ignore if pixel set to 0
  2380. if ( pixel == 0 )
  2381. {
  2382. goto pixel_process_final;
  2383. }
  2384. // Toggle channel
  2385. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2386. // Disable test mode
  2387. Pixel_testMode = PixelTest_Off;
  2388. goto pixel_process_done;
  2389. }
  2390. // Toggle current position, then increment
  2391. case PixelTest_Scan_Roll:
  2392. {
  2393. // Lookup pixel
  2394. uint16_t pixel = Pixel_ScanCodeToPixel[ Pixel_testPos ];
  2395. // Increment pixel
  2396. Pixel_testPos++;
  2397. if ( Pixel_testPos >= MaxScanCode_KLL )
  2398. Pixel_testPos = 0;
  2399. // Ignore if pixel set to 0
  2400. if ( pixel == 0 )
  2401. {
  2402. goto pixel_process_final;
  2403. }
  2404. // Toggle channel
  2405. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2406. goto pixel_process_done;
  2407. }
  2408. // Toggle all positions
  2409. case PixelTest_Scan_All:
  2410. for ( uint16_t px = Pixel_testPos; px < MaxScanCode_KLL; px++ )
  2411. {
  2412. // Lookup pixel
  2413. uint16_t pixel = Pixel_ScanCodeToPixel[ px ];
  2414. // Ignore if pixel set to 0
  2415. if ( pixel == 0 )
  2416. {
  2417. continue;
  2418. }
  2419. // Toggle pixel
  2420. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2421. }
  2422. goto pixel_process_done;
  2423. // Toggle current position, then increment
  2424. case PixelTest_XY_Roll:
  2425. {
  2426. // Lookup pixel
  2427. uint16_t pixel = Pixel_DisplayMapping[ Pixel_testPos ];
  2428. // Increment pixel
  2429. Pixel_testPos++;
  2430. if ( Pixel_testPos >= Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL )
  2431. Pixel_testPos = 0;
  2432. // Ignore if pixel set to 0
  2433. if ( pixel == 0 )
  2434. {
  2435. goto pixel_process_final;
  2436. }
  2437. // Toggle channel
  2438. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2439. goto pixel_process_done;
  2440. }
  2441. // Toggle all positions
  2442. case PixelTest_XY_All:
  2443. for ( uint16_t px = Pixel_testPos; px < Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL; px++ )
  2444. {
  2445. // Lookup pixel
  2446. uint16_t pixel = Pixel_DisplayMapping[ px ];
  2447. // Ignore if pixel set to 0
  2448. if ( pixel == 0 )
  2449. {
  2450. continue;
  2451. }
  2452. // Toggle pixel
  2453. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2454. }
  2455. goto pixel_process_done;
  2456. // Otherwise ignore
  2457. default:
  2458. break;
  2459. }
  2460. // Process Animation Stack
  2461. Pixel_stackProcess();
  2462. // Pause if necessary
  2463. switch( Pixel_animationControl )
  2464. {
  2465. case AnimationControl_ForwardOne:
  2466. Pixel_animationControl = AnimationControl_Pause;
  2467. break;
  2468. default:
  2469. break;
  2470. }
  2471. pixel_process_done:
  2472. // Apply secondary LED processing
  2473. // XXX (HaaTa): Disabling IRQ as a hack, some interrupt is causing corruption during the buffer handling
  2474. Pixel_SecondaryProcessing();
  2475. // Frame is now ready to send
  2476. Pixel_FrameState = FrameState_Ready;
  2477. pixel_process_final:
  2478. // End latency measurement
  2479. Latency_end_time( pixelLatencyResource );
  2480. }
  2481. inline void Pixel_setup()
  2482. {
  2483. // Register Pixel CLI dictionary
  2484. CLI_registerDictionary( pixelCLIDict, pixelCLIDictName );
  2485. // Iterate over starting animations
  2486. uint8_t add_animations = 0;
  2487. for ( uint32_t index = 0; index < Pixel_AnimationSettingsNum_KLL; index++ )
  2488. {
  2489. // Check if a starting animation
  2490. if ( Pixel_AnimationSettings[ index ].state & AnimationPlayState_AutoStart )
  2491. {
  2492. // Default animations are noted by the TriggerMacro *trigger pointer being set to 1
  2493. if ( (uintptr_t)(Pixel_AnimationSettings[ index ].trigger) == 1 )
  2494. {
  2495. // Add animation to the defaults stack
  2496. #if Storage_Enable_define == 1
  2497. defaults.animations[add_animations].index = index;
  2498. defaults.animations[add_animations].pos = Pixel_AnimationSettings[index].pos;
  2499. #endif
  2500. settings.animations[add_animations].index = index;
  2501. settings.animations[add_animations].pos = Pixel_AnimationSettings[index].pos;
  2502. add_animations++;
  2503. }
  2504. }
  2505. }
  2506. // Fill in rest of stack
  2507. for ( uint8_t animation = add_animations; animation < Pixel_AnimationStackSize; animation++ )
  2508. {
  2509. #if Storage_Enable_define == 1
  2510. defaults.animations[animation].index = 255;
  2511. defaults.animations[animation].pos = 0;
  2512. #endif
  2513. settings.animations[animation].index = 255;
  2514. settings.animations[animation].pos = 0;
  2515. }
  2516. // Setup fade defaults
  2517. for ( uint8_t profile = 0; profile < 4; profile++ )
  2518. {
  2519. for ( uint8_t config = 0; config < 4; config++ )
  2520. {
  2521. #if Storage_Enable_define == 1
  2522. defaults.fade_periods[profile][config] =
  2523. Pixel_LED_FadePeriods[Pixel_LED_FadePeriod_Defaults[profile][config]];
  2524. #endif
  2525. settings.fade_periods[profile][config] =
  2526. Pixel_LED_FadePeriods[Pixel_LED_FadePeriod_Defaults[profile][config]];
  2527. }
  2528. #if Storage_Enable_define == 1
  2529. defaults.fade_brightness[profile] = Pixel_LED_FadeBrightness[profile];
  2530. #endif
  2531. settings.fade_brightness[profile] = Pixel_LED_FadeBrightness[profile];
  2532. }
  2533. // Register storage module
  2534. #if Storage_Enable_define == 1
  2535. Storage_registerModule(&PixelStorage);
  2536. #endif
  2537. // Set frame state to update
  2538. Pixel_FrameState = FrameState_Update;
  2539. // Disable test modes by default, start at position 0
  2540. Pixel_testMode = Pixel_Test_Mode_define;
  2541. // Clear animation stack and Pixels
  2542. Pixel_clearAnimations();
  2543. Pixel_clearPixels();
  2544. // Set default animation control
  2545. Pixel_animationControl = AnimationControl_Forward;
  2546. // Add initial animations
  2547. Pixel_initializeStartAnimations();
  2548. // Initialize secondary buffer processing
  2549. Pixel_SecondaryProcessing_setup();
  2550. // Allocate latency resource
  2551. pixelLatencyResource = Latency_add_resource("PixelMap", LatencyOption_Ticks);
  2552. }
  2553. // ----- CLI Command Functions -----
  2554. void cliFunc_pixelList( char* args )
  2555. {
  2556. print( NL ); // No \r\n by default after the command is entered
  2557. char* curArgs;
  2558. char* arg1Ptr;
  2559. char* arg2Ptr = args;
  2560. // Process argument if given
  2561. curArgs = arg2Ptr;
  2562. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  2563. // Check for special args
  2564. switch ( *arg1Ptr )
  2565. {
  2566. case 'b':
  2567. case 'B':
  2568. info_msg("Buffer List");
  2569. // List all buffers
  2570. for ( uint8_t buf = 0; buf < Pixel_BuffersLen_KLL; buf++ )
  2571. {
  2572. print( NL "\t" );
  2573. printInt8( buf );
  2574. print(":");
  2575. printHex32( (uint32_t)(uintptr_t)(Pixel_Buffers[ buf ].data) );
  2576. print(":width(");
  2577. printInt8( Pixel_Buffers[ buf ].width );
  2578. print("):size(");
  2579. printInt8( Pixel_Buffers[ buf ].size );
  2580. print(")");
  2581. }
  2582. break;
  2583. default:
  2584. info_msg("Pixel List - <num>[<ch1>,...]<width>:...");
  2585. // List all pixels
  2586. for ( uint16_t pixel = 0; pixel < Pixel_TotalPixels_KLL; pixel++ )
  2587. {
  2588. // NL occaisionally
  2589. if ( pixel % 5 == 0 )
  2590. print( NL );
  2591. PixelElement *elem = (PixelElement*)&Pixel_Mapping[ pixel ];
  2592. printHex_op( pixel, 2 );
  2593. print(":");
  2594. printInt8( elem->width );
  2595. print("[");
  2596. // Display each of the channels
  2597. printHex_op( elem->indices[0], 2 );
  2598. for ( uint8_t ch = 1; ch < elem->channels; ch++ )
  2599. {
  2600. print(",");
  2601. printHex_op( elem->indices[ch], 2 );
  2602. }
  2603. print("]");
  2604. print(" ");
  2605. }
  2606. break;
  2607. }
  2608. }
  2609. void cliFunc_pixelTest( char* args )
  2610. {
  2611. print( NL ); // No \r\n by default after the command is entered
  2612. char* curArgs;
  2613. char* arg1Ptr;
  2614. char* arg2Ptr = args;
  2615. // Process argument if given
  2616. curArgs = arg2Ptr;
  2617. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  2618. // Check for special args
  2619. switch ( *arg1Ptr )
  2620. {
  2621. case 'a':
  2622. case 'A':
  2623. info_msg("All pixel test");
  2624. Pixel_testPos = 0;
  2625. Pixel_testMode = PixelTest_Pixel_All;
  2626. return;
  2627. case 'r':
  2628. case 'R':
  2629. info_msg("Pixel roll test");
  2630. Pixel_testPos = 0;
  2631. Pixel_testMode = PixelTest_Pixel_Roll;
  2632. return;
  2633. case 's':
  2634. case 'S':
  2635. info_msg("Stopping pixel test");
  2636. Pixel_testMode = PixelTest_Off;
  2637. return;
  2638. case 'f':
  2639. case 'F':
  2640. info_msg("Enable all pixels");
  2641. Pixel_testPos = 0;
  2642. Pixel_testMode = PixelTest_Pixel_Full;
  2643. return;
  2644. case 'o':
  2645. case 'O':
  2646. info_msg("Disable all pixels");
  2647. Pixel_testPos = 0;
  2648. Pixel_testMode = PixelTest_Pixel_Off;
  2649. return;
  2650. default:
  2651. Pixel_testMode = PixelTest_Pixel_Single;
  2652. break;
  2653. }
  2654. // Check for specific position
  2655. if ( *arg1Ptr != '\0' )
  2656. {
  2657. Pixel_testPos = numToInt( arg1Ptr );
  2658. }
  2659. // If 0, ignore
  2660. if ( Pixel_testPos == 0 )
  2661. {
  2662. Pixel_testMode = PixelTest_Off;
  2663. return;
  2664. }
  2665. // Debug info
  2666. print( NL );
  2667. info_msg("Pixel: ");
  2668. printInt16( Pixel_testPos );
  2669. print(" ");
  2670. }
  2671. void cliFunc_chanTest( char* args )
  2672. {
  2673. print( NL ); // No \r\n by default after the command is entered
  2674. char* curArgs;
  2675. char* arg1Ptr;
  2676. char* arg2Ptr = args;
  2677. // Process argument if given
  2678. curArgs = arg2Ptr;
  2679. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  2680. // Check for special args
  2681. switch ( *arg1Ptr )
  2682. {
  2683. case 'a':
  2684. case 'A':
  2685. info_msg("All channel test");
  2686. Pixel_testPos = 0;
  2687. Pixel_testMode = PixelTest_Chan_All;
  2688. return;
  2689. case 'r':
  2690. case 'R':
  2691. info_msg("Channel roll test");
  2692. Pixel_testPos = 0;
  2693. Pixel_testMode = PixelTest_Chan_Roll;
  2694. return;
  2695. case 's':
  2696. case 'S':
  2697. info_msg("Stopping channel test");
  2698. Pixel_testMode = PixelTest_Off;
  2699. return;
  2700. case 'f':
  2701. case 'F':
  2702. info_msg("Enable all pixels");
  2703. Pixel_testPos = 0;
  2704. Pixel_testMode = PixelTest_Chan_Full;
  2705. return;
  2706. case 'o':
  2707. case 'O':
  2708. info_msg("Disable all pixels");
  2709. Pixel_testPos = 0;
  2710. Pixel_testMode = PixelTest_Chan_Off;
  2711. return;
  2712. default:
  2713. Pixel_testMode = PixelTest_Chan_Single;
  2714. break;
  2715. }
  2716. // Check for specific position
  2717. if ( *arg1Ptr != '\0' )
  2718. {
  2719. Pixel_testPos = numToInt( arg1Ptr );
  2720. }
  2721. // Debug info
  2722. print( NL );
  2723. info_msg("Channel: ");
  2724. printInt16( Pixel_testPos );
  2725. print( NL );
  2726. }
  2727. void cliFunc_pixelSCTest( char* args )
  2728. {
  2729. print( NL ); // No \r\n by default after the command is entered
  2730. char* curArgs;
  2731. char* arg1Ptr;
  2732. char* arg2Ptr = args;
  2733. // Process argument if given
  2734. curArgs = arg2Ptr;
  2735. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  2736. // Check for special args
  2737. switch ( *arg1Ptr )
  2738. {
  2739. case 'a':
  2740. case 'A':
  2741. info_msg("All scancode pixel test");
  2742. Pixel_testPos = 0;
  2743. Pixel_testMode = PixelTest_Scan_All;
  2744. return;
  2745. case 'r':
  2746. case 'R':
  2747. info_msg("Scancode pixel roll test");
  2748. Pixel_testPos = 0;
  2749. Pixel_testMode = PixelTest_Scan_Roll;
  2750. return;
  2751. case 's':
  2752. case 'S':
  2753. info_msg("Stopping scancode pixel test");
  2754. Pixel_testMode = PixelTest_Off;
  2755. return;
  2756. default:
  2757. Pixel_testMode = PixelTest_Scan_Single;
  2758. break;
  2759. }
  2760. // Check for specific position
  2761. if ( *arg1Ptr != '\0' )
  2762. {
  2763. Pixel_testPos = numToInt( arg1Ptr );
  2764. }
  2765. // If 0, ignore
  2766. if ( Pixel_testPos == 0 )
  2767. {
  2768. Pixel_testMode = PixelTest_Off;
  2769. return;
  2770. }
  2771. // Lookup pixel
  2772. uint16_t pixel = Pixel_ScanCodeToPixel[ Pixel_testPos ];
  2773. // Debug info
  2774. print( NL );
  2775. info_msg("ScanCode: ");
  2776. printInt16( Pixel_testPos + 1 );
  2777. print(" Pixel: ");
  2778. printInt16( pixel );
  2779. print(" ");
  2780. }
  2781. void cliFunc_pixelXYTest( char* args )
  2782. {
  2783. print( NL ); // No \r\n by default after the command is entered
  2784. char* curArgs;
  2785. char* arg1Ptr;
  2786. char* arg2Ptr = args;
  2787. // Process argument if given
  2788. curArgs = arg2Ptr;
  2789. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  2790. // Check for special args
  2791. switch ( *arg1Ptr )
  2792. {
  2793. case 'a':
  2794. case 'A':
  2795. info_msg("All x,y pixel test");
  2796. Pixel_testPos = 0;
  2797. Pixel_testMode = PixelTest_XY_All;
  2798. return;
  2799. case 'r':
  2800. case 'R':
  2801. info_msg("x,y pixel roll test");
  2802. Pixel_testPos = 0;
  2803. Pixel_testMode = PixelTest_XY_Roll;
  2804. return;
  2805. case 's':
  2806. case 'S':
  2807. info_msg("Stopping x,y pixel test");
  2808. Pixel_testMode = PixelTest_Off;
  2809. return;
  2810. case 'h':
  2811. case 'H':
  2812. // Make sure we aren't too far already
  2813. if ( Pixel_testPos >= Pixel_DisplayMapping_Rows_KLL )
  2814. {
  2815. Pixel_testPos = 0;
  2816. }
  2817. info_msg("Horizontal: ");
  2818. printInt16( Pixel_testPos );
  2819. // Iterate over the row
  2820. for ( uint16_t pos = Pixel_DisplayMapping_Cols_KLL * Pixel_testPos;
  2821. pos < Pixel_DisplayMapping_Cols_KLL * ( Pixel_testPos + 1);
  2822. pos++
  2823. )
  2824. {
  2825. uint16_t pixel = Pixel_DisplayMapping[ pos ];
  2826. print(" ");
  2827. printInt16( pixel );
  2828. // Toggle pixel
  2829. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2830. }
  2831. Pixel_testPos++;
  2832. return;
  2833. case 'v':
  2834. case 'V':
  2835. // Make sure we aren't too far already
  2836. if ( Pixel_testPos >= Pixel_DisplayMapping_Cols_KLL )
  2837. {
  2838. Pixel_testPos = 0;
  2839. }
  2840. info_msg("Vertical: ");
  2841. printInt16( Pixel_testPos );
  2842. // Iterate over the column
  2843. for ( uint16_t pos = 0; pos < Pixel_DisplayMapping_Rows_KLL; pos++ )
  2844. {
  2845. uint16_t pos_calc = pos * Pixel_DisplayMapping_Cols_KLL + Pixel_testPos;
  2846. print(" ");
  2847. printInt16( pos_calc );
  2848. uint16_t pixel = Pixel_DisplayMapping[ pos_calc ];
  2849. print(":");
  2850. printInt16( pixel );
  2851. // Toggle pixel
  2852. Pixel_pixelToggle( (PixelElement*)&Pixel_Mapping[ pixel - 1 ] );
  2853. }
  2854. Pixel_testPos++;
  2855. return;
  2856. }
  2857. // Check for specific position
  2858. if ( *arg1Ptr != '\0' )
  2859. {
  2860. Pixel_testPos = numToInt( arg1Ptr );
  2861. }
  2862. // Lookup pixel
  2863. uint16_t pixel = Pixel_DisplayMapping[ Pixel_testPos ];
  2864. // Debug info
  2865. print( NL );
  2866. info_msg("Position (x,y): ");
  2867. printInt16( Pixel_testPos % Pixel_DisplayMapping_Cols_KLL );
  2868. print(",");
  2869. printInt16( Pixel_testPos / Pixel_DisplayMapping_Cols_KLL );
  2870. print(":");
  2871. printInt16( Pixel_testPos );
  2872. print(" Pixel: ");
  2873. printInt16( pixel );
  2874. print(" ");
  2875. // Lookup pixel element
  2876. PixelElement *elem = (PixelElement*)&Pixel_Mapping[ pixel - 1 ];
  2877. Pixel_showPixelElement( elem );
  2878. print( NL );
  2879. // Increment pixel
  2880. Pixel_testPos++;
  2881. if ( Pixel_testPos >= Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL )
  2882. Pixel_testPos = 0;
  2883. // Ignore if pixel set to 0
  2884. if ( pixel == 0 )
  2885. {
  2886. return;
  2887. }
  2888. // Toggle pixel
  2889. Pixel_pixelToggle( elem );
  2890. }
  2891. void cliFunc_aniAdd( char* args )
  2892. {
  2893. print( NL ); // No \r\n by default after the command is entered
  2894. // TODO
  2895. /*
  2896. uint16_t index = Pixel_AnimationStack.size;
  2897. Pixel_AnimationStack.stack[index].index = 1;
  2898. Pixel_AnimationStack.stack[index].pos = 1;
  2899. Pixel_AnimationStack.stack[index].loops = 1;
  2900. Pixel_AnimationStack.stack[index].divider = 0;
  2901. Pixel_AnimationStack.stack[index].modifier = AnimationModifier_None;
  2902. Pixel_AnimationStack.size++;
  2903. */
  2904. }
  2905. void cliFunc_aniDel( char* args )
  2906. {
  2907. print( NL ); // No \r\n by default after the command is entered
  2908. // TODO
  2909. Pixel_AnimationStack.size--;
  2910. }
  2911. void cliFunc_aniStack( char* args )
  2912. {
  2913. print(NL);
  2914. info_msg("Stack Size: ");
  2915. printInt16( Pixel_AnimationStack.size );
  2916. for ( uint8_t pos = 0; pos < Pixel_AnimationStack.size; pos++ )
  2917. {
  2918. print(NL);
  2919. AnimationStackElement *elem = Pixel_AnimationStack.stack[pos];
  2920. print(" index(");
  2921. printInt16( elem->index );
  2922. print(") pos(");
  2923. printInt16( elem->pos );
  2924. print(") loops(");
  2925. printInt8( elem->loops );
  2926. print(") framedelay(");
  2927. printInt8( elem->framedelay );
  2928. print(") frameoption(");
  2929. printInt8( elem->frameoption );
  2930. print(") ffunc(");
  2931. printInt8( elem->ffunc );
  2932. print(") pfunc(");
  2933. printInt8( elem->pfunc );
  2934. print(")");
  2935. }
  2936. }
  2937. void Pixel_dispBuffer()
  2938. {
  2939. uint8_t row = 0;
  2940. uint8_t col = 0;
  2941. for ( uint16_t px = 0; px < Pixel_DisplayMapping_Cols_KLL * Pixel_DisplayMapping_Rows_KLL; px++ )
  2942. {
  2943. // Display a + if it's a blank pixel
  2944. if ( Pixel_DisplayMapping[px] == 0 )
  2945. {
  2946. print("+");
  2947. }
  2948. // Lookup pixel
  2949. else
  2950. {
  2951. // Determine number of channels
  2952. // TODO Adjust output if single channel
  2953. PixelElement *elem = (PixelElement*)&Pixel_Mapping[ Pixel_DisplayMapping[px] - 1 ];
  2954. // Lookup channel data
  2955. // TODO account for different channel size mappings
  2956. print("\033[48;2");
  2957. for ( uint8_t ch = 0; ch < elem->channels; ch++ )
  2958. {
  2959. print(";");
  2960. uint16_t ch_pos = elem->indices[ch];
  2961. PixelBuf *pixbuf = Pixel_bufferMap( ch_pos );
  2962. printInt8( PixelBuf16( pixbuf, ch_pos ) );
  2963. }
  2964. print("m");
  2965. print(" ");
  2966. print("\033[0m");
  2967. }
  2968. // Determine what to increment next
  2969. if ( col >= Pixel_DisplayMapping_Cols_KLL - 1 )
  2970. {
  2971. col = 0;
  2972. row++;
  2973. print(" ");
  2974. print(NL);
  2975. }
  2976. else
  2977. {
  2978. col++;
  2979. }
  2980. }
  2981. }
  2982. void cliFunc_rectDisp( char* args )
  2983. {
  2984. print( NL ); // No \r\n by default after the command is entered
  2985. // TODO move to own function, use this func to control startup/args
  2986. Pixel_dispBuffer();
  2987. }
  2988. #if Storage_Enable_define == 1
  2989. void Pixel_loadConfig()
  2990. {
  2991. // Animation setup
  2992. Pixel_initializeStartAnimations();
  2993. // Fade periods
  2994. Pixel_SecondaryProcessing_setup();
  2995. }
  2996. void Pixel_saveConfig() {
  2997. // Animations
  2998. for ( uint8_t pos = 0; pos < Pixel_AnimationStackSize; pos++ )
  2999. {
  3000. if (pos < Pixel_AnimationStack.size) {
  3001. AnimationStackElement *elem = Pixel_AnimationStack.stack[pos];
  3002. settings.animations[pos].index = elem->index;
  3003. // Save position, only if paused
  3004. if ( ( elem->state & 0x7F ) == AnimationPlayState_Pause )
  3005. {
  3006. settings.animations[pos].pos = elem->pos - 1;
  3007. }
  3008. else
  3009. {
  3010. settings.animations[pos].pos = 0;
  3011. }
  3012. } else {
  3013. settings.animations[pos].index = 255;
  3014. settings.animations[pos].pos = 0;
  3015. }
  3016. }
  3017. // Fade periods
  3018. for (uint8_t profile=0; profile<4; profile++)
  3019. {
  3020. for (uint8_t config=0; config<4; config++)
  3021. {
  3022. // XXX TODO: Needs a real lookup
  3023. const PixelPeriodConfig period_config = Pixel_pixel_fade_profile_entries[profile].conf[config];
  3024. settings.fade_periods[profile][config] = period_config;
  3025. }
  3026. settings.fade_brightness[profile] = Pixel_pixel_fade_profile_entries[profile].brightness;
  3027. }
  3028. }
  3029. void Pixel_printConfig() {
  3030. // Animations
  3031. print(" \033[35mAnimations\033[0m" NL);
  3032. for ( uint8_t pos = 0; pos < Pixel_AnimationStackSize; pos++ )
  3033. {
  3034. uint8_t index = settings.animations[pos].index;
  3035. uint8_t fpos = settings.animations[pos].pos;
  3036. if (index != 255) {
  3037. print("AnimationStack.stack[");
  3038. printInt8(pos);
  3039. print("]->index = ");
  3040. printInt8(index);
  3041. print("; pos = ");
  3042. printInt8(fpos);
  3043. print(NL);
  3044. }
  3045. }
  3046. // Fade periods
  3047. print(NL " \033[35mFades\033[0m" NL);
  3048. for (uint8_t profile=0; profile<4; profile++)
  3049. {
  3050. for (uint8_t config=0; config<4; config++)
  3051. {
  3052. PixelPeriodConfig period = settings.fade_periods[profile][config];
  3053. print("FadeConfig[");
  3054. printInt8(profile);
  3055. print("][");
  3056. printInt8(config);
  3057. print("] = {");
  3058. printInt8(period.start);
  3059. print(", ");
  3060. printInt8(period.end);
  3061. print("}");
  3062. print(NL);
  3063. }
  3064. }
  3065. // Profile brightness
  3066. print(NL " \033[35mProfile Brightnesses\033[0m" NL);
  3067. for (uint8_t profile=0; profile<4; profile++)
  3068. {
  3069. printInt8(profile);
  3070. print(" ");
  3071. printInt8(settings.fade_brightness[profile]);
  3072. print(NL);
  3073. }
  3074. }
  3075. #endif