]> git.donarmstrong.com Git - kiibohd-controller.git/commitdiff
Adding more robust detection for the HP150
authorJacob Alexander <triplehaata@gmail.com>
Mon, 19 Nov 2012 08:55:30 +0000 (00:55 -0800)
committerJacob Alexander <triplehaata@gmail.com>
Mon, 19 Nov 2012 08:55:30 +0000 (00:55 -0800)
- All spare cycles are used to get a more accurate data line sample (waaaay more than actually needed, but this helps against noise)
- Switched to a pre/release (add/remove) rather than an add->clear mechanism (or a buffer+debounce/add->clear)
- Note that a pull-down resistor is NEEDED on the data line

Scan/HP150/scan_loop.c

index be17cabfb4fe76c2e2c3b0d8da30e4b1d6ff348b..bfa0424112127a9c2803cd8a0b3d9ba07408ed7d 100644 (file)
@@ -69,9 +69,12 @@ volatile uint8_t KeyIndex_BufferUsed;
 volatile uint8_t KeyIndex_Add_InputSignal; // Used to pass the (click/input value) to the keyboard for the clicker
 
 volatile uint8_t currentWaveState = 0;
-volatile uint8_t currentWaveDone = 0;
 volatile uint8_t positionCounter = 0;
 
+volatile uint8_t statePositionCounter = 0;
+volatile uint16_t stateSamplesTotal = 0;
+volatile uint16_t stateSamples = 0;
+
 
 // Buffer Signals
 volatile uint8_t BufferReadyToClear;
@@ -94,7 +97,7 @@ ISR( TIMER1_COMPA_vect )
        {
                CLOCK_PORT &= ~(1 << CLOCK_PIN);
                currentWaveState--; // Keeps track of the clock value (for direct clock output)
-               currentWaveDone--;  // Keeps track of whether the current falling edge has been processed
+               statePositionCounter = positionCounter;
                positionCounter++;  // Counts the number of falling edges, reset is done by the controlling section (reset, or main scan)
        }
        else
@@ -124,7 +127,9 @@ inline void scan_setup()
        OCR1AH = 0x03;
        OCR1AL = 0x1F;
        TIMSK1 = (1 << OCIE1A);
-       CLOCK_DDR = (1 << CLOCK_PIN);
+
+       CLOCK_DDR |= (1 << CLOCK_PIN); // Set the clock pin as an output
+       DATA_PORT |= (1 << DATA_PIN);  // Pull-up resistor for input the data line
        sei();
 
 
@@ -144,25 +149,12 @@ inline void scan_setup()
 // Once the end of the packet has been detected (always the same length), decode the pressed keys
 inline uint8_t scan_loop()
 {
-       // Read on each falling edge/after the falling edge of the clock
-       if ( !currentWaveDone )
+       // Only use as a valid signal
+       // Check if there was a position change
+       if ( positionCounter != statePositionCounter )
        {
-               // Sample the current value 50 times
-               // If there is a signal for 40/50 of the values, then it is active
-               // This works as a very simple debouncing mechanism
-               // XXX Could be done more intelligently:
-               //  Take into account the frequency of the clock + overhead, and space out the reads
-               //  Or do something like "dual edge" statistics, where you query the stats from both rising and falling edges
-               //   then make a decision (probably won't do much better against the last source of noise, but would do well for debouncing)
-               uint8_t total = 0;
-               uint8_t c = 0;
-               for ( ; c < 50; c++ )
-                       if ( DATA_OUT & (1 << DATA_PIN) )
-                               total++;
-
-
-               // Only use as a valid signal
-               if ( total >= 40 )
+               // At least 80% of the samples must be valid
+               if ( stateSamples * 100 / stateSamplesTotal >= 80 )
                {
                        // Reset the scan counter, all the keys have been iterated over
                        // Ideally this should reset at 128, however
@@ -174,25 +166,60 @@ inline uint8_t scan_loop()
                        if ( positionCounter >= 124 )
                        {
                                positionCounter = 0;
-
-                               // Clear key buffer
-                               KeyIndex_BufferUsed = 0;
                        }
                        // Key Press Detected
-                       else
+                       //  - Skip 0x00 to 0x0B (11) for better jitter immunity (as there are no keys mapped to those scancodes)
+                       else if ( positionCounter > 0x0B )
                        {
                                char tmp[15];
                                hexToStr( positionCounter, tmp );
                                dPrintStrsNL( "Key: ", tmp );
 
-                               bufferAdd( positionCounter );
+                               // Make sure there aren't any duplicate keys
+                               uint8_t c;
+                               for ( c = 0; c < KeyIndex_BufferUsed; c++ )
+                                       if ( KeyIndex_Buffer[c] == positionCounter )
+                                               break;
+
+                               // No duplicate keys, add it to the buffer
+                               if ( c == KeyIndex_BufferUsed )
+                                       bufferAdd( positionCounter );
+                       }
+               }
+               // Remove the key from the buffer
+               else if ( positionCounter < 124 && positionCounter > 0x0B )
+               {
+                       // Check for the released key, and shift the other keys lower on the buffer
+                       uint8_t c;
+                       for ( c = 0; c < KeyIndex_BufferUsed; c++ )
+                       {
+                               // Key to release found
+                               if ( KeyIndex_Buffer[c] == positionCounter )
+                               {
+                                       // 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;
+                               }
                        }
                }
 
-               // Wait until the next falling clock edge for the next DATA scan
-               currentWaveDone++;
+
+               // Clear the state counters
+               stateSamples = 0;
+               stateSamplesTotal = 0;
+               statePositionCounter = positionCounter;
        }
 
+       // Pull in a data sample for this read instance
+       if ( DATA_OUT & (1 <<DATA_PIN) )
+               stateSamples++;
+       stateSamplesTotal++;
+
        // Check if the clock de-synchronized
        // And reset
        if ( positionCounter > 128 )
@@ -205,6 +232,10 @@ inline uint8_t scan_loop()
                positionCounter = 0;
                KeyIndex_BufferUsed = 0;
 
+               // Clear the state counters
+               stateSamples = 0;
+               stateSamplesTotal = 0;
+
                // A keyboard reset requires interrupts to be enabled
                sei();
                scan_resetKeyboard();
@@ -257,22 +288,29 @@ void scan_resetKeyboard( void )
        uint8_t synchronized = 0;
        while ( !synchronized )
        {
-               // Read on each falling edge/after the falling edge of the clock
-               if ( !currentWaveDone )
+               // Only use as a valid signal
+               // Check if there was a position change
+               if ( positionCounter != statePositionCounter )
                {
-                       // Read the current data value
-                       if ( DATA_OUT & (1 << DATA_PIN) )
+                       // At least 80% of the samples must be valid
+                       if ( stateSamples * 100 / stateSamplesTotal >= 80 )
                        {
-                               // Check if synchronized
-                               // There are 128 positions to scan for with the HP150 keyboard protocol
-                               if ( positionCounter == 128 )
-                                       synchronized = 1;
-
-                               positionCounter = 0;
+                               // Read the current data value
+                               if ( DATA_OUT & (1 << DATA_PIN) )
+                               {
+                                       // Check if synchronized
+                                       // There are 128 positions to scan for with the HP150 keyboard protocol
+                                       if ( positionCounter == 128 )
+                                               synchronized = 1;
+
+                                       positionCounter = 0;
+                               }
                        }
 
-                       // Wait until the next falling clock edge for the next DATA scan
-                       currentWaveDone++;
+                       // Clear the state counters
+                       stateSamples = 0;
+                       stateSamplesTotal = 0;
+                       statePositionCounter = positionCounter;
                }
        }