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