Kiibohd Controller
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

main.c 8.8KB

13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
13 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. // ----- Includes -----
  22. // Compiler Includes
  23. #include <Lib/MainLib.h>
  24. // Project Includes
  25. #include <macro.h>
  26. #include <scan_loop.h>
  27. #include <output_com.h>
  28. #include <cli.h>
  29. #include <led.h>
  30. #include <print.h>
  31. // ----- Defines -----
  32. // Verified Keypress Defines
  33. #define USB_TRANSFER_DIVIDER 10 // 1024 == 1 Send of keypresses per second, 1 == 1 Send of keypresses per ~1 millisecond
  34. // ----- Macros -----
  35. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
  36. #define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
  37. #endif
  38. // ----- Function Declarations -----
  39. void cliFunc_distRead ( char* args );
  40. void cliFunc_free ( char* args );
  41. void cliFunc_gaugeHelp ( char* args );
  42. void cliFunc_single ( char* args );
  43. void cliFunc_start ( char* args );
  44. void cliFunc_zeroForce ( char* args );
  45. void cliFunc_zeroPosition( char* args );
  46. // ----- Variables -----
  47. // Timer Interrupt for flagging a send of the sampled key detection data to the USB host
  48. uint16_t sendKeypressCounter = 0;
  49. // Flag generated by the timer interrupt
  50. volatile uint8_t sendKeypresses = 0;
  51. // ----- Functions -----
  52. // Initial Pin Setup, make sure they are sane
  53. inline void pinSetup(void)
  54. {
  55. // AVR
  56. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
  57. // For each pin, 0=input, 1=output
  58. #if defined(__AVR_AT90USB1286__)
  59. DDRA = 0x00;
  60. #endif
  61. DDRB = 0x00;
  62. DDRC = 0x00;
  63. DDRD = 0x00;
  64. DDRE = 0x00;
  65. DDRF = 0x00;
  66. // Setting pins to either high or pull-up resistor
  67. #if defined(__AVR_AT90USB1286__)
  68. PORTA = 0x00;
  69. #endif
  70. PORTB = 0x00;
  71. PORTC = 0x00;
  72. PORTD = 0x00;
  73. PORTE = 0x00;
  74. PORTF = 0x00;
  75. // ARM
  76. #elif defined(_mk20dx128_)
  77. // TODO - Should be cleared, but not that necessary due to the pin layout
  78. #endif
  79. }
  80. inline void usbTimerSetup(void)
  81. {
  82. // AVR
  83. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
  84. // Setup with 16 MHz clock
  85. CPU_PRESCALE( 0 );
  86. // Setup ISR Timer for flagging a kepress send to USB
  87. // Set to 256 * 1024 (8 bit timer with Clock/1024 prescalar) timer
  88. TCCR0A = 0x00;
  89. TCCR0B = 0x03;
  90. TIMSK0 = (1 << TOIE0);
  91. // ARM
  92. #elif defined(_mk20dx128_)
  93. // 48 MHz clock by default
  94. // System Clock Gating Register Disable
  95. SIM_SCGC6 |= SIM_SCGC6_PIT;
  96. // Enable Timers
  97. PIT_MCR = 0x00;
  98. // Setup ISR Timer for flagging a kepress send to USB
  99. // 1 ms / (1 / 48 MHz) - 1 = 47999 cycles -> 0xBB7F
  100. PIT_LDVAL0 = 0x0000BB7F;
  101. PIT_TCTRL0 = 0x3; // Enable Timer 0 interrupts, and Enable Timer 0
  102. // Insert the required vector for Timer 0
  103. NVIC_ENABLE_IRQ( IRQ_PIT_CH0 );
  104. #endif
  105. }
  106. int main(void)
  107. {
  108. // Configuring Pins
  109. pinSetup();
  110. init_errorLED();
  111. // Setup Output Module
  112. output_setup();
  113. // Enable CLI
  114. init_cli();
  115. // Setup ISR Timer for flagging a kepress send to USB
  116. usbTimerSetup();
  117. // Main Detection Loop
  118. uint8_t ledTimer = F_CPU / 1000000; // Enable LED for a short time
  119. while ( 1 )
  120. {
  121. // Setup the scanning module
  122. scan_setup();
  123. while ( 1 )
  124. {
  125. // Acquire Key Indices
  126. // Loop continuously until scan_loop returns 0
  127. cli();
  128. while ( scan_loop() );
  129. sei();
  130. // Run Macros over Key Indices and convert to USB Keys
  131. process_macros();
  132. // Send keypresses over USB if the ISR has signalled that it's time
  133. if ( !sendKeypresses )
  134. continue;
  135. // Send USB Data
  136. usb_send();
  137. // Clear sendKeypresses Flag
  138. sendKeypresses = 0;
  139. // Indicate Error, if valid
  140. errorLED( ledTimer );
  141. if ( ledTimer > 0 )
  142. ledTimer--;
  143. }
  144. // Loop should never get here (indicate error)
  145. ledTimer = 255;
  146. // HID Debug Error message
  147. erro_print("Detection loop error, this is very bad...bug report!");
  148. }
  149. }
  150. // ----- Interrupts -----
  151. // USB Keyboard Data Send Counter Interrupt
  152. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
  153. ISR( TIMER0_OVF_vect )
  154. #elif defined(_mk20dx128_) // ARM
  155. void pit0_isr(void)
  156. #endif
  157. {
  158. sendKeypressCounter++;
  159. if ( sendKeypressCounter > USB_TRANSFER_DIVIDER ) {
  160. sendKeypressCounter = 0;
  161. sendKeypresses = 1;
  162. }
  163. #if defined(_mk20dx128_) // ARM
  164. // Clear the interrupt flag
  165. PIT_TFLG0 = 1;
  166. #endif
  167. }
  168. // ----- CLI Command Functions -----
  169. uint32_t readDistanceGauge()
  170. {
  171. // Setup distance read parameters for iGaging Distance Scale
  172. // freq = 9kHz
  173. // duty_cycle = 20%
  174. // high_delay = (1/freq) * (duty_cycle/100)
  175. // low_delay = (1/freq) * ((100-duty_cycle)/100)
  176. uint8_t bits = 21; // 21 clock pulses, for 21 bits
  177. uint32_t high_delay = 22; // Clock high time per pulse
  178. uint32_t low_delay = 89; // Clock low time per pulse
  179. // Data
  180. uint32_t distInput = 0;
  181. // Make sure clock is low initially
  182. GPIOC_PCOR |= (1<<2); // Set Clock low
  183. // Scan each of the bits
  184. for ( uint8_t bit = 0; bit < bits; bit++ )
  185. {
  186. // Begin clock pulse
  187. GPIOC_PSOR |= (1<<2); // Set Clock high
  188. // Delay for duty cycle
  189. delayMicroseconds( high_delay );
  190. // End clock pulse
  191. GPIOC_PCOR |= (1<<2); // Set Clock low
  192. // Read Data Bit
  193. distInput |= GPIOC_PDIR & (1<<1) ? (1 << bit) : 0;
  194. // Delay for duty cycle
  195. delayMicroseconds( low_delay );
  196. }
  197. return distInput;
  198. }
  199. void cliFunc_distRead( char* args )
  200. {
  201. // Parse number from argument
  202. // NOTE: Only first argument is used
  203. char* arg1Ptr;
  204. char* arg2Ptr;
  205. argumentIsolation_cli( args, &arg1Ptr, &arg2Ptr );
  206. // Convert the argument into an int
  207. int read_count = decToInt( arg1Ptr ) + 1;
  208. // If no argument specified, default to 1 read
  209. if ( *arg1Ptr == '\0' )
  210. {
  211. read_count = 2;
  212. }
  213. // Repeat reading as many times as specified in the argument
  214. print( NL );
  215. while ( --read_count > 0 )
  216. {
  217. // Prepare to print output
  218. info_msg("Distance: ");
  219. // Data
  220. uint32_t distInput = readDistanceGauge();
  221. // Output result
  222. printInt32( distInput );
  223. // Convert to mm
  224. // As per http://www.shumatech.com/web/21bit_protocol?page=0,1
  225. // 21 bits is 2560 CPI (counts per inch) (C/inch)
  226. // 1 inch is 25.4 mm
  227. // 2560 / 25.4 = 100.7874016... CPMM (C/mm)
  228. // Or
  229. // 1 count is 1/2560 = 0.000390625... inches
  230. // 1 count is (1/2560) * 25.4 = 0.00992187500000000 mm = 9.92187500000000 um = 9921.87500000000 nm
  231. // Since there are 21 bits (2 097 152 positions) converting to um is possible by multiplying by 1000
  232. // which is 2 097 152 000, and within 32 bits (4 294 967 295).
  233. // However, um is still not convenient, so 64 bits (18 446 744 073 709 551 615) is a more accurate alternative.
  234. // For each nm there are 2 097 152 000 000 positions.
  235. // And for shits:
  236. // mm is 2 097 152 : 0.009 921 875 000 mm : 32 bit
  237. // um is 2 097 152 000 : 9.921 875 000 um : 32 bit (ideal acc. for 32 bit)
  238. // nm is 2 097 152 000 000 : 9 921.875 000 nm : 64 bit
  239. // pm is 2 097 152 000 000 000 : 9 921 875.000 pm : 64 bit (ideal acc. for 64 bit)
  240. // XXX Apparently shumatech was sorta wrong about the 21 bits of usage
  241. // Yes there are 21 bits, but the values only go from ~338 to ~30681 which is less than 16 bits...
  242. // This means that the conversion at NM can use 32 bits :D
  243. // It's been noted that the multiplier should be 100.6 (and that it could vary from scale to scale)
  244. uint32_t distNM = distInput * 9921;;
  245. uint32_t distUM = distNM / 1000;
  246. uint32_t distMM = distUM / 1000;
  247. print(" ");
  248. printInt32( distMM );
  249. print(" mm ");
  250. printInt32( distUM );
  251. print(" um ");
  252. printInt32( distNM );
  253. print(" nm ");
  254. print( NL );
  255. // Only delay if still counting
  256. if ( read_count > 1 )
  257. delay( 50 );
  258. }
  259. }
  260. void cliFunc_free( char* args )
  261. {
  262. }
  263. void cliFunc_gaugeHelp( char* args )
  264. {
  265. }
  266. void cliFunc_single( char* args )
  267. {
  268. }
  269. void cliFunc_start( char* args )
  270. {
  271. }
  272. void cliFunc_zeroForce( char* args )
  273. {
  274. }
  275. void cliFunc_zeroPosition( char* args )
  276. {
  277. }