]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - Scan/DPH/scan_loop.c
Code cleanup
[kiibohd-controller.git] / Scan / DPH / scan_loop.c
index 77783a4e014f64c62fb66d74284e98d6481599f9..1a0176c4b5404932382e0a22d4e2bd6d05a1c82d 100644 (file)
@@ -23,6 +23,7 @@
 // Project Includes
 #include <cli.h>
 #include <led.h>
+#include <macro.h>
 #include <print.h>
 
 // Local Includes
 
 #define ADHSM 7
 
-#define RIGHT_JUSTIFY 0
-#define LEFT_JUSTIFY (0xff)
-
-// set left or right justification here:
-#define JUSTIFY_ADC RIGHT_JUSTIFY
-#define ADLAR_MASK (1 << ADLAR)
-
-#ifdef JUSTIFY_ADC
-#define ADLAR_BITS ((ADLAR_MASK) & (JUSTIFY_ADC))
-#else // defaults to right justification.
+// Right justification of ADLAR
 #define ADLAR_BITS 0
-#endif
 
 // full muxmask
 #define FULL_MUX_MASK ((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3) | (1 << MUX4))
 // Number of consecutive samples required to pass debounce
 #define DEBOUNCE_THRESHOLD 5
 
+// Scans to remain idle after all keys were release before starting averaging
+// XXX So this makes the initial keypresses fast,
+//      but it's still possible to lose a keypress if you press at the wrong time -HaaTa
+#define KEY_IDLE_SCANS 30000
+
+// Total number of muxes/sense lines available
 #define MUXES_COUNT 8
 #define MUXES_COUNT_XSHIFT 3
 
-#define WARMUP_LOOPS ( 2048 )
+// Number of warm-up loops before starting to scan keys
+#define WARMUP_LOOPS ( 1024 )
 #define WARMUP_STOP (WARMUP_LOOPS - 1)
 
 #define SAMPLE_CONTROL 3
@@ -99,7 +97,6 @@
 // mix in 1/4 of the current average to the running average. -> (@mux_mix = 2)
 #define MUX_MIX 2
 
-#define IDLE_COUNT_MASK 0xff
 #define IDLE_COUNT_SHIFT 8
 
 // av = (av << shift) - av + sample; av >>= shift
 // ----- Function Declarations -----
 
 // CLI Functions
-void cliFunc_avgDebug  ( char* args );
-void cliFunc_echo      ( char* args );
-void cliFunc_keyDebug  ( char* args );
-void cliFunc_pressDebug( char* args );
-void cliFunc_senseDebug( char* args );
+void cliFunc_avgDebug   ( char* args );
+void cliFunc_echo       ( char* args );
+void cliFunc_keyDebug   ( char* args );
+void cliFunc_pressDebug ( char* args );
+void cliFunc_problemKeys( char* args );
+void cliFunc_senseDebug ( char* args );
 
 // Debug Functions
 void dumpSenseTable();
@@ -145,26 +143,29 @@ void recovery( uint8_t on );
 
 // ----- Variables -----
 
-// Buffer used to inform the macro processing module which keys have been detected as pressed
-volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
-volatile uint8_t KeyIndex_BufferUsed;
-
-
 // Scan Module command dictionary
-char*       scanCLIDictName = "DPH Module Commands";
-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 },
-       { "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;
-uint8_t enablePressDebug = 1;
+uint8_t enablePressDebug = 0;
 uint8_t senseDebugCount  = 3; // In order to get boot-time oddities
 
 
@@ -180,8 +181,9 @@ uint8_t   low_count = 0;
 uint16_t samples[MAX_STROBES][MUXES_COUNT];   // Overall table of cap sense ADC values
 uint16_t sampleMax[MAX_STROBES][MUXES_COUNT]; // Records the max seen ADC value
 
-uint8_t key_activity = 0; // Increments for each detected key per each full scan of the keyboard, it is reset before each full scan
-uint8_t key_release  = 0; // Indicates if going from key press state to release state (some keys pressed to no keys pressed)
+uint8_t  key_activity = 0; // Increments for each detected key per each full scan of the keyboard, it is reset before each full scan
+uint16_t key_idle     = 0; // Defines how scans after all keys were released before starting averaging again
+uint8_t  key_release  = 0; // Indicates if going from key press state to release state (some keys pressed to no keys pressed)
 
 uint16_t threshold = THRESHOLD;
 
@@ -206,9 +208,82 @@ inline void Scan_setup()
        // Register Scan CLI dictionary
        CLI_registerDictionary( scanCLIDict, scanCLIDictName );
 
-       // TODO dfj code...needs cleanup + commenting...
-       setup_ADC();
+       // Scan for active strobes
+       // NOTE1: On IBM PCBs, each strobe line that is *NOT* used is connected to GND.
+       //       This means, the strobe GPIO can be set to Tri-State pull-up to detect which strobe lines are not used.
+       // NOTE2: This will *NOT* detect floating strobes.
+       // NOTE3: Rev 0.4, the strobe numbers are reversed, so D0 is actually strobe 0 and C7 is strobe 17
+       info_msg("Detecting Strobes...");
+
+       DDRC  = 0;
+       PORTC = C_MASK;
+       DDRD  = 0;
+       PORTD = D_MASK;
+       DDRE  = 0;
+       PORTE = E_MASK;
+
+       // Initially there are 0 strobes
+       total_strobes = 0;
+
+       // Iterate over each the strobes
+       for ( uint8_t strobe = 0; strobe < MAX_STROBES; strobe++ )
+       {
+               uint8_t detected = 0;
 
+               // If PIN is high, then strobe is *NOT* connected to GND and may be a strobe
+               switch ( strobe )
+               {
+
+               // Strobe Mappings
+               //              Rev  Rev
+               //              0.2  0.4
+#ifndef REV0_4_DEBUG // XXX These pins should be reworked, and connect to GND on Rev 0.4
+               case 0:  // D0   0   n/c
+               case 1:  // D1   1   n/c
+#endif
+               case 2:  // D2   2   15
+               case 3:  // D3   3   14
+               case 4:  // D4   4   13
+               case 5:  // D5   5   12
+               case 6:  // D6   6   11
+               case 7:  // D7   7   10
+                       detected = PIND & (1 << strobe);
+                       break;
+
+               case 8:  // E0   8    9
+               case 9:  // E1   9    8
+                       detected = PINE & (1 << (strobe - 8));
+                       break;
+
+               case 10: // C0  10    7
+               case 11: // C1  11    6
+               case 12: // C2  12    5
+               case 13: // C3  13    4
+               case 14: // C4  14    3
+               case 15: // C5  15    2
+#ifndef REV0_2_DEBUG // XXX If not using the 18 pin connector on Rev 0.2, rework these pins to GND
+               case 16: // C6  16    1
+               case 17: // C7  17    0
+#endif
+                       detected = PINC & (1 << (strobe - 10));
+                       break;
+
+               default:
+                       break;
+               }
+
+               // Potential strobe line detected
+               if ( detected )
+               {
+                       strobe_map[total_strobes] = strobe;
+                       total_strobes++;
+               }
+       }
+
+       printInt8( total_strobes );
+       print( " strobes found." NL );
+
+       // Setup Pins for Strobing
        DDRC  = C_MASK;
        PORTC = 0;
        DDRD  = D_MASK;
@@ -216,89 +291,8 @@ inline void Scan_setup()
        DDRE  = E_MASK;
        PORTE = 0 ;
 
-       // Hardcoded strobes for debugging
-       // Strobes start at 0 and go to 17 (18), not all Model Fs use all of the available strobes
-       // The single row ribbon connector Model Fs only have a max of 16 strobes
-#define KEYPAD_50KEY
-//#define KISHSAVER_STROBE
-//#define KISHSAVER_OLD_STROBE
-//#define TERMINAL_6110668_OLD_STROBE
-//#define UNSAVER_OLD_STROBE
-#ifdef KISHSAVER_OLD_STROBE
-       total_strobes = 9;
-
-       strobe_map[0] = 2; // Kishsaver doesn't use strobe 0 and 1
-       strobe_map[1] = 3;
-       strobe_map[2] = 4;
-       strobe_map[3] = 5;
-       strobe_map[4] = 6;
-       strobe_map[5] = 7;
-       strobe_map[6] = 8;
-       strobe_map[7] = 9;
-       strobe_map[8] = 15; // Test point strobe (3 test points, sense 1, 4, 5)
-#elif defined(KISHSAVER_STROBE)
-       total_strobes = 9;
-
-       strobe_map[0] = 15; // Kishsaver doesn't use strobe 0 and 1
-       strobe_map[1] = 14;
-       strobe_map[2] = 13;
-       strobe_map[3] = 12;
-       strobe_map[4] = 11;
-       strobe_map[5] = 10;
-       strobe_map[6] = 9;
-       strobe_map[7] = 8;
-       strobe_map[8] = 2; // Test point strobe (3 test points, sense 1, 4, 5)
-#elif defined(KEYPAD_50KEY)
-       total_strobes = 8;
-
-       strobe_map[0] = 14;
-       strobe_map[1] = 13;
-       strobe_map[2] = 12;
-       strobe_map[3] = 11;
-       strobe_map[4] = 10;
-       strobe_map[5] = 9;
-       strobe_map[6] = 8;
-       strobe_map[7] = 0;
-#elif defined(TERMINAL_6110668_OLD_STROBE)
-       total_strobes = 16;
-
-       strobe_map[0] = 0;
-       strobe_map[1] = 1;
-       strobe_map[2] = 2;
-       strobe_map[3] = 3;
-       strobe_map[4] = 4;
-       strobe_map[5] = 5;
-       strobe_map[6] = 6;
-       strobe_map[7] = 7;
-       strobe_map[8] = 8;
-       strobe_map[9] = 9;
-       strobe_map[10] = 10;
-       strobe_map[11] = 11;
-       strobe_map[12] = 12;
-       strobe_map[13] = 13;
-       strobe_map[14] = 14;
-       strobe_map[15] = 15;
-#elif defined(UNSAVER_OLD_STROBE)
-       total_strobes = 14;
-
-       strobe_map[0] = 0;
-       strobe_map[1] = 1;
-       strobe_map[2] = 2;
-       strobe_map[3] = 3;
-       strobe_map[4] = 4;
-       strobe_map[5] = 5;
-       strobe_map[6] = 6;
-       strobe_map[7] = 7;
-       strobe_map[8] = 8;
-       strobe_map[9] = 9;
-       strobe_map[10] = 10;
-       strobe_map[11] = 11;
-       strobe_map[12] = 12;
-       strobe_map[13] = 13;
-#else
-       // Strobe detection
-       // TODO
-#endif
+       // Initialize ADC
+       setup_ADC();
 
        // Reset debounce table
        for ( int i = 0; i < KEY_COUNT; ++i )
@@ -328,19 +322,17 @@ inline uint8_t Scan_loop()
 }
 
 
-// Signal KeyIndex_Buffer that it has been properly read
+// Signal from macro module that keys have been processed
 // NOTE: Only really required for implementing "tricks" in converters for odd protocols
-void Scan_finishedWithBuffer( uint8_t sentKeys )
+void Scan_finishedWithMacro( uint8_t sentKeys )
 {
-       // Convenient place to clear the KeyIndex_Buffer
-       KeyIndex_BufferUsed = 0;
        return;
 }
 
 
-// Signal KeyIndex_Buffer that it has been properly read and sent out by the USB module
+// Signal from output module that keys have been processed/sent
 // NOTE: Only really required for implementing "tricks" in converters for odd protocols
-void Scan_finishedWithUSBBuffer( uint8_t sentKeys )
+void Scan_finishedWithOutput( uint8_t sentKeys )
 {
        return;
 }
@@ -409,7 +401,8 @@ inline void capsense_scan()
                                }
 
                                // If sample is higher than previous high_avg, then mark as "problem key"
-                               keys_problem[strobe_line + mux] = sample > high_avg ? sample : 0;
+                               // XXX Giving a bit more margin to pass (high_avg vs. high_avg + high_avg - full_avg) -HaaTa
+                               keys_problem[strobe_line + mux] = sample > high_avg + (high_avg - full_avg) ? sample : 0;
 
                                // Prepare for next average
                                cur_full_avg += sample;
@@ -473,6 +466,9 @@ inline void capsense_scan()
                        printInt8( low_count );
                        print("): ");
                        printHex( low_avg );
+
+                       print("  Rejection threshold: ");
+                       printHex( high_avg + (high_avg - full_avg) );
                        print( NL );
 
                        // Display problem keys, and the sense value at the time
@@ -488,7 +484,8 @@ inline void capsense_scan()
                                }
                        }
 
-                       info_print("If problem keys were detected, and were being held down, they will be reset as soon as let go");
+                       info_print("If problem keys were detected, and were being held down, they will be reset as soon as let go.");
+                       info_print("Some keys have unusually high sense values, on the first press they should be re-enabled.");
                        break;
                }
        }
@@ -497,41 +494,50 @@ inline void capsense_scan()
                // No keypress, accumulate averages
                if( !key_activity )
                {
-                       // Average Debugging
-                       if ( enableAvgDebug )
+                       // Only start averaging once the idle counter has counted down to 0
+                       if ( key_idle == 0 )
                        {
-                               print("\033[1mAvg\033[0m: ");
-                       }
+                               // Average Debugging
+                               if ( enableAvgDebug )
+                               {
+                                       print("\033[1mAvg\033[0m: ");
+                               }
 
-                       // aggregate
-                       for ( uint8_t i = 0; i < KEY_COUNT; ++i )
-                       {
-                               uint16_t acc = keys_averages_acc[i];
-                               //uint16_t acc = keys_averages_acc[i] >> IDLE_COUNT_SHIFT; // XXX This fixes things... -HaaTa
-                               uint32_t av = keys_averages[i];
+                               // aggregate
+                               for ( uint8_t i = 0; i < KEY_COUNT; ++i )
+                               {
+                                       uint16_t acc = keys_averages_acc[i];
+                                       //uint16_t acc = keys_averages_acc[i] >> IDLE_COUNT_SHIFT; // XXX This fixes things... -HaaTa
+                                       uint32_t av = keys_averages[i];
+
+                                       av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
+                                       av >>= KEYS_AVERAGES_MIX_SHIFT;
 
-                               av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
-                               av >>= KEYS_AVERAGES_MIX_SHIFT;
+                                       keys_averages[i] = av;
+                                       keys_averages_acc[i] = 0;
 
-                               keys_averages[i] = av;
-                               keys_averages_acc[i] = 0;
+                                       // Average Debugging
+                                       if ( enableAvgDebug && av > 0 )
+                                       {
+                                               printHex( av );
+                                               print(" ");
+                                       }
+                               }
 
                                // Average Debugging
-                               if ( enableAvgDebug && av > 0 )
+                               if ( enableAvgDebug )
                                {
-                                       printHex( av );
-                                       print(" ");
+                                       print( NL );
                                }
-                       }
 
-                       // Average Debugging
-                       if ( enableAvgDebug )
+                               // No key presses detected, set key_release indicator
+                               key_release = 1;
+                       }
+                       // Otherwise decrement the idle counter
+                       else
                        {
-                               print( NL );
+                               key_idle--;
                        }
-
-                       // No key presses detected, set key_release indicator
-                       key_release = 1;
                }
                // Keypresses, reset accumulators
                else if ( key_release )
@@ -603,7 +609,7 @@ void recovery( uint8_t on )
                PORTD &= ~D_MASK;
                PORTE &= ~E_MASK;
 
-               DDRB  |= (1 << RECOVERY_SINK);   // SINK pull
+               DDRB  |= (1 << RECOVERY_SINK);   // SINK pull
                PORTB |= (1 << RECOVERY_CONTROL);
                PORTB |= (1 << RECOVERY_SOURCE); // SOURCE high
                DDRB  |= (1 << RECOVERY_SOURCE);
@@ -613,7 +619,7 @@ void recovery( uint8_t on )
                PORTB &= ~(1 << RECOVERY_CONTROL);
                DDRB  &= ~(1 << RECOVERY_SOURCE);
                PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low
-               DDRB  &= ~(1 << RECOVERY_SINK);   // SINK high-imp
+               DDRB  &= ~(1 << RECOVERY_SINK);   // SINK high-imp
        }
 }
 
@@ -760,9 +766,10 @@ void testColumn( uint8_t strobe )
                // Check if this is a bad key (e.g. test point, or non-existent key)
                if ( keys_problem[key] )
                {
-                       // If the sample value of the problem key goes below full_avg (overall initial average)
+                       // If the sample value of the problem key goes above initally recorded result + threshold
                        //  re-enable the key
-                       if ( (db_sample = samples[strobe][mux] >> 1) < full_avg )
+                       if ( (db_sample = samples[strobe][mux] >> 1) > keys_problem[key] + threshold )
+                       //if ( (db_sample = samples[strobe][mux] >> 1) < high_avg )
                        {
                                info_msg("Re-enabling problem key: ");
                                printHex( key );
@@ -781,6 +788,7 @@ void testColumn( uint8_t strobe )
                {
                        column |= bit;
                        key_activity++; // No longer idle, stop averaging ADC data
+                       key_idle = KEY_IDLE_SCANS; // Reset idle count-down
 
                        // Only register keypresses once the warmup is complete, or not enough debounce info
                        if ( keys_debounce[key] <= DEBOUNCE_THRESHOLD )
@@ -797,23 +805,26 @@ void testColumn( uint8_t strobe )
                                                print(" ");
                                        }
 
-                                       // Only add the key to the buffer once
-                                       // NOTE: Buffer can easily handle multiple adds, just more efficient
-                                       //        and nicer debug messages :P
-                                       //Macro_bufferAdd( key );
+                                       // Initial Keypress
+                                       Macro_keyState( key, 0x01 );
                                }
 
                                keys_debounce[key]++;
 
                        }
+                       else if ( keys_debounce[key] >= DEBOUNCE_THRESHOLD )
+                       {
+                               // Held Key
+                               Macro_keyState( key, 0x02 );
+                       }
 
                        // Long form key debugging
                        if ( enableKeyDebug )
                        {
                                // Debug message
                                // <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
-                               dbug_msg("0x");
-                               printHex_op( key, 2 );
+                               dbug_msg("");
+                               printHex_op( key, 1 );
                                print(" [");
                                printInt8( strobe );
                                print(":");
@@ -834,23 +845,11 @@ void testColumn( uint8_t strobe )
                // Clear debounce entry if no keypress detected
                else
                {
-                       // If the key was previously pressed, remove from the buffer
-                       for ( uint8_t c = 0; c < KeyIndex_BufferUsed; c++ )
-                        {
-                                // Key to release found
-                                if ( KeyIndex_Buffer[c] == key )
-                                {
-                                        // Shift keys from c position
-                                        for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
-                                                KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
-
-                                        // Decrement Buffer
-                                        KeyIndex_BufferUsed--;
-
-                                        break;
-                                }
-                        }
-
+                       // Release Key
+                       if ( keys_debounce[key] >= DEBOUNCE_THRESHOLD )
+                       {
+                               Macro_keyState( key, 0x03 );
+                       }
 
                        // Clear debounce entry
                        keys_debounce[key] = 0;
@@ -992,6 +991,30 @@ void cliFunc_pressDebug( char* args )
        }
 }
 
+void cliFunc_problemKeys( char* args )
+{
+       print( NL );
+
+       uint8_t count = 0;
+
+       // Args ignored, just displaying
+       // Display problem keys, and the sense value at the time
+       for ( uint8_t key = 0; key < KEY_COUNT; key++ )
+       {
+               if ( keys_problem[key] )
+               {
+                       if ( count++ == 0 )
+                       {
+                               warn_msg("Problem keys: ");
+                       }
+                       printHex( key );
+                       print(" (");
+                       printHex( keys_problem[key] );
+                       print(")   "  );
+               }
+       }
+}
+
 void cliFunc_senseDebug( char* args )
 {
        // Parse code from argument
@@ -1006,7 +1029,7 @@ void cliFunc_senseDebug( char* args )
        // If there was an argument, use that instead
        if ( *arg1Ptr != '\0' )
        {
-               senseDebugCount = decToInt( arg1Ptr );
+               senseDebugCount = numToInt( arg1Ptr );
        }
 }