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

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