]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/SonyOA-S3400/scan_loop.c
Preparing for Teensy 3 (ARM) integration, abstracting code hierarchy
[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 // Compiler Includes
25 #include <Lib/ScanLib.h>
26
27 // Project Includes
28 #include <led.h>
29 #include <print.h>
30
31 // Local Includes
32 #include "scan_loop.h"
33
34
35
36 // ----- Defines -----
37
38 // - Pinout Defines -
39
40 // Scan Bit Pins (from keyboard)
41 // - Reads in the ASCII scancode
42 // - Shift and ShiftLock are handled internally
43 #define READSCAN_PORT PORTC
44 #define READSCAN_DDR   DDRC
45 #define READSCAN_PIN   PINC
46
47
48 // Interrupt Pins (from keyboard)
49 // - CODEINT  (Code key signal  interrupt/press)
50 //   - Normally high, low when "Code" key is pressed; separate from all other key presses
51 // - PRESSINT (Press signal     interrupt/press)
52 //   - Normally high, low when any key (or multiple except "Code") is pressed, returns to high once all keys are released
53 //   - Signal is changed BEFORE the Scan Bits are updated
54 // - PULSEINT (Key action pulse interrupt/press)
55 //   - Normally high, low pulses of 147us on key presses (depending on the combination of mode control pins)
56 //   - Pulse is guarranteed to sent after the Scan Bits are updated
57 #define CODEINT_PORT PORTE
58 #define CODEINT_DDR   DDRE
59 #define CODEINT_PIN   PINE
60 #define CODEINT_POS      7
61
62 #define PRESSINT_PORT PORTE
63 #define PRESSINT_DDR   DDRE
64 #define PRESSINT_POS      6
65
66 #define PULSEINT_PORT PORTD
67 #define PULSEINT_DDR   DDRD
68 #define PULSEINT_POS      3
69
70
71 // LED Pins (to keyboard)
72 // - 1 disable LED
73 // - 1  enable LED
74 #define LED1_PORT PORTF // [Pin 19]
75 #define LED1_DDR   DDRF
76 #define LED1_POS      6
77
78 #define LED2_PORT PORTF // [Pin 20]
79 #define LED2_DDR   DDRF
80 #define LED2_POS      7
81
82
83 // Mode Control Pins (to keyboard)
84 // - Repeat [Pin 14]
85 //   - 1 Single   pulse mode (PULSEINT)
86 //   - 0 Repeated pulse mode (PULSEINT) (1 pulse, pause, then constant pulses)
87 // - Multi  [Pin 15]
88 //   - 1 1KRO mode (typewriter compatibility mode)
89 //   - 0 NKRO mode (new pulse on each keypress - PULSEINT)
90 // - Signal [Pin 18]
91 //   - 1 disables pulse interrupt (PULSEINT)
92 //   - 0 enables  pulse interrupt (PULSEINT)
93 #define REPEAT_PORT PORTF
94 #define REPEAT_DDR   DDRF
95 #define REPEAT_POS      3
96
97 #define MULTI_PORT PORTF
98 #define MULTI_DDR   DDRF
99 #define MULTI_POS      4
100
101 #define SIGNAL_PORT PORTF
102 #define SIGNAL_DDR   DDRF
103 #define SIGNAL_POS      5
104
105
106 // Manually Scanned Keys
107 // Keys that the controller screws up, requiring a separate wire to be brought to the controller
108 // Note: Safer to route these through a NOT gate to boost the signal strength
109 //       Values below are AFTER NOT gate
110 // - Shift (both shift keys are on the same scan line)
111 //   - 0 Released
112 //   - 1 Pressed
113 // - Shift Lock
114 //   - 0 Released
115 //   - 1 Pressed
116 #define MANUAL_SCAN_KEYS 2
117
118 #define SHIFT_KEY      0
119 #define SHIFT_PORT PORTF
120 #define SHIFT_DDR   DDRF
121 #define SHIFT_PIN   PINF
122 #define SHIFT_POS      0
123
124 #define SHIFTLOCK_KEY      1
125 #define SHIFTLOCK_PORT PORTF
126 #define SHIFTLOCK_DDR   DDRF
127 #define SHIFTLOCK_PIN   PINF
128 #define SHIFTLOCK_POS      1
129
130
131 // ----- Macros -----
132
133 // Make sure we haven't overflowed the buffer
134 #define bufferAdd(byte) \
135                 if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
136                         KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
137
138
139
140 // ----- Variables -----
141
142 // Buffer used to inform the macro processing module which keys have been detected as pressed
143 volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
144 volatile uint8_t KeyIndex_BufferUsed;
145 volatile uint8_t KeyIndex_Add_InputSignal; // Used to pass the (click/input value) to the keyboard for the clicker
146
147 volatile uint8_t KeyScan_Table[MANUAL_SCAN_KEYS]; // Used for tracking key status of manually scanned keys
148 volatile uint8_t KeyScan_Prev [MANUAL_SCAN_KEYS]; // Keeps track of key state changes
149 volatile uint8_t KeyScan_Count;
150
151
152
153 // ----- Functions -----
154
155 // Pre-declarations
156 void processKeyValue( uint8_t keyValue );
157
158
159
160 // Setup
161 inline void scan_setup()
162 {
163         // Setup the external interrupts for
164         // - General keypresses     (INT6/E6) ->         rising edge (to detect key       release)
165         // - "Code" key             (INT7/E7) -> falling/rising edge (to detect key press/release)
166         // - General keypress pulse (INT3/D3) -> falling        edge (to detect key press        )
167         EICRA = 0x80;
168         EICRB = 0x70;
169         EIMSK = 0xC8;
170
171
172         // Setup Interrupt Pins
173         CODEINT_PORT  |=  (1 << CODEINT_POS );
174         CODEINT_DDR   &= ~(1 << CODEINT_POS );
175
176         PRESSINT_PORT |=  (1 << PRESSINT_POS);
177         PRESSINT_DDR  &= ~(1 << PRESSINT_POS);
178
179         PULSEINT_PORT |=  (1 << PULSEINT_POS);
180         PULSEINT_DDR  &= ~(1 << PULSEINT_POS);
181
182
183         // Setup LED Pins (default off)
184         LED1_PORT |= (1 << LED1_POS);
185         LED1_DDR  |= (1 << LED1_POS);
186
187         LED2_PORT |= (1 << LED2_POS);
188         LED2_DDR  |= (1 << LED2_POS);
189
190
191         // Setup READSCAN pins to read out scancode
192         READSCAN_PORT = 0xFF;
193         READSCAN_DDR  = 0x00;
194
195
196         // Setup Mode Control Pins
197         // Note: These can be changed at any time, but there is no real reason too for a USB converter
198         REPEAT_PORT |=  (1 << REPEAT_POS); // Setting high for single press mode
199         REPEAT_DDR  |=  (1 << REPEAT_POS);
200
201         MULTI_PORT  &= ~(1 << MULTI_POS ); // Setting low for multi press mode (NKRO)
202         MULTI_DDR   |=  (1 << MULTI_POS );
203
204         SIGNAL_PORT &= ~(1 << SIGNAL_POS); // Setting low to enable PULSEINT
205         SIGNAL_DDR  |=  (1 << SIGNAL_POS);
206
207
208         // Setup Troublesome Key Pins
209         SHIFT_PORT     &= ~(1 << SHIFT_POS    );
210         SHIFT_DDR      &= ~(1 << SHIFT_POS    );
211
212         SHIFTLOCK_PORT &= ~(1 << SHIFTLOCK_POS);
213         SHIFTLOCK_DDR  &= ~(1 << SHIFTLOCK_POS);
214
215
216         // Reset the keyboard before scanning, we might be in a wierd state
217         scan_resetKeyboard();
218 }
219
220 // Main Detection Loop
221 // Not needed for the Sony OA-S3400 as signals are interrupt based, thus this is a busy loop
222 // XXX Function is used for scanning troublesome keys, technically this is not needed for a pure converter
223 //     I just want proper use of the shift and shift lock keys, without having to do major rework to attach to the entire matrix
224 inline uint8_t scan_loop()
225 {
226         // Loop through known keys
227         for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ ) switch ( key )
228         {
229         case SHIFT_KEY:
230                 if ( SHIFT_PIN & (1 << SHIFT_POS) )
231                 {
232                         KeyScan_Table[SHIFT_KEY]++;
233                 }
234                 break;
235         case SHIFTLOCK_KEY:
236                 if ( SHIFTLOCK_PIN & (1 << SHIFTLOCK_POS) )
237                 {
238                         KeyScan_Table[SHIFTLOCK_KEY]++;
239                 }
240                 break;
241         default:
242                 erro_print("Invalid key scan index");
243                 break;
244         }
245
246         // Increment vote instance
247         KeyScan_Count++;
248
249         // Loop function again if not enough votes have been tallied
250         if ( KeyScan_Count < 255 )
251                 return 1;
252
253         // Clear vote data
254         KeyScan_Count = 0;
255
256         // Loop through known keys
257         for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
258         {
259                 // Key scanned as pressed (might have been held from a previous vote)
260                 if ( KeyScan_Table[key] > 127 )
261                 {
262                         // Keypress detected
263                         if ( !KeyScan_Prev[key] )
264                         {
265                                 processKeyValue( 0x90 + key ); // Arbitrary key mapping starts at 0x90
266                                 KeyScan_Prev[key] = 1;
267                         }
268                 }
269                 // Key scanned as released
270                 else
271                 {
272                         // Keypress detected
273                         if ( KeyScan_Prev[key] )
274                         {
275                                 processKeyValue( 0xA0 + key ); // Arbitrary key mapping release starts at 0xA0
276                                 KeyScan_Prev[key] = 0;
277                         }
278                 }
279
280                 // Clear votes
281                 KeyScan_Table[key] = 0;
282         }
283
284         // End loop, process macros and USB data
285         return 0;
286 }
287
288 void processKeyValue( uint8_t keyValue )
289 {
290         // - Convert Shifted Value to non-shifted ASCII code -
291
292         // Alphabetic
293         if ( keyValue >= 0x61 && keyValue <= 0x7A )
294         {
295                 keyValue -= 0x20;
296         }
297         // Other keys with ASCII shift codes
298         else
299         {
300                 switch ( keyValue )
301                 {
302                 case 0x21: // 1
303                 case 0x23: // 3
304                 case 0x24: // 4
305                 case 0x25: // 5
306                         keyValue += 0x10;
307                         break;
308                 case 0x26: // 7
309                 case 0x28: // 9
310                         keyValue += 0x11;
311                         break;
312                 case 0x81: // 1/2
313                 case 0x3A: // ;
314                         keyValue += 0x01;
315                         break;
316                 case 0x29: // 0
317                         keyValue = 0x30;
318                         break;
319                 case 0x40: // 2
320                         keyValue = 0x32;
321                         break;
322                 case 0x80: // 6
323                         keyValue = 0x36;
324                         break;
325                 case 0x2A: // 8
326                         keyValue = 0x38;
327                         break;
328                 case 0x5F: // -
329                         keyValue = 0x2D;
330                         break;
331                 case 0x2B: // +
332                         keyValue = 0x3D;
333                         break;
334                 case 0x22: // "
335                         keyValue = 0x27;
336                         break;
337                 case 0x3F: // ?
338                         keyValue = 0x2F;
339                         break;
340                 }
341         }
342
343         // TODO Move to Macro Section
344         switch ( keyValue )
345         {
346         case 0xD3: // F11
347                 scan_sendData( 0x01 );
348                 break;
349         case 0xD4: // F12
350                 scan_sendData( 0x02 );
351                 break;
352         }
353
354         // Scan code is now finalized, and ready to add to buffer
355         // Note: Scan codes come from 3 different interrupts and a manual key scan into this function
356
357         // Debug
358         char tmpStr[6];
359         hexToStr( keyValue, tmpStr );
360         dPrintStrs( tmpStr, " " );
361
362         // Detect release condition
363         uint8_t release = 0;
364         switch ( keyValue )
365         {
366         case 0xA0:
367         case 0xA1:
368         case 0xA2:
369                 keyValue -= 0x10;
370         case 0xB0:
371                 release = 1;
372                 break;
373         }
374
375         // Key Release
376         if ( release )
377         {
378                 // Check for the released key, and shift the other keys lower on the buffer
379                 uint8_t c;
380                 for ( c = 0; c < KeyIndex_BufferUsed; c++ )
381                 {
382                         // General key buffer clear
383                         if ( keyValue == 0xB0 )
384                         {
385                                 switch ( KeyIndex_Buffer[c] )
386                                 {
387                                 // Ignore these keys on general key release (have their own release codes)
388                                 case 0x90:
389                                 case 0x91:
390                                 case 0x92:
391                                         break;
392
393                                 // Remove key from buffer
394                                 default:
395                                         // Shift keys from c position
396                                         for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
397                                                 KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
398
399                                         // Decrement Buffer
400                                         KeyIndex_BufferUsed--;
401
402                                         // Start at this position again for the next loop
403                                         c--;
404
405                                         break;
406                                 }
407                         }
408                         // Key to release found
409                         else if ( KeyIndex_Buffer[c] == keyValue )
410                         {
411                                 // Shift keys from c position
412                                 for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
413                                         KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
414
415                                 // Decrement Buffer
416                                 KeyIndex_BufferUsed--;
417
418                                 break;
419                         }
420                 }
421
422                 // Error case (no key to release)
423                 if ( c == KeyIndex_BufferUsed + 1 )
424                 {
425                         errorLED( 1 );
426                         char tmpStr[6];
427                         hexToStr( keyValue, tmpStr );
428                         erro_dPrint( "Could not find key to release: ", tmpStr );
429                 }
430         }
431         // Press or Repeated Key
432         else
433         {
434                 // Make sure the key isn't already in the buffer
435                 for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
436                 {
437                         // Key isn't in the buffer yet
438                         if ( c == KeyIndex_BufferUsed )
439                         {
440                                 bufferAdd( keyValue );
441                                 break;
442                         }
443
444                         // Key already in the buffer
445                         if ( KeyIndex_Buffer[c] == keyValue )
446                                 break;
447                 }
448         }
449 }
450
451 // Key Press Detected Interrupt
452 ISR(INT3_vect)
453 {
454         cli(); // Disable Interrupts
455
456         uint8_t keyValue = 0x00;
457
458         // Bits are flipped coming in from the keyboard
459         keyValue = ~READSCAN_PIN;
460
461         // Process the scancode
462         processKeyValue( keyValue );
463
464         sei(); // Re-enable Interrupts
465 }
466
467 // Key Release Detected Interrupt
468 ISR(INT6_vect)
469 {
470         cli(); // Disable Interrupts
471
472         // Send release code for general keys, 0xB0
473         processKeyValue( 0xB0 );
474
475         sei(); // Re-enable Interrupts
476 }
477
478 // Code Key Interrupt
479 ISR(INT7_vect)
480 {
481         cli(); // Disable Interrupts
482
483         // Code Key Released (send scancode)
484         if ( CODEINT_PIN & (1 << CODEINT_POS) )
485         {
486                 processKeyValue( 0xA2 );
487         }
488         // Code Key Pressed (send scancode)
489         else
490         {
491                 processKeyValue( 0x92 );
492         }
493
494         sei(); // Re-enable Interrupts
495 }
496
497
498 // Send data to keyboard
499 // Sony OA-S3400 has no serial/parallel dataport to send data too...
500 // Using this function for LED enable/disable
501 uint8_t scan_sendData( uint8_t dataPayload )
502 {
503         switch ( dataPayload )
504         {
505         case 0x01:
506                 LED1_PORT ^= (1 << LED1_POS);
507                 break;
508         case 0x02:
509                 LED2_PORT ^= (1 << LED2_POS);
510                 break;
511         default:
512                 erro_print("Invalid data send attempt");
513                 break;
514         }
515         return 0;
516 }
517
518 // Signal KeyIndex_Buffer that it has been properly read
519 // Not needed as a signal is sent to remove key-presses
520 void scan_finishedWithBuffer( uint8_t sentKeys )
521 {
522         return;
523 }
524
525 // Reset/Hold keyboard
526 // Sony OA-S3400 has no locking signals
527 void scan_lockKeyboard( void )
528 {
529 }
530
531 void scan_unlockKeyboard( void )
532 {
533 }
534
535 // Reset Keyboard
536 void scan_resetKeyboard( void )
537 {
538         // Empty buffer, now that keyboard has been reset
539         KeyIndex_BufferUsed = 0;
540
541         // Clear the KeyScan table and count
542         for ( uint8_t key = 0; key < MANUAL_SCAN_KEYS; key++ )
543         {
544                 KeyScan_Table[key] = 0;
545                 KeyScan_Prev [key] = 0;
546         }
547         KeyScan_Count = 0;
548 }
549
550 // USB module is finished with buffer
551 // Not needed as a signal is sent to remove key-presses
552 void scan_finishedWithUSBBuffer( uint8_t sentKeys )
553 {
554         return;
555 }
556