1 /* Copyright (C) 2012 by Jacob Alexander
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 // ----- Includes -----
25 #include <avr/interrupt.h>
27 #include <util/delay.h>
34 #include "scan_loop.h"
38 // ----- Defines -----
42 // Scan Bit Pins (from keyboard)
43 // - Reads in the ASCII scancode
44 // - Shift and ShiftLock are handled internally
45 #define READSCAN_PORT PORTC
46 #define READSCAN_DDR DDRC
47 #define READSCAN_PIN PINC
50 // Interrupt Pins (from keyboard)
51 // - CODEINT (Code key signal interrupt/press)
52 // - Normally high, low when "Code" key is pressed; separate from all other key presses
53 // - PRESSINT (Press signal interrupt/press)
54 // - Normally high, low when any key (or multiple except "Code") is pressed, returns to high once all keys are released
55 // - Signal is changed BEFORE the Scan Bits are updated
56 // - PULSEINT (Key action pulse interrupt/press)
57 // - Normally high, low pulses of 147us on key presses (depending on the combination of mode control pins)
58 // - Pulse is guarranteed to sent after the Scan Bits are updated
59 #define CODEINT_PORT PORTE
60 #define CODEINT_DDR DDRE
61 #define CODEINT_PIN PINE
64 #define PRESSINT_PORT PORTE
65 #define PRESSINT_DDR DDRE
66 #define PRESSINT_POS 6
68 #define PULSEINT_PORT PORTD
69 #define PULSEINT_DDR DDRD
70 #define PULSEINT_POS 3
73 // LED Pins (to keyboard)
76 #define LED1_PORT PORTF // [Pin 19]
80 #define LED2_PORT PORTF // [Pin 20]
85 // Mode Control Pins (to keyboard)
87 // - 1 Single pulse mode (PULSEINT)
88 // - 0 Repeated pulse mode (PULSEINT) (1 pulse, pause, then constant pulses)
90 // - 1 1KRO mode (typewriter compatibility mode)
91 // - 0 NKRO mode (new pulse on each keypress - PULSEINT)
93 // - 1 disables pulse interrupt (PULSEINT)
94 // - 0 enables pulse interrupt (PULSEINT)
95 #define REPEAT_PORT PORTF
96 #define REPEAT_DDR DDRF
99 #define MULTI_PORT PORTF
100 #define MULTI_DDR DDRF
103 #define SIGNAL_PORT PORTF
104 #define SIGNAL_DDR DDRF
108 // Manually Scanned Keys
109 // Keys that the controller screws up, requiring a separate wire to be brought to the controller
110 // Note: Safer to route these through a NOT gate to boost the signal strength
111 // Values below are AFTER NOT gate
112 // - Shift (both shift keys are on the same scan line)
118 #define MANUAL_SCAN_KEYS 2
121 #define SHIFT_PORT PORTF
122 #define SHIFT_DDR DDRF
123 #define SHIFT_PIN PINF
126 #define SHIFTLOCK_KEY 1
127 #define SHIFTLOCK_PORT PORTF
128 #define SHIFTLOCK_DDR DDRF
129 #define SHIFTLOCK_PIN PINF
130 #define SHIFTLOCK_POS 1
133 // ----- Macros -----
135 // Make sure we haven't overflowed the buffer
136 #define bufferAdd(byte) \
137 if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
138 KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
142 // ----- Variables -----
144 // Buffer used to inform the macro processing module which keys have been detected as pressed
145 volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
146 volatile uint8_t KeyIndex_BufferUsed;
147 volatile uint8_t KeyIndex_Add_InputSignal; // Used to pass the (click/input value) to the keyboard for the clicker
149 volatile uint8_t KeyScan_Table[MANUAL_SCAN_KEYS]; // Used for tracking key status of manually scanned keys
150 volatile uint8_t KeyScan_Prev [MANUAL_SCAN_KEYS]; // Keeps track of key state changes
151 volatile uint8_t KeyScan_Count;
155 // ----- Functions -----
158 void processKeyValue( uint8_t keyValue );
163 inline void scan_setup()
165 // Setup the external interrupts for
166 // - General keypresses (INT6/E6) -> rising edge (to detect key release)
167 // - "Code" key (INT7/E7) -> falling/rising edge (to detect key press/release)
168 // - General keypress pulse (INT3/D3) -> falling edge (to detect key press )
174 // Setup Interrupt Pins
175 CODEINT_PORT |= (1 << CODEINT_POS );
176 CODEINT_DDR &= ~(1 << CODEINT_POS );
178 PRESSINT_PORT |= (1 << PRESSINT_POS);
179 PRESSINT_DDR &= ~(1 << PRESSINT_POS);
181 PULSEINT_PORT |= (1 << PULSEINT_POS);
182 PULSEINT_DDR &= ~(1 << PULSEINT_POS);
185 // Setup LED Pins (default off)
186 LED1_PORT |= (1 << LED1_POS);
187 LED1_DDR |= (1 << LED1_POS);
189 LED2_PORT |= (1 << LED2_POS);
190 LED2_DDR |= (1 << LED2_POS);
193 // Setup READSCAN pins to read out scancode
194 READSCAN_PORT = 0xFF;
198 // Setup Mode Control Pins
199 // Note: These can be changed at any time, but there is no real reason too for a USB converter
200 REPEAT_PORT |= (1 << REPEAT_POS); // Setting high for single press mode
201 REPEAT_DDR |= (1 << REPEAT_POS);
203 MULTI_PORT &= ~(1 << MULTI_POS ); // Setting low for multi press mode (NKRO)
204 MULTI_DDR |= (1 << MULTI_POS );
206 SIGNAL_PORT &= ~(1 << SIGNAL_POS); // Setting low to enable PULSEINT
207 SIGNAL_DDR |= (1 << SIGNAL_POS);
210 // Setup Troublesome Key Pins
211 SHIFT_PORT &= ~(1 << SHIFT_POS );
212 SHIFT_DDR &= ~(1 << SHIFT_POS );
214 SHIFTLOCK_PORT &= ~(1 << SHIFTLOCK_POS);
215 SHIFTLOCK_DDR &= ~(1 << SHIFTLOCK_POS);
218 // Reset the keyboard before scanning, we might be in a wierd state
219 scan_resetKeyboard();
222 // Main Detection Loop
223 // Not needed for the Sony OA-S3400 as signals are interrupt based, thus this is a busy loop
224 // XXX Function is used for scanning troublesome keys, technically this is not needed for a pure converter
225 // I just want proper use of the shift and shift lock keys, without having to do major rework to attach to the entire matrix
226 inline uint8_t scan_loop()
228 // Loop through known keys
229 for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ ) switch ( key )
232 if ( SHIFT_PIN & (1 << SHIFT_POS) )
234 KeyScan_Table[SHIFT_KEY]++;
238 if ( SHIFTLOCK_PIN & (1 << SHIFTLOCK_POS) )
240 KeyScan_Table[SHIFTLOCK_KEY]++;
244 erro_print("Invalid key scan index");
248 // Increment vote instance
251 // Loop function again if not enough votes have been tallied
252 if ( KeyScan_Count < 255 )
258 // Loop through known keys
259 for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
261 // Key scanned as pressed (might have been held from a previous vote)
262 if ( KeyScan_Table[key] > 127 )
265 if ( !KeyScan_Prev[key] )
267 processKeyValue( 0x90 + key ); // Arbitrary key mapping starts at 0x90
268 KeyScan_Prev[key] = 1;
271 // Key scanned as released
275 if ( KeyScan_Prev[key] )
277 processKeyValue( 0xA0 + key ); // Arbitrary key mapping release starts at 0xA0
278 KeyScan_Prev[key] = 0;
283 KeyScan_Table[key] = 0;
286 // End loop, process macros and USB data
290 void processKeyValue( uint8_t keyValue )
292 // - Convert Shifted Value to non-shifted ASCII code -
295 if ( keyValue >= 0x61 && keyValue <= 0x7A )
299 // Other keys with ASCII shift codes
345 // TODO Move to Macro Section
349 scan_sendData( 0x01 );
352 scan_sendData( 0x02 );
356 // Scan code is now finalized, and ready to add to buffer
357 // Note: Scan codes come from 3 different interrupts and a manual key scan into this function
361 hexToStr( keyValue, tmpStr );
362 dPrintStrs( tmpStr, " " );
364 // Detect release condition
380 // Check for the released key, and shift the other keys lower on the buffer
382 for ( c = 0; c < KeyIndex_BufferUsed; c++ )
384 // General key buffer clear
385 if ( keyValue == 0xB0 )
387 switch ( KeyIndex_Buffer[c] )
389 // Ignore these keys on general key release (have their own release codes)
395 // Remove key from buffer
397 // Shift keys from c position
398 for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
399 KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
402 KeyIndex_BufferUsed--;
404 // Start at this position again for the next loop
410 // Key to release found
411 else if ( KeyIndex_Buffer[c] == keyValue )
413 // Shift keys from c position
414 for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
415 KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
418 KeyIndex_BufferUsed--;
424 // Error case (no key to release)
425 if ( c == KeyIndex_BufferUsed + 1 )
429 hexToStr( keyValue, tmpStr );
430 erro_dPrint( "Could not find key to release: ", tmpStr );
433 // Press or Repeated Key
436 // Make sure the key isn't already in the buffer
437 for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
439 // Key isn't in the buffer yet
440 if ( c == KeyIndex_BufferUsed )
442 bufferAdd( keyValue );
446 // Key already in the buffer
447 if ( KeyIndex_Buffer[c] == keyValue )
453 // Key Press Detected Interrupt
456 cli(); // Disable Interrupts
458 uint8_t keyValue = 0x00;
460 // Bits are flipped coming in from the keyboard
461 keyValue = ~READSCAN_PIN;
463 // Process the scancode
464 processKeyValue( keyValue );
466 sei(); // Re-enable Interrupts
469 // Key Release Detected Interrupt
472 cli(); // Disable Interrupts
474 // Send release code for general keys, 0xB0
475 processKeyValue( 0xB0 );
477 sei(); // Re-enable Interrupts
480 // Code Key Interrupt
483 cli(); // Disable Interrupts
485 // Code Key Released (send scancode)
486 if ( CODEINT_PIN & (1 << CODEINT_POS) )
488 processKeyValue( 0xA2 );
490 // Code Key Pressed (send scancode)
493 processKeyValue( 0x92 );
496 sei(); // Re-enable Interrupts
500 // Send data to keyboard
501 // Sony OA-S3400 has no serial/parallel dataport to send data too...
502 // Using this function for LED enable/disable
503 uint8_t scan_sendData( uint8_t dataPayload )
505 switch ( dataPayload )
508 LED1_PORT ^= (1 << LED1_POS);
511 LED2_PORT ^= (1 << LED2_POS);
514 erro_print("Invalid data send attempt");
520 // Signal KeyIndex_Buffer that it has been properly read
521 // Not needed as a signal is sent to remove key-presses
522 void scan_finishedWithBuffer( void )
527 // Reset/Hold keyboard
528 // Sony OA-S3400 has no locking signals
529 void scan_lockKeyboard( void )
533 void scan_unlockKeyboard( void )
538 void scan_resetKeyboard( void )
540 // Empty buffer, now that keyboard has been reset
541 KeyIndex_BufferUsed = 0;
543 // Clear the KeyScan table and count
544 for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
546 KeyScan_Table[key] = 0;
547 KeyScan_Prev [key] = 0;
552 // USB module is finished with buffer
553 // Not needed as a signal is sent to remove key-presses
554 void scan_finishedWithUSBBuffer( void )