]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/MicroSwitch8304/scan_loop.c
Adding support for the Micro Switch 8304 Hall Effect Keyboard
[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 = 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
99
100 // Main Detection Loop
101 // Not needed for the Micro Switch 8304, this is just a busy loop
102 inline uint8_t scan_loop()
103 {
104         return 0;
105 }
106
107 void processKeyValue( uint8_t keyValue )
108 {
109         // Finalize output buffer
110         // Mask 8th bit
111         keyValue &= 0x7F;
112
113         // Interpret scan code
114         switch ( keyValue )
115         {
116         case 0x40: // Clear buffer command
117                 info_print("CLEAR!");
118
119                 BufferReadyToClear = 1;
120                 break;
121         case 0x7F:
122                 scan_lockKeyboard();
123                 _delay_ms(3000);
124                 scan_unlockKeyboard();
125
126         default:
127                 // Make sure the key isn't already in the buffer
128                 for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
129                 {
130                         // Key isn't in the buffer yet
131                         if ( c == KeyIndex_BufferUsed )
132                         {
133                                 bufferAdd( keyValue );
134                                 break;
135                         }
136
137                         // Key already in the buffer
138                         if ( KeyIndex_Buffer[c] == keyValue )
139                                 break;
140                 }
141                 break;
142         }
143 }
144
145 // USART Receive Buffer Full Interrupt
146 ISR(USART1_RX_vect)
147 {
148         cli(); // Disable Interrupts
149
150         uint8_t keyValue = 0x00;
151
152         // The interrupt is always for the first item of the packet set, reset the buffer
153         KeyIndex_BufferUsed = 0;
154
155         // Only the first 7 bits have scancode data
156         // The last packet of the packet set has the 8th bit high, all the others are low
157         //
158         // Interrupts are too slow for the rest of the packet set, poll for the rest
159         while ( 1 )
160         {
161                 // Read the raw packet from the USART
162                 keyValue = UDR1;
163
164                 // Debug
165                 char tmpStr[6];
166                 hexToStr( keyValue, tmpStr );
167                 dPrintStrs( tmpStr, " " );
168
169                 // Process the scancode
170                 processKeyValue( keyValue );
171
172                 // Last packet of the set
173                 if ( keyValue & 0x80 )
174                 {
175                         dPrintStrs( "**" );
176                         break;
177                 }
178
179                 // Delay enough so we don't run into the same packet (or the previous buffered packet)
180                 _delay_us(10000);
181         }
182
183         sei(); // Re-enable Interrupts
184 }
185
186 // Send data 
187 //
188 // Keyboard Input Guide for Micro Switch 8304
189 // 0xBX is for LED F1,F2,Over Type,Lock
190 // 0xAX is for LED F3,F8,F9,F10
191 // 0x92 resets keyboard (LED off, echo scancode mode off)
192 // 0x9E sets echo scancode mode from (0x81 to 0xFF; translates to 0x01 to 0x7F)
193 // Other echos: 0x15~0x19 send 0x15~0x19, 0x40 sends 0x40 (as well as 0x44,0x45, 0x80)
194 // 0x8C Acks the keyboard and gets 0x70 sent back (delayed)
195 uint8_t scan_sendData( uint8_t dataPayload )
196 {
197         UDR1 = dataPayload;
198         return 0;
199 }
200
201 // Signal KeyIndex_Buffer that it has been properly read
202 // In the case of the Micro Switch 8304, we leave the buffer alone until more scancode data comes in
203 void scan_finishedWithBuffer( void )
204 {
205         // We received a Clear code from the 8304, clear the buffer now that we've used it
206         if ( BufferReadyToClear )
207         {
208                 KeyIndex_BufferUsed = 0;
209                 BufferReadyToClear = 0;
210         }
211 }
212
213 // Reset/Hold keyboard
214 // Warning! This will cause the keyboard to not send any data, so you can't disable with a keypress
215 // The Micro Switch 8304 has a dedicated reset line
216 void scan_lockKeyboard( void )
217 {
218         UNSET_RESET();
219 }
220
221 void scan_unlockKeyboard( void )
222 {
223         SET_RESET();
224 }
225