]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/MicroSwitch8304/scan_loop.c
Intial commit of the SonyNEWS scan module
[kiibohd-controller.git] / Scan / MicroSwitch8304 / scan_loop.c
1 /* Copyright (C) 2011 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 #define RESET_PORT PORTB
42 #define RESET_DDR   DDRD
43 #define RESET_PIN      0
44
45
46 // ----- Macros -----
47
48 // Make sure we haven't overflowed the buffer
49 #define bufferAdd(byte) \
50                 if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
51                         KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
52
53 #define UNSET_RESET()   RESET_DDR &= ~(1 << RESET_PIN)
54 #define   SET_RESET()   RESET_DDR |=  (1 << RESET_PIN)
55
56
57
58 // ----- Variables -----
59
60 // Buffer used to inform the macro processing module which keys have been detected as pressed
61 volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
62 volatile uint8_t KeyIndex_BufferUsed;
63
64
65 // Buffer Signals
66 volatile uint8_t BufferReadyToClear;
67
68
69
70 // ----- Functions -----
71
72 // Setup
73 inline void scan_setup()
74 {
75         // Setup the the USART interface for keyboard data input
76         // NOTE: The input data signal needs to be inverted for the Teensy USART to properly work
77         
78         // Setup baud rate
79         // 16 MHz / ( 16 * Baud ) = UBRR
80         // Baud <- 0.82020 ms per bit, thus 1000 / 0.82020 = 1219.2
81         // Thus baud setting = 820
82         uint16_t baud = 820; // Max setting of 4095
83         UBRR1H = (uint8_t)(baud >> 8);
84         UBRR1L = (uint8_t)baud;
85
86         // Enable the receiver, transitter, and RX Complete Interrupt
87         UCSR1B = 0x98;
88
89         // Set frame format: 8 data, no stop bits or parity
90         // Asynchrounous USART mode
91         // 8304 sends encoded scancodes (for example Alphanumeric 0-9 follows their keypad encoding scheme)
92         // Separate line is for reset
93         UCSR1C = 0x06;
94
95         // Initially buffer doesn't need to be cleared (it's empty...)
96         BufferReadyToClear = 0;
97
98         // Reset the keyboard before scanning, we might be in a wierd state
99         // Note: This should be run asap, but we need the USART setup to run this command on the 8304
100         scan_resetKeyboard();
101 }
102
103
104 // Main Detection Loop
105 // Not needed for the Micro Switch 8304, this is just a busy loop
106 inline uint8_t scan_loop()
107 {
108         return 0;
109 }
110
111 void processKeyValue( uint8_t keyValue )
112 {
113         // Finalize output buffer
114         // Mask 8th bit
115         keyValue &= 0x7F;
116
117         // Interpret scan code
118         switch ( keyValue )
119         {
120         case 0x40: // Clear buffer command
121                 info_print("CLEAR!");
122
123                 BufferReadyToClear = 1;
124                 break;
125         case 0x7F:
126                 scan_lockKeyboard();
127                 _delay_ms(3000);
128                 scan_unlockKeyboard();
129
130         default:
131                 // Make sure the key isn't already in the buffer
132                 for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
133                 {
134                         // Key isn't in the buffer yet
135                         if ( c == KeyIndex_BufferUsed )
136                         {
137                                 bufferAdd( keyValue );
138                                 break;
139                         }
140
141                         // Key already in the buffer
142                         if ( KeyIndex_Buffer[c] == keyValue )
143                                 break;
144                 }
145                 break;
146         }
147 }
148
149 // USART Receive Buffer Full Interrupt
150 ISR(USART1_RX_vect)
151 {
152         cli(); // Disable Interrupts
153
154         uint8_t keyValue = 0x00;
155
156         // The interrupt is always for the first item of the packet set, reset the buffer
157         KeyIndex_BufferUsed = 0;
158
159         // Only the first 7 bits have scancode data
160         // The last packet of the packet set has the 8th bit high, all the others are low
161         //
162         // Interrupts are too slow for the rest of the packet set, poll for the rest
163         while ( 1 )
164         {
165                 // Read the raw packet from the USART
166                 keyValue = UDR1;
167
168                 // Debug
169                 char tmpStr[6];
170                 hexToStr( keyValue, tmpStr );
171                 dPrintStrs( tmpStr, " " );
172
173                 // Process the scancode
174                 processKeyValue( keyValue );
175
176                 // Last packet of the set
177                 if ( keyValue & 0x80 )
178                 {
179                         dPrintStrs( "**" );
180                         break;
181                 }
182
183                 // Delay enough so we don't run into the same packet (or the previous buffered packet)
184                 _delay_us(10000);
185         }
186
187         sei(); // Re-enable Interrupts
188 }
189
190 // Send data 
191 //
192 // Keyboard Input Guide for Micro Switch 8304
193 // 0xBX is for LED F1,F2,Over Type,Lock
194 // 0xAX is for LED F3,F8,F9,F10
195 // 0x92 resets keyboard (LED off, echo scancode mode off)
196 // 0x9E sets echo scancode mode from (0x81 to 0xFF; translates to 0x01 to 0x7F)
197 // Other echos: 0x15~0x19 send 0x15~0x19, 0x40 sends 0x40 (as well as 0x44,0x45, 0x80)
198 // 0x8C Acks the keyboard and gets 0x70 sent back (delayed)
199 uint8_t scan_sendData( uint8_t dataPayload )
200 {
201         UDR1 = dataPayload;
202         return 0;
203 }
204
205 // Signal KeyIndex_Buffer that it has been properly read
206 // In the case of the Micro Switch 8304, we leave the buffer alone until more scancode data comes in
207 void scan_finishedWithBuffer( void )
208 {
209         // We received a Clear code from the 8304, clear the buffer now that we've used it
210         if ( BufferReadyToClear )
211         {
212                 KeyIndex_BufferUsed = 0;
213                 BufferReadyToClear = 0;
214         }
215 }
216
217 // Reset/Hold keyboard
218 // Warning! This will cause the keyboard to not send any data, so you can't disable with a keypress
219 // The Micro Switch 8304 has a dedicated reset line
220 void scan_lockKeyboard( void )
221 {
222         UNSET_RESET();
223 }
224
225 void scan_unlockKeyboard( void )
226 {
227         SET_RESET();
228 }
229
230 // Reset Keyboard
231 void scan_resetKeyboard( void )
232 {
233         // Reset command for the 8304
234         scan_sendData( 0x92 );
235 }
236