Kiibohd Controller
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
Este repositório está arquivado. Você pode visualizar os arquivos e realizar clone, mas não poderá realizar push nem abrir issues e pull requests.

scan_loop.c 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /* Copyright (C) 2012 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. // Pinout Defines
  31. #define DATA_PORT PORTC
  32. #define DATA_DDR DDRC
  33. #define DATA_PIN 7
  34. #define DATA_OUT PINC
  35. #define CLOCK_PORT PORTC
  36. #define CLOCK_DDR DDRC
  37. #define CLOCK_PIN 6
  38. #define RESET_PORT PORTF
  39. #define RESET_DDR DDRF
  40. #define RESET_PIN 7
  41. // ----- Macros -----
  42. // Make sure we haven't overflowed the buffer
  43. #define bufferAdd(byte) \
  44. if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
  45. KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
  46. // ----- Variables -----
  47. // Buffer used to inform the macro processing module which keys have been detected as pressed
  48. volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
  49. volatile uint8_t KeyIndex_BufferUsed;
  50. volatile uint8_t KeyIndex_Add_InputSignal; // Used to pass the (click/input value) to the keyboard for the clicker
  51. volatile uint8_t currentWaveState = 0;
  52. volatile uint8_t positionCounter = 0;
  53. volatile uint8_t statePositionCounter = 0;
  54. volatile uint16_t stateSamplesTotal = 0;
  55. volatile uint16_t stateSamples = 0;
  56. // Buffer Signals
  57. volatile uint8_t BufferReadyToClear;
  58. // ----- Function Declarations -----
  59. void processKeyValue( uint8_t keyValue );
  60. void removeKeyValue( uint8_t keyValue );
  61. // ----- Interrupt Functions -----
  62. // Generates a constant external clock
  63. ISR( TIMER1_COMPA_vect )
  64. {
  65. if ( currentWaveState )
  66. {
  67. CLOCK_PORT &= ~(1 << CLOCK_PIN);
  68. currentWaveState--; // Keeps track of the clock value (for direct clock output)
  69. statePositionCounter = positionCounter;
  70. positionCounter++; // Counts the number of falling edges, reset is done by the controlling section (reset, or main scan)
  71. }
  72. else
  73. {
  74. CLOCK_PORT |= (1 << CLOCK_PIN);
  75. currentWaveState++;
  76. }
  77. }
  78. // ----- Functions -----
  79. // Setup
  80. inline void scan_setup()
  81. {
  82. // Setup Timer Pulse (16 bit)
  83. // TODO Clock can be adjusted to whatever (read chip datasheets for limits)
  84. // This seems like a good scan speed, as there don't seem to be any periodic
  85. // de-synchronization events, and is fast enough for scanning keys
  86. // Anything much more (100k baud), tends to cause a lot of de-synchronization
  87. // 16 MHz / (2 * Prescaler * (1 + OCR1A)) = 10k baud
  88. // Prescaler is 1
  89. cli();
  90. TCCR1B = 0x09;
  91. OCR1AH = 0x03;
  92. OCR1AL = 0x1F;
  93. TIMSK1 = (1 << OCIE1A);
  94. CLOCK_DDR |= (1 << CLOCK_PIN); // Set the clock pin as an output
  95. DATA_PORT |= (1 << DATA_PIN); // Pull-up resistor for input the data line
  96. sei();
  97. // Initially buffer doesn't need to be cleared (it's empty...)
  98. BufferReadyToClear = 0;
  99. // Reset the keyboard before scanning, we might be in a wierd state
  100. scan_resetKeyboard();
  101. }
  102. // Main Detection Loop
  103. // Since this function is non-interruptable, we can do checks here on what stage of the
  104. // output clock we are at (0 or 1)
  105. // We are looking for a start of packet
  106. // If detected, all subsequent bits are then logged into a variable
  107. // Once the end of the packet has been detected (always the same length), decode the pressed keys
  108. inline uint8_t scan_loop()
  109. {
  110. // Only use as a valid signal
  111. // Check if there was a position change
  112. if ( positionCounter != statePositionCounter )
  113. {
  114. // At least 80% of the samples must be valid
  115. if ( stateSamples * 100 / stateSamplesTotal >= 80 )
  116. {
  117. // Reset the scan counter, all the keys have been iterated over
  118. // Ideally this should reset at 128, however
  119. // due to noise in the cabling, this often moves around
  120. // The minimum this can possibly set to is 124 as there
  121. // are keys to service at 123 (0x78)
  122. // Usually, unless there is lots of interference,
  123. // this should limit most of the noise.
  124. if ( positionCounter >= 124 )
  125. {
  126. positionCounter = 0;
  127. }
  128. // Key Press Detected
  129. // - Skip 0x00 to 0x0B (11) for better jitter immunity (as there are no keys mapped to those scancodes)
  130. else if ( positionCounter > 0x0B )
  131. {
  132. char tmp[15];
  133. hexToStr( positionCounter, tmp );
  134. dPrintStrsNL( "Key: ", tmp );
  135. // Make sure there aren't any duplicate keys
  136. uint8_t c;
  137. for ( c = 0; c < KeyIndex_BufferUsed; c++ )
  138. if ( KeyIndex_Buffer[c] == positionCounter )
  139. break;
  140. // No duplicate keys, add it to the buffer
  141. if ( c == KeyIndex_BufferUsed )
  142. bufferAdd( positionCounter );
  143. }
  144. }
  145. // Remove the key from the buffer
  146. else if ( positionCounter < 124 && positionCounter > 0x0B )
  147. {
  148. // Check for the released key, and shift the other keys lower on the buffer
  149. uint8_t c;
  150. for ( c = 0; c < KeyIndex_BufferUsed; c++ )
  151. {
  152. // Key to release found
  153. if ( KeyIndex_Buffer[c] == positionCounter )
  154. {
  155. // Shift keys from c position
  156. for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
  157. KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
  158. // Decrement Buffer
  159. KeyIndex_BufferUsed--;
  160. break;
  161. }
  162. }
  163. }
  164. // Clear the state counters
  165. stateSamples = 0;
  166. stateSamplesTotal = 0;
  167. statePositionCounter = positionCounter;
  168. }
  169. // Pull in a data sample for this read instance
  170. if ( DATA_OUT & (1 <<DATA_PIN) )
  171. stateSamples++;
  172. stateSamplesTotal++;
  173. // Check if the clock de-synchronized
  174. // And reset
  175. if ( positionCounter > 128 )
  176. {
  177. char tmp[15];
  178. hexToStr( positionCounter, tmp );
  179. erro_dPrint( "De-synchronization detected at: ", tmp );
  180. errorLED( 1 );
  181. positionCounter = 0;
  182. KeyIndex_BufferUsed = 0;
  183. // Clear the state counters
  184. stateSamples = 0;
  185. stateSamplesTotal = 0;
  186. // A keyboard reset requires interrupts to be enabled
  187. sei();
  188. scan_resetKeyboard();
  189. cli();
  190. }
  191. // Regardless of what happens, always return 0
  192. return 0;
  193. }
  194. // Send data
  195. uint8_t scan_sendData( uint8_t dataPayload )
  196. {
  197. return 0;
  198. }
  199. // Signal KeyIndex_Buffer that it has been properly read
  200. void scan_finishedWithBuffer( uint8_t sentKeys )
  201. {
  202. }
  203. // Signal that the keys have been properly sent over USB
  204. void scan_finishedWithUSBBuffer( uint8_t sentKeys )
  205. {
  206. }
  207. // Reset/Hold keyboard
  208. // NOTE: Does nothing with the HP150
  209. void scan_lockKeyboard( void )
  210. {
  211. }
  212. // NOTE: Does nothing with the HP150
  213. void scan_unlockKeyboard( void )
  214. {
  215. }
  216. // Reset Keyboard
  217. void scan_resetKeyboard( void )
  218. {
  219. info_print("Attempting to synchronize the keyboard, do not press any keys...");
  220. errorLED( 1 );
  221. // Do a proper keyboard reset (flushes the ripple counters)
  222. RESET_PORT |= (1 << RESET_PIN);
  223. _delay_us(10);
  224. RESET_PORT &= ~(1 << RESET_PIN);
  225. // Delay main keyboard scanning, until the bit counter is synchronized
  226. uint8_t synchronized = 0;
  227. while ( !synchronized )
  228. {
  229. // Only use as a valid signal
  230. // Check if there was a position change
  231. if ( positionCounter != statePositionCounter )
  232. {
  233. // At least 80% of the samples must be valid
  234. if ( stateSamples * 100 / stateSamplesTotal >= 80 )
  235. {
  236. // Read the current data value
  237. if ( DATA_OUT & (1 << DATA_PIN) )
  238. {
  239. // Check if synchronized
  240. // There are 128 positions to scan for with the HP150 keyboard protocol
  241. if ( positionCounter == 128 )
  242. synchronized = 1;
  243. positionCounter = 0;
  244. }
  245. }
  246. // Clear the state counters
  247. stateSamples = 0;
  248. stateSamplesTotal = 0;
  249. statePositionCounter = positionCounter;
  250. }
  251. }
  252. info_print("Keyboard Synchronized!");
  253. }