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