1 /* Copyright (C) 2011 by Jacob Alexander
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:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
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
22 // ----- Includes -----
25 #include <avr/interrupt.h>
27 #include <util/delay.h>
34 #include "scan_loop.h"
38 // ----- Defines -----
41 #define RESET_PORT PORTB
42 #define RESET_DDR DDRD
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
53 #define UNSET_RESET() RESET_DDR &= ~(1 << RESET_PIN)
54 #define SET_RESET() RESET_DDR |= (1 << RESET_PIN)
58 // ----- Variables -----
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;
66 volatile uint8_t BufferReadyToClear;
70 // ----- Functions -----
73 inline void scan_setup()
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
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;
86 // Enable the receiver, transitter, and RX Complete Interrupt
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
95 // Initially buffer doesn't need to be cleared (it's empty...)
96 BufferReadyToClear = 0;
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();
104 // Main Detection Loop
105 // Not needed for the Micro Switch 8304, this is just a busy loop
106 inline uint8_t scan_loop()
111 void processKeyValue( uint8_t keyValue )
113 // Finalize output buffer
117 // Interpret scan code
120 case 0x40: // Clear buffer command
121 info_print("CLEAR!");
123 BufferReadyToClear = 1;
128 scan_unlockKeyboard();
131 // Make sure the key isn't already in the buffer
132 for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
134 // Key isn't in the buffer yet
135 if ( c == KeyIndex_BufferUsed )
137 bufferAdd( keyValue );
141 // Key already in the buffer
142 if ( KeyIndex_Buffer[c] == keyValue )
149 // USART Receive Buffer Full Interrupt
152 cli(); // Disable Interrupts
154 uint8_t keyValue = 0x00;
156 // The interrupt is always for the first item of the packet set, reset the buffer
157 KeyIndex_BufferUsed = 0;
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
162 // Interrupts are too slow for the rest of the packet set, poll for the rest
165 // Read the raw packet from the USART
170 hexToStr( keyValue, tmpStr );
171 dPrintStrs( tmpStr, " " );
173 // Process the scancode
174 processKeyValue( keyValue );
176 // Last packet of the set
177 if ( keyValue & 0x80 )
183 // Delay enough so we don't run into the same packet (or the previous buffered packet)
187 sei(); // Re-enable Interrupts
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 )
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 )
209 // We received a Clear code from the 8304, clear the buffer now that we've used it
210 if ( BufferReadyToClear )
212 KeyIndex_BufferUsed = 0;
213 BufferReadyToClear = 0;
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 )
225 void scan_unlockKeyboard( void )
231 void scan_resetKeyboard( void )
233 // Reset command for the 8304
234 scan_sendData( 0x92 );