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.

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