]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/FACOM6684/scan_loop.c
7babd64f4da70620a5eba857df5f24105ae3b24f
[kiibohd-controller.git] / Scan / FACOM6684 / scan_loop.c
1 /* Copyright (C) 2013 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
41 // ----- Macros -----
42
43 // Make sure we haven't overflowed the buffer
44 #define bufferAdd(byte) \
45                 if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
46                         KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
47
48
49
50 // ----- Variables -----
51
52 // Buffer used to inform the macro processing module which keys have been detected as pressed
53 volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
54 volatile uint8_t KeyIndex_BufferUsed;
55
56 volatile uint8_t KeyBufferRemove[6];
57 volatile uint8_t KeyBufferRemoveCount = 0;
58
59 static uint8_t KeyBuffer[3];
60 volatile static uint8_t KeyBufferCount = 0;
61
62
63
64 // ----- Function Declarations -----
65
66 void processKeyValue( uint8_t valueType, uint8_t keyValue );
67 void  removeKeyValue( uint8_t keyValue );
68
69
70
71 // ----- Interrupt Functions -----
72
73 // USART Receive Buffer Full Interrupt
74 ISR(USART1_RX_vect)
75 {
76         cli(); // Disable Interrupts
77
78         // Read part of the scan code (3 8bit chunks) from USART
79         KeyBuffer[KeyBufferCount] = UDR1;
80
81         if ( KeyBufferCount >= 2 )
82         {
83                 // Debug
84                 for ( uint8_t c = 0; c <= 2; c++ )
85                 {
86                         // Debug
87                         char tmpStr[6];
88                         hexToStr( KeyBuffer[c], tmpStr );
89                         dPrintStrs( tmpStr, " " ); // Debug
90                 }
91                 print("\n");
92
93                 processKeyValue( KeyBuffer[1], KeyBuffer[2] );
94
95                 KeyBufferCount = 0;
96         }
97         else
98         {
99                 KeyBufferCount++;
100         }
101
102         sei(); // Re-enable Interrupts
103 }
104
105
106
107 // ----- Functions -----
108
109 // Setup
110 inline void scan_setup()
111 {
112         // Setup the the USART interface for keyboard data input
113         // NOTE: The input data signal needs to be inverted for the Teensy USART to properly work
114         
115         // Setup baud rate
116         // 16 MHz / ( 16 * Baud ) = UBRR
117         // Baud: 4817 -> 16 MHz / ( 16 * 4817 ) = 207.5981
118         // Thus baud setting = 208
119         uint16_t baud = 208; // Max setting of 4095
120         UBRR1H = (uint8_t)(baud >> 8);
121         UBRR1L = (uint8_t)baud;
122
123         // Enable the receiver, transmitter, and RX Complete Interrupt
124         UCSR1B = 0x98;
125
126         // Set frame format: 8 data, 1 stop bit, odd parity
127         // Asynchrounous USART mode
128         UCSR1C = 0x36;
129
130         // Reset the keyboard before scanning, we might be in a wierd state
131         scan_resetKeyboard();
132 }
133
134
135 // Main Detection Loop
136 inline uint8_t scan_loop()
137 {
138         // Remove any "released keys", this is delayed due to buffer release synchronization issues
139         for ( uint8_t c = 0; c < KeyBufferRemoveCount; c++ )
140         {
141                 removeKeyValue( KeyBufferRemove[c] );
142         }
143
144         KeyBufferRemoveCount = 0;
145
146         return 0;
147 }
148
149 void processKeyValue( uint8_t valueType, uint8_t keyValue )
150 {
151         switch ( valueType )
152         {
153         // Single Key Press
154         case 0x00:
155                 break;
156         // Repeated Key Press
157         case 0x01:
158                 break;
159         // Modifier Key Release
160         case 0x02:
161                 KeyBufferRemove[KeyBufferRemoveCount++] = keyValue;
162                 return;
163         }
164
165         // Make sure the key isn't already in the buffer
166         for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
167         {
168                 // Key isn't in the buffer yet
169                 if ( c == KeyIndex_BufferUsed )
170                 {
171                         bufferAdd( keyValue );
172                         break;
173                 }
174
175                 // Key already in the buffer
176                 if ( KeyIndex_Buffer[c] == keyValue )
177                         break;
178         }
179 }
180
181 void removeKeyValue( uint8_t keyValue )
182 {
183         // Check for the released key, and shift the other keys lower on the buffer
184         uint8_t c;
185         for ( c = 0; c < KeyIndex_BufferUsed; c++ )
186         {
187                 // Key to release found
188                 if ( KeyIndex_Buffer[c] == keyValue )
189                 {
190                         // Shift keys from c position
191                         for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
192                                 KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
193
194                         // Decrement Buffer
195                         KeyIndex_BufferUsed--;
196
197                         break;
198                 }
199         }
200
201         // Error case (no key to release)
202         if ( c == KeyIndex_BufferUsed + 1 )
203         {
204                 errorLED( 1 );
205                 char tmpStr[6];
206                 hexToStr( keyValue, tmpStr );
207                 erro_dPrint( "Could not find key to release: ", tmpStr );
208         }
209 }
210
211 // Send data 
212 uint8_t scan_sendData( uint8_t dataPayload )
213 {
214         // Debug
215         char tmpStr[6];
216         hexToStr( dataPayload, tmpStr );
217         info_dPrint( "Sending - ", tmpStr );
218
219         UDR1 = dataPayload;
220
221         return 0;
222 }
223
224 // Signal KeyIndex_Buffer that it has been properly read
225 void scan_finishedWithBuffer( uint8_t sentKeys )
226 {
227         // Make sure we aren't in the middle of a receiving a new scancode
228         while ( KeyBufferCount != 0 );
229
230         cli(); // Disable Interrupts
231
232         // Count for number of modifiers to maintain in the buffer
233         uint8_t filled = 0;
234         uint8_t latched = 0;
235         uint8_t latchBuffer[13]; // There are only 13 keys that can possibly be latched at the same time...
236         uint8_t normal = 0;
237         uint8_t prevBuffer = KeyIndex_BufferUsed;
238
239         // Clean out all keys except "special" keys (designated modifiers)
240         uint8_t key;
241         for ( key = 0; key < sentKeys; key++ )
242         {
243                 switch ( KeyIndex_Buffer[key] )
244                 {
245                 // Dedicated Modifier Keys
246                 // NOTE: Both shifts are represented as the same scan code
247                 case 0x04:
248                 case 0x05:
249                 case 0x12:
250                         KeyIndex_Buffer[filled++] = KeyIndex_Buffer[key];
251                         break;
252                 // Latched Keys, only released if a non-modifier is pressed along with it
253                 // NOTE: This keys do not have a built in repeating
254                 case 0x00:
255                 case 0x01:
256                 case 0x03:
257                 //case 0x0B: // XXX Being used as an alternate Enter, since it is labelled as such
258                 case 0x22:
259                 case 0x10:
260                 case 0x11:
261                 case 0x20:
262                 case 0x21:
263                 case 0x30:
264                 case 0x31:
265                 case 0x40:
266                 //case 0x41: // XXX Being used as ESC
267                         latchBuffer[latched++] = KeyIndex_Buffer[key];
268                         break;
269                 // Allow the scancode to be removed, normal keys
270                 default:
271                         normal++;
272                         break;
273                 }
274         }
275
276         // Reset the buffer counter
277         KeyIndex_BufferUsed = filled;
278
279         // Add back lost keys, so they are processed on the next USB send
280         for ( ; key < prevBuffer; key++ )
281         {
282                 bufferAdd( KeyIndex_Buffer[key] );
283                 info_print("Re-appending lost key after USB send...");
284         }
285
286         // Only "re-add" the latched keys if they weren't used
287         if ( latched > 0 && normal == 0 )
288         {
289                 for ( uint8_t c = 0; c < latched; c++ )
290                 {
291                         bufferAdd( latchBuffer[c] );
292                 }
293         }
294
295         sei(); // Re-enable Interrupts
296 }
297
298 // Signal that the keys have been properly sent over USB
299 void scan_finishedWithUSBBuffer( uint8_t sentKeys )
300 {
301 }
302
303 // Reset/Hold keyboard
304 // NOTE: Does nothing with the FACOM6684
305 void scan_lockKeyboard( void )
306 {
307 }
308
309 // NOTE: Does nothing with the FACOM6684
310 void scan_unlockKeyboard( void )
311 {
312 }
313
314 // Reset Keyboard
315 void scan_resetKeyboard( void )
316 {
317         // Not a calculated valued...
318         _delay_ms( 50 );
319
320         KeyBufferCount = 0;
321         KeyBufferRemoveCount = 0;
322         KeyIndex_BufferUsed = 0;
323 }
324