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