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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /* Copyright (C) 2013 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. // AVR Includes
  23. #include <avr/interrupt.h>
  24. #include <avr/io.h>
  25. #include <util/delay.h>
  26. // Project Includes
  27. #include <led.h>
  28. #include <print.h>
  29. // Local Includes
  30. #include "scan_loop.h"
  31. // ----- Defines -----
  32. // ----- Macros -----
  33. // Make sure we haven't overflowed the buffer
  34. #define bufferAdd(byte) \
  35. if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
  36. KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
  37. // ----- Variables -----
  38. // Buffer used to inform the macro processing module which keys have been detected as pressed
  39. volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
  40. volatile uint8_t KeyIndex_BufferUsed;
  41. volatile uint8_t KeyBufferRemove[6];
  42. volatile uint8_t KeyBufferRemoveCount = 0;
  43. static uint8_t KeyBuffer[3];
  44. volatile static uint8_t KeyBufferCount = 0;
  45. // ----- Function Declarations -----
  46. void processKeyValue( uint8_t valueType, uint8_t keyValue );
  47. void removeKeyValue( uint8_t keyValue );
  48. // ----- Interrupt Functions -----
  49. // USART Receive Buffer Full Interrupt
  50. ISR(USART1_RX_vect)
  51. {
  52. cli(); // Disable Interrupts
  53. // Read part of the scan code (3 8bit chunks) from USART
  54. KeyBuffer[KeyBufferCount] = UDR1;
  55. if ( KeyBufferCount >= 2 )
  56. {
  57. // Debug
  58. for ( uint8_t c = 0; c <= 2; c++ )
  59. {
  60. // Debug
  61. char tmpStr[6];
  62. hexToStr( KeyBuffer[c], tmpStr );
  63. dPrintStrs( tmpStr, " " ); // Debug
  64. }
  65. print("\n");
  66. processKeyValue( KeyBuffer[1], KeyBuffer[2] );
  67. KeyBufferCount = 0;
  68. }
  69. else
  70. {
  71. KeyBufferCount++;
  72. }
  73. sei(); // Re-enable Interrupts
  74. }
  75. // ----- Functions -----
  76. // Setup
  77. inline void scan_setup()
  78. {
  79. // Setup the the USART interface for keyboard data input
  80. // NOTE: The input data signal needs to be inverted for the Teensy USART to properly work
  81. // Setup baud rate
  82. // 16 MHz / ( 16 * Baud ) = UBRR
  83. // Baud: 4817 -> 16 MHz / ( 16 * 4817 ) = 207.5981
  84. // Thus baud setting = 208
  85. uint16_t baud = 208; // Max setting of 4095
  86. UBRR1H = (uint8_t)(baud >> 8);
  87. UBRR1L = (uint8_t)baud;
  88. // Enable the receiver, transmitter, and RX Complete Interrupt
  89. UCSR1B = 0x98;
  90. // Set frame format: 8 data, 1 stop bit, odd parity
  91. // Asynchrounous USART mode
  92. UCSR1C = 0x36;
  93. // Reset the keyboard before scanning, we might be in a wierd state
  94. scan_resetKeyboard();
  95. }
  96. // Main Detection Loop
  97. inline uint8_t scan_loop()
  98. {
  99. // Remove any "released keys", this is delayed due to buffer release synchronization issues
  100. for ( uint8_t c = 0; c < KeyBufferRemoveCount; c++ )
  101. {
  102. removeKeyValue( KeyBufferRemove[c] );
  103. }
  104. KeyBufferRemoveCount = 0;
  105. return 0;
  106. }
  107. void processKeyValue( uint8_t valueType, uint8_t keyValue )
  108. {
  109. switch ( valueType )
  110. {
  111. // Single Key Press
  112. case 0x00:
  113. break;
  114. // Repeated Key Press
  115. case 0x01:
  116. break;
  117. // Modifier Key Release
  118. case 0x02:
  119. KeyBufferRemove[KeyBufferRemoveCount++] = keyValue;
  120. return;
  121. }
  122. // Make sure the key isn't already in the buffer
  123. for ( uint8_t c = 0; c < KeyIndex_BufferUsed + 1; c++ )
  124. {
  125. // Key isn't in the buffer yet
  126. if ( c == KeyIndex_BufferUsed )
  127. {
  128. bufferAdd( keyValue );
  129. break;
  130. }
  131. // Key already in the buffer
  132. if ( KeyIndex_Buffer[c] == keyValue )
  133. break;
  134. }
  135. }
  136. void removeKeyValue( uint8_t keyValue )
  137. {
  138. // Check for the released key, and shift the other keys lower on the buffer
  139. uint8_t c;
  140. for ( c = 0; c < KeyIndex_BufferUsed; c++ )
  141. {
  142. // Key to release found
  143. if ( KeyIndex_Buffer[c] == keyValue )
  144. {
  145. // Shift keys from c position
  146. for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
  147. KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
  148. // Decrement Buffer
  149. KeyIndex_BufferUsed--;
  150. break;
  151. }
  152. }
  153. // Error case (no key to release)
  154. if ( c == KeyIndex_BufferUsed + 1 )
  155. {
  156. errorLED( 1 );
  157. char tmpStr[6];
  158. hexToStr( keyValue, tmpStr );
  159. erro_dPrint( "Could not find key to release: ", tmpStr );
  160. }
  161. }
  162. // Send data
  163. uint8_t scan_sendData( uint8_t dataPayload )
  164. {
  165. // Debug
  166. char tmpStr[6];
  167. hexToStr( dataPayload, tmpStr );
  168. info_dPrint( "Sending - ", tmpStr );
  169. UDR1 = dataPayload;
  170. return 0;
  171. }
  172. // Signal KeyIndex_Buffer that it has been properly read
  173. void scan_finishedWithBuffer( uint8_t sentKeys )
  174. {
  175. // Make sure we aren't in the middle of a receiving a new scancode
  176. while ( KeyBufferCount != 0 );
  177. cli(); // Disable Interrupts
  178. // Count for number of modifiers to maintain in the buffer
  179. uint8_t filled = 0;
  180. uint8_t latched = 0;
  181. uint8_t latchBuffer[13]; // There are only 13 keys that can possibly be latched at the same time...
  182. uint8_t normal = 0;
  183. uint8_t prevBuffer = KeyIndex_BufferUsed;
  184. // Clean out all keys except "special" keys (designated modifiers)
  185. uint8_t key;
  186. for ( key = 0; key < sentKeys; key++ )
  187. {
  188. switch ( KeyIndex_Buffer[key] )
  189. {
  190. // Dedicated Modifier Keys
  191. // NOTE: Both shifts are represented as the same scan code
  192. case 0x04:
  193. case 0x05:
  194. case 0x12:
  195. KeyIndex_Buffer[filled++] = KeyIndex_Buffer[key];
  196. break;
  197. // Latched Keys, only released if a non-modifier is pressed along with it
  198. // NOTE: This keys do not have a built in repeating
  199. case 0x00:
  200. case 0x01:
  201. case 0x03:
  202. case 0x0B:
  203. case 0x22:
  204. case 0x10:
  205. case 0x11:
  206. case 0x20:
  207. case 0x21:
  208. case 0x30:
  209. case 0x31:
  210. case 0x40:
  211. //case 0x41: // XXX Being used as ESC
  212. latchBuffer[latched++] = KeyIndex_Buffer[key];
  213. break;
  214. // Allow the scancode to be removed, normal keys
  215. default:
  216. normal++;
  217. break;
  218. }
  219. }
  220. // Reset the buffer counter
  221. KeyIndex_BufferUsed = filled;
  222. // Add back lost keys, so they are processed on the next USB send
  223. for ( ; key < prevBuffer; key++ )
  224. {
  225. bufferAdd( KeyIndex_Buffer[key] );
  226. info_print("Re-appending lost key after USB send...");
  227. }
  228. // Only "re-add" the latched keys if they weren't used
  229. if ( latched > 0 && normal == 0 )
  230. {
  231. for ( uint8_t c = 0; c < latched; c++ )
  232. {
  233. bufferAdd( latchBuffer[c] );
  234. }
  235. }
  236. sei(); // Re-enable Interrupts
  237. }
  238. // Signal that the keys have been properly sent over USB
  239. void scan_finishedWithUSBBuffer( uint8_t sentKeys )
  240. {
  241. }
  242. // Reset/Hold keyboard
  243. // NOTE: Does nothing with the FACOM6684
  244. void scan_lockKeyboard( void )
  245. {
  246. }
  247. // NOTE: Does nothing with the FACOM6684
  248. void scan_unlockKeyboard( void )
  249. {
  250. }
  251. // Reset Keyboard
  252. void scan_resetKeyboard( void )
  253. {
  254. // Not a calculated valued...
  255. _delay_ms( 50 );
  256. KeyBufferCount = 0;
  257. KeyBufferRemoveCount = 0;
  258. KeyIndex_BufferUsed = 0;
  259. }