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.

scan_loop.c 7.2KB

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