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