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 26KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /* Copyright (C) 2011-2013 by Joseph Makuch ([email protected])
  2. * Additions by Jacob Alexander (2013-2014) ([email protected])
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. // ----- Includes -----
  23. // Compiler Includes
  24. #include <Lib/ScanLib.h>
  25. // Project Includes
  26. #include <cli.h>
  27. #include <led.h>
  28. #include <macro.h>
  29. #include <print.h>
  30. // Local Includes
  31. #include "scan_loop.h"
  32. // ----- Defines -----
  33. // TODO dfj defines...needs commenting and maybe some cleaning...
  34. #define MAX_PRESS_DELTA_MV 450 // As measured from the Teensy ADC pin
  35. #define THRESHOLD_MV (MAX_PRESS_DELTA_MV >> 1)
  36. //(2560 / (0x3ff/2)) ~= 5
  37. #define MV_PER_ADC 5
  38. #define THRESHOLD (THRESHOLD_MV / MV_PER_ADC)
  39. #define STROBE_SETTLE 1
  40. #define ADHSM 7
  41. // Right justification of ADLAR
  42. #define ADLAR_BITS 0
  43. // full muxmask
  44. #define FULL_MUX_MASK ((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3) | (1 << MUX4))
  45. // F0-f7 pins only muxmask.
  46. #define MUX_MASK ((1 << MUX0) | (1 << MUX1) | (1 << MUX2))
  47. // Strobe Masks
  48. #define D_MASK (0xff)
  49. #define E_MASK (0x03)
  50. #define C_MASK (0xff)
  51. // set ADC clock prescale
  52. #define PRESCALE_MASK ((1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2))
  53. #define PRESCALE_SHIFT (ADPS0)
  54. #define PRESCALE 3
  55. // Max number of strobes supported by the hardware
  56. // Strobe lines are detected at startup, extra strobes cause anomalies like phantom keypresses
  57. #define MAX_STROBES 18
  58. // Number of consecutive samples required to pass debounce
  59. #define DEBOUNCE_THRESHOLD 5
  60. // Scans to remain idle after all keys were release before starting averaging
  61. // XXX So this makes the initial keypresses fast,
  62. // but it's still possible to lose a keypress if you press at the wrong time -HaaTa
  63. #define KEY_IDLE_SCANS 30000
  64. // Total number of muxes/sense lines available
  65. #define MUXES_COUNT 8
  66. #define MUXES_COUNT_XSHIFT 3
  67. // Number of warm-up loops before starting to scan keys
  68. #define WARMUP_LOOPS ( 1024 )
  69. #define WARMUP_STOP (WARMUP_LOOPS - 1)
  70. #define SAMPLE_CONTROL 3
  71. #define KEY_COUNT ((MAX_STROBES) * (MUXES_COUNT))
  72. #define RECOVERY_CONTROL 1
  73. #define RECOVERY_SOURCE 0
  74. #define RECOVERY_SINK 2
  75. #define ON 1
  76. #define OFF 0
  77. // mix in 1/4 of the current average to the running average. -> (@mux_mix = 2)
  78. #define MUX_MIX 2
  79. #define IDLE_COUNT_SHIFT 8
  80. // av = (av << shift) - av + sample; av >>= shift
  81. // e.g. 1 -> (av + sample) / 2 simple average of new and old
  82. // 2 -> (3 * av + sample) / 4 i.e. 3:1 mix of old to new.
  83. // 3 -> (7 * av + sample) / 8 i.e. 7:1 mix of old to new.
  84. #define KEYS_AVERAGES_MIX_SHIFT 3
  85. // ----- Macros -----
  86. // Select mux
  87. #define SET_FULL_MUX(X) ((ADMUX) = (((ADMUX) & ~(FULL_MUX_MASK)) | ((X) & (FULL_MUX_MASK))))
  88. // ----- Function Declarations -----
  89. // CLI Functions
  90. void cliFunc_avgDebug ( char* args );
  91. void cliFunc_echo ( char* args );
  92. void cliFunc_keyDebug ( char* args );
  93. void cliFunc_pressDebug ( char* args );
  94. void cliFunc_problemKeys( char* args );
  95. void cliFunc_senseDebug ( char* args );
  96. // Debug Functions
  97. void dumpSenseTable();
  98. // High-level Capsense Functions
  99. void setup_ADC();
  100. void capsense_scan();
  101. // Capsense Sense Functions
  102. void testColumn ( uint8_t strobe );
  103. void sampleColumn( uint8_t column );
  104. // Low-level Capsense Functions
  105. void strobe_w( uint8_t strobe_num );
  106. void recovery( uint8_t on );
  107. // ----- Variables -----
  108. // Scan Module command dictionary
  109. CLIDict_Entry( echo, "Example command, echos the arguments." );
  110. CLIDict_Entry( avgDebug, "Enables/Disables averaging results." NL "\t\tDisplays each average, starting from Key 0x00, ignoring 0 valued averages." );
  111. CLIDict_Entry( keyDebug, "Enables/Disables long debug for each keypress." NL "\t\tkeycode - [strobe:mux] : sense val : threshold+delta=total : margin" );
  112. CLIDict_Entry( pressDebug, "Enables/Disables short debug for each keypress." );
  113. CLIDict_Entry( problemKeys, "Display current list of problem keys," );
  114. CLIDict_Entry( senseDebug, "Prints out the current sense table N times." NL "\t\tsense:max sense:delta" );
  115. CLIDict_Def( scanCLIDict, "DPH Module Commands" ) = {
  116. CLIDict_Item( echo ),
  117. CLIDict_Item( avgDebug ),
  118. CLIDict_Item( keyDebug ),
  119. CLIDict_Item( pressDebug ),
  120. CLIDict_Item( problemKeys ),
  121. CLIDict_Item( senseDebug ),
  122. { 0, 0, 0 } // Null entry for dictionary end
  123. };
  124. // CLI Control Variables
  125. uint8_t enableAvgDebug = 0;
  126. uint8_t enableKeyDebug = 0;
  127. uint8_t enablePressDebug = 0;
  128. uint8_t senseDebugCount = 3; // In order to get boot-time oddities
  129. // Variables used to calculate the starting sense value (averaging)
  130. uint32_t full_avg = 0;
  131. uint32_t high_avg = 0;
  132. uint32_t low_avg = 0;
  133. uint8_t high_count = 0;
  134. uint8_t low_count = 0;
  135. uint16_t samples[MAX_STROBES][MUXES_COUNT]; // Overall table of cap sense ADC values
  136. uint16_t sampleMax[MAX_STROBES][MUXES_COUNT]; // Records the max seen ADC value
  137. uint8_t key_activity = 0; // Increments for each detected key per each full scan of the keyboard, it is reset before each full scan
  138. uint16_t key_idle = 0; // Defines how scans after all keys were released before starting averaging again
  139. uint8_t key_release = 0; // Indicates if going from key press state to release state (some keys pressed to no keys pressed)
  140. uint16_t threshold = THRESHOLD;
  141. uint16_t keys_averages_acc[KEY_COUNT];
  142. uint16_t keys_averages [KEY_COUNT];
  143. uint8_t keys_debounce [KEY_COUNT]; // Contains debounce statistics
  144. uint8_t keys_problem [KEY_COUNT]; // Marks keys that should be ignored (determined by averaging at startup)
  145. // TODO: change this to 'booting', then count down.
  146. uint16_t boot_count = 0;
  147. uint8_t total_strobes = MAX_STROBES;
  148. uint8_t strobe_map[MAX_STROBES];
  149. // ----- Functions -----
  150. // Initial setup for cap sense controller
  151. inline void Scan_setup()
  152. {
  153. // Register Scan CLI dictionary
  154. CLI_registerDictionary( scanCLIDict, scanCLIDictName );
  155. // Scan for active strobes
  156. // NOTE1: On IBM PCBs, each strobe line that is *NOT* used is connected to GND.
  157. // This means, the strobe GPIO can be set to Tri-State pull-up to detect which strobe lines are not used.
  158. // NOTE2: This will *NOT* detect floating strobes.
  159. // NOTE3: Rev 0.4, the strobe numbers are reversed, so D0 is actually strobe 0 and C7 is strobe 17
  160. info_msg("Detecting Strobes...");
  161. DDRC = 0;
  162. PORTC = C_MASK;
  163. DDRD = 0;
  164. PORTD = D_MASK;
  165. DDRE = 0;
  166. PORTE = E_MASK;
  167. // Initially there are 0 strobes
  168. total_strobes = 0;
  169. // Iterate over each the strobes
  170. for ( uint8_t strobe = 0; strobe < MAX_STROBES; strobe++ )
  171. {
  172. uint8_t detected = 0;
  173. // If PIN is high, then strobe is *NOT* connected to GND and may be a strobe
  174. switch ( strobe )
  175. {
  176. // Strobe Mappings
  177. // Rev Rev
  178. // 0.2 0.4
  179. #ifndef REV0_4_DEBUG // XXX These pins should be reworked, and connect to GND on Rev 0.4
  180. case 0: // D0 0 n/c
  181. case 1: // D1 1 n/c
  182. #endif
  183. case 2: // D2 2 15
  184. case 3: // D3 3 14
  185. case 4: // D4 4 13
  186. case 5: // D5 5 12
  187. case 6: // D6 6 11
  188. case 7: // D7 7 10
  189. detected = PIND & (1 << strobe);
  190. break;
  191. case 8: // E0 8 9
  192. case 9: // E1 9 8
  193. detected = PINE & (1 << (strobe - 8));
  194. break;
  195. case 10: // C0 10 7
  196. case 11: // C1 11 6
  197. case 12: // C2 12 5
  198. case 13: // C3 13 4
  199. case 14: // C4 14 3
  200. case 15: // C5 15 2
  201. #ifndef REV0_2_DEBUG // XXX If not using the 18 pin connector on Rev 0.2, rework these pins to GND
  202. case 16: // C6 16 1
  203. case 17: // C7 17 0
  204. #endif
  205. detected = PINC & (1 << (strobe - 10));
  206. break;
  207. default:
  208. break;
  209. }
  210. // Potential strobe line detected
  211. if ( detected )
  212. {
  213. strobe_map[total_strobes] = strobe;
  214. total_strobes++;
  215. }
  216. }
  217. printInt8( total_strobes );
  218. print( " strobes found." NL );
  219. // Setup Pins for Strobing
  220. DDRC = C_MASK;
  221. PORTC = 0;
  222. DDRD = D_MASK;
  223. PORTD = 0;
  224. DDRE = E_MASK;
  225. PORTE = 0 ;
  226. // Initialize ADC
  227. setup_ADC();
  228. // Reset debounce table
  229. for ( int i = 0; i < KEY_COUNT; ++i )
  230. {
  231. keys_debounce[i] = 0;
  232. }
  233. // Warm things up a bit before we start collecting data, taking real samples.
  234. for ( uint8_t i = 0; i < total_strobes; ++i )
  235. {
  236. sampleColumn( strobe_map[i] );
  237. }
  238. }
  239. // Main Detection Loop
  240. // This is where the important stuff happens
  241. inline uint8_t Scan_loop()
  242. {
  243. capsense_scan();
  244. // Return non-zero if macro and USB processing should be delayed
  245. // Macro processing will always run if returning 0
  246. // USB processing only happens once the USB send timer expires, if it has not, Scan_loop will be called
  247. // after the macro processing has been completed
  248. return 0;
  249. }
  250. // Signal from macro module that keys have been processed
  251. // NOTE: Only really required for implementing "tricks" in converters for odd protocols
  252. void Scan_finishedWithMacro( uint8_t sentKeys )
  253. {
  254. return;
  255. }
  256. // Signal from output module that keys have been processed/sent
  257. // NOTE: Only really required for implementing "tricks" in converters for odd protocols
  258. void Scan_finishedWithOutput( uint8_t sentKeys )
  259. {
  260. return;
  261. }
  262. inline void capsense_scan()
  263. {
  264. // Accumulated average used for the next scan
  265. uint32_t cur_full_avg = 0;
  266. uint32_t cur_high_avg = 0;
  267. // Reset average counters
  268. low_avg = 0;
  269. low_count = 0;
  270. high_count = 0;
  271. // Reset key activity, if there is no key activity, averages will accumulate for sense deltas, otherwise they will be reset
  272. key_activity = 0;
  273. // Scan each of the mapped strobes in the matrix
  274. for ( uint8_t strober = 0; strober < total_strobes; ++strober )
  275. {
  276. uint8_t map_strobe = strobe_map[strober];
  277. // Sample the ADCs for the given column/strobe
  278. sampleColumn( map_strobe );
  279. // Only process sense data if warmup is finished
  280. if ( boot_count >= WARMUP_LOOPS )
  281. {
  282. testColumn( map_strobe );
  283. }
  284. uint8_t strobe_line = map_strobe << MUXES_COUNT_XSHIFT;
  285. for ( int mux = 0; mux < MUXES_COUNT; ++mux )
  286. {
  287. // discard sketchy low bit, and meaningless high bits.
  288. uint8_t sample = samples[map_strobe][mux] >> 1;
  289. keys_averages_acc[strobe_line + mux] += sample;
  290. }
  291. // Accumulate 3 total averages (used for determining starting average during warmup)
  292. // full_avg - Average of all sampled lines on the previous scan set
  293. // cur_full_avg - Average of all sampled lines for this scan set
  294. // high_avg - Average of all sampled lines above full_avg on the previous scan set
  295. // cur_high_avg - Average of all sampled lines above full_avg
  296. // low_avg - Average of all sampled lines below or equal to full_avg
  297. if ( boot_count < WARMUP_LOOPS )
  298. {
  299. for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
  300. {
  301. uint8_t sample = samples[map_strobe][mux] >> 1;
  302. // Sample is high, add it to high avg
  303. if ( sample > full_avg )
  304. {
  305. high_count++;
  306. cur_high_avg += sample;
  307. }
  308. // Sample is low, add it to low avg
  309. else
  310. {
  311. low_count++;
  312. low_avg += sample;
  313. }
  314. // If sample is higher than previous high_avg, then mark as "problem key"
  315. // XXX Giving a bit more margin to pass (high_avg vs. high_avg + high_avg - full_avg) -HaaTa
  316. keys_problem[strobe_line + mux] = sample > high_avg + (high_avg - full_avg) ? sample : 0;
  317. // Prepare for next average
  318. cur_full_avg += sample;
  319. }
  320. }
  321. } // for strober
  322. // Update total sense average (only during warm-up)
  323. if ( boot_count < WARMUP_LOOPS )
  324. {
  325. full_avg = cur_full_avg / (total_strobes * MUXES_COUNT);
  326. high_avg = cur_high_avg / high_count;
  327. low_avg /= low_count;
  328. // Update the base average value using the low_avg (best chance of not ignoring a keypress)
  329. for ( int i = 0; i < KEY_COUNT; ++i )
  330. {
  331. keys_averages[i] = low_avg;
  332. keys_averages_acc[i] = low_avg;
  333. }
  334. }
  335. // Warm up voltage references
  336. if ( boot_count < WARMUP_LOOPS )
  337. {
  338. boot_count++;
  339. switch ( boot_count )
  340. {
  341. // First loop
  342. case 1:
  343. // Show msg at first iteration only
  344. info_msg("Warming up the voltage references");
  345. break;
  346. // Middle iterations
  347. case 300:
  348. case 600:
  349. case 900:
  350. case 1200:
  351. print(".");
  352. break;
  353. // Last loop
  354. case WARMUP_STOP:
  355. print( NL );
  356. info_msg("Warmup finished using ");
  357. printInt16( WARMUP_LOOPS );
  358. print(" iterations" NL );
  359. // Display the final calculated averages of all the sensed strobes
  360. info_msg("Full average (");
  361. printInt8( total_strobes * MUXES_COUNT );
  362. print("): ");
  363. printHex( full_avg );
  364. print(" High average (");
  365. printInt8( high_count );
  366. print("): ");
  367. printHex( high_avg );
  368. print(" Low average (");
  369. printInt8( low_count );
  370. print("): ");
  371. printHex( low_avg );
  372. print(" Rejection threshold: ");
  373. printHex( high_avg + (high_avg - full_avg) );
  374. print( NL );
  375. // Display problem keys, and the sense value at the time
  376. for ( uint8_t key = 0; key < KEY_COUNT; key++ )
  377. {
  378. if ( keys_problem[key] )
  379. {
  380. warn_msg("Problem key detected: ");
  381. printHex( key );
  382. print(" (");
  383. printHex( keys_problem[key] );
  384. print(")" NL );
  385. }
  386. }
  387. info_print("If problem keys were detected, and were being held down, they will be reset as soon as let go.");
  388. info_print("Some keys have unusually high sense values, on the first press they should be re-enabled.");
  389. break;
  390. }
  391. }
  392. else
  393. {
  394. // No keypress, accumulate averages
  395. if( !key_activity )
  396. {
  397. // Only start averaging once the idle counter has counted down to 0
  398. if ( key_idle == 0 )
  399. {
  400. // Average Debugging
  401. if ( enableAvgDebug )
  402. {
  403. print("\033[1mAvg\033[0m: ");
  404. }
  405. // aggregate
  406. for ( uint8_t i = 0; i < KEY_COUNT; ++i )
  407. {
  408. uint16_t acc = keys_averages_acc[i];
  409. //uint16_t acc = keys_averages_acc[i] >> IDLE_COUNT_SHIFT; // XXX This fixes things... -HaaTa
  410. uint32_t av = keys_averages[i];
  411. av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
  412. av >>= KEYS_AVERAGES_MIX_SHIFT;
  413. keys_averages[i] = av;
  414. keys_averages_acc[i] = 0;
  415. // Average Debugging
  416. if ( enableAvgDebug && av > 0 )
  417. {
  418. printHex( av );
  419. print(" ");
  420. }
  421. }
  422. // Average Debugging
  423. if ( enableAvgDebug )
  424. {
  425. print( NL );
  426. }
  427. // No key presses detected, set key_release indicator
  428. key_release = 1;
  429. }
  430. // Otherwise decrement the idle counter
  431. else
  432. {
  433. key_idle--;
  434. }
  435. }
  436. // Keypresses, reset accumulators
  437. else if ( key_release )
  438. {
  439. for ( uint8_t c = 0; c < KEY_COUNT; ++c ) { keys_averages_acc[c] = 0; }
  440. key_release = 0;
  441. }
  442. // If the debugging sense table is non-zero, display
  443. if ( senseDebugCount > 0 )
  444. {
  445. senseDebugCount--;
  446. print( NL );
  447. dumpSenseTable();
  448. }
  449. }
  450. }
  451. void setup_ADC()
  452. {
  453. // disable adc digital pins.
  454. DIDR1 |= (1 << AIN0D) | (1<<AIN1D); // set disable on pins 1,0.
  455. DDRF = 0x0;
  456. PORTF = 0x0;
  457. uint8_t mux = 0 & 0x1f; // 0 == first. // 0x1e = 1.1V ref.
  458. // 0 = external aref 1,1 = 2.56V internal ref
  459. uint8_t aref = ((1 << REFS1) | (1 << REFS0)) & ((1 << REFS1) | (1 << REFS0));
  460. uint8_t adate = (1 << ADATE) & (1 << ADATE); // trigger enable
  461. uint8_t trig = 0 & ((1 << ADTS0) | (1 << ADTS1) | (1 << ADTS2)); // 0 = free running
  462. // ps2, ps1 := /64 ( 2^6 ) ps2 := /16 (2^4), ps1 := 4, ps0 :=2, PS1,PS0 := 8 (2^8)
  463. uint8_t prescale = ( ((PRESCALE) << PRESCALE_SHIFT) & PRESCALE_MASK ); // 001 == 2^1 == 2
  464. uint8_t hispeed = (1 << ADHSM);
  465. uint8_t en_mux = (1 << ACME);
  466. ADCSRA = (1 << ADEN) | prescale; // ADC enable
  467. // select ref.
  468. //ADMUX |= ((1 << REFS1) | (1 << REFS0)); // 2.56 V internal.
  469. //ADMUX |= ((1 << REFS0) ); // Vcc with external cap.
  470. //ADMUX &= ~((1 << REFS1) | (1 << REFS0)); // 0,0 : aref.
  471. ADMUX = aref | mux | ADLAR_BITS;
  472. // set free-running
  473. ADCSRA |= adate; // trigger enable
  474. ADCSRB = en_mux | hispeed | trig | (ADCSRB & ~((1 << ADTS0) | (1 << ADTS1) | (1 << ADTS2))); // trigger select free running
  475. ADCSRA |= (1 << ADEN); // ADC enable
  476. ADCSRA |= (1 << ADSC); // start conversions q
  477. }
  478. void recovery( uint8_t on )
  479. {
  480. DDRB |= (1 << RECOVERY_CONTROL);
  481. PORTB &= ~(1 << RECOVERY_SINK); // SINK always zero
  482. DDRB &= ~(1 << RECOVERY_SOURCE); // SOURCE high imp
  483. if ( on )
  484. {
  485. // set strobes to sink to gnd.
  486. DDRC |= C_MASK;
  487. DDRD |= D_MASK;
  488. DDRE |= E_MASK;
  489. PORTC &= ~C_MASK;
  490. PORTD &= ~D_MASK;
  491. PORTE &= ~E_MASK;
  492. DDRB |= (1 << RECOVERY_SINK); // SINK pull
  493. PORTB |= (1 << RECOVERY_CONTROL);
  494. PORTB |= (1 << RECOVERY_SOURCE); // SOURCE high
  495. DDRB |= (1 << RECOVERY_SOURCE);
  496. }
  497. else
  498. {
  499. PORTB &= ~(1 << RECOVERY_CONTROL);
  500. DDRB &= ~(1 << RECOVERY_SOURCE);
  501. PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low
  502. DDRB &= ~(1 << RECOVERY_SINK); // SINK high-imp
  503. }
  504. }
  505. void hold_sample( uint8_t on )
  506. {
  507. if ( !on )
  508. {
  509. PORTB |= (1 << SAMPLE_CONTROL);
  510. DDRB |= (1 << SAMPLE_CONTROL);
  511. }
  512. else
  513. {
  514. DDRB |= (1 << SAMPLE_CONTROL);
  515. PORTB &= ~(1 << SAMPLE_CONTROL);
  516. }
  517. }
  518. void strobe_w( uint8_t strobe_num )
  519. {
  520. PORTC &= ~(C_MASK);
  521. PORTD &= ~(D_MASK);
  522. PORTE &= ~(E_MASK);
  523. // Strobe table
  524. // Not all strobes are used depending on which are detected
  525. switch ( strobe_num )
  526. {
  527. case 0: PORTD |= (1 << 0); break;
  528. case 1: PORTD |= (1 << 1); break;
  529. case 2: PORTD |= (1 << 2); break;
  530. case 3: PORTD |= (1 << 3); break;
  531. case 4: PORTD |= (1 << 4); break;
  532. case 5: PORTD |= (1 << 5); break;
  533. case 6: PORTD |= (1 << 6); break;
  534. case 7: PORTD |= (1 << 7); break;
  535. case 8: PORTE |= (1 << 0); break;
  536. case 9: PORTE |= (1 << 1); break;
  537. case 10: PORTC |= (1 << 0); break;
  538. case 11: PORTC |= (1 << 1); break;
  539. case 12: PORTC |= (1 << 2); break;
  540. case 13: PORTC |= (1 << 3); break;
  541. case 14: PORTC |= (1 << 4); break;
  542. case 15: PORTC |= (1 << 5); break;
  543. case 16: PORTC |= (1 << 6); break;
  544. case 17: PORTC |= (1 << 7); break;
  545. default:
  546. break;
  547. }
  548. }
  549. inline uint16_t getADC(void)
  550. {
  551. ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
  552. //wait for last read to complete.
  553. while ( !( ADCSRA & (1 << ADIF) ) );
  554. return ADC; // return sample
  555. }
  556. void sampleColumn( uint8_t column )
  557. {
  558. // ensure all probe lines are driven low, and chill for recovery delay.
  559. ADCSRA |= (1 << ADEN) | (1 << ADSC); // enable and start conversions
  560. PORTC &= ~C_MASK;
  561. PORTD &= ~D_MASK;
  562. PORTE &= ~E_MASK;
  563. PORTF = 0;
  564. DDRF = 0;
  565. recovery( OFF );
  566. strobe_w( column );
  567. hold_sample( OFF );
  568. SET_FULL_MUX( 0 );
  569. // Allow strobes to settle
  570. for ( uint8_t i = 0; i < STROBE_SETTLE; ++i ) { getADC(); }
  571. hold_sample( ON );
  572. uint8_t mux = 0;
  573. SET_FULL_MUX( mux );
  574. getADC(); // throw away; unknown mux.
  575. do {
  576. SET_FULL_MUX( mux + 1 ); // our *next* sample will use this
  577. // retrieve current read.
  578. uint16_t readVal = getADC();
  579. samples[column][mux] = readVal;
  580. // Update max sense sample table
  581. if ( readVal > sampleMax[column][mux] )
  582. {
  583. sampleMax[column][mux] = readVal;
  584. }
  585. mux++;
  586. } while ( mux < 8 );
  587. hold_sample( OFF );
  588. recovery( ON );
  589. // turn off adc.
  590. ADCSRA &= ~(1 << ADEN);
  591. // pull all columns' strobe-lines low.
  592. DDRC |= C_MASK;
  593. DDRD |= D_MASK;
  594. DDRE |= E_MASK;
  595. PORTC &= ~C_MASK;
  596. PORTD &= ~D_MASK;
  597. PORTE &= ~E_MASK;
  598. }
  599. void testColumn( uint8_t strobe )
  600. {
  601. uint16_t db_delta = 0;
  602. uint8_t db_sample = 0;
  603. uint16_t db_threshold = 0;
  604. uint8_t column = 0;
  605. uint8_t bit = 1;
  606. for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
  607. {
  608. uint16_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + mux];
  609. uint8_t key = (strobe << MUXES_COUNT_XSHIFT) + mux;
  610. // Check if this is a bad key (e.g. test point, or non-existent key)
  611. if ( keys_problem[key] )
  612. {
  613. // If the sample value of the problem key goes above initally recorded result + threshold
  614. // re-enable the key
  615. if ( (db_sample = samples[strobe][mux] >> 1) > keys_problem[key] + threshold )
  616. //if ( (db_sample = samples[strobe][mux] >> 1) < high_avg )
  617. {
  618. info_msg("Re-enabling problem key: ");
  619. printHex( key );
  620. print( NL );
  621. keys_problem[key] = 0;
  622. }
  623. // Do not waste any more cycles processing, regardless, a keypress cannot be detected
  624. continue;
  625. }
  626. // Keypress detected
  627. // db_sample (uint8_t), discard meaningless high bit, and garbage low bit
  628. if ( (db_sample = samples[strobe][mux] >> 1) > (db_threshold = threshold) + (db_delta = delta) )
  629. {
  630. column |= bit;
  631. key_activity++; // No longer idle, stop averaging ADC data
  632. key_idle = KEY_IDLE_SCANS; // Reset idle count-down
  633. // Only register keypresses once the warmup is complete, or not enough debounce info
  634. if ( keys_debounce[key] <= DEBOUNCE_THRESHOLD )
  635. {
  636. // Add to the Macro processing buffer if debounce criteria met
  637. // Automatically handles converting to a USB code and sending off to the PC
  638. if ( keys_debounce[key] == DEBOUNCE_THRESHOLD )
  639. {
  640. // Debug message, pressDebug CLI
  641. if ( enablePressDebug )
  642. {
  643. print("0x");
  644. printHex_op( key, 2 );
  645. print(" ");
  646. }
  647. // Initial Keypress
  648. Macro_keyState( key, 0x01 );
  649. }
  650. keys_debounce[key]++;
  651. }
  652. else if ( keys_debounce[key] >= DEBOUNCE_THRESHOLD )
  653. {
  654. // Held Key
  655. Macro_keyState( key, 0x02 );
  656. }
  657. // Long form key debugging
  658. if ( enableKeyDebug )
  659. {
  660. // Debug message
  661. // <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
  662. dbug_msg("");
  663. printHex_op( key, 1 );
  664. print(" [");
  665. printInt8( strobe );
  666. print(":");
  667. printInt8( mux );
  668. print("] : ");
  669. printHex( db_sample ); // Sense
  670. print(" : ");
  671. printHex( db_threshold );
  672. print("+");
  673. printHex( db_delta );
  674. print("=");
  675. printHex( db_threshold + db_delta ); // Sense compare
  676. print(" : ");
  677. printHex( db_sample - ( db_threshold + db_delta ) ); // Margin
  678. print( NL );
  679. }
  680. }
  681. // Clear debounce entry if no keypress detected
  682. else
  683. {
  684. // Release Key
  685. if ( keys_debounce[key] >= DEBOUNCE_THRESHOLD )
  686. {
  687. Macro_keyState( key, 0x03 );
  688. }
  689. // Clear debounce entry
  690. keys_debounce[key] = 0;
  691. }
  692. bit <<= 1;
  693. }
  694. }
  695. void dumpSenseTable()
  696. {
  697. // Initial table alignment, with base threshold used for every key
  698. print("\033[1m");
  699. printHex( threshold );
  700. print("\033[0m ");
  701. // Print out headers first
  702. for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
  703. {
  704. print(" Mux \033[1m");
  705. printInt8( mux );
  706. print("\033[0m ");
  707. }
  708. print( NL );
  709. // Display the full strobe/sense table
  710. for ( uint8_t strober = 0; strober < total_strobes; ++strober )
  711. {
  712. uint8_t strobe = strobe_map[strober];
  713. // Display the strobe
  714. print("Strobe \033[1m");
  715. printHex( strobe );
  716. print("\033[0m ");
  717. // For each mux, display sense:threshold:delta
  718. for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
  719. {
  720. uint8_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + mux];
  721. uint8_t sample = samples[strobe][mux] >> 1;
  722. uint8_t max = sampleMax[strobe][mux] >> 1;
  723. // Indicate if the key is being pressed by displaying green
  724. if ( sample > delta + threshold )
  725. {
  726. print("\033[1;32m");
  727. }
  728. printHex_op( sample, 2 );
  729. print(":");
  730. printHex_op( max, 2 );
  731. print(":");
  732. printHex_op( delta, 2 );
  733. print("\033[0m ");
  734. }
  735. // New line for each strobe
  736. print( NL );
  737. }
  738. }
  739. // ----- CLI Command Functions -----
  740. // XXX Just an example command showing how to parse arguments (more complex than generally needed)
  741. void cliFunc_echo( char* args )
  742. {
  743. char* curArgs;
  744. char* arg1Ptr;
  745. char* arg2Ptr = args;
  746. // Parse args until a \0 is found
  747. while ( 1 )
  748. {
  749. print( NL ); // No \r\n by default after the command is entered
  750. curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
  751. CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
  752. // Stop processing args if no more are found
  753. if ( *arg1Ptr == '\0' )
  754. break;
  755. // Print out the arg
  756. dPrint( arg1Ptr );
  757. }
  758. }
  759. void cliFunc_avgDebug( char* args )
  760. {
  761. print( NL );
  762. // Args ignored, just toggling
  763. if ( enableAvgDebug )
  764. {
  765. info_print("Cap Sense averaging debug disabled.");
  766. enableAvgDebug = 0;
  767. }
  768. else
  769. {
  770. info_print("Cap Sense averaging debug enabled.");
  771. enableAvgDebug = 1;
  772. }
  773. }
  774. void cliFunc_keyDebug( char* args )
  775. {
  776. print( NL );
  777. // Args ignored, just toggling
  778. if ( enableKeyDebug )
  779. {
  780. info_print("Cap Sense key long debug disabled - pre debounce.");
  781. enableKeyDebug = 0;
  782. }
  783. else
  784. {
  785. info_print("Cap Sense key long debug enabled - pre debounce.");
  786. enableKeyDebug = 1;
  787. }
  788. }
  789. void cliFunc_pressDebug( char* args )
  790. {
  791. print( NL );
  792. // Args ignored, just toggling
  793. if ( enablePressDebug )
  794. {
  795. info_print("Cap Sense key debug disabled - post debounce.");
  796. enablePressDebug = 0;
  797. }
  798. else
  799. {
  800. info_print("Cap Sense key debug enabled - post debounce.");
  801. enablePressDebug = 1;
  802. }
  803. }
  804. void cliFunc_problemKeys( char* args )
  805. {
  806. print( NL );
  807. uint8_t count = 0;
  808. // Args ignored, just displaying
  809. // Display problem keys, and the sense value at the time
  810. for ( uint8_t key = 0; key < KEY_COUNT; key++ )
  811. {
  812. if ( keys_problem[key] )
  813. {
  814. if ( count++ == 0 )
  815. {
  816. warn_msg("Problem keys: ");
  817. }
  818. printHex( key );
  819. print(" (");
  820. printHex( keys_problem[key] );
  821. print(") " );
  822. }
  823. }
  824. }
  825. void cliFunc_senseDebug( char* args )
  826. {
  827. // Parse code from argument
  828. // NOTE: Only first argument is used
  829. char* arg1Ptr;
  830. char* arg2Ptr;
  831. CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
  832. // Default to a single print
  833. senseDebugCount = 1;
  834. // If there was an argument, use that instead
  835. if ( *arg1Ptr != '\0' )
  836. {
  837. senseDebugCount = numToInt( arg1Ptr );
  838. }
  839. }