]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Macro/PartialMap/macro.c
Fixing order of layer debug stack display
[kiibohd-controller.git] / Macro / PartialMap / macro.c
1 /* Copyright (C) 2014-2015 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 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 General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this file.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 // ----- Includes -----
18
19 // Compiler Includes
20 #include <Lib/MacroLib.h>
21
22 // Project Includes
23 #include <cli.h>
24 #include <led.h>
25 #include <print.h>
26 #include <scan_loop.h>
27
28 // Keymaps
29 #include "usb_hid.h"
30 #include <generatedKeymap.h> // Generated using kll at compile time, in build directory
31
32 // Local Includes
33 #include "macro.h"
34
35
36
37 // ----- Function Declarations -----
38
39 void cliFunc_capList   ( char* args );
40 void cliFunc_capSelect ( char* args );
41 void cliFunc_keyHold   ( char* args );
42 void cliFunc_keyPress  ( char* args );
43 void cliFunc_keyRelease( char* args );
44 void cliFunc_layerDebug( char* args );
45 void cliFunc_layerList ( char* args );
46 void cliFunc_layerState( char* args );
47 void cliFunc_macroDebug( char* args );
48 void cliFunc_macroList ( char* args );
49 void cliFunc_macroProc ( char* args );
50 void cliFunc_macroShow ( char* args );
51 void cliFunc_macroStep ( char* args );
52
53
54
55 // ----- Enums -----
56
57 // Bit positions are important, passes (correct key) always trump incorrect key votes
58 typedef enum TriggerMacroVote {
59         TriggerMacroVote_Release          = 0x10, // Correct key
60         TriggerMacroVote_PassRelease      = 0x18, // Correct key (both pass and release)
61         TriggerMacroVote_Pass             = 0x8,  // Correct key
62         TriggerMacroVote_DoNothingRelease = 0x4,  // Incorrect key
63         TriggerMacroVote_DoNothing        = 0x2,  // Incorrect key
64         TriggerMacroVote_Fail             = 0x1,  // Incorrect key
65         TriggerMacroVote_Invalid          = 0x0,  // Invalid state
66 } TriggerMacroVote;
67
68 typedef enum TriggerMacroEval {
69         TriggerMacroEval_DoNothing,
70         TriggerMacroEval_DoResult,
71         TriggerMacroEval_DoResultAndRemove,
72         TriggerMacroEval_Remove,
73 } TriggerMacroEval;
74
75 typedef enum ResultMacroEval {
76         ResultMacroEval_DoNothing,
77         ResultMacroEval_Remove,
78 } ResultMacroEval;
79
80
81
82 // ----- Variables -----
83
84 // Macro Module command dictionary
85 CLIDict_Entry( capList,     "Prints an indexed list of all non USB keycode capabilities." );
86 CLIDict_Entry( capSelect,   "Triggers the specified capabilities. First two args are state and stateType." NL "\t\t\033[35mK11\033[0m Keyboard Capability 0x0B" );
87 CLIDict_Entry( keyHold,     "Send key-hold events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" );
88 CLIDict_Entry( keyPress,    "Send key-press events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" );
89 CLIDict_Entry( keyRelease,  "Send key-release event to macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" );
90 CLIDict_Entry( layerDebug,  "Layer debug mode. Shows layer stack and any changes." );
91 CLIDict_Entry( layerList,   "List available layers." );
92 CLIDict_Entry( layerState,  "Modify specified indexed layer state <layer> <state byte>." NL "\t\t\033[35mL2\033[0m Indexed Layer 0x02" NL "\t\t0 Off, 1 Shift, 2 Latch, 4 Lock States" );
93 CLIDict_Entry( macroDebug,  "Disables/Enables sending USB keycodes to the Output Module and prints U/K codes." );
94 CLIDict_Entry( macroList,   "List the defined trigger and result macros." );
95 CLIDict_Entry( macroProc,   "Pause/Resume macro processing." );
96 CLIDict_Entry( macroShow,   "Show the macro corresponding to the given index." NL "\t\t\033[35mT16\033[0m Indexed Trigger Macro 0x10, \033[35mR12\033[0m Indexed Result Macro 0x0C" );
97 CLIDict_Entry( macroStep,   "Do N macro processing steps. Defaults to 1." );
98
99 CLIDict_Def( macroCLIDict, "Macro Module Commands" ) = {
100         CLIDict_Item( capList ),
101         CLIDict_Item( capSelect ),
102         CLIDict_Item( keyHold ),
103         CLIDict_Item( keyPress ),
104         CLIDict_Item( keyRelease ),
105         CLIDict_Item( layerDebug ),
106         CLIDict_Item( layerList ),
107         CLIDict_Item( layerState ),
108         CLIDict_Item( macroDebug ),
109         CLIDict_Item( macroList ),
110         CLIDict_Item( macroProc ),
111         CLIDict_Item( macroShow ),
112         CLIDict_Item( macroStep ),
113         { 0, 0, 0 } // Null entry for dictionary end
114 };
115
116
117 // Layer debug flag - If set, displays any changes to layers and the full layer stack on change
118 uint8_t layerDebugMode = 0;
119
120 // Macro debug flag - If set, clears the USB Buffers after signalling processing completion
121 uint8_t macroDebugMode = 0;
122
123 // Macro pause flag - If set, the macro module pauses processing, unless unset, or the step counter is non-zero
124 uint8_t macroPauseMode = 0;
125
126 // Macro step counter - If non-zero, the step counter counts down every time the macro module does one processing loop
127 uint16_t macroStepCounter = 0;
128
129
130 // Key Trigger List Buffer and Layer Cache
131 // The layer cache is set on press only, hold and release events refer to the value set on press
132 TriggerGuide macroTriggerListBuffer[ MaxScanCode ];
133 uint8_t macroTriggerListBufferSize = 0;
134 var_uint_t macroTriggerListLayerCache[ MaxScanCode ];
135
136 // Pending Trigger Macro Index List
137 //  * Any trigger macros that need processing from a previous macro processing loop
138 // TODO, figure out a good way to scale this array size without wasting too much memory, but not rejecting macros
139 //       Possibly could be calculated by the KLL compiler
140 // XXX It may be possible to calculate the worst case using the KLL compiler
141 uint16_t macroTriggerMacroPendingList[ TriggerMacroNum ] = { 0 };
142 uint16_t macroTriggerMacroPendingListSize = 0;
143
144 // Layer Index Stack
145 //  * When modifying layer state and the state is non-0x0, the stack must be adjusted
146 uint16_t macroLayerIndexStack[ LayerNum + 1 ] = { 0 };
147 uint16_t macroLayerIndexStackSize = 0;
148
149 // Pending Result Macro Index List
150 //  * Any result macro that needs processing from a previous macro processing loop
151 uint16_t macroResultMacroPendingList[ ResultMacroNum ] = { 0 };
152 uint16_t macroResultMacroPendingListSize = 0;
153
154
155
156 // ----- Capabilities -----
157
158 // Sets the given layer with the specified layerState
159 void Macro_layerState( uint8_t state, uint8_t stateType, uint16_t layer, uint8_t layerState )
160 {
161         // Ignore if layer does not exist
162         if ( layer >= LayerNum )
163                 return;
164
165         // Is layer in the LayerIndexStack?
166         uint8_t inLayerIndexStack = 0;
167         uint16_t stackItem = 0;
168         while ( stackItem < macroLayerIndexStackSize )
169         {
170                 // Flag if layer is already in the LayerIndexStack
171                 if ( macroLayerIndexStack[ stackItem ] == layer )
172                 {
173                         inLayerIndexStack = 1;
174                         break;
175                 }
176
177                 // Increment to next item
178                 stackItem++;
179         }
180
181         // Toggle Layer State Byte
182         if ( LayerState[ layer ] & layerState )
183         {
184                 // Unset
185                 LayerState[ layer ] &= ~layerState;
186         }
187         else
188         {
189                 // Set
190                 LayerState[ layer ] |= layerState;
191         }
192
193         // If the layer was not in the LayerIndexStack add it
194         if ( !inLayerIndexStack )
195         {
196                 macroLayerIndexStack[ macroLayerIndexStackSize++ ] = layer;
197         }
198
199         // If the layer is in the LayerIndexStack and the state is 0x00, remove
200         if ( LayerState[ layer ] == 0x00 && inLayerIndexStack )
201         {
202                 // Remove the layer from the LayerIndexStack
203                 // Using the already positioned stackItem variable from the loop above
204                 while ( stackItem < macroLayerIndexStackSize )
205                 {
206                         macroLayerIndexStack[ stackItem ] = macroLayerIndexStack[ stackItem + 1 ];
207                         stackItem++;
208                 }
209
210                 // Reduce LayerIndexStack size
211                 macroLayerIndexStackSize--;
212         }
213
214         // Layer Debug Mode
215         if ( layerDebugMode )
216         {
217                 dbug_msg("Layer ");
218
219                 // Iterate over each of the layers displaying the state as a hex value
220                 for ( uint16_t index = 0; index < LayerNum; index++ )
221                 {
222                         printHex_op( LayerState[ index ], 0 );
223                 }
224
225                 // Always show the default layer (it's always 0)
226                 print(" 0");
227
228                 // Iterate over the layer stack starting from the bottom of the stack
229                 for ( uint16_t index = macroLayerIndexStackSize; index > 0; index-- )
230                 {
231                         print(":");
232                         printHex_op( macroLayerIndexStack[ index - 1 ], 0 );
233                 }
234
235                 print( NL );
236         }
237 }
238
239 // Modifies the specified Layer control byte
240 // Argument #1: Layer Index -> uint16_t
241 // Argument #2: Layer State -> uint8_t
242 void Macro_layerState_capability( uint8_t state, uint8_t stateType, uint8_t *args )
243 {
244         // Display capability name
245         if ( stateType == 0xFF && state == 0xFF )
246         {
247                 print("Macro_layerState(layerIndex,layerState)");
248                 return;
249         }
250
251         // Only use capability on press or release
252         // TODO Analog
253         // XXX This may cause issues, might be better to implement state table here to decide -HaaTa
254         if ( stateType == 0x00 && state == 0x02 ) // Hold condition
255                 return;
256
257         // Get layer index from arguments
258         // Cast pointer to uint8_t to uint16_t then access that memory location
259         uint16_t layer = *(uint16_t*)(&args[0]);
260
261         // Get layer toggle byte
262         uint8_t layerState = args[ sizeof(uint16_t) ];
263
264         Macro_layerState( state, stateType, layer, layerState );
265 }
266
267
268 // Latches given layer
269 // Argument #1: Layer Index -> uint16_t
270 void Macro_layerLatch_capability( uint8_t state, uint8_t stateType, uint8_t *args )
271 {
272         // Display capability name
273         if ( stateType == 0xFF && state == 0xFF )
274         {
275                 print("Macro_layerLatch(layerIndex)");
276                 return;
277         }
278
279         // Only use capability on press
280         // TODO Analog
281         if ( stateType == 0x00 && state != 0x03 ) // Only on release
282                 return;
283
284         // Get layer index from arguments
285         // Cast pointer to uint8_t to uint16_t then access that memory location
286         uint16_t layer = *(uint16_t*)(&args[0]);
287
288         Macro_layerState( state, stateType, layer, 0x02 );
289 }
290
291
292 // Locks given layer
293 // Argument #1: Layer Index -> uint16_t
294 void Macro_layerLock_capability( uint8_t state, uint8_t stateType, uint8_t *args )
295 {
296         // Display capability name
297         if ( stateType == 0xFF && state == 0xFF )
298         {
299                 print("Macro_layerLock(layerIndex)");
300                 return;
301         }
302
303         // Only use capability on press
304         // TODO Analog
305         // XXX Could also be on release, but that's sorta dumb -HaaTa
306         if ( stateType == 0x00 && state != 0x01 ) // All normal key conditions except press
307                 return;
308
309         // Get layer index from arguments
310         // Cast pointer to uint8_t to uint16_t then access that memory location
311         uint16_t layer = *(uint16_t*)(&args[0]);
312
313         Macro_layerState( state, stateType, layer, 0x04 );
314 }
315
316
317 // Shifts given layer
318 // Argument #1: Layer Index -> uint16_t
319 void Macro_layerShift_capability( uint8_t state, uint8_t stateType, uint8_t *args )
320 {
321         // Display capability name
322         if ( stateType == 0xFF && state == 0xFF )
323         {
324                 print("Macro_layerShift(layerIndex)");
325                 return;
326         }
327
328         // Only use capability on press or release
329         // TODO Analog
330         if ( stateType == 0x00 && ( state == 0x00 || state == 0x02 ) ) // Only pass press or release conditions
331                 return;
332
333         // Get layer index from arguments
334         // Cast pointer to uint8_t to uint16_t then access that memory location
335         uint16_t layer = *(uint16_t*)(&args[0]);
336
337         Macro_layerState( state, stateType, layer, 0x01 );
338 }
339
340
341
342 // ----- Functions -----
343
344 // Looks up the trigger list for the given scan code (from the active layer)
345 // NOTE: Calling function must handle the NULL pointer case
346 nat_ptr_t *Macro_layerLookup( TriggerGuide *guide, uint8_t latch_expire )
347 {
348         uint8_t scanCode = guide->scanCode;
349
350         // TODO Analog
351         // If a normal key, and not pressed, do a layer cache lookup
352         if ( guide->type == 0x00 && guide->state != 0x01 )
353         {
354                 // Cached layer
355                 var_uint_t cachedLayer = macroTriggerListLayerCache[ scanCode ];
356
357                 // Lookup map, then layer
358                 nat_ptr_t **map = (nat_ptr_t**)LayerIndex[ cachedLayer ].triggerMap;
359                 const Layer *layer = &LayerIndex[ cachedLayer ];
360
361                 return map[ scanCode - layer->first ];
362         }
363
364         // If no trigger macro is defined at the given layer, fallthrough to the next layer
365         for ( uint16_t layerIndex = 0; layerIndex < macroLayerIndexStackSize; layerIndex++ )
366         {
367                 // Lookup Layer
368                 const Layer *layer = &LayerIndex[ macroLayerIndexStack[ layerIndex ] ];
369
370                 // Check if latch has been pressed for this layer
371                 // XXX Regardless of whether a key is found, the latch is removed on first lookup
372                 uint8_t latch = LayerState[ macroLayerIndexStack[ layerIndex ] ] & 0x02;
373                 if ( latch && latch_expire )
374                 {
375                         Macro_layerState( 0, 0, macroLayerIndexStack[ layerIndex ], 0x02 );
376                 }
377
378                 // Only use layer, if state is valid
379                 // XOR each of the state bits
380                 // If only two are enabled, do not use this state
381                 if ( (LayerState[ macroLayerIndexStack[ layerIndex ] ] & 0x01) ^ (latch>>1) ^ ((LayerState[ macroLayerIndexStack[ layerIndex ] ] & 0x04)>>2) )
382                 {
383                         // Lookup layer
384                         nat_ptr_t **map = (nat_ptr_t**)layer->triggerMap;
385
386                         // Determine if layer has key defined
387                         // Make sure scanCode is between layer first and last scancodes
388                         if ( map != 0
389                           && scanCode <= layer->last
390                           && scanCode >= layer->first
391                           && *map[ scanCode - layer->first ] != 0 )
392                         {
393                                 // Set the layer cache
394                                 macroTriggerListLayerCache[ scanCode ] = macroLayerIndexStack[ layerIndex ];
395
396                                 return map[ scanCode - layer->first ];
397                         }
398                 }
399         }
400
401         // Do lookup on default layer
402         nat_ptr_t **map = (nat_ptr_t**)LayerIndex[0].triggerMap;
403
404         // Lookup default layer
405         const Layer *layer = &LayerIndex[0];
406
407         // Make sure scanCode is between layer first and last scancodes
408         if ( map != 0
409           && scanCode <= layer->last
410           && scanCode >= layer->first
411           && *map[ scanCode - layer->first ] != 0 )
412         {
413                 // Set the layer cache to default map
414                 macroTriggerListLayerCache[ scanCode ] = 0;
415
416                 return map[ scanCode - layer->first ];
417         }
418
419         // Otherwise no defined Trigger Macro
420         erro_msg("Scan Code has no defined Trigger Macro: ");
421         printHex( scanCode );
422         return 0;
423 }
424
425
426 // Update the scancode using a list of TriggerGuides
427 // TODO Handle led state and analog
428 inline void Macro_triggerState( void *triggers, uint8_t num )
429 {
430         // Copy each of the TriggerGuides to the TriggerListBuffer
431         for ( uint8_t c = 0; c < num; c++ )
432                 macroTriggerListBuffer[ macroTriggerListBufferSize++ ] = ((TriggerGuide*)triggers)[ c ];
433 }
434
435
436 // Update the scancode key state
437 // States:
438 //   * 0x00 - Off
439 //   * 0x01 - Pressed
440 //   * 0x02 - Held
441 //   * 0x03 - Released
442 //   * 0x04 - Unpressed (this is currently ignored)
443 inline void Macro_keyState( uint8_t scanCode, uint8_t state )
444 {
445         // Only add to macro trigger list if one of three states
446         switch ( state )
447         {
448         case 0x01: // Pressed
449         case 0x02: // Held
450         case 0x03: // Released
451                 macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
452                 macroTriggerListBuffer[ macroTriggerListBufferSize ].state    = state;
453                 macroTriggerListBuffer[ macroTriggerListBufferSize ].type     = 0x00; // Normal key
454                 macroTriggerListBufferSize++;
455                 break;
456         }
457 }
458
459
460 // Update the scancode analog state
461 // States:
462 //   * 0x00      - Off
463 //   * 0x01      - Released
464 //   * 0x02-0xFF - Analog value (low to high)
465 inline void Macro_analogState( uint8_t scanCode, uint8_t state )
466 {
467         // Only add to macro trigger list if non-off
468         if ( state != 0x00 )
469         {
470                 macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = scanCode;
471                 macroTriggerListBuffer[ macroTriggerListBufferSize ].state    = state;
472                 macroTriggerListBuffer[ macroTriggerListBufferSize ].type     = 0x02; // Analog key
473                 macroTriggerListBufferSize++;
474         }
475 }
476
477
478 // Update led state
479 // States:
480 //   * 0x00 - Off
481 //   * 0x01 - On
482 inline void Macro_ledState( uint8_t ledCode, uint8_t state )
483 {
484         // Only add to macro trigger list if non-off
485         if ( state != 0x00 )
486         {
487                 macroTriggerListBuffer[ macroTriggerListBufferSize ].scanCode = ledCode;
488                 macroTriggerListBuffer[ macroTriggerListBufferSize ].state    = state;
489                 macroTriggerListBuffer[ macroTriggerListBufferSize ].type     = 0x01; // LED key
490                 macroTriggerListBufferSize++;
491         }
492 }
493
494
495 // Append result macro to pending list, checking for duplicates
496 // Do nothing if duplicate
497 inline void Macro_appendResultMacroToPendingList( const TriggerMacro *triggerMacro )
498 {
499         // Lookup result macro index
500         var_uint_t resultMacroIndex = triggerMacro->result;
501
502         // Iterate through result macro pending list, making sure this macro hasn't been added yet
503         for ( var_uint_t macro = 0; macro < macroResultMacroPendingListSize; macro++ )
504         {
505                 // If duplicate found, do nothing
506                 if ( macroResultMacroPendingList[ macro ] == resultMacroIndex )
507                         return;
508         }
509
510         // No duplicates found, add to pending list
511         macroResultMacroPendingList[ macroResultMacroPendingListSize++ ] = resultMacroIndex;
512
513         // Lookup scanCode of the last key in the last combo
514         var_uint_t pos = 0;
515         for ( uint8_t comboLength = triggerMacro->guide[0]; comboLength > 0; )
516         {
517                 pos += TriggerGuideSize * comboLength + 1;
518                 comboLength = triggerMacro->guide[ pos ];
519         }
520
521         uint8_t scanCode = ((TriggerGuide*)&triggerMacro->guide[ pos - TriggerGuideSize ])->scanCode;
522
523         // Lookup scanCode in buffer list for the current state and stateType
524         for ( uint8_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ )
525         {
526                 if ( macroTriggerListBuffer[ keyIndex ].scanCode == scanCode )
527                 {
528                         ResultMacroRecordList[ resultMacroIndex ].state     = macroTriggerListBuffer[ keyIndex ].state;
529                         ResultMacroRecordList[ resultMacroIndex ].stateType = macroTriggerListBuffer[ keyIndex ].type;
530                 }
531         }
532
533         // Reset the macro position
534         ResultMacroRecordList[ resultMacroIndex ].pos = 0;
535 }
536
537
538 // Determine if long ResultMacro (more than 1 seqence element)
539 inline uint8_t Macro_isLongResultMacro( const ResultMacro *macro )
540 {
541         // Check the second sequence combo length
542         // If non-zero return non-zero (long sequence)
543         // 0 otherwise (short sequence)
544         var_uint_t position = 1;
545         for ( var_uint_t result = 0; result < macro->guide[0]; result++ )
546                 position += ResultGuideSize( (ResultGuide*)&macro->guide[ position ] );
547         return macro->guide[ position ];
548 }
549
550
551 // Determine if long TriggerMacro (more than 1 sequence element)
552 inline uint8_t Macro_isLongTriggerMacro( const TriggerMacro *macro )
553 {
554         // Check the second sequence combo length
555         // If non-zero return non-zero (long sequence)
556         // 0 otherwise (short sequence)
557         return macro->guide[ macro->guide[0] * TriggerGuideSize + 1 ];
558 }
559
560
561 // Votes on the given key vs. guide, short macros
562 inline TriggerMacroVote Macro_evalShortTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
563 {
564         // Depending on key type
565         switch ( guide->type )
566         {
567         // Normal State Type
568         case 0x00:
569                 // For short TriggerMacros completely ignore incorrect keys
570                 if ( guide->scanCode == key->scanCode )
571                 {
572                         switch ( key->state )
573                         {
574                         // Correct key, pressed, possible passing
575                         case 0x01:
576                                 return TriggerMacroVote_Pass;
577
578                         // Correct key, held, possible passing or release
579                         case 0x02:
580                                 return TriggerMacroVote_PassRelease;
581
582                         // Correct key, released, possible release
583                         case 0x03:
584                                 return TriggerMacroVote_Release;
585                         }
586                 }
587
588                 return TriggerMacroVote_DoNothing;
589
590         // LED State Type
591         case 0x01:
592                 erro_print("LED State Type - Not implemented...");
593                 break;
594
595         // Analog State Type
596         case 0x02:
597                 erro_print("Analog State Type - Not implemented...");
598                 break;
599
600         // Invalid State Type
601         default:
602                 erro_print("Invalid State Type. This is a bug.");
603                 break;
604         }
605
606         // XXX Shouldn't reach here
607         return TriggerMacroVote_Invalid;
608 }
609
610
611 // Votes on the given key vs. guide, long macros
612 // A long macro is defined as a guide with more than 1 combo
613 inline TriggerMacroVote Macro_evalLongTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
614 {
615         // Depending on key type
616         switch ( guide->type )
617         {
618         // Normal State Type
619         case 0x00:
620                 // Depending on the state of the buffered key, make voting decision
621                 // Incorrect key
622                 if ( guide->scanCode != key->scanCode )
623                 {
624                         switch ( key->state )
625                         {
626                         // Wrong key, pressed, fail
627                         case 0x01:
628                                 return TriggerMacroVote_Fail;
629
630                         // Wrong key, held, do not pass (no effect)
631                         case 0x02:
632                                 return TriggerMacroVote_DoNothing;
633
634                         // Wrong key released, fail out if pos == 0
635                         case 0x03:
636                                 return TriggerMacroVote_DoNothing | TriggerMacroVote_DoNothingRelease;
637                         }
638                 }
639
640                 // Correct key
641                 else
642                 {
643                         switch ( key->state )
644                         {
645                         // Correct key, pressed, possible passing
646                         case 0x01:
647                                 return TriggerMacroVote_Pass;
648
649                         // Correct key, held, possible passing or release
650                         case 0x02:
651                                 return TriggerMacroVote_PassRelease;
652
653                         // Correct key, released, possible release
654                         case 0x03:
655                                 return TriggerMacroVote_Release;
656                         }
657                 }
658
659                 break;
660
661         // LED State Type
662         case 0x01:
663                 erro_print("LED State Type - Not implemented...");
664                 break;
665
666         // Analog State Type
667         case 0x02:
668                 erro_print("Analog State Type - Not implemented...");
669                 break;
670
671         // Invalid State Type
672         default:
673                 erro_print("Invalid State Type. This is a bug.");
674                 break;
675         }
676
677         // XXX Shouldn't reach here
678         return TriggerMacroVote_Invalid;
679 }
680
681
682 // Evaluate/Update TriggerMacro
683 TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex )
684 {
685         // Lookup TriggerMacro
686         const TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ];
687         TriggerMacroRecord *record = &TriggerMacroRecordList[ triggerMacroIndex ];
688
689         // Check if macro has finished and should be incremented sequence elements
690         if ( record->state == TriggerMacro_Release )
691         {
692                 record->state = TriggerMacro_Waiting;
693                 record->pos = record->pos + macro->guide[ record->pos ] * TriggerGuideSize + 1;
694         }
695
696         // Current Macro position
697         var_uint_t pos = record->pos;
698
699         // Length of the combo being processed
700         uint8_t comboLength = macro->guide[ pos ] * TriggerGuideSize;
701
702         // If no combo items are left, remove the TriggerMacro from the pending list
703         if ( comboLength == 0 )
704         {
705                 return TriggerMacroEval_Remove;
706         }
707
708         // Check if this is a long Trigger Macro
709         uint8_t longMacro = Macro_isLongTriggerMacro( macro );
710
711         // Iterate through the items in the combo, voting the on the key state
712         // If any of the pressed keys do not match, fail the macro
713         //
714         // The macro is waiting for input when in the TriggerMacro_Waiting state
715         // Once all keys have been pressed/held (only those keys), entered TriggerMacro_Press state (passing)
716         // Transition to the next combo (if it exists) when a single key is released (TriggerMacro_Release state)
717         // On scan after position increment, change to TriggerMacro_Waiting state
718         // TODO Add support for system LED states (NumLock, CapsLock, etc.)
719         // TODO Add support for analog key states
720         // TODO Add support for 0x00 Key state (not pressing a key, not all that useful in general)
721         // TODO Add support for Press/Hold/Release differentiation when evaluating (not sure if useful)
722         TriggerMacroVote overallVote = TriggerMacroVote_Invalid;
723         for ( uint8_t comboItem = pos + 1; comboItem < pos + comboLength + 1; comboItem += TriggerGuideSize )
724         {
725                 // Assign TriggerGuide element (key type, state and scancode)
726                 TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ comboItem ]);
727
728                 TriggerMacroVote vote = TriggerMacroVote_Invalid;
729                 // Iterate through the key buffer, comparing to each key in the combo
730                 for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
731                 {
732                         // Lookup key information
733                         TriggerGuide *keyInfo = &macroTriggerListBuffer[ key ];
734
735                         // If vote is a pass (>= 0x08, no more keys in the combo need to be looked at)
736                         // Also mask all of the non-passing votes
737                         vote |= longMacro
738                                 ? Macro_evalLongTriggerMacroVote( keyInfo, guide )
739                                 : Macro_evalShortTriggerMacroVote( keyInfo, guide );
740                         if ( vote >= TriggerMacroVote_Pass )
741                         {
742                                 vote &= TriggerMacroVote_Release | TriggerMacroVote_PassRelease | TriggerMacroVote_Pass;
743                                 break;
744                         }
745                 }
746
747                 // If no pass vote was found after scanning all of the keys
748                 // Fail the combo, if this is a short macro (long macros already will have a fail vote)
749                 if ( !longMacro && vote < TriggerMacroVote_Pass )
750                         vote |= TriggerMacroVote_Fail;
751
752                 // After voting, append to overall vote
753                 overallVote |= vote;
754         }
755
756         // If no pass vote was found after scanning the entire combo
757         // And this is the first position in the combo, just remove it (nothing important happened)
758         if ( longMacro && overallVote & TriggerMacroVote_DoNothingRelease && pos == 0 )
759                 overallVote |= TriggerMacroVote_Fail;
760
761         // Decide new state of macro after voting
762         // Fail macro, remove from pending list
763         if ( overallVote & TriggerMacroVote_Fail )
764         {
765                 return TriggerMacroEval_Remove;
766         }
767         // Do nothing, incorrect key is being held or released
768         else if ( overallVote & TriggerMacroVote_DoNothing && longMacro )
769         {
770                 // Just doing nothing :)
771         }
772         // If ready for transition and in Press state, set to Waiting and increment combo position
773         // Position is incremented (and possibly remove the macro from the pending list) on the next iteration
774         else if ( overallVote & TriggerMacroVote_Release && record->state == TriggerMacro_Press )
775         {
776                 record->state = TriggerMacro_Release;
777
778                 // If this is the last combo in the sequence, remove from the pending list
779                 if ( macro->guide[ record->pos + macro->guide[ record->pos ] * TriggerGuideSize + 1 ] == 0 )
780                         return TriggerMacroEval_DoResultAndRemove;
781         }
782         // If passing and in Waiting state, set macro state to Press
783         else if ( overallVote & TriggerMacroVote_Pass
784              && ( record->state == TriggerMacro_Waiting || record->state == TriggerMacro_Press ) )
785         {
786                 record->state = TriggerMacro_Press;
787
788                 // If in press state, and this is the final combo, send request for ResultMacro
789                 // Check to see if the result macro only has a single element
790                 // If this result macro has more than 1 key, only send once
791                 // TODO Add option to have long macro repeat rate
792                 if ( macro->guide[ pos + comboLength + 1 ] == 0 )
793                 {
794                         // Long result macro (more than 1 combo)
795                         if ( Macro_isLongResultMacro( &ResultMacroList[ macro->result ] ) )
796                         {
797                                 // Only ever trigger result once, on press
798                                 if ( overallVote == TriggerMacroVote_Pass )
799                                 {
800                                         return TriggerMacroEval_DoResultAndRemove;
801                                 }
802                         }
803                         // Short result macro
804                         else
805                         {
806                                 // Only trigger result once, on press, if long trigger (more than 1 combo)
807                                 if ( Macro_isLongTriggerMacro( macro ) )
808                                 {
809                                         return TriggerMacroEval_DoResultAndRemove;
810                                 }
811                                 // Otherwise, trigger result continuously
812                                 else
813                                 {
814                                         return TriggerMacroEval_DoResult;
815                                 }
816                         }
817                 }
818         }
819         // Otherwise, just remove the macro on key release
820         // One more result has to be called to indicate to the ResultMacro that the key transitioned to the release state
821         else if ( overallVote & TriggerMacroVote_Release )
822         {
823                 return TriggerMacroEval_DoResultAndRemove;
824         }
825
826         // If this is a short macro, just remove it
827         // The state can be rebuilt on the next iteration
828         if ( !longMacro )
829                 return TriggerMacroEval_Remove;
830
831         return TriggerMacroEval_DoNothing;
832 }
833
834
835 // Evaluate/Update ResultMacro
836 inline ResultMacroEval Macro_evalResultMacro( var_uint_t resultMacroIndex )
837 {
838         // Lookup ResultMacro
839         const ResultMacro *macro = &ResultMacroList[ resultMacroIndex ];
840         ResultMacroRecord *record = &ResultMacroRecordList[ resultMacroIndex ];
841
842         // Current Macro position
843         var_uint_t pos = record->pos;
844
845         // Length of combo being processed
846         uint8_t comboLength = macro->guide[ pos ];
847
848         // Function Counter, used to keep track of the combo items processed
849         var_uint_t funcCount = 0;
850
851         // Combo Item Position within the guide
852         var_uint_t comboItem = pos + 1;
853
854         // Iterate through the Result Combo
855         while ( funcCount < comboLength )
856         {
857                 // Assign TriggerGuide element (key type, state and scancode)
858                 ResultGuide *guide = (ResultGuide*)(&macro->guide[ comboItem ]);
859
860                 // Do lookup on capability function
861                 void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
862
863                 // Call capability
864                 capability( record->state, record->stateType, &guide->args );
865
866                 // Increment counters
867                 funcCount++;
868                 comboItem += ResultGuideSize( (ResultGuide*)(&macro->guide[ comboItem ]) );
869         }
870
871         // Move to next item in the sequence
872         record->pos = comboItem;
873
874         // If the ResultMacro is finished, remove
875         if ( macro->guide[ comboItem ] == 0 )
876         {
877                 record->pos = 0;
878                 return ResultMacroEval_Remove;
879         }
880
881         // Otherwise leave the macro in the list
882         return ResultMacroEval_DoNothing;
883 }
884
885
886 // Update pending trigger list
887 inline void Macro_updateTriggerMacroPendingList()
888 {
889         // Iterate over the macroTriggerListBuffer to add any new Trigger Macros to the pending list
890         for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
891         {
892                 // TODO LED States
893                 // TODO Analog Switches
894                 // Only add TriggerMacro to pending list if key was pressed (not held, released or off)
895                 if ( macroTriggerListBuffer[ key ].state == 0x00 && macroTriggerListBuffer[ key ].state != 0x01 )
896                         continue;
897
898                 // TODO Analog
899                 // If this is a release case, indicate to layer lookup for possible latch expiry
900                 uint8_t latch_expire = macroTriggerListBuffer[ key ].state == 0x03;
901
902                 // Lookup Trigger List
903                 nat_ptr_t *triggerList = Macro_layerLookup( &macroTriggerListBuffer[ key ], latch_expire );
904
905                 // Number of Triggers in list
906                 nat_ptr_t triggerListSize = triggerList[0];
907
908                 // Iterate over triggerList to see if any TriggerMacros need to be added
909                 // First item is the number of items in the TriggerList
910                 for ( var_uint_t macro = 1; macro < triggerListSize + 1; macro++ )
911                 {
912                         // Lookup trigger macro index
913                         var_uint_t triggerMacroIndex = triggerList[ macro ];
914
915                         // Iterate over macroTriggerMacroPendingList to see if any macro in the scancode's
916                         //  triggerList needs to be added
917                         var_uint_t pending = 0;
918                         for ( ; pending < macroTriggerMacroPendingListSize; pending++ )
919                         {
920                                 // Stop scanning if the trigger macro index is found in the pending list
921                                 if ( macroTriggerMacroPendingList[ pending ] == triggerMacroIndex )
922                                         break;
923                         }
924
925                         // If the triggerMacroIndex (macro) was not found in the macroTriggerMacroPendingList
926                         // Add it to the list
927                         if ( pending == macroTriggerMacroPendingListSize )
928                         {
929                                 macroTriggerMacroPendingList[ macroTriggerMacroPendingListSize++ ] = triggerMacroIndex;
930
931                                 // Reset macro position
932                                 TriggerMacroRecordList[ triggerMacroIndex ].pos   = 0;
933                                 TriggerMacroRecordList[ triggerMacroIndex ].state = TriggerMacro_Waiting;
934                         }
935                 }
936         }
937 }
938
939
940 // Macro Procesing Loop
941 // Called once per USB buffer send
942 inline void Macro_process()
943 {
944         // Only do one round of macro processing between Output Module timer sends
945         if ( USBKeys_Sent != 0 )
946                 return;
947
948         // If the pause flag is set, only process if the step counter is non-zero
949         if ( macroPauseMode )
950         {
951                 if ( macroStepCounter == 0 )
952                         return;
953
954                 // Proceed, decrementing the step counter
955                 macroStepCounter--;
956                 dbug_print("Macro Step");
957         }
958
959         // Update pending trigger list, before processing TriggerMacros
960         Macro_updateTriggerMacroPendingList();
961
962         // Tail pointer for macroTriggerMacroPendingList
963         // Macros must be explicitly re-added
964         var_uint_t macroTriggerMacroPendingListTail = 0;
965
966         // Iterate through the pending TriggerMacros, processing each of them
967         for ( var_uint_t macro = 0; macro < macroTriggerMacroPendingListSize; macro++ )
968         {
969                 switch ( Macro_evalTriggerMacro( macroTriggerMacroPendingList[ macro ] ) )
970                 {
971                 // Trigger Result Macro (purposely falling through)
972                 case TriggerMacroEval_DoResult:
973                         // Append ResultMacro to PendingList
974                         Macro_appendResultMacroToPendingList( &TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ] );
975
976                 default:
977                         macroTriggerMacroPendingList[ macroTriggerMacroPendingListTail++ ] = macroTriggerMacroPendingList[ macro ];
978                         break;
979
980                 // Trigger Result Macro and Remove (purposely falling through)
981                 case TriggerMacroEval_DoResultAndRemove:
982                         // Append ResultMacro to PendingList
983                         Macro_appendResultMacroToPendingList( &TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ] );
984
985                 // Remove Macro from Pending List, nothing to do, removing by default
986                 case TriggerMacroEval_Remove:
987                         break;
988                 }
989         }
990
991         // Update the macroTriggerMacroPendingListSize with the tail pointer
992         macroTriggerMacroPendingListSize = macroTriggerMacroPendingListTail;
993
994
995         // Tail pointer for macroResultMacroPendingList
996         // Macros must be explicitly re-added
997         var_uint_t macroResultMacroPendingListTail = 0;
998
999         // Iterate through the pending ResultMacros, processing each of them
1000         for ( var_uint_t macro = 0; macro < macroResultMacroPendingListSize; macro++ )
1001         {
1002                 switch ( Macro_evalResultMacro( macroResultMacroPendingList[ macro ] ) )
1003                 {
1004                 // Re-add macros to pending list
1005                 case ResultMacroEval_DoNothing:
1006                 default:
1007                         macroResultMacroPendingList[ macroResultMacroPendingListTail++ ] = macroResultMacroPendingList[ macro ];
1008                         break;
1009
1010                 // Remove Macro from Pending List, nothing to do, removing by default
1011                 case ResultMacroEval_Remove:
1012                         break;
1013                 }
1014         }
1015
1016         // Update the macroResultMacroPendingListSize with the tail pointer
1017         macroResultMacroPendingListSize = macroResultMacroPendingListTail;
1018
1019         // Signal buffer that we've used it
1020         Scan_finishedWithMacro( macroTriggerListBufferSize );
1021
1022         // Reset TriggerList buffer
1023         macroTriggerListBufferSize = 0;
1024
1025         // If Macro debug mode is set, clear the USB Buffer
1026         if ( macroDebugMode )
1027         {
1028                 USBKeys_Modifiers = 0;
1029                 USBKeys_Sent = 0;
1030         }
1031 }
1032
1033
1034 inline void Macro_setup()
1035 {
1036         // Register Macro CLI dictionary
1037         CLI_registerDictionary( macroCLIDict, macroCLIDictName );
1038
1039         // Disable Macro debug mode
1040         macroDebugMode = 0;
1041
1042         // Disable Macro pause flag
1043         macroPauseMode = 0;
1044
1045         // Set Macro step counter to zero
1046         macroStepCounter = 0;
1047
1048         // Make sure macro trigger buffer is empty
1049         macroTriggerListBufferSize = 0;
1050
1051         // Initialize TriggerMacro states
1052         for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ )
1053         {
1054                 TriggerMacroRecordList[ macro ].pos   = 0;
1055                 TriggerMacroRecordList[ macro ].state = TriggerMacro_Waiting;
1056         }
1057
1058         // Initialize ResultMacro states
1059         for ( var_uint_t macro = 0; macro < ResultMacroNum; macro++ )
1060         {
1061                 ResultMacroRecordList[ macro ].pos       = 0;
1062                 ResultMacroRecordList[ macro ].state     = 0;
1063                 ResultMacroRecordList[ macro ].stateType = 0;
1064         }
1065 }
1066
1067
1068 // ----- CLI Command Functions -----
1069
1070 void cliFunc_capList( char* args )
1071 {
1072         print( NL );
1073         info_msg("Capabilities List ");
1074         printHex( CapabilitiesNum );
1075
1076         // Iterate through all of the capabilities and display them
1077         for ( var_uint_t cap = 0; cap < CapabilitiesNum; cap++ )
1078         {
1079                 print( NL "\t" );
1080                 printHex( cap );
1081                 print(" - ");
1082
1083                 // Display/Lookup Capability Name (utilize debug mode of capability)
1084                 void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ cap ].func);
1085                 capability( 0xFF, 0xFF, 0 );
1086         }
1087 }
1088
1089 void cliFunc_capSelect( char* args )
1090 {
1091         // Parse code from argument
1092         char* curArgs;
1093         char* arg1Ptr;
1094         char* arg2Ptr = args;
1095
1096         // Total number of args to scan (must do a lookup if a keyboard capability is selected)
1097         var_uint_t totalArgs = 2; // Always at least two args
1098         var_uint_t cap = 0;
1099
1100         // Arguments used for keyboard capability function
1101         var_uint_t argSetCount = 0;
1102         uint8_t *argSet = (uint8_t*)args;
1103
1104         // Process all args
1105         for ( var_uint_t c = 0; argSetCount < totalArgs; c++ )
1106         {
1107                 curArgs = arg2Ptr;
1108                 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
1109
1110                 // Stop processing args if no more are found
1111                 // Extra arguments are ignored
1112                 if ( *arg1Ptr == '\0' )
1113                         break;
1114
1115                 // For the first argument, choose the capability
1116                 if ( c == 0 ) switch ( arg1Ptr[0] )
1117                 {
1118                 // Keyboard Capability
1119                 case 'K':
1120                         // Determine capability index
1121                         cap = numToInt( &arg1Ptr[1] );
1122
1123                         // Lookup the number of args
1124                         totalArgs += CapabilitiesList[ cap ].argCount;
1125                         continue;
1126                 }
1127
1128                 // Because allocating memory isn't doable, and the argument count is arbitrary
1129                 // The argument pointer is repurposed as the argument list (much smaller anyways)
1130                 argSet[ argSetCount++ ] = (uint8_t)numToInt( arg1Ptr );
1131
1132                 // Once all the arguments are prepared, call the keyboard capability function
1133                 if ( argSetCount == totalArgs )
1134                 {
1135                         // Indicate that the capability was called
1136                         print( NL );
1137                         info_msg("K");
1138                         printInt8( cap );
1139                         print(" - ");
1140                         printHex( argSet[0] );
1141                         print(" - ");
1142                         printHex( argSet[1] );
1143                         print(" - ");
1144                         printHex( argSet[2] );
1145                         print( "..." NL );
1146
1147                         void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ cap ].func);
1148                         capability( argSet[0], argSet[1], &argSet[2] );
1149                 }
1150         }
1151 }
1152
1153 void cliFunc_keyHold( char* args )
1154 {
1155         // Parse codes from arguments
1156         char* curArgs;
1157         char* arg1Ptr;
1158         char* arg2Ptr = args;
1159
1160         // Process all args
1161         for ( ;; )
1162         {
1163                 curArgs = arg2Ptr;
1164                 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
1165
1166                 // Stop processing args if no more are found
1167                 if ( *arg1Ptr == '\0' )
1168                         break;
1169
1170                 // Ignore non-Scancode numbers
1171                 switch ( arg1Ptr[0] )
1172                 {
1173                 // Scancode
1174                 case 'S':
1175                         Macro_keyState( (uint8_t)numToInt( &arg1Ptr[1] ), 0x02 ); // Hold scancode
1176                         break;
1177                 }
1178         }
1179 }
1180
1181 void cliFunc_keyPress( char* args )
1182 {
1183         // Parse codes from arguments
1184         char* curArgs;
1185         char* arg1Ptr;
1186         char* arg2Ptr = args;
1187
1188         // Process all args
1189         for ( ;; )
1190         {
1191                 curArgs = arg2Ptr;
1192                 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
1193
1194                 // Stop processing args if no more are found
1195                 if ( *arg1Ptr == '\0' )
1196                         break;
1197
1198                 // Ignore non-Scancode numbers
1199                 switch ( arg1Ptr[0] )
1200                 {
1201                 // Scancode
1202                 case 'S':
1203                         Macro_keyState( (uint8_t)numToInt( &arg1Ptr[1] ), 0x01 ); // Press scancode
1204                         break;
1205                 }
1206         }
1207 }
1208
1209 void cliFunc_keyRelease( char* args )
1210 {
1211         // Parse codes from arguments
1212         char* curArgs;
1213         char* arg1Ptr;
1214         char* arg2Ptr = args;
1215
1216         // Process all args
1217         for ( ;; )
1218         {
1219                 curArgs = arg2Ptr;
1220                 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
1221
1222                 // Stop processing args if no more are found
1223                 if ( *arg1Ptr == '\0' )
1224                         break;
1225
1226                 // Ignore non-Scancode numbers
1227                 switch ( arg1Ptr[0] )
1228                 {
1229                 // Scancode
1230                 case 'S':
1231                         Macro_keyState( (uint8_t)numToInt( &arg1Ptr[1] ), 0x03 ); // Release scancode
1232                         break;
1233                 }
1234         }
1235 }
1236
1237 void cliFunc_layerDebug( char *args )
1238 {
1239         // Toggle layer debug mode
1240         layerDebugMode = layerDebugMode ? 0 : 1;
1241
1242         print( NL );
1243         info_msg("Layer Debug Mode: ");
1244         printInt8( layerDebugMode );
1245 }
1246
1247 void cliFunc_layerList( char* args )
1248 {
1249         print( NL );
1250         info_msg("Layer List");
1251
1252         // Iterate through all of the layers and display them
1253         for ( uint16_t layer = 0; layer < LayerNum; layer++ )
1254         {
1255                 print( NL "\t" );
1256                 printHex( layer );
1257                 print(" - ");
1258
1259                 // Display layer name
1260                 dPrint( (char*)LayerIndex[ layer ].name );
1261
1262                 // Default map
1263                 if ( layer == 0 )
1264                         print(" \033[1m(default)\033[0m");
1265
1266                 // Layer State
1267                 print( NL "\t\t Layer State: " );
1268                 printHex( LayerState[ layer ] );
1269
1270                 // First -> Last Indices
1271                 print(" First -> Last Indices: ");
1272                 printHex( LayerIndex[ layer ].first );
1273                 print(" -> ");
1274                 printHex( LayerIndex[ layer ].last );
1275         }
1276 }
1277
1278 void cliFunc_layerState( char* args )
1279 {
1280         // Parse codes from arguments
1281         char* curArgs;
1282         char* arg1Ptr;
1283         char* arg2Ptr = args;
1284
1285         uint8_t arg1 = 0;
1286         uint8_t arg2 = 0;
1287
1288         // Process first two args
1289         for ( uint8_t c = 0; c < 2; c++ )
1290         {
1291                 curArgs = arg2Ptr;
1292                 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
1293
1294                 // Stop processing args if no more are found
1295                 if ( *arg1Ptr == '\0' )
1296                         break;
1297
1298                 switch ( c )
1299                 {
1300                 // First argument (e.g. L1)
1301                 case 0:
1302                         if ( arg1Ptr[0] != 'L' )
1303                                 return;
1304
1305                         arg1 = (uint8_t)numToInt( &arg1Ptr[1] );
1306                         break;
1307                 // Second argument (e.g. 4)
1308                 case 1:
1309                         arg2 = (uint8_t)numToInt( arg1Ptr );
1310
1311                         // Display operation (to indicate that it worked)
1312                         print( NL );
1313                         info_msg("Setting Layer L");
1314                         printInt8( arg1 );
1315                         print(" to - ");
1316                         printHex( arg2 );
1317
1318                         // Set the layer state
1319                         LayerState[ arg1 ] = arg2;
1320                         break;
1321                 }
1322         }
1323 }
1324
1325 void cliFunc_macroDebug( char* args )
1326 {
1327         // Toggle macro debug mode
1328         macroDebugMode = macroDebugMode ? 0 : 1;
1329
1330         print( NL );
1331         info_msg("Macro Debug Mode: ");
1332         printInt8( macroDebugMode );
1333 }
1334
1335 void cliFunc_macroList( char* args )
1336 {
1337         // Show pending key events
1338         print( NL );
1339         info_msg("Pending Key Events: ");
1340         printInt16( (uint16_t)macroTriggerListBufferSize );
1341         print(" : ");
1342         for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
1343         {
1344                 printHex( macroTriggerListBuffer[ key ].scanCode );
1345                 print(" ");
1346         }
1347
1348         // Show pending trigger macros
1349         print( NL );
1350         info_msg("Pending Trigger Macros: ");
1351         printInt16( (uint16_t)macroTriggerMacroPendingListSize );
1352         print(" : ");
1353         for ( var_uint_t macro = 0; macro < macroTriggerMacroPendingListSize; macro++ )
1354         {
1355                 printHex( macroTriggerMacroPendingList[ macro ] );
1356                 print(" ");
1357         }
1358
1359         // Show pending result macros
1360         print( NL );
1361         info_msg("Pending Result Macros: ");
1362         printInt16( (uint16_t)macroResultMacroPendingListSize );
1363         print(" : ");
1364         for ( var_uint_t macro = 0; macro < macroResultMacroPendingListSize; macro++ )
1365         {
1366                 printHex( macroResultMacroPendingList[ macro ] );
1367                 print(" ");
1368         }
1369
1370         // Show available trigger macro indices
1371         print( NL );
1372         info_msg("Trigger Macros Range: T0 -> T");
1373         printInt16( (uint16_t)TriggerMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)
1374
1375         // Show available result macro indices
1376         print( NL );
1377         info_msg("Result  Macros Range: R0 -> R");
1378         printInt16( (uint16_t)ResultMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)
1379
1380         // Show Trigger to Result Macro Links
1381         print( NL );
1382         info_msg("Trigger : Result Macro Pairs");
1383         for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ )
1384         {
1385                 print( NL );
1386                 print("\tT");
1387                 printInt16( (uint16_t)macro ); // Hopefully large enough :P (can't assume 32-bit)
1388                 print(" : R");
1389                 printInt16( (uint16_t)TriggerMacroList[ macro ].result ); // Hopefully large enough :P (can't assume 32-bit)
1390         }
1391 }
1392
1393 void cliFunc_macroProc( char* args )
1394 {
1395         // Toggle macro pause mode
1396         macroPauseMode = macroPauseMode ? 0 : 1;
1397
1398         print( NL );
1399         info_msg("Macro Processing Mode: ");
1400         printInt8( macroPauseMode );
1401 }
1402
1403 void macroDebugShowTrigger( var_uint_t index )
1404 {
1405         // Only proceed if the macro exists
1406         if ( index >= TriggerMacroNum )
1407                 return;
1408
1409         // Trigger Macro Show
1410         const TriggerMacro *macro = &TriggerMacroList[ index ];
1411         TriggerMacroRecord *record = &TriggerMacroRecordList[ index ];
1412
1413         print( NL );
1414         info_msg("Trigger Macro Index: ");
1415         printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
1416         print( NL );
1417
1418         // Read the comboLength for combo in the sequence (sequence of combos)
1419         var_uint_t pos = 0;
1420         uint8_t comboLength = macro->guide[ pos ];
1421
1422         // Iterate through and interpret the guide
1423         while ( comboLength != 0 )
1424         {
1425                 // Initial position of the combo
1426                 var_uint_t comboPos = ++pos;
1427
1428                 // Iterate through the combo
1429                 while ( pos < comboLength * TriggerGuideSize + comboPos )
1430                 {
1431                         // Assign TriggerGuide element (key type, state and scancode)
1432                         TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ pos ]);
1433
1434                         // Display guide information about trigger key
1435                         printHex( guide->scanCode );
1436                         print("|");
1437                         printHex( guide->type );
1438                         print("|");
1439                         printHex( guide->state );
1440
1441                         // Increment position
1442                         pos += TriggerGuideSize;
1443
1444                         // Only show combo separator if there are combos left in the sequence element
1445                         if ( pos < comboLength * TriggerGuideSize + comboPos )
1446                                 print("+");
1447                 }
1448
1449                 // Read the next comboLength
1450                 comboLength = macro->guide[ pos ];
1451
1452                 // Only show sequence separator if there is another combo to process
1453                 if ( comboLength != 0 )
1454                         print(";");
1455         }
1456
1457         // Display current position
1458         print( NL "Position: " );
1459         printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)
1460
1461         // Display result macro index
1462         print( NL "Result Macro Index: " );
1463         printInt16( (uint16_t)macro->result ); // Hopefully large enough :P (can't assume 32-bit)
1464
1465         // Display trigger macro state
1466         print( NL "Trigger Macro State: " );
1467         switch ( record->state )
1468         {
1469         case TriggerMacro_Press:   print("Press");   break;
1470         case TriggerMacro_Release: print("Release"); break;
1471         case TriggerMacro_Waiting: print("Waiting"); break;
1472         }
1473 }
1474
1475 void macroDebugShowResult( var_uint_t index )
1476 {
1477         // Only proceed if the macro exists
1478         if ( index >= ResultMacroNum )
1479                 return;
1480
1481         // Trigger Macro Show
1482         const ResultMacro *macro = &ResultMacroList[ index ];
1483         ResultMacroRecord *record = &ResultMacroRecordList[ index ];
1484
1485         print( NL );
1486         info_msg("Result Macro Index: ");
1487         printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
1488         print( NL );
1489
1490         // Read the comboLength for combo in the sequence (sequence of combos)
1491         var_uint_t pos = 0;
1492         uint8_t comboLength = macro->guide[ pos++ ];
1493
1494         // Iterate through and interpret the guide
1495         while ( comboLength != 0 )
1496         {
1497                 // Function Counter, used to keep track of the combos processed
1498                 var_uint_t funcCount = 0;
1499
1500                 // Iterate through the combo
1501                 while ( funcCount < comboLength )
1502                 {
1503                         // Assign TriggerGuide element (key type, state and scancode)
1504                         ResultGuide *guide = (ResultGuide*)(&macro->guide[ pos ]);
1505
1506                         // Display Function Index
1507                         printHex( guide->index );
1508                         print("|");
1509
1510                         // Display Function Ptr Address
1511                         printHex( (nat_ptr_t)CapabilitiesList[ guide->index ].func );
1512                         print("|");
1513
1514                         // Display/Lookup Capability Name (utilize debug mode of capability)
1515                         void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
1516                         capability( 0xFF, 0xFF, 0 );
1517
1518                         // Display Argument(s)
1519                         print("(");
1520                         for ( var_uint_t arg = 0; arg < CapabilitiesList[ guide->index ].argCount; arg++ )
1521                         {
1522                                 // Arguments are only 8 bit values
1523                                 printHex( (&guide->args)[ arg ] );
1524
1525                                 // Only show arg separator if there are args left
1526                                 if ( arg + 1 < CapabilitiesList[ guide->index ].argCount )
1527                                         print(",");
1528                         }
1529                         print(")");
1530
1531                         // Increment position
1532                         pos += ResultGuideSize( guide );
1533
1534                         // Increment function count
1535                         funcCount++;
1536
1537                         // Only show combo separator if there are combos left in the sequence element
1538                         if ( funcCount < comboLength )
1539                                 print("+");
1540                 }
1541
1542                 // Read the next comboLength
1543                 comboLength = macro->guide[ pos++ ];
1544
1545                 // Only show sequence separator if there is another combo to process
1546                 if ( comboLength != 0 )
1547                         print(";");
1548         }
1549
1550         // Display current position
1551         print( NL "Position: " );
1552         printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)
1553
1554         // Display final trigger state/type
1555         print( NL "Final Trigger State (State/Type): " );
1556         printHex( record->state );
1557         print("/");
1558         printHex( record->stateType );
1559 }
1560
1561 void cliFunc_macroShow( char* args )
1562 {
1563         // Parse codes from arguments
1564         char* curArgs;
1565         char* arg1Ptr;
1566         char* arg2Ptr = args;
1567
1568         // Process all args
1569         for ( ;; )
1570         {
1571                 curArgs = arg2Ptr;
1572                 CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
1573
1574                 // Stop processing args if no more are found
1575                 if ( *arg1Ptr == '\0' )
1576                         break;
1577
1578                 // Ignore invalid codes
1579                 switch ( arg1Ptr[0] )
1580                 {
1581                 // Indexed Trigger Macro
1582                 case 'T':
1583                         macroDebugShowTrigger( numToInt( &arg1Ptr[1] ) );
1584                         break;
1585                 // Indexed Result Macro
1586                 case 'R':
1587                         macroDebugShowResult( numToInt( &arg1Ptr[1] ) );
1588                         break;
1589                 }
1590         }
1591 }
1592
1593 void cliFunc_macroStep( char* args )
1594 {
1595         // Parse number from argument
1596         //  NOTE: Only first argument is used
1597         char* arg1Ptr;
1598         char* arg2Ptr;
1599         CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
1600
1601         // Default to 1, if no argument given
1602         var_uint_t count = (var_uint_t)numToInt( arg1Ptr );
1603
1604         if ( count == 0 )
1605                 count = 1;
1606
1607         // Set the macro step counter, negative int's are cast to uint
1608         macroStepCounter = count;
1609 }
1610