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.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* Copyright (C) 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 <cli.h>
  26. #include <led.h>
  27. #include <print.h>
  28. // Local Includes
  29. #include "scan_loop.h"
  30. // ----- Defines -----
  31. // ADC Clock divisor settings (F_BUS == 48000000)
  32. #define ADC_CFG1_6MHZ ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1)
  33. #define ADC_CFG1_12MHZ ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1)
  34. #define ADC_CFG1_24MHZ ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1)
  35. // ----- Macros -----
  36. // ----- Function Declarations -----
  37. void cliFunc_adc ( char* args );
  38. void cliFunc_adcInit( char* args );
  39. void cliFunc_dac ( char* args );
  40. void cliFunc_dacVref( char* args );
  41. void cliFunc_echo ( char* args );
  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. // Scan Module command dictionary
  47. char scanCLIDictName[] = "ADC Test Module Commands";
  48. const CLIDictItem scanCLIDict[] = {
  49. #if defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
  50. { "adc", "Read the specified number of values from the ADC at the given pin: <pin> [# of reads]"
  51. NL "\t\t See \033[35mLib/pin_map.teensy3\033[0m for ADC0 channel number.", cliFunc_adc },
  52. { "adcInit", "Intialize/calibrate ADC: <ADC Resolution> <Vref> <Hardware averaging samples>"
  53. NL "\t\tADC Resolution -> 8, 10, 12, 16 (bit)"
  54. NL "\t\t Vref -> 0 (1.2 V), 1 (External)"
  55. NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit },
  56. #endif
  57. #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
  58. { "dac", "Set DAC output value, from 0 to 4095 (1/4096 Vref to Vref).", cliFunc_dac },
  59. { "dacVref", "Set DAC Vref. 0 is 1.2V. 1 is 3.3V.", cliFunc_dacVref },
  60. #endif
  61. { "echo", "Example command, echos the arguments.", cliFunc_echo },
  62. { 0, 0, 0 } // Null entry for dictionary end
  63. };
  64. // ----- Functions -----
  65. // Setup
  66. inline void Scan_setup()
  67. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
  68. {
  69. // Register Scan CLI dictionary
  70. CLI_registerDictionary( scanCLIDict, scanCLIDictName );
  71. }
  72. #elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
  73. {
  74. // Register Scan CLI dictionary
  75. CLI_registerDictionary( scanCLIDict, scanCLIDictName );
  76. // ADC Setup
  77. VREF_TRM = 0x60;
  78. VREF_SC = 0xE1; // Enable 1.2V Vref
  79. #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
  80. // DAC Setup
  81. SIM_SCGC2 |= SIM_SCGC2_DAC0;
  82. DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
  83. #endif
  84. }
  85. #endif
  86. // Main Detection Loop
  87. inline uint8_t Scan_loop()
  88. {
  89. return 0;
  90. }
  91. // Signal KeyIndex_Buffer that it has been properly read
  92. void Scan_finishedWithBuffer( uint8_t sentKeys )
  93. {
  94. }
  95. // Signal that the keys have been properly sent over USB
  96. void Scan_finishedWithUSBBuffer( uint8_t sentKeys )
  97. {
  98. }
  99. // Reset Keyboard
  100. void Scan_resetKeyboard()
  101. {
  102. }
  103. // ----- CLI Command Functions -----
  104. // XXX Just an example command showing how to parse arguments (more complex than generally needed)
  105. void cliFunc_echo( char* args )
  106. {
  107. char* curArgs;
  108. char* arg1Ptr;
  109. char* arg2Ptr = args;
  110. // Parse args until a \0 is found
  111. while ( 1 )
  112. {
  113. print( NL ); // No \r\n by default after the command is entered
  114. curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
  115. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  116. // Stop processing args if no more are found
  117. if ( *arg1Ptr == '\0' )
  118. break;
  119. // Print out the arg
  120. dPrint( arg1Ptr );
  121. }
  122. }
  123. void cliFunc_adc( char* args )
  124. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
  125. {
  126. }
  127. #elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
  128. {
  129. // Parse code from argument
  130. // NOTE: Only first argument is used
  131. char* arg1Ptr;
  132. char* arg2Ptr;
  133. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  134. // Set the ADC Channel
  135. uint8_t channel = numToInt( arg1Ptr );
  136. __disable_irq();
  137. ADC0_SC1A = channel;
  138. __enable_irq();
  139. // Number of ADC samples to display
  140. CLI_argumentIsolation( arg2Ptr, &arg1Ptr, &arg2Ptr );
  141. int displayedADC = 1; // Default to 1 read
  142. if ( arg1Ptr ) // If there is an argument, use that instead
  143. {
  144. displayedADC = numToInt( arg1Ptr );
  145. }
  146. // Poll ADC until it gets a value, making sure to serve interrupts on each attempt
  147. while ( displayedADC > 0 )
  148. {
  149. __disable_irq();
  150. // ADC Sample is ready
  151. if ( (ADC0_SC1A & ADC_SC1_COCO) )
  152. {
  153. int result = ADC0_RA;
  154. print( NL );
  155. printInt32( result );
  156. displayedADC--;
  157. // Prepare for another read
  158. if ( displayedADC > 0 )
  159. {
  160. ADC0_SC1A = channel;
  161. }
  162. }
  163. __enable_irq();
  164. yield(); // Make sure interrupts actually get serviced
  165. }
  166. }
  167. #endif
  168. void cliFunc_adcInit( char* args )
  169. #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
  170. {
  171. }
  172. #elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
  173. {
  174. // Parse code from argument
  175. // NOTE: Only first argument is used
  176. char* arg1Ptr;
  177. char* arg2Ptr;
  178. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  179. // Make sure calibration has stopped
  180. ADC0_SC3 = 0;
  181. // Select bit resolution
  182. int bitResolution = numToInt( arg1Ptr );
  183. switch ( bitResolution )
  184. {
  185. case 8: // 8-bit
  186. ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
  187. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  188. break;
  189. case 10: // 10-bit
  190. ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
  191. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
  192. break;
  193. case 12: // 12-bit
  194. ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
  195. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  196. break;
  197. case 16: // 16-bit
  198. ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
  199. ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
  200. break;
  201. default: return; // Do nothing, invalid arg
  202. }
  203. // Select Vref
  204. CLI_argumentIsolation( arg2Ptr, &arg1Ptr, &arg2Ptr );
  205. int vRef = numToInt( arg1Ptr );
  206. switch ( vRef )
  207. {
  208. case 0: // 1.2V internal Vref
  209. ADC0_SC2 = ADC_SC2_REFSEL(1);
  210. break;
  211. case 1: // Vcc/Ext Vref
  212. ADC0_SC2 = ADC_SC2_REFSEL(0);
  213. break;
  214. default: return; // Do nothing, invalid arg
  215. }
  216. // Hardware averaging (and start calibration)
  217. CLI_argumentIsolation( arg2Ptr, &arg1Ptr, &arg2Ptr );
  218. int hardwareAvg = numToInt( arg1Ptr );
  219. switch ( hardwareAvg )
  220. {
  221. case 0: // No hardware averaging
  222. ADC0_SC3 = ADC_SC3_CAL; // Just start calibration
  223. break;
  224. case 4: // 4 sample averaging
  225. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
  226. break;
  227. case 8: // 8 sample averaging
  228. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
  229. break;
  230. case 16: // 16 sample averaging
  231. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
  232. break;
  233. case 32: // 32 sample averaging
  234. ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
  235. break;
  236. default: return; // Do nothing, invalid arg
  237. }
  238. // Wait for calibration
  239. while ( ADC0_SC3 & ADC_SC3_CAL );
  240. // Set calibration
  241. uint16_t sum;
  242. // XXX Why is PJRC doing this? Is the self-calibration not good enough? -HaaTa
  243. // ADC Plus-Side Gain Register
  244. __disable_irq(); // Disable interrupts
  245. sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
  246. sum = (sum / 2) | 0x8000;
  247. ADC0_PG = sum;
  248. print( NL );
  249. info_msg("Calibration ADC0_PG (Plus-Side Gain Register) set to: ");
  250. printInt16( sum );
  251. // ADC Minus-Side Gain Register
  252. // XXX I don't think this is necessary when doing single-ended (as opposed to differential) -HaaTa
  253. // K20P64M72SF1RM.pdf 31.3.10 pg. 666
  254. sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0;
  255. sum = (sum / 2) | 0x8000;
  256. ADC0_MG = sum;
  257. print( NL );
  258. info_msg("Calibration ADC0_MG (Minus-Side Gain Register) set to: ");
  259. printInt16( sum );
  260. __enable_irq(); // Re-enable interrupts
  261. }
  262. #endif
  263. void cliFunc_dac( char* args )
  264. {
  265. #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
  266. // Parse code from argument
  267. // NOTE: Only first argument is used
  268. char* arg1Ptr;
  269. char* arg2Ptr;
  270. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  271. int dacOut = numToInt( arg1Ptr );
  272. // Make sure the value is between 0 and 4096, otherwise ignore
  273. if ( dacOut >= 0 && dacOut <= 4095 )
  274. {
  275. *(int16_t *) &(DAC0_DAT0L) = dacOut;
  276. }
  277. #endif
  278. }
  279. void cliFunc_dacVref( char* args )
  280. {
  281. #if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
  282. // Parse code from argument
  283. // NOTE: Only first argument is used
  284. char* arg1Ptr;
  285. char* arg2Ptr;
  286. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  287. switch ( numToInt( arg1Ptr ) )
  288. {
  289. case 0:
  290. DAC0_C0 = DAC_C0_DACEN; // 1.2V Vref is DACREF_1
  291. break;
  292. case 1:
  293. DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
  294. break;
  295. }
  296. #endif
  297. }