]> git.donarmstrong.com Git - kiibohd-controller.git/blob - main.c
Adding basic CLI functionality.
[kiibohd-controller.git] / main.c
1 /* Copyright (C) 2011-2014 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/MainLib.h>
26
27 // Project Includes
28 #include <macro.h>
29 #include <scan_loop.h>
30 #include <output_com.h>
31
32 #include <cli.h>
33 #include <led.h>
34 #include <print.h>
35
36
37
38 // ----- Defines -----
39
40 // Verified Keypress Defines
41 #define USB_TRANSFER_DIVIDER 10 // 1024 == 1 Send of keypresses per second, 1 == 1 Send of keypresses per ~1 millisecond
42
43
44
45 // ----- Macros -----
46 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
47 #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
48 #endif
49
50
51
52 // ----- Variables -----
53
54 // Timer Interrupt for flagging a send of the sampled key detection data to the USB host
55 uint16_t sendKeypressCounter = 0;
56
57 // Flag generated by the timer interrupt
58 volatile uint8_t sendKeypresses = 0;
59
60
61
62 // ----- Functions -----
63
64 // Initial Pin Setup, make sure they are sane
65 inline void pinSetup(void)
66 {
67
68 // AVR
69 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
70
71         // For each pin, 0=input, 1=output
72 #if defined(__AVR_AT90USB1286__)
73         DDRA = 0x00;
74 #endif
75         DDRB = 0x00;
76         DDRC = 0x00;
77         DDRD = 0x00;
78         DDRE = 0x00;
79         DDRF = 0x00;
80
81
82         // Setting pins to either high or pull-up resistor
83 #if defined(__AVR_AT90USB1286__)
84         PORTA = 0x00;
85 #endif
86         PORTB = 0x00;
87         PORTC = 0x00;
88         PORTD = 0x00;
89         PORTE = 0x00;
90         PORTF = 0x00;
91
92 // ARM
93 #elif defined(_mk20dx128_)
94         // TODO - Should be cleared, but not that necessary due to the pin layout
95 #endif
96 }
97
98
99 inline void usbTimerSetup(void)
100 {
101 // AVR
102 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
103
104         // Setup with 16 MHz clock
105         CPU_PRESCALE( 0 );
106
107         // Setup ISR Timer for flagging a kepress send to USB
108         // Set to 256 * 1024 (8 bit timer with Clock/1024 prescalar) timer
109         TCCR0A = 0x00;
110         TCCR0B = 0x03;
111         TIMSK0 = (1 << TOIE0);
112
113 // ARM
114 #elif defined(_mk20dx128_)
115         // 48 MHz clock by default
116
117         // System Clock Gating Register Disable
118         SIM_SCGC6 |= SIM_SCGC6_PIT;
119
120         // Enable Timers
121         PIT_MCR = 0x00;
122
123         // Setup ISR Timer for flagging a kepress send to USB
124         // 1 ms / (1 / 48 MHz) - 1 = 47999 cycles -> 0xBB7F
125         PIT_LDVAL0 = 0x0000BB7F;
126         PIT_TCTRL0 = 0x3; // Enable Timer 0 interrupts, and Enable Timer 0
127
128         // Insert the required vector for Timer 0
129         NVIC_ENABLE_IRQ( IRQ_PIT_CH0 );
130 #endif
131 }
132
133
134 int main(void)
135 {
136         // Configuring Pins
137         pinSetup();
138         init_errorLED();
139
140         // Setup Output Module
141         output_setup();
142
143         // Enable CLI
144         init_cli();
145
146         // Setup ISR Timer for flagging a kepress send to USB
147         usbTimerSetup();
148
149         // Main Detection Loop
150         uint8_t ledTimer = F_CPU / 1000000; // Enable LED for a short time
151         while ( 1 )
152         {
153                 // Setup the scanning module
154                 scan_setup();
155
156                 while ( 1 )
157                 {
158                         // Acquire Key Indices
159                         // Loop continuously until scan_loop returns 0
160                         cli();
161                         while ( scan_loop() );
162                         sei();
163
164                         // Run Macros over Key Indices and convert to USB Keys
165                         process_macros();
166
167                         // Send keypresses over USB if the ISR has signalled that it's time
168                         if ( !sendKeypresses )
169                                 continue;
170
171                         // Send USB Data
172                         usb_send();
173
174                         // Clear sendKeypresses Flag
175                         sendKeypresses = 0;
176
177                         // Indicate Error, if valid
178                         errorLED( ledTimer );
179
180                         if ( ledTimer > 0 )
181                                 ledTimer--;
182                 }
183
184                 // Loop should never get here (indicate error)
185                 ledTimer = 255;
186
187                 // HID Debug Error message
188                 erro_print("Detection loop error, this is very bad...bug report!");
189         }
190 }
191
192
193 // ----- Interrupts -----
194
195 // USB Keyboard Data Send Counter Interrupt
196 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
197 ISR( TIMER0_OVF_vect )
198 #elif defined(_mk20dx128_) // ARM
199 void pit0_isr(void)
200 #endif
201 {
202         sendKeypressCounter++;
203         if ( sendKeypressCounter > USB_TRANSFER_DIVIDER ) {
204                 sendKeypressCounter = 0;
205                 sendKeypresses = 1;
206         }
207
208 #if defined(_mk20dx128_) // ARM
209         // Clear the interrupt flag
210         PIT_TFLG0 = 1;
211 #endif
212 }
213