|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- /* Copyright (C) 2012 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
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
- // ----- Includes -----
-
- // Compiler Includes
- #include <Lib/ScanLib.h>
-
- // Project Includes
- #include <led.h>
- #include <print.h>
-
- // Local Includes
- #include "scan_loop.h"
-
-
-
- // ----- Defines -----
-
- // - Pinout Defines -
-
- // Scan Bit Pins (from keyboard)
- // - Reads in the ASCII scancode
- // - Shift and ShiftLock are handled internally
- #define READSCAN_PORT PORTC
- #define READSCAN_DDR DDRC
- #define READSCAN_PIN PINC
-
-
- // Interrupt Pins (from keyboard)
- // - CODEINT (Code key signal interrupt/press)
- // - Normally high, low when "Code" key is pressed; separate from all other key presses
- // - PRESSINT (Press signal interrupt/press)
- // - Normally high, low when any key (or multiple except "Code") is pressed, returns to high once all keys are released
- // - Signal is changed BEFORE the Scan Bits are updated
- // - PULSEINT (Key action pulse interrupt/press)
- // - Normally high, low pulses of 147us on key presses (depending on the combination of mode control pins)
- // - Pulse is guarranteed to sent after the Scan Bits are updated
- #define CODEINT_PORT PORTE
- #define CODEINT_DDR DDRE
- #define CODEINT_PIN PINE
- #define CODEINT_POS 7
-
- #define PRESSINT_PORT PORTE
- #define PRESSINT_DDR DDRE
- #define PRESSINT_POS 6
-
- #define PULSEINT_PORT PORTD
- #define PULSEINT_DDR DDRD
- #define PULSEINT_POS 3
-
-
- // LED Pins (to keyboard)
- // - 1 disable LED
- // - 1 enable LED
- #define LED1_PORT PORTF // [Pin 19]
- #define LED1_DDR DDRF
- #define LED1_POS 6
-
- #define LED2_PORT PORTF // [Pin 20]
- #define LED2_DDR DDRF
- #define LED2_POS 7
-
-
- // Mode Control Pins (to keyboard)
- // - Repeat [Pin 14]
- // - 1 Single pulse mode (PULSEINT)
- // - 0 Repeated pulse mode (PULSEINT) (1 pulse, pause, then constant pulses)
- // - Multi [Pin 15]
- // - 1 1KRO mode (typewriter compatibility mode)
- // - 0 NKRO mode (new pulse on each keypress - PULSEINT)
- // - Signal [Pin 18]
- // - 1 disables pulse interrupt (PULSEINT)
- // - 0 enables pulse interrupt (PULSEINT)
- #define REPEAT_PORT PORTF
- #define REPEAT_DDR DDRF
- #define REPEAT_POS 3
-
- #define MULTI_PORT PORTF
- #define MULTI_DDR DDRF
- #define MULTI_POS 4
-
- #define SIGNAL_PORT PORTF
- #define SIGNAL_DDR DDRF
- #define SIGNAL_POS 5
-
-
- // Manually Scanned Keys
- // Keys that the controller screws up, requiring a separate wire to be brought to the controller
- // Note: Safer to route these through a NOT gate to boost the signal strength
- // Values below are AFTER NOT gate
- // - Shift (both shift keys are on the same scan line)
- // - 0 Released
- // - 1 Pressed
- // - Shift Lock
- // - 0 Released
- // - 1 Pressed
- #define MANUAL_SCAN_KEYS 2
-
- #define SHIFT_KEY 0
- #define SHIFT_PORT PORTF
- #define SHIFT_DDR DDRF
- #define SHIFT_PIN PINF
- #define SHIFT_POS 0
-
- #define SHIFTLOCK_KEY 1
- #define SHIFTLOCK_PORT PORTF
- #define SHIFTLOCK_DDR DDRF
- #define SHIFTLOCK_PIN PINF
- #define SHIFTLOCK_POS 1
-
-
- // ----- Macros -----
-
- // Make sure we haven't overflowed the buffer
- #define bufferAdd(byte) \
- if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
- KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
-
-
-
- // ----- 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;
- volatile uint8_t KeyIndex_Add_InputSignal; // Used to pass the (click/input value) to the keyboard for the clicker
-
- volatile uint8_t KeyScan_Table[MANUAL_SCAN_KEYS]; // Used for tracking key status of manually scanned keys
- volatile uint8_t KeyScan_Prev [MANUAL_SCAN_KEYS]; // Keeps track of key state changes
- volatile uint8_t KeyScan_Count;
-
-
-
- // ----- Functions -----
-
- // Pre-declarations
- void processKeyValue( uint8_t keyValue );
-
-
-
- // Setup
- inline void scan_setup()
- {
- // Setup the external interrupts for
- // - General keypresses (INT6/E6) -> rising edge (to detect key release)
- // - "Code" key (INT7/E7) -> falling/rising edge (to detect key press/release)
- // - General keypress pulse (INT3/D3) -> falling edge (to detect key press )
- EICRA = 0x80;
- EICRB = 0x70;
- EIMSK = 0xC8;
-
-
- // Setup Interrupt Pins
- CODEINT_PORT |= (1 << CODEINT_POS );
- CODEINT_DDR &= ~(1 << CODEINT_POS );
-
- PRESSINT_PORT |= (1 << PRESSINT_POS);
- PRESSINT_DDR &= ~(1 << PRESSINT_POS);
-
- PULSEINT_PORT |= (1 << PULSEINT_POS);
- PULSEINT_DDR &= ~(1 << PULSEINT_POS);
-
-
- // Setup LED Pins (default off)
- LED1_PORT |= (1 << LED1_POS);
- LED1_DDR |= (1 << LED1_POS);
-
- LED2_PORT |= (1 << LED2_POS);
- LED2_DDR |= (1 << LED2_POS);
-
-
- // Setup READSCAN pins to read out scancode
- READSCAN_PORT = 0xFF;
- READSCAN_DDR = 0x00;
-
-
- // Setup Mode Control Pins
- // Note: These can be changed at any time, but there is no real reason too for a USB converter
- REPEAT_PORT |= (1 << REPEAT_POS); // Setting high for single press mode
- REPEAT_DDR |= (1 << REPEAT_POS);
-
- MULTI_PORT &= ~(1 << MULTI_POS ); // Setting low for multi press mode (NKRO)
- MULTI_DDR |= (1 << MULTI_POS );
-
- SIGNAL_PORT &= ~(1 << SIGNAL_POS); // Setting low to enable PULSEINT
- SIGNAL_DDR |= (1 << SIGNAL_POS);
-
-
- // Setup Troublesome Key Pins
- SHIFT_PORT &= ~(1 << SHIFT_POS );
- SHIFT_DDR &= ~(1 << SHIFT_POS );
-
- SHIFTLOCK_PORT &= ~(1 << SHIFTLOCK_POS);
- SHIFTLOCK_DDR &= ~(1 << SHIFTLOCK_POS);
-
-
- // Reset the keyboard before scanning, we might be in a wierd state
- scan_resetKeyboard();
- }
-
- // Main Detection Loop
- // Not needed for the Sony OA-S3400 as signals are interrupt based, thus this is a busy loop
- // XXX Function is used for scanning troublesome keys, technically this is not needed for a pure converter
- // I just want proper use of the shift and shift lock keys, without having to do major rework to attach to the entire matrix
- inline uint8_t scan_loop()
- {
- // Loop through known keys
- for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ ) switch ( key )
- {
- case SHIFT_KEY:
- if ( SHIFT_PIN & (1 << SHIFT_POS) )
- {
- KeyScan_Table[SHIFT_KEY]++;
- }
- break;
- case SHIFTLOCK_KEY:
- if ( SHIFTLOCK_PIN & (1 << SHIFTLOCK_POS) )
- {
- KeyScan_Table[SHIFTLOCK_KEY]++;
- }
- break;
- default:
- erro_print("Invalid key scan index");
- break;
- }
-
- // Increment vote instance
- KeyScan_Count++;
-
- // Loop function again if not enough votes have been tallied
- if ( KeyScan_Count < 255 )
- return 1;
-
- // Clear vote data
- KeyScan_Count = 0;
-
- // Loop through known keys
- for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
- {
- // Key scanned as pressed (might have been held from a previous vote)
- if ( KeyScan_Table[key] > 127 )
- {
- // Keypress detected
- if ( !KeyScan_Prev[key] )
- {
- processKeyValue( 0x90 + key ); // Arbitrary key mapping starts at 0x90
- KeyScan_Prev[key] = 1;
- }
- }
- // Key scanned as released
- else
- {
- // Keypress detected
- if ( KeyScan_Prev[key] )
- {
- processKeyValue( 0xA0 + key ); // Arbitrary key mapping release starts at 0xA0
- KeyScan_Prev[key] = 0;
- }
- }
-
- // Clear votes
- KeyScan_Table[key] = 0;
- }
-
- // End loop, process macros and USB data
- return 0;
- }
-
- void processKeyValue( uint8_t keyValue )
- {
- // - Convert Shifted Value to non-shifted ASCII code -
-
- // Alphabetic
- if ( keyValue >= 0x61 && keyValue <= 0x7A )
- {
- keyValue -= 0x20;
- }
- // Other keys with ASCII shift codes
- else
- {
- switch ( keyValue )
- {
- case 0x21: // 1
- case 0x23: // 3
- case 0x24: // 4
- case 0x25: // 5
- keyValue += 0x10;
- break;
- case 0x26: // 7
- case 0x28: // 9
- keyValue += 0x11;
- break;
- case 0x81: // 1/2
- case 0x3A: // ;
- keyValue += 0x01;
- break;
- case 0x29: // 0
- keyValue = 0x30;
- break;
- case 0x40: // 2
- keyValue = 0x32;
- break;
- case 0x80: // 6
- keyValue = 0x36;
- break;
- case 0x2A: // 8
- keyValue = 0x38;
- break;
- case 0x5F: // -
- keyValue = 0x2D;
- break;
- case 0x2B: // +
- keyValue = 0x3D;
- break;
- case 0x22: // "
- keyValue = 0x27;
- break;
- case 0x3F: // ?
- keyValue = 0x2F;
- break;
- }
- }
-
- // TODO Move to Macro Section
- switch ( keyValue )
- {
- case 0xD3: // F11
- scan_sendData( 0x01 );
- break;
- case 0xD4: // F12
- scan_sendData( 0x02 );
- break;
- }
-
- // Scan code is now finalized, and ready to add to buffer
- // Note: Scan codes come from 3 different interrupts and a manual key scan into this function
-
- // Debug
- char tmpStr[6];
- hexToStr( keyValue, tmpStr );
- dPrintStrs( tmpStr, " " );
-
- // Detect release condition
- uint8_t release = 0;
- switch ( keyValue )
- {
- case 0xA0:
- case 0xA1:
- case 0xA2:
- keyValue -= 0x10;
- case 0xB0:
- release = 1;
- break;
- }
-
- // Key Release
- if ( release )
- {
- // Check for the released key, and shift the other keys lower on the buffer
- uint8_t c;
- for ( c = 0; c < KeyIndex_BufferUsed; c++ )
- {
- // General key buffer clear
- if ( keyValue == 0xB0 )
- {
- switch ( KeyIndex_Buffer[c] )
- {
- // Ignore these keys on general key release (have their own release codes)
- case 0x90:
- case 0x91:
- case 0x92:
- break;
-
- // Remove key from buffer
- default:
- // 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--;
-
- // Start at this position again for the next loop
- c--;
-
- break;
- }
- }
- // Key to release found
- else if ( KeyIndex_Buffer[c] == keyValue )
- {
- // 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;
- }
- }
-
- // Error case (no key to release)
- if ( c == KeyIndex_BufferUsed + 1 )
- {
- errorLED( 1 );
- char tmpStr[6];
- hexToStr( keyValue, tmpStr );
- erro_dPrint( "Could not find key to release: ", tmpStr );
- }
- }
- // Press or Repeated Key
- else
- {
- // Make sure the key isn't already in the buffer
- for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
- {
- // Key isn't in the buffer yet
- if ( c == KeyIndex_BufferUsed )
- {
- bufferAdd( keyValue );
- break;
- }
-
- // Key already in the buffer
- if ( KeyIndex_Buffer[c] == keyValue )
- break;
- }
- }
- }
-
- // Key Press Detected Interrupt
- ISR(INT3_vect)
- {
- cli(); // Disable Interrupts
-
- uint8_t keyValue = 0x00;
-
- // Bits are flipped coming in from the keyboard
- keyValue = ~READSCAN_PIN;
-
- // Process the scancode
- processKeyValue( keyValue );
-
- sei(); // Re-enable Interrupts
- }
-
- // Key Release Detected Interrupt
- ISR(INT6_vect)
- {
- cli(); // Disable Interrupts
-
- // Send release code for general keys, 0xB0
- processKeyValue( 0xB0 );
-
- sei(); // Re-enable Interrupts
- }
-
- // Code Key Interrupt
- ISR(INT7_vect)
- {
- cli(); // Disable Interrupts
-
- // Code Key Released (send scancode)
- if ( CODEINT_PIN & (1 << CODEINT_POS) )
- {
- processKeyValue( 0xA2 );
- }
- // Code Key Pressed (send scancode)
- else
- {
- processKeyValue( 0x92 );
- }
-
- sei(); // Re-enable Interrupts
- }
-
-
- // Send data to keyboard
- // Sony OA-S3400 has no serial/parallel dataport to send data too...
- // Using this function for LED enable/disable
- uint8_t scan_sendData( uint8_t dataPayload )
- {
- switch ( dataPayload )
- {
- case 0x01:
- LED1_PORT ^= (1 << LED1_POS);
- break;
- case 0x02:
- LED2_PORT ^= (1 << LED2_POS);
- break;
- default:
- erro_print("Invalid data send attempt");
- break;
- }
- return 0;
- }
-
- // Signal KeyIndex_Buffer that it has been properly read
- // Not needed as a signal is sent to remove key-presses
- void scan_finishedWithBuffer( uint8_t sentKeys )
- {
- return;
- }
-
- // Reset/Hold keyboard
- // Sony OA-S3400 has no locking signals
- void scan_lockKeyboard( void )
- {
- }
-
- void scan_unlockKeyboard( void )
- {
- }
-
- // Reset Keyboard
- void scan_resetKeyboard( void )
- {
- // Empty buffer, now that keyboard has been reset
- KeyIndex_BufferUsed = 0;
-
- // Clear the KeyScan table and count
- for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
- {
- KeyScan_Table[key] = 0;
- KeyScan_Prev [key] = 0;
- }
- KeyScan_Count = 0;
- }
-
- // USB module is finished with buffer
- // Not needed as a signal is sent to remove key-presses
- void scan_finishedWithUSBBuffer( uint8_t sentKeys )
- {
- return;
- }
-
|