]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - Scan/HP150/scan_loop.c
Bootloader fix
[kiibohd-controller.git] / Scan / HP150 / scan_loop.c
index a8f7b55334d599910907b24e2eef77d10d89583f..6533091539e5a7db370e02af9ea628142e057d32 100644 (file)
@@ -1,15 +1,15 @@
-/* Copyright (C) 2012 by Jacob Alexander
- * 
+/* Copyright (C) 2012,2014 by Jacob Alexander
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
 // ----- Includes -----
 
-// AVR Includes
-#include <avr/interrupt.h>
-#include <avr/io.h>
-#include <util/delay.h>
+// Compiler Includes
+#include <Lib/ScanLib.h>
 
 // Project Includes
 #include <led.h>
@@ -41,6 +39,7 @@
 #define DATA_PORT PORTC
 #define DATA_DDR   DDRC
 #define DATA_PIN      7
+#define DATA_OUT   PINC
 
 #define CLOCK_PORT PORTC
 #define CLOCK_DDR   DDRC
 
 // ----- Macros -----
 
-// Make sure we haven't overflowed the buffer
-#define bufferAdd(byte) \
-               if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
-                       KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
-
 
 
 // ----- Variables -----
@@ -68,6 +62,11 @@ 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 positionCounter = 0;
+
+volatile uint8_t statePositionCounter = 0;
+volatile uint16_t stateSamplesTotal = 0;
+volatile uint16_t stateSamples = 0;
 
 
 // Buffer Signals
@@ -90,7 +89,9 @@ ISR( TIMER1_COMPA_vect )
        if ( currentWaveState )
        {
                CLOCK_PORT &= ~(1 << CLOCK_PIN);
-               currentWaveState--;
+               currentWaveState--; // Keeps track of the clock value (for direct clock output)
+               statePositionCounter = positionCounter;
+               positionCounter++;  // Counts the number of falling edges, reset is done by the controlling section (reset, or main scan)
        }
        else
        {
@@ -104,30 +105,30 @@ ISR( TIMER1_COMPA_vect )
 // ----- Functions -----
 
 // Setup
-inline void scan_setup()
+inline void Scan_setup()
 {
        // Setup Timer Pulse (16 bit)
 
        // TODO Clock can be adjusted to whatever (read chip datasheets for limits)
-       // 16 MHz / (2 * Prescaler * (1 + OCR1A)) = 1200.1 baud
+       // This seems like a good scan speed, as there don't seem to be any periodic
+       //  de-synchronization events, and is fast enough for scanning keys
+       // Anything much more (100k baud), tends to cause a lot of de-synchronization
+       // 16 MHz / (2 * Prescaler * (1 + OCR1A)) = 10k baud
        // Prescaler is 1
-       // Twice every 1200 baud (actually 1200.1, timer isn't accurate enough)
-       // This is close to 820 us, but a bit slower
        cli();
        TCCR1B = 0x09;
-       OCR1AH = 0x01;
-       OCR1AL = 0x09;
+       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();
 
 
        // Initially buffer doesn't need to be cleared (it's empty...)
        BufferReadyToClear = 0;
 
-       // InputSignal is off by default
-       KeyIndex_Add_InputSignal = 0x00;
-
        // Reset the keyboard before scanning, we might be in a wierd state
        scan_resetKeyboard();
 }
@@ -139,101 +140,173 @@ inline void scan_setup()
 // We are looking for a start of packet
 // If detected, all subsequent bits are then logged into a variable
 // Once the end of the packet has been detected (always the same length), decode the pressed keys
-inline uint8_t scan_loop()
-{
-       return 0;
-}
-
-void processKeyValue( uint8_t keyValue )
+inline uint8_t Scan_loop()
 {
-       // Interpret scan code
-       switch ( keyValue )
+       // Only use as a valid signal
+       // Check if there was a position change
+       if ( positionCounter != statePositionCounter )
        {
-       case 0x00: // Break code from input?
-               break;
-       default:
-               // Make sure the key isn't already in the buffer
-               for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
+               // At least 80% of the samples must be valid
+               if ( stateSamples * 100 / stateSamplesTotal >= 80 )
                {
-                       // Key isn't in the buffer yet
-                       if ( c == KeyIndex_BufferUsed )
+                       // Reset the scan counter, all the keys have been iterated over
+                       // Ideally this should reset at 128, however
+                       //  due to noise in the cabling, this often moves around
+                       // The minimum this can possibly set to is 124 as there
+                       //  are keys to service at 123 (0x78)
+                       // Usually, unless there is lots of interference,
+                       //  this should limit most of the noise.
+                       if ( positionCounter >= 124 )
                        {
-                               bufferAdd( keyValue );
-
-                               // Only send data if enabled
-                               if ( KeyIndex_Add_InputSignal )
-                                       scan_sendData( KeyIndex_Add_InputSignal );
-                               break;
+                               positionCounter = 0;
+                       }
+                       // Key Press Detected
+                       //  - 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 );
+
+                               // 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 )
+                                       Macro_bufferAdd( positionCounter );
                        }
-
-                       // Key already in the buffer
-                       if ( KeyIndex_Buffer[c] == keyValue )
-                               break;
                }
-               break;
-       }
-}
-
-void removeKeyValue( uint8_t keyValue )
-{
-       // 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] == keyValue )
+               // Remove the key from the buffer
+               else if ( positionCounter < 124 && positionCounter > 0x0B )
                {
-                       // Shift keys from c position
-                       for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
-                               KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
+                       // 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;
+                               }
+                       }
+               }
 
-                       // Decrement Buffer
-                       KeyIndex_BufferUsed--;
 
-                       break;
-               }
+               // Clear the state counters
+               stateSamples = 0;
+               stateSamplesTotal = 0;
+               statePositionCounter = positionCounter;
        }
 
-       // Error case (no key to release)
-       if ( c == KeyIndex_BufferUsed + 1 )
+       // 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 )
        {
+               char tmp[15];
+               hexToStr( positionCounter, tmp );
+               erro_dPrint( "De-synchronization detected at: ", tmp );
                errorLED( 1 );
-               char tmpStr[6];
-               hexToStr( keyValue, tmpStr );
-               erro_dPrint( "Could not find key to release: ", tmpStr );
+
+               positionCounter = 0;
+               KeyIndex_BufferUsed = 0;
+
+               // Clear the state counters
+               stateSamples = 0;
+               stateSamplesTotal = 0;
+
+               // A keyboard reset requires interrupts to be enabled
+               sei();
+               scan_resetKeyboard();
+               cli();
        }
+
+       // Regardless of what happens, always return 0
+       return 0;
 }
 
-// Send data 
-uint8_t scan_sendData( uint8_t dataPayload )
+// Send data
+uint8_t Scan_sendData( uint8_t dataPayload )
 {
        return 0;
 }
 
 // Signal KeyIndex_Buffer that it has been properly read
-void scan_finishedWithBuffer( void )
+void Scan_finishedWithBuffer( uint8_t sentKeys )
 {
 }
 
 // Signal that the keys have been properly sent over USB
-void scan_finishedWithUSBBuffer( void )
+void Scan_finishedWithUSBBuffer( uint8_t sentKeys )
 {
 }
 
 // Reset/Hold keyboard
-// NOTE: Does nothing with the BETKB
-void scan_lockKeyboard( void )
+// NOTE: Does nothing with the HP150
+void Scan_lockKeyboard( void )
 {
 }
 
-// NOTE: Does nothing with the BETKB
-void scan_unlockKeyboard( void )
+// NOTE: Does nothing with the HP150
+void Scan_unlockKeyboard( void )
 {
 }
 
 // Reset Keyboard
-void scan_resetKeyboard( void )
+void Scan_resetKeyboard( void )
 {
-       // TODO Determine the scan period, and the interval to scan each bit
+       info_print("Attempting to synchronize the keyboard, do not press any keys...");
+       errorLED( 1 );
+
+       // Do a proper keyboard reset (flushes the ripple counters)
+       RESET_PORT |=  (1 << RESET_PIN);
+       _delay_us(10);
+       RESET_PORT &= ~(1 << RESET_PIN);
+
+       // Delay main keyboard scanning, until the bit counter is synchronized
+       uint8_t synchronized = 0;
+       while ( !synchronized )
+       {
+               // Only use as a valid signal
+               // Check if there was a position change
+               if ( positionCounter != statePositionCounter )
+               {
+                       // At least 80% of the samples must be valid
+                       if ( stateSamples * 100 / stateSamplesTotal >= 80 )
+                       {
+                               // 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;
+                               }
+                       }
+
+                       // Clear the state counters
+                       stateSamples = 0;
+                       stateSamplesTotal = 0;
+                       statePositionCounter = positionCounter;
+               }
+       }
+
+       info_print("Keyboard Synchronized!");
 }