Kiibohd Controller
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
Это архивный репозиторий. Вы можете его клонировать или просматривать файлы, но не вносить изменения или открывать задачи/запросы на слияние.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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 REQUEST_PORT PORTD
  32. #define REQUEST_DDR DDRD
  33. #define REQUEST_PIN 3
  34. #define DATA_READ PIND
  35. #define DATA_PORT PORTD
  36. #define DATA_DDR DDRD
  37. #define DATA_PIN 2
  38. #define MAX_SAMPLES 10
  39. #define MAX_FAILURES 3731
  40. #define PACKET_STORAGE 24 // At worst only 8 packets, but with you keypresses you can get more
  41. // ----- Macros -----
  42. #define READ_DATA DATA_READ & (1 << DATA_PIN) ? 0 : 1
  43. #define REQUEST_DATA() REQUEST_DDR &= ~(1 << REQUEST_PIN) // Start incoming keyboard transfer
  44. #define STOP_DATA() REQUEST_DDR |= (1 << REQUEST_PIN) // Stop incoming keyboard data
  45. // Make sure we haven't overflowed the buffer
  46. #define bufferAdd(byte) \
  47. if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
  48. KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
  49. // ----- Variables -----
  50. // Buffer used to inform the macro processing module which keys have been detected as pressed
  51. volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
  52. volatile uint8_t KeyIndex_BufferUsed;
  53. // ----- Function Declarations -----
  54. void processPacketValue( uint16_t packetValue );
  55. // ----- Interrupt Functions -----
  56. // XXX - None Required
  57. // ----- Functions -----
  58. // Setup
  59. // This setup is very simple, as there is no extra hardware used in this scan module, other than GPIOs.
  60. // To be nice, we wait a little bit after powering on, and dump any of the pending keyboard data.
  61. // Afterwards (as long as no keys were being held), the keyboard should have a clean buffer, and be ready to go.
  62. // (Even if keys were held down, everything should probably still work...)
  63. inline void scan_setup()
  64. {
  65. // Setup the DATA pin
  66. DATA_DDR &= ~(1 << DATA_PIN); // Set to input
  67. DATA_PORT |= (1 << DATA_PIN); // Set to pull-up resistor
  68. // Setup the REQUEST pin
  69. REQUEST_PORT |= (1 << REQUEST_PIN); // Set to output
  70. STOP_DATA(); // Set the line high to stop incoming data
  71. REQUEST_DATA();
  72. DDRD |= (1 << 4);
  73. PORTD &= ~(1 << 4);
  74. // Message
  75. info_print("Pins Setup");
  76. // Reset the keyboard before scanning, we might be in a wierd state
  77. _delay_ms( 50 );
  78. //scan_resetKeyboard();
  79. // Message
  80. info_print("Keyboard Buffer Flushed");
  81. }
  82. // Main Detection Loop
  83. // The Univac-Sperry F3W9 has a convenient feature, an internal 8 key buffer
  84. // This buffer is only emptied (i.e. sent over the bus) when the REQUEST line is held high
  85. // Because of this, we can utilize the scan_loop to do all of the critical processing,
  86. // without having to resort to interrupts, giving the data reading 100% of the CPU.
  87. // This is because the USB interrupts can wait until the scan_loop is finished to continue.
  88. //
  89. // Normally, this approach isn't taken, as it's easier/faster/safer to use Teensy hardware shift registers
  90. // for serial data transfers.
  91. // However, since the Univac-Sperry F3W9 sends 20 bit packets (including the start bit), the Teensy
  92. // doesn't have a shift register large enough (9 bit max), to hold the data.
  93. // So the line must be polled manually using CPU cycles
  94. //
  95. // Another interesting feature is that there are 2 data lines.
  96. // Output and /Output (NOT'ted version).
  97. // Not really useful here, but could be used for error checking, or eliminating an external NOT gate if
  98. // we were using (but can't...) a hardware decoder like a USART.
  99. inline uint8_t scan_loop()
  100. {
  101. return 0;
  102. // Protocol Notes:
  103. // - Packets are 20 bits long, including the start bit
  104. // - Each bit is ~105 usecs in length
  105. // - Thus the average packet length is 2.205 msecs
  106. // - Each packet is separated by at least 240 usecs (during a buffer unload)
  107. // - While holding the key down, each packet has a space of about 910 usecs
  108. // - A max of 8 keys can be sent at once (note, the arrow keys seem use 2 packets each, and thus take up twice as much buffer)
  109. // - There is no timing danger for holding the request line, just that data may come in when you don't want it
  110. // Now that the scan loop has been entered, we don't have to worry about interrupts stealing
  111. // precious cycles.
  112. REQUEST_DATA();
  113. // = Delays =
  114. //
  115. // For these calculations to work out properly, then Teensy should be running at 16 MHz
  116. // - 1 bit : 105 usecs is 16 000 000 * 0.000105 = 1680 instructions
  117. // - Bit centering : 52.5 usecs is 16 000 000 * 0.0000525 = 840 instructions
  118. // - Delay : 5 msecs is 16 000 000 * 0.005 = 80 000 instructions
  119. // - Microsecond : 1 usec is 16 000 000 * 0.000001 = 16 instructions
  120. //
  121. // Now, either I can follow these exactly, or based upon the fact that I have >840 tries to find the
  122. // the start bit, and >1680 tries to read the subsequent bits, I have some "flex" time.
  123. // Knowing this, I can make some assumptions that because I'm only reading a total of 20 bits, and will
  124. // be re-centering for each packet.
  125. // This will allow for less worrying about compiler optimizations (and porting!).
  126. // The basic idea is to find a "reliable" value for the start bit, e.g. read it ~10 times.
  127. // Using a for-loop and some addition counters, this should eat up approximately 20-30 instructions per read
  128. // (very loose estimation).
  129. // So reading 10 * 30 instructions = 300 instructions, which is much less than 840 instructions to where the
  130. // bit center is, but is close enough that further delays of ~>1680 instructions will put the next read
  131. // within the next bit period.
  132. // This is all possible because interrupts are disabled at this point, otherwise, all of this reasoning
  133. // would fall apart.
  134. // _delay_us is available to use, fortunately.
  135. // Input Packet Storage (before being processed)
  136. uint16_t incomingPacket[PACKET_STORAGE];
  137. uint8_t numberOfIncomingPackets = 0;
  138. // Sample the data line for ~5 ms, looking for a start bit
  139. // - Sampling every 1 usecs, looking for 10 good samples
  140. // - Accumulated samples will dumped if a high is detected
  141. uint8_t samples = 0;
  142. uint16_t failures = 0;
  143. // Continue waiting for a start bit until MAX_FAILURES has been reached (~5ms of nothing)
  144. while ( failures <= MAX_FAILURES )
  145. {
  146. // Attempt to find the start bit
  147. while ( samples < MAX_SAMPLES )
  148. {
  149. // Delay first
  150. _delay_us( 1 );
  151. // If data is valid, increment
  152. if ( READ_DATA )
  153. {
  154. samples++;
  155. }
  156. // Reset
  157. else
  158. {
  159. samples = 0;
  160. failures++;
  161. // After ~5ms of failures, break the loop
  162. // Each failure is approx 5 instructions + 1 usec, or approximately 1.34 usec)
  163. // So ~3731 failures for ~5ms
  164. // Being exact doesn't matter, as this is just to let the other parts of the
  165. // controller do some processing
  166. if ( failures > MAX_FAILURES )
  167. break;
  168. }
  169. }
  170. // If 10 valid samples of the start bit were obtained,
  171. if ( samples >= MAX_SAMPLES )
  172. {
  173. // Clean out the old packet memory
  174. incomingPacket[numberOfIncomingPackets] = 0;
  175. // Read the next 19 bits into memory (bit 0 is the start bit, which is always 0)
  176. for ( uint8_t c = 1; c < 20; c++ )
  177. {
  178. // Wait until the middle of the next bit
  179. _delay_us( 105 );
  180. // Append the current bit value
  181. incomingPacket[numberOfIncomingPackets] |= (READ_DATA << c);
  182. }
  183. // Packet finished, increment counter
  184. numberOfIncomingPackets++;
  185. }
  186. }
  187. // Stop the keyboard input
  188. STOP_DATA();
  189. // Finished receiving data from keyboard, start packet processing
  190. for ( uint8_t packet = 0; packet < numberOfIncomingPackets; packet++ )
  191. processPacketValue( incomingPacket[packet] );
  192. return 0;
  193. }
  194. // Read in the Packet Data, and decide what to do with it
  195. void processPacketValue( uint16_t packetValue )
  196. {
  197. // = Packet Layout =
  198. //
  199. // A is the first bit received (bit 0), T is the last
  200. //
  201. // | Modifier? | ?? | Scan Code |
  202. // A B C D E F G H I J K L M N O P Q R S T
  203. //
  204. // A - Start bit
  205. // - Always Low
  206. // B -> H - Modifier enabled bits
  207. // - Each bit represents a different modifier "mode"
  208. // - B -> Shift/Lock
  209. // - C -> ??
  210. // - D -> Func
  211. // - E -> ??
  212. // - F -> ??
  213. // - G -> ??
  214. // - H -> ??
  215. // I -> L - ?? No idea yet...
  216. // - The bits change for some combinations, but not pattern has been found yet...
  217. // - I -> ??
  218. // - J -> ??
  219. // - K -> ??
  220. // - L -> ??
  221. // M -> T - Scan Code
  222. // - Bits are organized from low to high (8 bit value)
  223. // - M -> Bit 1
  224. // - N -> Bit 2
  225. // - O -> Bit 3
  226. // - P -> Bit 4
  227. // - Q -> Bit 5
  228. // - R -> Bit 6
  229. // - S -> Bit 7
  230. // - T -> Bit 8
  231. // Separate packet into sections
  232. uint8_t scanCode = (packetValue & 0xFF000) << 12;
  233. uint8_t modifiers = (packetValue & 0x000FE);
  234. uint8_t extra = (packetValue & 0x00F00) << 8;
  235. // Debug Info
  236. char tmpStr1[3];
  237. char tmpStr2[3];
  238. char tmpStr3[3];
  239. hexToStr_op( scanCode, tmpStr1, 2 );
  240. hexToStr_op( modifiers, tmpStr2, 2 );
  241. hexToStr_op( extra, tmpStr3, 2 );
  242. dbug_dPrint( "Scancode: 0x", tmpStr1, " Modifiers: 0x", tmpStr2, " Extra: 0x", tmpStr3 );
  243. dbug_dPrint( "Packet: 0x", tmpStr2, tmpStr3, tmpStr1 );
  244. // TODO List
  245. // - Modifier keys
  246. // - Key Release mechanism
  247. // Compute Modifier keys
  248. // TODO
  249. // Deal with special scan codes
  250. switch ( scanCode )
  251. {
  252. default:
  253. //bufferAdd( scanCode ); TODO - Uncomment when ready for USB output
  254. break;
  255. }
  256. }
  257. // Send data
  258. // NOTE: Does nothing with the Univac-Sperry F3W9
  259. uint8_t scan_sendData( uint8_t dataPayload )
  260. {
  261. return 0;
  262. }
  263. // Signal KeyIndex_Buffer that it has been properly read
  264. inline void scan_finishedWithBuffer( uint8_t sentKeys )
  265. {
  266. return;
  267. }
  268. // Signal that the keys have been properly sent over USB
  269. // TODO
  270. inline void scan_finishedWithUSBBuffer( uint8_t sentKeys )
  271. {
  272. /*
  273. uint8_t foundModifiers = 0;
  274. // Look for all of the modifiers present, there is a max of 8 (but only keys for 5 on the HASCI version)
  275. for ( uint8_t c = 0; c < KeyIndex_BufferUsed; c++ )
  276. {
  277. // The modifier range is from 0x80 to 0x8F (well, the last bit is the ON/OFF signal, but whatever...)
  278. if ( KeyIndex_Buffer[c] <= 0x8F && KeyIndex_Buffer[c] >= 0x80 )
  279. {
  280. // Add the modifier back into the the Key Buffer
  281. KeyIndex_Buffer[foundModifiers] = KeyIndex_Buffer[c];
  282. foundModifiers++;
  283. }
  284. }
  285. // Adjust the size of the new Key Buffer
  286. KeyIndex_BufferUsed = foundModifiers;
  287. */
  288. }
  289. // Reset/Hold keyboard
  290. // NOTE: Does nothing with the Univac-Sperry F3W9
  291. void scan_lockKeyboard( void )
  292. {
  293. }
  294. // NOTE: Does nothing with the Univac-Sperry F3W9
  295. void scan_unlockKeyboard( void )
  296. {
  297. }
  298. // Reset Keyboard
  299. // - Holds the input read line high to flush the buffer
  300. // - This does not actually reset the keyboard, but always seems brings it to a sane state
  301. // - Won't work fully if keys are being pressed done at the same time
  302. void scan_resetKeyboard( void )
  303. {
  304. // Initiate data request line, but don't read the incoming data
  305. REQUEST_DATA();
  306. // We shouldn't be receiving more than 8 packets (and maybe +1 error signal)
  307. // This is around 22 ms of data, so a delay of 50 ms should be sufficient.
  308. _delay_ms( 50 );
  309. // Stop request line
  310. STOP_DATA();
  311. }