]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/SonyOA-S3400/scan_loop.c
Completing Sony OA-S3400 adapter.
[kiibohd-controller.git] / Scan / SonyOA-S3400 / scan_loop.c
1 /* Copyright (C) 2012 by Jacob Alexander
2  * 
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:
9  * 
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  * 
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
19  * THE SOFTWARE.
20  */
21
22 // ----- Includes -----
23
24 // AVR Includes
25 #include <avr/interrupt.h>
26 #include <avr/io.h>
27 #include <util/delay.h>
28
29 // Project Includes
30 #include <led.h>
31 #include <print.h>
32
33 // Local Includes
34 #include "scan_loop.h"
35
36
37
38 // ----- Defines -----
39
40 // - Pinout Defines -
41
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
48
49
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
62 #define CODEINT_POS      7
63
64 #define PRESSINT_PORT PORTE
65 #define PRESSINT_DDR   DDRE
66 #define PRESSINT_POS      6
67
68 #define PULSEINT_PORT PORTD
69 #define PULSEINT_DDR   DDRD
70 #define PULSEINT_POS      3
71
72
73 // LED Pins (to keyboard)
74 // - 1 disable LED
75 // - 1  enable LED
76 #define LED1_PORT PORTF // [Pin 19]
77 #define LED1_DDR   DDRF
78 #define LED1_POS      6
79
80 #define LED2_PORT PORTF // [Pin 20]
81 #define LED2_DDR   DDRF
82 #define LED2_POS      7
83
84
85 // Mode Control Pins (to keyboard)
86 // - Repeat [Pin 14]
87 //   - 1 Single   pulse mode (PULSEINT)
88 //   - 0 Repeated pulse mode (PULSEINT) (1 pulse, pause, then constant pulses)
89 // - Multi  [Pin 15]
90 //   - 1 1KRO mode (typewriter compatibility mode)
91 //   - 0 NKRO mode (new pulse on each keypress - PULSEINT)
92 // - Signal [Pin 18]
93 //   - 1 disables pulse interrupt (PULSEINT)
94 //   - 0 enables  pulse interrupt (PULSEINT)
95 #define REPEAT_PORT PORTF
96 #define REPEAT_DDR   DDRF
97 #define REPEAT_POS      3
98
99 #define MULTI_PORT PORTF
100 #define MULTI_DDR   DDRF
101 #define MULTI_POS      4
102
103 #define SIGNAL_PORT PORTF
104 #define SIGNAL_DDR   DDRF
105 #define SIGNAL_POS      5
106
107
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)
113 //   - 0 Released
114 //   - 1 Pressed
115 // - Shift Lock
116 //   - 0 Released
117 //   - 1 Pressed
118 #define MANUAL_SCAN_KEYS 2
119
120 #define SHIFT_KEY      0
121 #define SHIFT_PORT PORTF
122 #define SHIFT_DDR   DDRF
123 #define SHIFT_PIN   PINF
124 #define SHIFT_POS      0
125
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
131
132
133 // ----- Macros -----
134
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
139
140
141
142 // ----- Variables -----
143
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
148
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;
152
153
154
155 // ----- Functions -----
156
157 // Pre-declarations
158 void processKeyValue( uint8_t keyValue );
159
160
161
162 // Setup
163 inline void scan_setup()
164 {
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        )
169         EICRA = 0x80;
170         EICRB = 0x70;
171         EIMSK = 0xC8;
172
173
174         // Setup Interrupt Pins
175         CODEINT_PORT  |=  (1 << CODEINT_POS );
176         CODEINT_DDR   &= ~(1 << CODEINT_POS );
177
178         PRESSINT_PORT |=  (1 << PRESSINT_POS);
179         PRESSINT_DDR  &= ~(1 << PRESSINT_POS);
180
181         PULSEINT_PORT |=  (1 << PULSEINT_POS);
182         PULSEINT_DDR  &= ~(1 << PULSEINT_POS);
183
184
185         // Setup LED Pins (default off)
186         LED1_PORT |= (1 << LED1_POS);
187         LED1_DDR  |= (1 << LED1_POS);
188
189         LED2_PORT |= (1 << LED2_POS);
190         LED2_DDR  |= (1 << LED2_POS);
191
192
193         // Setup READSCAN pins to read out scancode
194         READSCAN_PORT = 0xFF;
195         READSCAN_DDR  = 0x00;
196
197
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);
202
203         MULTI_PORT  &= ~(1 << MULTI_POS ); // Setting low for multi press mode (NKRO)
204         MULTI_DDR   |=  (1 << MULTI_POS );
205
206         SIGNAL_PORT &= ~(1 << SIGNAL_POS); // Setting low to enable PULSEINT
207         SIGNAL_DDR  |=  (1 << SIGNAL_POS);
208
209
210         // Setup Troublesome Key Pins
211         SHIFT_PORT     &= ~(1 << SHIFT_POS    );
212         SHIFT_DDR      &= ~(1 << SHIFT_POS    );
213
214         SHIFTLOCK_PORT &= ~(1 << SHIFTLOCK_POS);
215         SHIFTLOCK_DDR  &= ~(1 << SHIFTLOCK_POS);
216
217
218         // Reset the keyboard before scanning, we might be in a wierd state
219         scan_resetKeyboard();
220 }
221
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()
227 {
228         // Loop through known keys
229         for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ ) switch ( key )
230         {
231         case SHIFT_KEY:
232                 if ( SHIFT_PIN & (1 << SHIFT_POS) )
233                 {
234                         KeyScan_Table[SHIFT_KEY]++;
235                 }
236                 break;
237         case SHIFTLOCK_KEY:
238                 if ( SHIFTLOCK_PIN & (1 << SHIFTLOCK_POS) )
239                 {
240                         KeyScan_Table[SHIFTLOCK_KEY]++;
241                 }
242                 break;
243         default:
244                 erro_print("Invalid key scan index");
245                 break;
246         }
247
248         // Increment vote instance
249         KeyScan_Count++;
250
251         // Loop function again if not enough votes have been tallied
252         if ( KeyScan_Count < 255 )
253                 return 1;
254
255         // Clear vote data
256         KeyScan_Count = 0;
257
258         // Loop through known keys
259         for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
260         {
261                 // Key scanned as pressed (might have been held from a previous vote)
262                 if ( KeyScan_Table[key] > 127 )
263                 {
264                         // Keypress detected
265                         if ( !KeyScan_Prev[key] )
266                         {
267                                 processKeyValue( 0x90 + key ); // Arbitrary key mapping starts at 0x90
268                                 KeyScan_Prev[key] = 1;
269                         }
270                 }
271                 // Key scanned as released
272                 else
273                 {
274                         // Keypress detected
275                         if ( KeyScan_Prev[key] )
276                         {
277                                 processKeyValue( 0xA0 + key ); // Arbitrary key mapping release starts at 0xA0
278                                 KeyScan_Prev[key] = 0;
279                         }
280                 }
281
282                 // Clear votes
283                 KeyScan_Table[key] = 0;
284         }
285
286         // End loop, process macros and USB data
287         return 0;
288 }
289
290 void processKeyValue( uint8_t keyValue )
291 {
292         // - Convert Shifted Value to non-shifted ASCII code -
293
294         // Alphabetic
295         if ( keyValue >= 0x61 && keyValue <= 0x7A )
296         {
297                 keyValue -= 0x20;
298         }
299         // Other keys with ASCII shift codes
300         else
301         {
302                 switch ( keyValue )
303                 {
304                 case 0x21: // 1
305                 case 0x23: // 3
306                 case 0x24: // 4
307                 case 0x25: // 5
308                         keyValue += 0x10;
309                         break;
310                 case 0x26: // 7
311                 case 0x28: // 9
312                         keyValue += 0x11;
313                         break;
314                 case 0x81: // 1/2
315                 case 0x3A: // ;
316                         keyValue += 0x01;
317                         break;
318                 case 0x29: // 0
319                         keyValue = 0x30;
320                         break;
321                 case 0x40: // 2
322                         keyValue = 0x32;
323                         break;
324                 case 0x80: // 6
325                         keyValue = 0x36;
326                         break;
327                 case 0x2A: // 8
328                         keyValue = 0x38;
329                         break;
330                 case 0x5F: // -
331                         keyValue = 0x2D;
332                         break;
333                 case 0x2B: // +
334                         keyValue = 0x3D;
335                         break;
336                 case 0x22: // "
337                         keyValue = 0x27;
338                         break;
339                 case 0x3F: // ?
340                         keyValue = 0x2F;
341                         break;
342                 }
343         }
344
345         // TODO Move to Macro Section
346         switch ( keyValue )
347         {
348         case 0xD3: // F11
349                 scan_sendData( 0x01 );
350                 break;
351         case 0xD4: // F12
352                 scan_sendData( 0x02 );
353                 break;
354         }
355
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
358
359         // Debug
360         char tmpStr[6];
361         hexToStr( keyValue, tmpStr );
362         dPrintStrs( tmpStr, " " );
363
364         // Detect release condition
365         uint8_t release = 0;
366         switch ( keyValue )
367         {
368         case 0xA0:
369         case 0xA1:
370         case 0xA2:
371                 keyValue -= 0x10;
372         case 0xB0:
373                 release = 1;
374                 break;
375         }
376
377         // Key Release
378         if ( release )
379         {
380                 // Check for the released key, and shift the other keys lower on the buffer
381                 uint8_t c;
382                 for ( c = 0; c < KeyIndex_BufferUsed; c++ )
383                 {
384                         // General key buffer clear
385                         if ( keyValue == 0xB0 )
386                         {
387                                 switch ( KeyIndex_Buffer[c] )
388                                 {
389                                 // Ignore these keys on general key release (have their own release codes)
390                                 case 0x90:
391                                 case 0x91:
392                                 case 0x92:
393                                         break;
394
395                                 // Remove key from buffer
396                                 default:
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];
400
401                                         // Decrement Buffer
402                                         KeyIndex_BufferUsed--;
403
404                                         // Start at this position again for the next loop
405                                         c--;
406
407                                         break;
408                                 }
409                         }
410                         // Key to release found
411                         else if ( KeyIndex_Buffer[c] == keyValue )
412                         {
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];
416
417                                 // Decrement Buffer
418                                 KeyIndex_BufferUsed--;
419
420                                 break;
421                         }
422                 }
423
424                 // Error case (no key to release)
425                 if ( c == KeyIndex_BufferUsed + 1 )
426                 {
427                         errorLED( 1 );
428                         char tmpStr[6];
429                         hexToStr( keyValue, tmpStr );
430                         erro_dPrint( "Could not find key to release: ", tmpStr );
431                 }
432         }
433         // Press or Repeated Key
434         else
435         {
436                 // Make sure the key isn't already in the buffer
437                 for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
438                 {
439                         // Key isn't in the buffer yet
440                         if ( c == KeyIndex_BufferUsed )
441                         {
442                                 bufferAdd( keyValue );
443                                 break;
444                         }
445
446                         // Key already in the buffer
447                         if ( KeyIndex_Buffer[c] == keyValue )
448                                 break;
449                 }
450         }
451 }
452
453 // Key Press Detected Interrupt
454 ISR(INT3_vect)
455 {
456         cli(); // Disable Interrupts
457
458         uint8_t keyValue = 0x00;
459
460         // Bits are flipped coming in from the keyboard
461         keyValue = ~READSCAN_PIN;
462
463         // Process the scancode
464         processKeyValue( keyValue );
465
466         sei(); // Re-enable Interrupts
467 }
468
469 // Key Release Detected Interrupt
470 ISR(INT6_vect)
471 {
472         cli(); // Disable Interrupts
473
474         // Send release code for general keys, 0xB0
475         processKeyValue( 0xB0 );
476
477         sei(); // Re-enable Interrupts
478 }
479
480 // Code Key Interrupt
481 ISR(INT7_vect)
482 {
483         cli(); // Disable Interrupts
484
485         // Code Key Released (send scancode)
486         if ( CODEINT_PIN & (1 << CODEINT_POS) )
487         {
488                 processKeyValue( 0xA2 );
489         }
490         // Code Key Pressed (send scancode)
491         else
492         {
493                 processKeyValue( 0x92 );
494         }
495
496         sei(); // Re-enable Interrupts
497 }
498
499
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 )
504 {
505         switch ( dataPayload )
506         {
507         case 0x01:
508                 LED1_PORT ^= (1 << LED1_POS);
509                 break;
510         case 0x02:
511                 LED2_PORT ^= (1 << LED2_POS);
512                 break;
513         default:
514                 erro_print("Invalid data send attempt");
515                 break;
516         }
517         return 0;
518 }
519
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 )
523 {
524         return;
525 }
526
527 // Reset/Hold keyboard
528 // Sony OA-S3400 has no locking signals
529 void scan_lockKeyboard( void )
530 {
531 }
532
533 void scan_unlockKeyboard( void )
534 {
535 }
536
537 // Reset Keyboard
538 void scan_resetKeyboard( void )
539 {
540         // Empty buffer, now that keyboard has been reset
541         KeyIndex_BufferUsed = 0;
542
543         // Clear the KeyScan table and count
544         for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
545         {
546                 KeyScan_Table[key] = 0;
547                 KeyScan_Prev [key] = 0;
548         }
549         KeyScan_Count = 0;
550 }
551
552 // USB module is finished with buffer
553 // Not needed as a signal is sent to remove key-presses
554 void scan_finishedWithUSBBuffer( void )
555 {
556         return;
557 }
558