From 6e4c28ef84af42280ebbf991f7376a413181368e Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Thu, 2 Oct 2014 22:09:34 -0700 Subject: [PATCH] HUGE AVR RAM optimization (~28%). - It's possible to get even more, but this is probably as far as I'll go - PROGMEM is really annoying to use, and makes the code look like ass - Now the Teensy 2++ should have enough RAM to use PartialMap easily --- Debug/cli/cli.c | 42 +++++++++++++++++++++------------- Debug/cli/cli.h | 37 +++++++++++++++++++++++++++--- Debug/print/print.h | 2 +- Macro/PartialMap/macro.c | 40 ++++++++++++++++++++------------ Output/pjrcUSB/output_com.c | 19 +++++++++------ Output/uartOut/output_com.c | 19 +++++++++------ Output/usbMuxUart/output_com.c | 25 ++++++++++++-------- Scan/DPH/scan_loop.c | 23 ++++++++++++------- Scan/MD1/scan_loop.c | 7 +++--- Scan/MatrixARM/matrix_scan.c | 10 ++++---- 10 files changed, 152 insertions(+), 72 deletions(-) diff --git a/Debug/cli/cli.c b/Debug/cli/cli.c index fcee021..570c621 100644 --- a/Debug/cli/cli.c +++ b/Debug/cli/cli.c @@ -35,15 +35,22 @@ // ----- Variables ----- // Basic command dictionary -const char basicCLIDictName[] = "General Commands"; -const CLIDictItem basicCLIDict[] = { - { "cliDebug", "Enables/Disables hex output of the most recent cli input.", cliFunc_cliDebug }, - { "help", "You're looking at it :P", cliFunc_help }, - { "led", "Enables/Disables indicator LED. Try a couple times just in case the LED is in an odd state.\r\n\t\t\033[33mWarning\033[0m: May adversely affect some modules...", cliFunc_led }, - { "reload", "Signals microcontroller to reflash/reload.", cliFunc_reload }, - { "reset", "Resets the terminal back to initial settings.", cliFunc_reset }, - { "restart", "Sends a software restart, should be similar to powering on the device.", cliFunc_restart }, - { "version", "Version information about this firmware.", cliFunc_version }, +CLIDict_Entry( cliDebug, "Enables/Disables hex output of the most recent cli input." ); +CLIDict_Entry( help, "You're looking at it :P" ); +CLIDict_Entry( led, "Enables/Disables indicator LED. Try a couple times just in case the LED is in an odd state.\r\n\t\t\033[33mWarning\033[0m: May adversely affect some modules..." ); +CLIDict_Entry( reload, "Signals microcontroller to reflash/reload." ); +CLIDict_Entry( reset, "Resets the terminal back to initial settings." ); +CLIDict_Entry( restart, "Sends a software restart, should be similar to powering on the device." ); +CLIDict_Entry( version, "Version information about this firmware." ); + +CLIDict_Def( basicCLIDict, "General Commands" ) = { + CLIDict_Item( cliDebug ), + CLIDict_Item( help ), + CLIDict_Item( led ), + CLIDict_Item( reload ), + CLIDict_Item( reset ), + CLIDict_Item( restart ), + CLIDict_Item( version ), { 0, 0, 0 } // Null entry for dictionary end }; @@ -250,11 +257,11 @@ void CLI_commandLookup() for ( uint8_t cmd = 0; CLIDict[dict][cmd].name != 0; cmd++ ) { // Compare the first argument and each command entry - if ( eqStr( cmdPtr, CLIDict[dict][cmd].name ) == -1 ) + if ( eqStr( cmdPtr, (char*)CLIDict[dict][cmd].name ) == -1 ) { // Run the specified command function pointer // argPtr is already pointing at the first character of the arguments - (*CLIDict[dict][cmd].function)( argPtr ); + (*(void (*)(char*))CLIDict[dict][cmd].function)( argPtr ); return; } @@ -310,11 +317,11 @@ inline void CLI_tabCompletion() // NOTE: To save on processing, we only care about the commands and ignore the arguments // If there are arguments, and a valid tab match is found, buffer is cleared (args lost) // Also ignores full matches - if ( eqStr( cmdPtr, CLIDict[dict][cmd].name ) == 0 ) + if ( eqStr( cmdPtr, (char*)CLIDict[dict][cmd].name ) == 0 ) { // TODO Make list of commands if multiple matches matches++; - tabMatch = CLIDict[dict][cmd].name; + tabMatch = (char*)CLIDict[dict][cmd].name; } } } @@ -367,7 +374,9 @@ void cliFunc_help( char* args ) for ( uint8_t dict = 0; dict < CLIDictionariesUsed; dict++ ) { // Print the name of each dictionary as a title - dPrintStrsNL( NL, "\033[1;32m", CLIDictNames[dict], "\033[0m" ); + print( NL "\033[1;32m" ); + _print( CLIDictNames[dict] ); // This print is requride by AVR (flash) + print( "\033[0m" NL ); // Parse each cmd/description until a null command entry is found for ( uint8_t cmd = 0; CLIDict[dict][cmd].name != 0; cmd++ ) @@ -375,11 +384,12 @@ void cliFunc_help( char* args ) dPrintStrs(" \033[35m", CLIDict[dict][cmd].name, "\033[0m"); // Determine number of spaces to tab by the length of the command and TabAlign - uint8_t padLength = CLIEntryTabAlign - lenStr( CLIDict[dict][cmd].name ); + uint8_t padLength = CLIEntryTabAlign - lenStr( (char*)CLIDict[dict][cmd].name ); while ( padLength-- > 0 ) print(" "); - dPrintStrNL( CLIDict[dict][cmd].description ); + _print( CLIDict[dict][cmd].description ); // This print is required by AVR (flash) + print( NL ); } } } diff --git a/Debug/cli/cli.h b/Debug/cli/cli.h index 84266a3..5432c94 100644 --- a/Debug/cli/cli.h +++ b/Debug/cli/cli.h @@ -38,13 +38,44 @@ #define CLIEntryTabAlign 13 + +// ----- Macros ----- + +// AVR CLI Dictionary definitions (has to deal with the annoying PROGMEM +// Only using PROGMEM with descriptions (all the string comparison tools need to be re-written otherwise) +#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR +#define CLIDict_Def(name,description) \ + const PROGMEM char name##Name[] = description; \ + const CLIDictItem name[] + +#define CLIDict_Item(name) \ + { #name, name##CLIDict_DescEntry, (const void (*)(char*))cliFunc_##name } + +#define CLIDict_Entry(name,description) \ + const PROGMEM char name##CLIDict_DescEntry[] = description; + +// ARM is easy :P +#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // ARM +#define CLIDict_Def(name,description) \ + const char name##Name[] = description; \ + const CLIDictItem name[] + +#define CLIDict_Item(name) \ + { #name, name##CLIDict_DescEntry, (const void (*)(char*))cliFunc_##name } + +#define CLIDict_Entry(name,description) \ + const char name##CLIDict_DescEntry[] = description; +#endif + + + // ----- Structs ----- // Each item has a name, description, and function pointer with an argument for arguments typedef struct CLIDictItem { - char* name; - char* description; - void (*function)(char*); + const char* name; + const char* description; + const void (*function)(char*); } CLIDictItem; diff --git a/Debug/print/print.h b/Debug/print/print.h index c349432..0eec7cb 100644 --- a/Debug/print/print.h +++ b/Debug/print/print.h @@ -88,7 +88,7 @@ #define print(s) _print(s) #endif -void _print(const char *s); +void _print( const char *s ); void printstrs( char* first, ... ); diff --git a/Macro/PartialMap/macro.c b/Macro/PartialMap/macro.c index 73e643a..5cca4d3 100644 --- a/Macro/PartialMap/macro.c +++ b/Macro/PartialMap/macro.c @@ -81,20 +81,32 @@ typedef enum ResultMacroEval { // ----- Variables ----- // Macro Module command dictionary -const char macroCLIDictName[] = "Macro Module Commands"; -const CLIDictItem macroCLIDict[] = { - { "capList", "Prints an indexed list of all non USB keycode capabilities.", cliFunc_capList }, - { "capSelect", "Triggers the specified capabilities. First two args are state and stateType." NL "\t\t\033[35mK11\033[0m Keyboard Capability 0x0B", cliFunc_capSelect }, - { "keyHold", "Send key-hold events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A", cliFunc_keyHold }, - { "keyPress", "Send key-press events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A", cliFunc_keyPress }, - { "keyRelease", "Send key-release event to macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A", cliFunc_keyRelease }, - { "layerList", "List available layers.", cliFunc_layerList }, - { "layerState", "Modify specified indexed layer state ." NL "\t\t\033[35mL2\033[0m Indexed Layer 0x02" NL "\t\t0 Off, 1 Shift, 2 Latch, 4 Lock States", cliFunc_layerState }, - { "macroDebug", "Disables/Enables sending USB keycodes to the Output Module and prints U/K codes.", cliFunc_macroDebug }, - { "macroList", "List the defined trigger and result macros.", cliFunc_macroList }, - { "macroProc", "Pause/Resume macro processing.", cliFunc_macroProc }, - { "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 }, - { "macroStep", "Do N macro processing steps. Defaults to 1.", cliFunc_macroStep }, +CLIDict_Entry( capList, "Prints an indexed list of all non USB keycode capabilities." ); +CLIDict_Entry( capSelect, "Triggers the specified capabilities. First two args are state and stateType." NL "\t\t\033[35mK11\033[0m Keyboard Capability 0x0B" ); +CLIDict_Entry( keyHold, "Send key-hold events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" ); +CLIDict_Entry( keyPress, "Send key-press events to the macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" ); +CLIDict_Entry( keyRelease, "Send key-release event to macro module. Duplicates have undefined behaviour." NL "\t\t\033[35mS10\033[0m Scancode 0x0A" ); +CLIDict_Entry( layerList, "List available layers." ); +CLIDict_Entry( layerState, "Modify specified indexed layer state ." NL "\t\t\033[35mL2\033[0m Indexed Layer 0x02" NL "\t\t0 Off, 1 Shift, 2 Latch, 4 Lock States" ); +CLIDict_Entry( macroDebug, "Disables/Enables sending USB keycodes to the Output Module and prints U/K codes." ); +CLIDict_Entry( macroList, "List the defined trigger and result macros." ); +CLIDict_Entry( macroProc, "Pause/Resume macro processing." ); +CLIDict_Entry( macroShow, "Show the macro corresponding to the given index." NL "\t\t\033[35mT16\033[0m Indexed Trigger Macro 0x10, \033[35mR12\033[0m Indexed Result Macro 0x0C" ); +CLIDict_Entry( macroStep, "Do N macro processing steps. Defaults to 1." ); + +CLIDict_Def( macroCLIDict, "Macro Module Commands" ) = { + CLIDict_Item( capList ), + CLIDict_Item( capSelect ), + CLIDict_Item( keyHold ), + CLIDict_Item( keyPress ), + CLIDict_Item( keyRelease ), + CLIDict_Item( layerList ), + CLIDict_Item( layerState ), + CLIDict_Item( macroDebug ), + CLIDict_Item( macroList ), + CLIDict_Item( macroProc ), + CLIDict_Item( macroShow ), + CLIDict_Item( macroStep ), { 0, 0, 0 } // Null entry for dictionary end }; diff --git a/Output/pjrcUSB/output_com.c b/Output/pjrcUSB/output_com.c index cb85fcd..21e2f0b 100644 --- a/Output/pjrcUSB/output_com.c +++ b/Output/pjrcUSB/output_com.c @@ -71,13 +71,18 @@ void cliFunc_setMod ( char* args ); // ----- Variables ----- // Output Module command dictionary -const char outputCLIDictName[] = "USB Module Commands"; -const CLIDictItem outputCLIDict[] = { - { "kbdProtocol", "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode", cliFunc_kbdProtocol }, - { "readLEDs", "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_readLEDs }, - { "sendKeys", "Send the prepared list of USB codes and modifier byte.", cliFunc_sendKeys }, - { "setKeys", "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m.", cliFunc_setKeys }, - { "setMod", "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod }, +CLIDict_Entry( kbdProtocol, "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode" ); +CLIDict_Entry( readLEDs, "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." ); +CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); +CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); +CLIDict_Entry( setMod, "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI" ); + +CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { + CLIDict_Item( kbdProtocol ), + CLIDict_Item( readLEDs ), + CLIDict_Item( sendKeys ), + CLIDict_Item( setKeys ), + CLIDict_Item( setMod ), { 0, 0, 0 } // Null entry for dictionary end }; diff --git a/Output/uartOut/output_com.c b/Output/uartOut/output_com.c index 4942b57..0b3de2f 100644 --- a/Output/uartOut/output_com.c +++ b/Output/uartOut/output_com.c @@ -54,13 +54,18 @@ void cliFunc_setMod ( char* args ); // ----- Variables ----- // Output Module command dictionary -const char outputCLIDictName[] = "USB Module Commands"; -const CLIDictItem outputCLIDict[] = { - { "kbdProtocol", "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode", cliFunc_kbdProtocol }, - { "readLEDs", "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_readLEDs }, - { "sendKeys", "Send the prepared list of USB codes and modifier byte.", cliFunc_sendKeys }, - { "setKeys", "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m.", cliFunc_setKeys }, - { "setMod", "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod }, +CLIDict_Entry( kbdProtocol, "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode" ); +CLIDict_Entry( readLEDs, "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." ); +CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); +CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); +CLIDict_Entry( setMod, "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI" ); + +CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { + CLIDict_Item( kbdProtocol ), + CLIDict_Item( readLEDs ), + CLIDict_Item( sendKeys ), + CLIDict_Item( setKeys ), + CLIDict_Item( setMod ), { 0, 0, 0 } // Null entry for dictionary end }; diff --git a/Output/usbMuxUart/output_com.c b/Output/usbMuxUart/output_com.c index 98baa96..d7389bf 100644 --- a/Output/usbMuxUart/output_com.c +++ b/Output/usbMuxUart/output_com.c @@ -73,15 +73,22 @@ void cliFunc_setMod ( char* args ); // ----- Variables ----- // Output Module command dictionary -const char outputCLIDictName[] = "USB Module Commands"; -const CLIDictItem outputCLIDict[] = { - { "kbdProtocol", "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode", cliFunc_kbdProtocol }, - { "readLEDs", "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_readLEDs }, - { "readUART", "Read UART buffer until empty.", cliFunc_readUART }, - { "sendKeys", "Send the prepared list of USB codes and modifier byte.", cliFunc_sendKeys }, - { "sendUART", "Send characters over UART0.", cliFunc_sendUART }, - { "setKeys", "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m.", cliFunc_setKeys }, - { "setMod", "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod }, +CLIDict_Entry( kbdProtocol, "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode" ); +CLIDict_Entry( readLEDs, "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." ); +CLIDict_Entry( readUART, "Read UART buffer until empty." ); +CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); +CLIDict_Entry( sendUART, "Send characters over UART0." ); +CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); +CLIDict_Entry( setMod, "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI" ); + +CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { + CLIDict_Item( kbdProtocol ), + CLIDict_Item( readLEDs ), + CLIDict_Item( readUART ), + CLIDict_Item( sendKeys ), + CLIDict_Item( sendUART ), + CLIDict_Item( setKeys ), + CLIDict_Item( setMod ), { 0, 0, 0 } // Null entry for dictionary end }; diff --git a/Scan/DPH/scan_loop.c b/Scan/DPH/scan_loop.c index 31ece08..c3e22ac 100644 --- a/Scan/DPH/scan_loop.c +++ b/Scan/DPH/scan_loop.c @@ -144,17 +144,24 @@ void recovery( uint8_t on ); // ----- Variables ----- // Scan Module command dictionary -const char scanCLIDictName[] = "DPH Module Commands"; -const CLIDictItem scanCLIDict[] = { - { "echo", "Example command, echos the arguments.", cliFunc_echo }, - { "avgDebug", "Enables/Disables averaging results." NL "\t\tDisplays each average, starting from Key 0x00, ignoring 0 valued averages.", cliFunc_avgDebug }, - { "keyDebug", "Enables/Disables long debug for each keypress." NL "\t\tkeycode - [strobe:mux] : sense val : threshold+delta=total : margin", cliFunc_keyDebug }, - { "pressDebug", "Enables/Disables short debug for each keypress.", cliFunc_pressDebug }, - { "problemKeys", "Display current list of problem keys,", cliFunc_problemKeys }, - { "senseDebug", "Prints out the current sense table N times." NL "\t\tsense:max sense:delta", cliFunc_senseDebug }, +CLIDict_Entry( echo, "Example command, echos the arguments." ); +CLIDict_Entry( avgDebug, "Enables/Disables averaging results." NL "\t\tDisplays each average, starting from Key 0x00, ignoring 0 valued averages." ); +CLIDict_Entry( keyDebug, "Enables/Disables long debug for each keypress." NL "\t\tkeycode - [strobe:mux] : sense val : threshold+delta=total : margin" ); +CLIDict_Entry( pressDebug, "Enables/Disables short debug for each keypress." ); +CLIDict_Entry( problemKeys, "Display current list of problem keys," ); +CLIDict_Entry( senseDebug, "Prints out the current sense table N times." NL "\t\tsense:max sense:delta" ); + +CLIDict_Def( scanCLIDict, "DPH Module Commands" ) = { + CLIDict_Item( echo ), + CLIDict_Item( avgDebug ), + CLIDict_Item( keyDebug ), + CLIDict_Item( pressDebug ), + CLIDict_Item( problemKeys ), + CLIDict_Item( senseDebug ), { 0, 0, 0 } // Null entry for dictionary end }; + // CLI Control Variables uint8_t enableAvgDebug = 0; uint8_t enableKeyDebug = 0; diff --git a/Scan/MD1/scan_loop.c b/Scan/MD1/scan_loop.c index 9d28055..b75dc0b 100644 --- a/Scan/MD1/scan_loop.c +++ b/Scan/MD1/scan_loop.c @@ -46,9 +46,10 @@ void cliFunc_echo( char* args ); // ----- Variables ----- // Scan Module command dictionary -const char scanCLIDictName[] = "Scan Module Commands"; -const CLIDictItem scanCLIDict[] = { - { "echo", "Example command, echos the arguments.", cliFunc_echo }, +CLIDict_Entry( echo, "Example command, echos the arguments." ); + +CLIDict_Def( scanCLIDict, "Scan Module Commands" ) = { + CLIDict_Item( echo ), { 0, 0, 0 } // Null entry for dictionary end }; diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c index 1362707..b336efe 100644 --- a/Scan/MatrixARM/matrix_scan.c +++ b/Scan/MatrixARM/matrix_scan.c @@ -49,10 +49,12 @@ void cliFunc_matrixState( char* args ); // ----- Variables ----- // Scan Module command dictionary -const char matrixCLIDictName[] = "Matrix Module Commands"; -const CLIDictItem matrixCLIDict[] = { - { "matrixDebug", "Enables matrix debug mode, prints out each scan code." NL "\t\tIf argument \033[35mT\033[0m is given, prints out each scan code state transition.", cliFunc_matrixDebug }, - { "matrixState", "Prints out the current scan table N times." NL "\t\t \033[1mO\033[0m - Off, \033[1;33mP\033[0m - Press, \033[1;32mH\033[0m - Hold, \033[1;35mR\033[0m - Release, \033[1;31mI\033[0m - Invalid", cliFunc_matrixState }, +CLIDict_Entry( matrixDebug, "Enables matrix debug mode, prints out each scan code." NL "\t\tIf argument \033[35mT\033[0m is given, prints out each scan code state transition." ); +CLIDict_Entry( matrixState, "Prints out the current scan table N times." NL "\t\t \033[1mO\033[0m - Off, \033[1;33mP\033[0m - Press, \033[1;32mH\033[0m - Hold, \033[1;35mR\033[0m - Release, \033[1;31mI\033[0m - Invalid" ); + +CLIDict_Def( matrixCLIDict, "Matrix Module Commands" ) = { + CLIDict_Item( matrixDebug ), + CLIDict_Item( matrixState ), { 0, 0, 0 } // Null entry for dictionary end };