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