Browse Source

Basic code for Simple/Normal macro processing

- Needs more testing
- Simple ResultMacros are called immediately instead of delaying
  (Normal macros need to be delayed)
- Removed old code that determined at runtime if a macro was Simple/Normal
  (Replaced with a lookup)
- Added some flash optimizations
simple
Jacob Alexander 9 years ago
parent
commit
a056317203
2 changed files with 83 additions and 59 deletions
  1. 1
    1
      Macro/Common/kll.h
  2. 82
    58
      Macro/PartialMap/macro.c

+ 1
- 1
Macro/Common/kll.h View File

/* Copyright (C) 2014 by Jacob Alexander
/* Copyright (C) 2014-2015 by Jacob Alexander
* *
* This file is free software: you can redistribute it and/or modify * This file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

+ 82
- 58
Macro/PartialMap/macro.c View File

// TODO, figure out a good way to scale this array size without wasting too much memory, but not rejecting macros // TODO, figure out a good way to scale this array size without wasting too much memory, but not rejecting macros
// Possibly could be calculated by the KLL compiler // Possibly could be calculated by the KLL compiler
// XXX It may be possible to calculate the worst case using the KLL compiler // XXX It may be possible to calculate the worst case using the KLL compiler
uint16_t macroTriggerMacroPendingList[ TriggerMacroNum ] = { 0 };
uint16_t macroTriggerMacroPendingList[ TriggerMacroNum ];
uint16_t macroTriggerMacroPendingListSize = 0; uint16_t macroTriggerMacroPendingListSize = 0;


// Layer Index Stack // Layer Index Stack
// * When modifying layer state and the state is non-0x0, the stack must be adjusted // * When modifying layer state and the state is non-0x0, the stack must be adjusted
uint16_t macroLayerIndexStack[ LayerNum + 1 ] = { 0 };
uint16_t macroLayerIndexStack[ LayerNum + 1 ];
uint16_t macroLayerIndexStackSize = 0; uint16_t macroLayerIndexStackSize = 0;


// Pending Result Macro Index List // Pending Result Macro Index List
// * Any result macro that needs processing from a previous macro processing loop // * Any result macro that needs processing from a previous macro processing loop
uint16_t macroResultMacroPendingList[ ResultMacroNum ] = { 0 };
uint16_t macroResultMacroPendingList[ ResultMacroNum ];
uint16_t macroResultMacroPendingListSize = 0; uint16_t macroResultMacroPendingListSize = 0;




} }




// Evaluate a ResultMacro Combination
var_uint_t Macro_evalResultMacroCombo( const uint8_t *guidePos, var_uint_t comboItem, uint8_t comboLength, const uint8_t state, const uint8_t stateType )
{
var_uint_t funcCount = 0;

// Iterate through the Result Combo
while ( funcCount < comboLength )
{
// Assign TriggerGuide element (key type, state and scancode)
ResultGuide *guide = (ResultGuide*)(&guidePos[ 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);

// Call capability
capability( state, stateType, &guide->args );

// Increment counters
funcCount++;
comboItem += ResultGuideSize( (ResultGuide*)(&guide[ comboItem ]) );
}

return comboItem;
}


// Append result macro to pending list, checking for duplicates // Append result macro to pending list, checking for duplicates
// Do nothing if duplicate // Do nothing if duplicate
inline void Macro_appendResultMacroToPendingList( const TriggerMacro *triggerMacro ) inline void Macro_appendResultMacroToPendingList( const TriggerMacro *triggerMacro )
uint8_t scanCode = ((TriggerGuide*)&triggerMacro->guide[ pos - TriggerGuideSize ])->scanCode; uint8_t scanCode = ((TriggerGuide*)&triggerMacro->guide[ pos - TriggerGuideSize ])->scanCode;


// Lookup scanCode in buffer list for the current state and stateType // Lookup scanCode in buffer list for the current state and stateType
TriggerGuide *guide = 0;
for ( uint8_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ ) for ( uint8_t keyIndex = 0; keyIndex < macroTriggerListBufferSize; keyIndex++ )
{ {
if ( macroTriggerListBuffer[ keyIndex ].scanCode == scanCode ) if ( macroTriggerListBuffer[ keyIndex ].scanCode == scanCode )
{ {
ResultMacroList[ resultMacroIndex ].record->state = macroTriggerListBuffer[ keyIndex ].state;
ResultMacroList[ resultMacroIndex ].record->stateType = macroTriggerListBuffer[ keyIndex ].type;
guide = &macroTriggerListBuffer[ keyIndex ];
break;
} }
} }


// Reset the macro position
ResultMacroList[ resultMacroIndex ].record->pos = 0;
}

// Depending on the type of ResultMacro, either call the capability immediately, or delay
switch ( ResultMacroList[ resultMacroIndex ].type )
{
// Simple ResultMacro
case MacroType_Simple:
// Call Capability immediately instead of waiting
// This means we don't have to store the state and type information
// (It would be thrown away during this scan cycle anyways)
Macro_evalResultMacroCombo( ResultMacroList[ resultMacroIndex ].guide, 1, ResultMacroList[ resultMacroIndex ].guide[ 0 ], guide->state, guide->type );
break;


// Determine if long ResultMacro (more than 1 seqence element)
inline uint8_t Macro_isLongResultMacro( const ResultMacro *macro )
{
// Check the second sequence combo length
// If non-zero return non-zero (long sequence)
// 0 otherwise (short sequence)
var_uint_t position = 1;
for ( var_uint_t result = 0; result < macro->guide[0]; result++ )
position += ResultGuideSize( (ResultGuide*)&macro->guide[ position ] );
return macro->guide[ position ];
}
// Complex ResultMacro
case MacroType_Normal:
ResultMacroList[ resultMacroIndex ].record->state = guide->state;
ResultMacroList[ resultMacroIndex ].record->stateType = guide->type;


// Reset the macro position
ResultMacroList[ resultMacroIndex ].record->pos = 0;
break;


// Determine if long TriggerMacro (more than 1 sequence element)
inline uint8_t Macro_isLongTriggerMacro( const 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 ];
default:
erro_print("Invalid MacroType. This is a bug");
break;
}
} }




} }


// Check if this is a long Trigger Macro // Check if this is a long Trigger Macro
uint8_t longMacro = Macro_isLongTriggerMacro( macro );
uint8_t longMacro = macro->type == MacroType_Normal;


// Iterate through the items in the combo, voting the on the key state // 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 // If any of the pressed keys do not match, fail the macro
if ( macro->guide[ pos + comboLength + 1 ] == 0 ) if ( macro->guide[ pos + comboLength + 1 ] == 0 )
{ {
// Long result macro (more than 1 combo) // Long result macro (more than 1 combo)
if ( Macro_isLongResultMacro( &ResultMacroList[ macro->result ] ) )
if ( ResultMacroList[ macro->result ].type == MacroType_Normal )
{ {
// Only ever trigger result once, on press // Only ever trigger result once, on press
if ( overallVote == TriggerMacroVote_Pass ) if ( overallVote == TriggerMacroVote_Pass )
else else
{ {
// Only trigger result once, on press, if long trigger (more than 1 combo) // Only trigger result once, on press, if long trigger (more than 1 combo)
if ( Macro_isLongTriggerMacro( macro ) )
if ( macro->type == MacroType_Normal )
{ {
return TriggerMacroEval_DoResultAndRemove; return TriggerMacroEval_DoResultAndRemove;
} }
const ResultMacro *macro = &ResultMacroList[ resultMacroIndex ]; const ResultMacro *macro = &ResultMacroList[ resultMacroIndex ];
ResultMacroRecord *record = ResultMacroList[ resultMacroIndex ].record; ResultMacroRecord *record = ResultMacroList[ resultMacroIndex ].record;


// If this is a simple ResultMacro, the capability has already been called, remove
if ( macro->type == MacroType_Simple )
{
return ResultMacroEval_Remove;
}

// Current Macro position // Current Macro position
var_uint_t pos = record->pos; var_uint_t pos = record->pos;


// Length of combo being processed // Length of combo being processed
uint8_t comboLength = macro->guide[ pos ]; uint8_t comboLength = macro->guide[ pos ];


// Function Counter, used to keep track of the combo items processed
var_uint_t funcCount = 0;

// Combo Item Position within the guide // Combo Item Position within the guide
var_uint_t comboItem = pos + 1; var_uint_t comboItem = pos + 1;


// Iterate through the Result Combo
while ( funcCount < comboLength )
{
// Assign TriggerGuide element (key type, state and scancode)
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);

// Call capability
capability( record->state, record->stateType, &guide->args );

// Increment counters
funcCount++;
comboItem += ResultGuideSize( (ResultGuide*)(&macro->guide[ comboItem ]) );
}
// Evaluate ResultCombo
comboItem = Macro_evalResultMacroCombo( macro->guide, comboItem, comboLength, record->state, record->stateType );


// Move to next item in the sequence // Move to next item in the sequence
record->pos = comboItem; record->pos = comboItem;
// Initialize TriggerMacro states // Initialize TriggerMacro states
for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ ) for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ )
{ {
TriggerMacroList[ macro ].record->pos = 0;
TriggerMacroList[ macro ].record->state = TriggerMacro_Waiting;
if ( TriggerMacroList[ macro ].type == MacroType_Normal )
{
TriggerMacroList[ macro ].record->pos = 0;
TriggerMacroList[ macro ].record->state = TriggerMacro_Waiting;
}
} }


// Initialize ResultMacro states // Initialize ResultMacro states
for ( var_uint_t macro = 0; macro < ResultMacroNum; macro++ ) for ( var_uint_t macro = 0; macro < ResultMacroNum; macro++ )
{ {
ResultMacroList[ macro ].record->pos = 0;
ResultMacroList[ macro ].record->state = 0;
ResultMacroList[ macro ].record->stateType = 0;
if ( ResultMacroList[ macro ].type == MacroType_Normal )
{
ResultMacroList[ macro ].record->pos = 0;
ResultMacroList[ macro ].record->state = 0;
ResultMacroList[ macro ].record->stateType = 0;
}
} }
} }


printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit) printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)


// Display final trigger state/type // Display final trigger state/type
print( NL "Final Trigger State (State/Type): " );
printHex( record->state );
print("/");
printHex( record->stateType );
if ( macro->type == MacroType_Normal )
{
print( NL "Final Trigger State (State/Type): " );
printHex( record->state );
print("/");
printHex( record->stateType );
}
} }


void cliFunc_macroShow( char* args ) void cliFunc_macroShow( char* args )