]> git.donarmstrong.com Git - kiibohd-controller.git/commitdiff
Basic Trigger and Result Macros are now working.
authorJacob Alexander <haata@kiibohd.com>
Wed, 20 Aug 2014 17:53:22 +0000 (10:53 -0700)
committerJacob Alexander <haata@kiibohd.com>
Wed, 20 Aug 2014 17:53:22 +0000 (10:53 -0700)
- More complex macro not yet tested (long Trigger to long Result)
- Long Trigger Macros not tested yet

Macro/PartialMap/generatedKeymap.h
Macro/PartialMap/macro.c

index d8e2de4f29fe353c21efa85c5b3b7facf2110e61..7455c4f04e54b17fa4a5b18886c1b5f1bbc2b462 100644 (file)
@@ -188,6 +188,7 @@ Guide_RM( 0 ) = { 1, 0, 0xDA, 0 };
 Guide_RM( 1 ) = { 1, 0, 0xBE, 1, 0, 0xEF, 0 };
 Guide_RM( 2 ) = { 2, 0, 0xFA, 0, 0xAD, 0 };
 Guide_RM( 3 ) = { 1, 1, 0xCA, 0xFE, 0 };
+Guide_RM( 4 ) = { 1, 0, 0xDA, 0 };
 
 
 // -- Result Macro List
@@ -202,6 +203,7 @@ ResultMacro ResultMacroList[] = {
        Define_RM( 1 ),
        Define_RM( 2 ),
        Define_RM( 3 ),
+       Define_RM( 4 ),
 };
 
 
@@ -222,6 +224,12 @@ Guide_TM( 1 ) = { 1, 0x00, 0x01, 0x73, 1, 0x00, 0x01, 0x75, 0 };
 Guide_TM( 2 ) = { 2, 0x00, 0x01, 0x73, 0x00, 0x01, 0x74, 0 };
 Guide_TM( 3 ) = { 1, 0x00, 0x01, 0x76, 0 };
 Guide_TM( 4 ) = { 1, 0x00, 0x01, 0x77, 0 };
+Guide_TM( 5 ) = { 1, 0x00, 0x01, 0x2E, 0 };
+Guide_TM( 6 ) = { 1, 0x00, 0x01, 0x2D, 0 };
+Guide_TM( 7 ) = { 1, 0x00, 0x01, 0x2C, 0 };
+Guide_TM( 8 ) = { 2, 0x00, 0x01, 0x20, 0x00, 0x01, 0x21, 0 };
+Guide_TM( 9 ) = { 1, 0x00, 0x01, 0x20, 1, 0x00, 0x01, 0x22, 0 };
+Guide_TM( 10 ) = { 1, 0x00, 0x01, 0x2B, 0 };
 
 
 // -- Trigger Macro List
@@ -237,6 +245,12 @@ TriggerMacro TriggerMacroList[] = {
        Define_TM( 2, 2 ),
        Define_TM( 3, 3 ),
        Define_TM( 4, 0 ),
+       Define_TM( 5, 0 ),
+       Define_TM( 6, 1 ),
+       Define_TM( 7, 2 ),
+       Define_TM( 8, 0 ),
+       Define_TM( 9, 0 ), // TODO
+       Define_TM( 10, 4 ),
 };
 
 
@@ -294,8 +308,8 @@ Define_TL( default, 0x1C ) = { 0 };
 Define_TL( default, 0x1D ) = { 0 };
 Define_TL( default, 0x1E ) = { 0 };
 Define_TL( default, 0x1F ) = { 0 };
-Define_TL( default, 0x20 ) = { 0 };
-Define_TL( default, 0x21 ) = { 0 };
+Define_TL( default, 0x20 ) = { 1, 8 };
+Define_TL( default, 0x21 ) = { 1, 8 };
 Define_TL( default, 0x22 ) = { 0 };
 Define_TL( default, 0x23 ) = { 0 };
 Define_TL( default, 0x24 ) = { 0 };
@@ -305,10 +319,10 @@ Define_TL( default, 0x27 ) = { 0 };
 Define_TL( default, 0x28 ) = { 0 };
 Define_TL( default, 0x29 ) = { 0 };
 Define_TL( default, 0x2A ) = { 0 };
-Define_TL( default, 0x2B ) = { 0 };
-Define_TL( default, 0x2C ) = { 0 };
-Define_TL( default, 0x2D ) = { 0 };
-Define_TL( default, 0x2E ) = { 0 };
+Define_TL( default, 0x2B ) = { 1, 10 };
+Define_TL( default, 0x2C ) = { 1, 7 };
+Define_TL( default, 0x2D ) = { 1, 6 };
+Define_TL( default, 0x2E ) = { 1, 5 };
 Define_TL( default, 0x2F ) = { 0 };
 Define_TL( default, 0x30 ) = { 0 };
 Define_TL( default, 0x31 ) = { 0 };
index e6c82ecae2a9257af9f56d9c8b03f88f560be7c2..3e31bb35d2f8338d863c0dd6c0ca5445a177a8ba 100644 (file)
@@ -317,8 +317,11 @@ inline void Macro_ledState( uint8_t ledCode, uint8_t state )
 
 // Append result macro to pending list, checking for duplicates
 // Do nothing if duplicate
-inline void Macro_appendResultMacroToPendingList( unsigned int resultMacroIndex )
+inline void Macro_appendResultMacroToPendingList( TriggerMacro *triggerMacro )
 {
+       // Lookup result macro index
+       unsigned int resultMacroIndex = triggerMacro->result;
+
        // Iterate through result macro pending list, making sure this macro hasn't been added yet
        for ( unsigned int macro = 0; macro < macroResultMacroPendingListSize; macro++ )
        {
@@ -329,6 +332,29 @@ inline void Macro_appendResultMacroToPendingList( unsigned int resultMacroIndex
 
        // No duplicates found, add to pending list
        macroResultMacroPendingList[ macroResultMacroPendingListSize++ ] = resultMacroIndex;
+
+       // Lookup scanCode of the last key in the last combo
+       unsigned int pos = 0;
+       for ( uint8_t comboLength = triggerMacro->guide[0]; comboLength > 0; )
+       {
+               pos += TriggerGuideSize * comboLength + 1;
+               comboLength = triggerMacro->guide[ pos ];
+       }
+
+       uint8_t scanCode = ((TriggerGuide*)&triggerMacro->guide[ pos - TriggerGuideSize ])->scanCode;
+
+       // Lookup scanCode in buffer list for the current state and stateType
+       for ( uint8_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ )
+       {
+               if ( macroTriggerListBuffer[ keyIndex ].scanCode == scanCode )
+               {
+                       ResultMacroList[ resultMacroIndex ].state     = macroTriggerListBuffer[ keyIndex ].state;
+                       ResultMacroList[ resultMacroIndex ].stateType = macroTriggerListBuffer[ keyIndex ].type;
+               }
+       }
+
+       // Reset the macro position
+       ResultMacroList[ resultMacroIndex ].pos = 0;
 }
 
 
@@ -336,14 +362,78 @@ inline void Macro_appendResultMacroToPendingList( unsigned int resultMacroIndex
 inline uint8_t Macro_isLongResultMacro( ResultMacro *macro )
 {
        // Check the second sequence combo length
-       // If non-zero return 1 (long sequence)
+       // If non-zero return non-zero (long sequence)
        // 0 otherwise (short sequence)
-       return macro->guide[ macro->guide[0] * ResultGuideSize( (ResultGuide*)macro->guide ) ] > 0 ? 1 : 0;
+       unsigned int position = 1;
+       for ( unsigned int result = 0; result < macro->guide[0]; result++ )
+               position += ResultGuideSize( (ResultGuide*)&macro->guide[ position ] );
+       return macro->guide[ position ];
 }
 
 
-// Votes on the given key vs. guide
-inline TriggerMacroVote Macro_evalTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
+// Determine if long TriggerMacro (more than 1 sequence element)
+inline uint8_t Macro_isLongTriggerMacro( TriggerMacro *macro )
+{
+       // Check the second sequence combo length
+       // If non-zero return non-zero (long sequence)
+       // 0 otherwise (short sequence)
+       return macro->guide[ macro->guide[0] * TriggerGuideSize + 1 ];
+}
+
+
+// Votes on the given key vs. guide, short macros
+inline TriggerMacroVote Macro_evalShortTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
+{
+       // Depending on key type
+       switch ( guide->type )
+       {
+       // Normal State Type
+       case 0x00:
+               // For short TriggerMacros completely ignore incorrect keys
+               if ( guide->scanCode == key->scanCode )
+               {
+                       switch ( key->state )
+                       {
+                       // Correct key, pressed, possible passing
+                       case 0x01:
+                               return TriggerMacroVote_Pass;
+
+                       // Correct key, held, possible passing or release
+                       case 0x02:
+                               return TriggerMacroVote_PassRelease;
+
+                       // Correct key, released, possible release
+                       case 0x03:
+                               return TriggerMacroVote_Release;
+                       }
+               }
+
+               return TriggerMacroVote_DoNothing;
+
+       // LED State Type
+       case 0x01:
+               erro_print("LED State Type - Not implemented...");
+               break;
+
+       // Analog State Type
+       case 0x02:
+               erro_print("Analog State Type - Not implemented...");
+               break;
+
+       // Invalid State Type
+       default:
+               erro_print("Invalid State Type. This is a bug.");
+               break;
+       }
+
+       // XXX Shouldn't reach here
+       return TriggerMacroVote_Invalid;
+}
+
+
+// Votes on the given key vs. guide, long macros
+// A long macro is defined as a guide with more than 1 combo
+inline TriggerMacroVote Macro_evalLongTriggerMacroVote( TriggerGuide *key, TriggerGuide *guide )
 {
        // Depending on key type
        switch ( guide->type )
@@ -419,14 +509,14 @@ inline TriggerMacroEval Macro_evalTriggerMacro( unsigned int triggerMacroIndex )
        if ( macro->state == TriggerMacro_Release )
        {
                macro->state = TriggerMacro_Waiting;
-               macro->pos = macro->pos + macro->guide[ macro->pos ] * TriggerGuideSize;
+               macro->pos = macro->pos + macro->guide[ macro->pos ] * TriggerGuideSize + 1;
        }
 
        // Current Macro position
        unsigned int pos = macro->pos;
 
        // Length of the combo being processed
-       uint8_t comboLength = macro->guide[ pos ];
+       uint8_t comboLength = macro->guide[ pos ] * TriggerGuideSize;
 
        // If no combo items are left, remove the TriggerMacro from the pending list
        if ( comboLength == 0 )
@@ -434,7 +524,10 @@ inline TriggerMacroEval Macro_evalTriggerMacro( unsigned int triggerMacroIndex )
                return TriggerMacroEval_Remove;
        }
 
-       // Iterate through the key buffer, comparing to each key in the combo
+       // Check if this is a long Trigger Macro
+       uint8_t longMacro = Macro_isLongTriggerMacro( macro );
+
+       // Iterate through the items in the combo, voting the on the key state
        // If any of the pressed keys do not match, fail the macro
        //
        // The macro is waiting for input when in the TriggerMacro_Waiting state
@@ -446,21 +539,23 @@ inline TriggerMacroEval Macro_evalTriggerMacro( unsigned int triggerMacroIndex )
        // TODO Add support for 0x00 Key state (not pressing a key, not all that useful in general)
        // TODO Add support for Press/Hold/Release differentiation when evaluating (not sure if useful)
        TriggerMacroVote overallVote = TriggerMacroVote_Invalid;
-       for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
+       for ( uint8_t comboItem = pos + 1; comboItem < pos + comboLength + 1; comboItem += TriggerGuideSize )
        {
-               // Lookup key information
-               TriggerGuide *keyInfo = &macroTriggerListBuffer[ key ];
+               // Assign TriggerGuide element (key type, state and scancode)
+               TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ comboItem ]);
 
-               // Iterate through the items in the combo, voting the on the key state
                TriggerMacroVote vote = TriggerMacroVote_Invalid;
-               for ( uint8_t comboItem = pos + 1; comboItem < pos + comboLength + 1; comboItem += TriggerGuideSize )
+               // Iterate through the key buffer, comparing to each key in the combo
+               for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
                {
-                       // Assign TriggerGuide element (key type, state and scancode)
-                       TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ comboItem ]);
+                       // Lookup key information
+                       TriggerGuide *keyInfo = &macroTriggerListBuffer[ key ];
 
                        // If vote is a pass (>= 0x08, no more keys in the combo need to be looked at)
                        // Also mask all of the non-passing votes
-                       vote |= Macro_evalTriggerMacroVote( keyInfo, guide );
+                       vote |= longMacro
+                               ? Macro_evalLongTriggerMacroVote( keyInfo, guide )
+                               : Macro_evalShortTriggerMacroVote( keyInfo, guide );
                        if ( vote >= TriggerMacroVote_Pass )
                        {
                                vote &= TriggerMacroVote_Release | TriggerMacroVote_PassRelease | TriggerMacroVote_Pass;
@@ -468,6 +563,11 @@ inline TriggerMacroEval Macro_evalTriggerMacro( unsigned int triggerMacroIndex )
                        }
                }
 
+               // If no pass vote was found after scanning all of the keys
+               // Fail the combo, if this is a short macro (long macros already will have a fail vote)
+               if ( !longMacro && vote < TriggerMacroVote_Pass )
+                       vote |= TriggerMacroVote_Fail;
+
                // After voting, append to overall vote
                overallVote |= vote;
        }
@@ -479,36 +579,69 @@ inline TriggerMacroEval Macro_evalTriggerMacro( unsigned int triggerMacroIndex )
                return TriggerMacroEval_Remove;
        }
        // Do nothing, incorrect key is being held or released
-       else if ( overallVote & TriggerMacroVote_DoNothing )
+       else if ( overallVote & TriggerMacroVote_DoNothing && longMacro )
        {
                // Just doing nothing :)
        }
        // If passing and in Waiting state, set macro state to Press
-       else if ( overallVote & TriggerMacroVote_Pass && macro->state == TriggerMacro_Waiting )
+       else if ( overallVote & TriggerMacroVote_Pass
+            && ( macro->state == TriggerMacro_Waiting || macro->state == TriggerMacro_Press ) )
        {
                macro->state = TriggerMacro_Press;
 
                // If in press state, and this is the final combo, send request for ResultMacro
                // Check to see if the result macro only has a single element
                // If this result macro has more than 1 key, only send once
-               // TODO Add option to have macro repeat rate
-               if ( macro->guide[ pos + comboLength ] == 0 )
+               // TODO Add option to have long macro repeat rate
+               if ( macro->guide[ pos + comboLength + 1 ] == 0 )
                {
-                       // Long Macro, only send once (more than 1 sequence item)
-                       // Short Macro (only 1 sequence item)
-                       return Macro_isLongResultMacro( &ResultMacroList[ macro->result ] )
-                               ? TriggerMacroEval_DoResult
-                               : TriggerMacroEval_DoResultAndRemove;
+                       // Long result macro (more than 1 combo)
+                       if ( Macro_isLongResultMacro( &ResultMacroList[ macro->result ] ) )
+                       {
+                               // Only ever trigger result once, on press
+                               if ( overallVote == TriggerMacroVote_Pass )
+                               {
+                                       return TriggerMacroEval_DoResultAndRemove;
+                               }
+                       }
+                       // Short result macro
+                       else
+                       {
+                               // Only trigger result once, on press, if long trigger (more than 1 combo)
+                               if ( Macro_isLongTriggerMacro( macro ) )
+                               {
+                                       return TriggerMacroEval_DoResultAndRemove;
+                               }
+                               // Otherwise, trigger result continuously
+                               else
+                               {
+                                       return TriggerMacroEval_DoResult;
+                               }
+                       }
                }
-
        }
        // If ready for transition and in Press state, set to Waiting and increment combo position
        // Position is incremented (and possibly remove the macro from the pending list) on the next iteration
        else if ( overallVote & TriggerMacroVote_Release && macro->state == TriggerMacro_Press )
        {
                macro->state = TriggerMacro_Release;
+
+               // If this is the last combo in the sequence, remove from the pending list
+               if ( macro->guide[ macro->pos + macro->guide[ macro->pos ] * TriggerGuideSize + 1 ] == 0 )
+                       return TriggerMacroEval_Remove;
+       }
+       // Otherwise, just remove the macro on key release
+       // XXX Might cause some issues
+       else if ( overallVote & TriggerMacroVote_Release )
+       {
+               return TriggerMacroEval_Remove;
        }
 
+       // If this is a short macro, just remove it
+       // The state can be rebuilt on the next iteration
+       if ( !longMacro )
+               return TriggerMacroEval_Remove;
+
        return TriggerMacroEval_DoNothing;
 }
 
@@ -525,12 +658,6 @@ inline ResultMacroEval Macro_evalResultMacro( unsigned int resultMacroIndex )
        // Length of combo being processed
        uint8_t comboLength = macro->guide[ pos ];
 
-       // If no combo items are left, remove the ResultMacro from the pending list
-       if ( comboLength == 0 )
-       {
-               return ResultMacroEval_Remove;
-       }
-
        // Function Counter, used to keep track of the combo items processed
        unsigned int funcCount = 0;
 
@@ -541,7 +668,7 @@ inline ResultMacroEval Macro_evalResultMacro( unsigned int resultMacroIndex )
        while ( funcCount < comboLength )
        {
                // Assign TriggerGuide element (key type, state and scancode)
-               ResultGuide *guide = (ResultGuide*)(&macro->guide[ pos ]);
+               ResultGuide *guide = (ResultGuide*)(&macro->guide[ comboItem ]);
 
                // Do lookup on capability function
                void (*capability)(uint8_t, uint8_t, uint8_t*) = (void(*)(uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
@@ -557,17 +684,29 @@ inline ResultMacroEval Macro_evalResultMacro( unsigned int resultMacroIndex )
        // Move to next item in the sequence
        macro->pos = comboItem;
 
-       // If the ResultMacro is finished, it will be removed on the next iteration
+       // If the ResultMacro is finished, remove
+       if ( macro->guide[ comboItem ] == 0 )
+       {
+               return ResultMacroEval_Remove;
+       }
+
+       // Otherwise leave the macro in the list
        return ResultMacroEval_DoNothing;
 }
 
 
 // Update pending trigger list
-void Macro_updateTriggerMacroPendingList()
+inline void Macro_updateTriggerMacroPendingList()
 {
        // Iterate over the macroTriggerListBuffer to add any new Trigger Macros to the pending list
        for ( uint8_t key = 0; key < macroTriggerListBufferSize; key++ )
        {
+               // TODO LED States
+               // TODO Analog Switches
+               // Only add TriggerMacro to pending list if key was pressed (not held, released or off)
+               if ( macroTriggerListBuffer[ key ].state == 0x00 && macroTriggerListBuffer[ key ].state != 0x01 )
+                       continue;
+
                // Lookup Trigger List
                unsigned int *triggerList = Macro_layerLookup( macroTriggerListBuffer[ key ].scanCode );
 
@@ -596,6 +735,10 @@ void Macro_updateTriggerMacroPendingList()
                        if ( pending == macroTriggerMacroPendingListSize )
                        {
                                macroTriggerMacroPendingList[ macroTriggerMacroPendingListSize++ ] = triggerMacroIndex;
+
+                               // Reset macro position
+                               TriggerMacroList[ triggerMacroIndex ].pos   = 0;
+                               TriggerMacroList[ triggerMacroIndex ].state = TriggerMacro_Waiting;
                        }
                }
        }
@@ -636,20 +779,23 @@ inline void Macro_process()
                // Trigger Result Macro (purposely falling through)
                case TriggerMacroEval_DoResult:
                        // Append ResultMacro to PendingList
-                       Macro_appendResultMacroToPendingList( TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ].result );
+                       Macro_appendResultMacroToPendingList( &TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ] );
+                       print("D");
 
-               // Otherwise, just re-add
                default:
                        macroTriggerMacroPendingList[ macroTriggerMacroPendingListTail++ ] = macroTriggerMacroPendingList[ macro ];
+                       print("A");
                        break;
 
                // Trigger Result Macro and Remove (purposely falling through)
                case TriggerMacroEval_DoResultAndRemove:
                        // Append ResultMacro to PendingList
-                       Macro_appendResultMacroToPendingList( TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ].result );
+                       Macro_appendResultMacroToPendingList( &TriggerMacroList[ macroTriggerMacroPendingList[ macro ] ] );
+                       print("&");
 
                // Remove Macro from Pending List, nothing to do, removing by default
                case TriggerMacroEval_Remove:
+                       print("R");
                        break;
                }
        }
@@ -717,8 +863,8 @@ inline void Macro_setup()
        // Initialize TriggerMacro states
        for ( unsigned int macro = 0; macro < TriggerMacroNum; macro++ )
        {
-               TriggerMacroList[ macro ].pos    = 0;
-               TriggerMacroList[ macro ].state  = TriggerMacro_Waiting;
+               TriggerMacroList[ macro ].pos   = 0;
+               TriggerMacroList[ macro ].state = TriggerMacro_Waiting;
        }
 
        // Initialize ResultMacro states
@@ -1114,6 +1260,15 @@ void macroDebugShowTrigger( unsigned int index )
        // Display result macro index
        print( NL "Result Macro Index: " );
        printInt16( (uint16_t)macro->result ); // Hopefully large enough :P (can't assume 32-bit)
+
+       // Display trigger macro state
+       print( NL "Trigger Macro State: " );
+       switch ( macro->state )
+       {
+       case TriggerMacro_Press:   print("Press");   break;
+       case TriggerMacro_Release: print("Release"); break;
+       case TriggerMacro_Waiting: print("Waiting"); break;
+       }
 }
 
 void macroDebugShowResult( unsigned int index )