// ----- Defines -----
// TODO dfj defines...needs cleaning up and commenting...
-#define THRESHOLD 0x0a
+#define LED_CONFIG (DDRD |= (1<<6))
+#define LED_ON (PORTD &= ~(1<<6))
+#define LED_OFF (PORTD |= (1<<6))
+#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+
+#define MAX_PRESS_DELTA_MV 470
+#define THRESHOLD_MV (MAX_PRESS_DELTA_MV >> 1)
+//(2560 / (0x3ff/2)) ~= 5
+#define MV_PER_ADC 5
+// 5
+
+#define THRESHOLD (THRESHOLD_MV / MV_PER_ADC)
+
+#define BUMP_DETECTION 0
#define BUMP_THRESHOLD 0x50
//((THRESHOLD) * 3)
#define BUMP_REST_US 1200
+#define STROBE_SETTLE 1
+#define MUX_SETTLE 1
+
#define HYST 1
#define HYST_T 0x10
// rough offset voltage: one diode drop, about 50mV = 0x3ff * 50/3560 = 20
//#define OFFSET_VOLTAGE 0x14
-#define OFFSET_VOLTAGE 0x28
+//#define OFFSET_VOLTAGE 0x28
#define RIGHT_JUSTIFY 0
// F0-f7 pins only muxmask.
#define MUX_MASK ((1 << MUX0) | (1 << MUX1) | (1 << MUX2))
+#define SET_MUX(X) ((ADMUX) = (((ADMUX) & ~(MUX_MASK)) | ((X) & (MUX_MASK))))
+#define SET_FULL_MUX(X) ((ADMUX) = (((ADMUX) & ~(FULL_MUX_MASK)) | ((X) & (FULL_MUX_MASK))))
+
#define MUX_1_1 0x1e
#define MUX_GND 0x1f
#define WARMUP_LOOPS ( 1024 )
-#define RECOVERY_US 6
+#define RECOVERY_US 2
#define SAMPLES 10
//#define SAMPLE_OFFSET 9
#define STROBE_OFFSET 0
+#define SAMPLE_CONTROL 3
+
+#define DEFAULT_KEY_BASE 0x95
#define KEY_COUNT ((STROBE_LINES) * (MUXES_COUNT))
#define RECOVERY_SINK 2
#define RECOVERY_MASK 0x03
+#define ON 1
+#define OFF 0
+
// mix in 1/4 of the current average to the running average. -> (@mux_mix = 2)
#define MUX_MIX 2
#define IDLE_COUNT_MASK 0xff
-#define MAX_ICS 8
+#define IDLE_COUNT_MAX (IDLE_COUNT_MASK + 1)
+#define IDLE_COUNT_SHIFT 8
-#define IDLE_COUNT_SHIFT 4
#define KEYS_AVERAGES_MIX 2
// TODO dfj variables...needs cleaning up and commenting
uint8_t blink = 0;
-volatile uint8_t idle_count = 1;
volatile uint16_t full_av = 0;
/**/ uint8_t ze_strober = 0;
-int16_t samples [SAMPLES];
+uint16_t samples [SAMPLES];
//int16_t gsamples [SAMPLES];
-/**/ int16_t adc_mux_averages[MUXES_COUNT];
-/**/ int16_t adc_strobe_averages[STROBE_LINES];
+int16_t adc_mux_averages[MUXES_COUNT];
+int16_t adc_strobe_averages[STROBE_LINES];
-/**/ uint8_t cur_keymap[STROBE_LINES];
+uint8_t cur_keymap[STROBE_LINES];
// /**/ int8_t last_keymap[STROBE_LINES];
-/**/ uint8_t usb_keymap[STROBE_LINES];
+uint8_t usb_keymap[STROBE_LINES];
+uint16_t keys_down=0;
+
uint8_t dirty;
uint8_t unstable;
uint8_t usb_dirty;
-int16_t threshold = THRESHOLD;
+uint16_t threshold = THRESHOLD;
uint16_t tests = 0;
uint8_t col_a=0;
uint8_t column=0;
-int16_t keys_averages_acc[KEY_COUNT];
+uint16_t keys_averages_acc[KEY_COUNT];
uint16_t keys_averages[KEY_COUNT];
+uint16_t keys_averages_acc_count=0;
uint8_t full_samples[KEY_COUNT];
-/* viable starting biases for near 0.830V offset. and adc PRESCALE 3
-0017 0016 001B 001A 0016 0016 000F 000E 001B 001E 001E 0018 0017 0015 000E 001D
-001B 001A 0016 0016 000F 000E 001C 001B 001E 0018 0017 0015 000E 001D 0024 001F
-0016 0016 000F 000E 001C 001B 001E 001E 0017 0015 000E 001D 0024 001F 0020 001F
-000F 000E 001C 001B 001E 001E 0018 0017 000E 001D 0024 001F 0020 001F 0020 0017
-001C 001B 001E 001E 0018 0017 0015 000E 0024 001F 0020 001F 0020 0017 0010 001D
-001E 001E 0018 0017 0015 000E 001D 0024 0020 001F 0020 0017 0010 001D 0024 0021
-0018 0017 0015 000E 001D 0024 001F 0020 0020 0017 0010 001D 0024 0021 0021 0021
-0015 000E 001D 0024 001F 0020 001F 0020 0010 001D 0024 0021 0021 0021 0021 0018
-*/
+// 0x9f...f
+// #define COUNT_MASK 0x9fff
+// #define COUNT_HIGH_BIT (INT16_MIN)
+// TODO: change this to 'booting', then count down.
+uint16_t boot_count = 0;
-/*** starting bias relative to fixed offset estimate of 820mV (0x50)
- * 77 69 65 5B 50 4E 4C 45 66 53 4D 49 45 3F 3E 35
- * 68 54 4F 49 45 40 3F 34 74 66 5F 56 4E 4D 4C 3F
- * 6D 5D 53 4C 49 46 45 38 6D 5A 53 4E 49 48 45 3E
- * 6F 5D 56 4E 4B 48 48 3A 6D 5C 54 4E 48 48 45 37
- * 75 68 5F 57 4F 4D 4C 3F 60 4E 48 41 3C 3C 39 2F
- * 65 53 4E 49 41 3F 3E 34 65 54 4E 49 43 3F 3E 34
- * 60 51 4A 45 3F 3E 3C 30 57 4C 45 3E 3B 37 37 2E
- * 64 4E 48 44 3C 3B 39 2F 5D 4F 48 45 3E 3C 3B 30
- */
+uint16_t idle_count=0;
+uint8_t idle = 1;
/*volatile*/ uint16_t count = 0;
uint8_t dump_count = 0;
+//uint8_t column =0;
+uint16_t db_delta = 0;
+uint8_t db_sample = 0;
+uint16_t db_threshold = 0;
+
+
// ----- Function Declarations -----
}
for(int i=0; i< KEY_COUNT; ++i) {
- keys_averages[i] = 0x40;
- keys_averages_acc[i] = (0x400);
+ keys_averages[i] = DEFAULT_KEY_BASE;
+ keys_averages_acc[i] = (DEFAULT_KEY_BASE);
}
/** warm things up a bit before we start collecting data, taking real samples. */
tries = 1;
while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
column = testColumn(strober);
+ idle |= column; // if column has any pressed keys, then we are not idle.
if( column != cur_keymap[strober] && (count >= WARMUP_LOOPS) ) {
tests++;
+#if 0
tries = 1;
- while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+ while (tries++ && sampleColumn(strober)) { tries &= 0x7; }
col_a = testColumn(strober);
tries = 1;
- while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+ while (tries++ && sampleColumn(strober)) { tries &= 0x7; }
col_b = testColumn(strober);
tries = 1;
- while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+ while (tries++ && sampleColumn(strober)) { tries &= 0x7; }
col_c = testColumn(strober);
if( (col_a == col_b) && (col_b == col_c) && (cur_keymap[strober] != col_a) ) {
cur_keymap[strober] = col_a;
usb_dirty = 1;
}
+#else
+ cur_keymap[strober] = column;
+ usb_dirty = 1;
+#endif
}
+ idle |= usb_dirty; // if any keys have changed inc. released, then we are not idle.
+
if(error == 0x50) {
error_data |= (((uint16_t)strober) << 12);
}
+ uint8_t strobe_line = strober << MUXES_COUNT_XSHIFT;
for(int i=0; i<MUXES_COUNT; ++i) {
- full_samples[(strober << MUXES_COUNT_XSHIFT) + i] = samples[SAMPLE_OFFSET + i];
+ // discard sketchy low bit, and meaningless high bits.
+ uint8_t sample = samples[SAMPLE_OFFSET + i] >> 1;
+ full_samples[strobe_line + i] = sample;
+ keys_averages_acc[strobe_line + i] += sample;
}
+ keys_averages_acc_count++;
strobe_averages[strober] = 0;
for (uint8_t i = SAMPLE_OFFSET; i < (SAMPLE_OFFSET + MUXES_COUNT); ++i) {
//samples[i] -= OFFSET_VOLTAGE; // moved to sampleColumn.
full_av_acc += (samples[i]);
+#ifdef COLLECT_STROBE_AVERAGES
mux_averages[i - SAMPLE_OFFSET] += samples[i];
strobe_averages[strober] += samples[i];
+#endif
//samples[i] -= (full_av - HYST_T);
//++count;
}
+
+#ifdef COLLECT_STROBE_AVERAGES
adc_strobe_averages[strober] += strobe_averages[strober] >> 3;
adc_strobe_averages[strober] >>= 1;
/** test if we went negative. */
- if ((adc_strobe_averages[strober] & 0xFF00) && (count
+ if ((adc_strobe_averages[strober] & 0xFF00) && (boot_count
>= WARMUP_LOOPS)) {
- //count = 0; // TODO : constrain properly.
error = 0xf; error_data = adc_strobe_averages[strober];
}
-
- uint8_t strobe_line = strober << MUXES_COUNT_XSHIFT;
- for (int i = 0; i < MUXES_COUNT; ++i) {
- keys_averages_acc[strobe_line + i]
- += samples[SAMPLE_OFFSET + i];
- }
-
+#endif
} // for strober
- if (count < WARMUP_LOOPS) {
- error = 0x0C;
- error_data = count;
- count++;
- }
-
+#ifdef VERIFY_TEST_PAD
// verify test key is not down.
if((cur_keymap[TEST_KEY_STROBE] & TEST_KEY_MASK) ) {
//count=0;
error_data += full_samples[TEST_KEY_STROBE * 8];
//threshold++;
}
+#endif
+#ifdef COLLECT_STROBE_AVERAGES
// calc mux averages.
- if (count < WARMUP_LOOPS) {
+ if (boot_count < WARMUP_LOOPS) {
full_av += (full_av_acc >> (7));
full_av >>= 1;
//full_av = full_av_acc / count;
full_av_acc = 0;
- for (int i=0; i < MUXES_COUNT; ++i) {
+ for (int i=0; i < MUXES_COUNT; ++i) {
+#define MUX_MIX 2 // mix in 1/4 of the current average to the running average. -> (@mux_mix = 2)
adc_mux_averages[i] = (adc_mux_averages[i] << MUX_MIX) - adc_mux_averages[i];
adc_mux_averages[i] += (mux_averages[i] >> 4);
adc_mux_averages[i] >>= MUX_MIX;
mux_averages[i] = 0;
}
-
}
+#endif
+
+// av = (av << shift) - av + sample; av >>= shift
+// e.g. 1 -> (av + sample) / 2 simple average of new and old
+// 2 -> (3 * av + sample) / 4 i.e. 3:1 mix of old to new.
+// 3 -> (7 * av + sample) / 8 i.e. 7:1 mix of old to new.
+#define KEYS_AVERAGES_MIX_SHIFT 3
+
+ /** aggregate if booting, or if idle;
+ * else, if not booting, check for dirty USB.
+ * */
idle_count++;
idle_count &= IDLE_COUNT_MASK;
- if (/*usb_dirty &&*/ (count >= WARMUP_LOOPS) ) {
- for (int i=0; i<STROBE_LINES; ++i) {
- usb_keymap[i] = cur_keymap[i];
- }
+ idle = idle && !keys_down;
- dumpkeys();
- usb_dirty=0;
- _delay_ms(2);
- }
+ if (boot_count < WARMUP_LOOPS) {
+ error = 0x0C;
+ error_data = boot_count;
+ boot_count++;
+ } else { // count >= WARMUP_LOOPS
+ if (usb_dirty) {
+ for (int i=0; i<STROBE_LINES; ++i) {
+ usb_keymap[i] = cur_keymap[i];
+ }
- if (count < WARMUP_LOOPS) {
- for (uint8_t i = 0; i < KEY_COUNT; ++i) {
- uint16_t acc = keys_averages_acc[i];
- uint32_t av = keys_averages[i];
+ dumpkeys();
+ usb_dirty=0;
+ memset(((void *)keys_averages_acc), 0, (size_t)(KEY_COUNT * sizeof (uint16_t)));
+ keys_averages_acc_count = 0;
+ idle_count = 0;
+ idle = 0;
+ _delay_us(100);
+ }
- av = av + av + av + acc;
- av >>= 2;
+ if (!idle_count) {
+ if(idle) {
+ // aggregate
+ for (uint8_t i = 0; i < KEY_COUNT; ++i) {
+ uint16_t acc = keys_averages_acc[i] >> IDLE_COUNT_SHIFT;
+ uint32_t av = keys_averages[i];
- keys_averages[i] = av;
- keys_averages_acc[i] = 0;
- }
- }
+ av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
+ av >>= KEYS_AVERAGES_MIX_SHIFT;
+ keys_averages[i] = av;
+ keys_averages_acc[i] = 0;
+ }
+ }
+ keys_averages_acc_count = 0;
- if(!idle_count) {
+ if(boot_count >= WARMUP_LOOPS) {
+ dump();
+ }
- for (int i=0; i< KEY_COUNT; ++i) {
- keys_averages_acc[i] = 0;
+ sampleColumn(0x0); // to resync us if we dumped a mess 'o text.
}
- sampleColumn(0x0); // to resync us if we dumped a mess 'o text.
}
}
-void
-_delay_loop(uint8_t __count)
+void _delay_loop(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" "\n\t"
ADCSRA |= (1 << ADEN); // ADC enable
ADCSRA |= (1 << ADSC); // start conversions q
-
}
DDRB &= ~(1 << RECOVERY_SOURCE); // SOURCE high imp
if(on) {
- DDRB |= (1 << RECOVERY_SINK); // SINK pull
+ // set strobes to sink to gnd.
+ DDRC |= C_MASK;
+ DDRD |= D_MASK;
+ DDRE |= E_MASK;
+
+ PORTC &= ~C_MASK;
+ PORTD &= ~D_MASK;
+ PORTE &= ~E_MASK;
+ DDRB |= (1 << RECOVERY_SINK); // SINK pull
PORTB |= (1 << RECOVERY_CONTROL);
PORTB |= (1 << RECOVERY_SOURCE); // SOURCE high
DDRB |= (1 << RECOVERY_SOURCE);
} else {
- _delay_loop(10);
+// _delay_loop(10);
PORTB &= ~(1 << RECOVERY_CONTROL);
DDRB &= ~(1 << RECOVERY_SOURCE);
}
+void hold_sample(uint8_t on) {
+ if (!on) {
+ PORTB |= (1 << SAMPLE_CONTROL);
+ DDRB |= (1 << SAMPLE_CONTROL);
+ } else {
+ DDRB |= (1 << SAMPLE_CONTROL);
+ PORTB &= ~(1 << SAMPLE_CONTROL);
+ }
+}
+
+
void strobe_w(uint8_t strobe_num) {
PORTC &= ~(C_MASK);
break;
}
-}
-
-#if 0
-int sampleColumn_i(uint8_t column, uint8_t muxes, int16_t * buffer) {
-
- // ensure all probe lines are driven low, and chill for recovery delay.
- PORTC &= ~C_MASK;
- PORTD &= ~D_MASK;
- PORTE &= ~E_MASK;
- recovery(1);
- _delay_us(RECOVERY_US);
- recovery(0);
- //uint8_t index = 0;
+#if 0 // New code from dfj -> still needs redoing for kishsaver and autodetection of strobes
+#ifdef SHORT_C
+ strobe_num = 15 - strobe_num;
+#endif
- for (uint8_t i=0; i<8; ++i) {
- if(muxes & (1 << i)) {
- buffer[index++] = i;
- }
- }
+#ifdef SINGLE_COLUMN_TEST
+ strobe_num = 5;
+#endif
- SET_FULL_MUX(MUX_1_1); // crap sample will use this.
- ADCSRA |= (1 << ADEN) | (1 << ADSC); // enable and start conversions
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+ switch(strobe_num) {
- //uint16_t sample;
+ case 0: PORTD |= (1 << 0); DDRD &= ~(1 << 0); break;
+ case 1: PORTD |= (1 << 1); DDRD &= ~(1 << 1); break;
+ case 2: PORTD |= (1 << 2); DDRD &= ~(1 << 2); break;
+ case 3: PORTD |= (1 << 3); DDRD &= ~(1 << 3); break;
+ case 4: PORTD |= (1 << 4); DDRD &= ~(1 << 4); break;
+ case 5: PORTD |= (1 << 5); DDRD &= ~(1 << 5); break;
- while (! (ADCSRA & (1 << ADIF))); // wait until ready.
- sample = ADC; // 1st sample, icky.
- //ADC; // 1st sample, icky. XXX Not sure if the compiler throws this away, but less compiler warnings -HaaTa
+#ifdef ALL_D
- strobe_w(column);
- //recovery(0);
-
- /**
- * we are running in continuous mode, so we must setup the next
- * read _before_ the current read completes.
- *
- * setup 0,
- * read garbage,
- * do not store
- *
- * setup 1,
- * read 0,
- * store 0,
- *
- * ...
- *
- * setup junk,
- * read n
- * store n
- *
- * */
+ case 6: PORTD |= (1 << 6); break;
+ case 7: PORTD |= (1 << 7); break;
+ case 8: PORTC |= (1 << 0); break;
+ case 9: PORTC |= (1 << 1); break;
+ case 10: PORTC |= (1 << 2); break;
+ case 11: PORTC |= (1 << 3); break;
+ case 12: PORTC |= (1 << 4); break;
+ case 13: PORTC |= (1 << 5); break;
+ case 14: PORTC |= (1 << 6); break;
+ case 15: PORTC |= (1 << 7); break;
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- //wait for last read to complete.
- while (! (ADCSRA & (1 << ADIF)));
- sample = ADC; // throw away strobe'd value.
- //ADC; // throw away strobe'd value.
+ case 16: PORTE |= (1 << 0); break;
+ case 17: PORTE |= (1 << 1); break;
-#if 0
- for (uint8_t i=0; i <= index; ++i) {
-
- // setup i'th read.
- SET_FULL_MUX(buffer[i]); // _next_ read will use this.
- // wait for i-1'th read to complete:
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- while (! (ADCSRA & (1 << ADIF)));
-
- // retrieve last (i-1'th) read.
- if (i) {
- buffer[i-1] = ADC - OFFSET_VOLTAGE;
- } /*else {
- buffer[0] = ADC - OFFSET_VOLTAGE;
- }*/
-
- //index++;
- }
#else
- for (uint8_t i=0; i < index; ++i) {
+#ifdef SHORT_D
- // setup i'th read.
- SET_FULL_MUX(buffer[i]); // _next_ read will use this.
+ case 6: PORTE |= (1 << 0); break;
+ case 7: PORTE |= (1 << 1); break;
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- while (! (ADCSRA & (1 << ADIF)));
- sample = ADC; // throw away warmup value.
- //ADC; // throw away warmup value.
+ case 8: PORTC |= (1 << 0); break;
+ case 9: PORTC |= (1 << 1); break;
+ case 10: PORTC |= (1 << 2); break;
+ case 11: PORTC |= (1 << 3); break;
+ case 12: PORTC |= (1 << 4); break;
+ case 13: PORTC |= (1 << 5); break;
+ case 14: PORTC |= (1 << 6); break;
+ case 15: PORTC |= (1 << 7); break;
+#else
+#ifdef SHORT_C
+ case 6: PORTD |= (1 << 6); DDRD &= ~(1 << 6); break;
+ case 7: PORTD |= (1 << 7); DDRD &= ~(1 << 7); break;
- /*
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- while (! (ADCSRA & (1 << ADIF)));
- //sample = ADC; // throw away warmup value.
- ADC; // throw away warmup value.
-*/
+ case 8: PORTE |= (1 << 0); DDRE &= ~(1 << 0); break;
+ case 9: PORTE |= (1 << 1); DDRE &= ~(1 << 1); break;
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- while (! (ADCSRA & (1 << ADIF)));
+ case 10: PORTC |= (1 << 0); DDRC &= ~(1 << 0); break;
+ case 11: PORTC |= (1 << 1); DDRC &= ~(1 << 1); break;
+ case 12: PORTC |= (1 << 2); DDRC &= ~(1 << 2); break;
+ case 13: PORTC |= (1 << 3); DDRC &= ~(1 << 3); break;
+ case 14: PORTC |= (1 << 4); DDRC &= ~(1 << 4); break;
+ case 15: PORTC |= (1 << 5); DDRC &= ~(1 << 5); break;
- // retrieve current read.
- buffer[i] = ADC - OFFSET_VOLTAGE;
+ case 16: PORTC |= (1 << 6); DDRC &= ~(1 << 6); break;
+ case 17: PORTC |= (1 << 7); DDRC &= ~(1 << 7); break;
+#endif
+#endif
+#endif
+ default:
+ break;
}
+
#endif
- // turn off adc.
- ADCSRA &= ~(1 << ADEN);
-
- // pull all columns' probe-lines low.
- PORTC &= ~C_MASK;
- PORTD &= ~D_MASK;
- PORTE &= ~E_MASK;
+}
- // test for humps. :/
- /*uint16_t delta = full_av;
- if(buffer[0] > BUMP_THRESHOLD + delta) {
- // ze horror.
- return 1;
- } else {
- return 0; //all good.
- }*/
- return 0;
+inline uint16_t getADC() {
+ ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+ //wait for last read to complete.
+ while (! (ADCSRA & (1 << ADIF)));
+ return ADC; // return sample
}
-#endif
-int sampleColumn_k(uint8_t column, int16_t * buffer) {
+int sampleColumn_8x(uint8_t column, uint16_t * buffer) {
// ensure all probe lines are driven low, and chill for recovery delay.
uint16_t sample;
ADCSRA |= (1 << ADEN) | (1 << ADSC); // enable and start conversions
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
// sync up with adc clock:
- while (! (ADCSRA & (1 << ADIF))); // wait until ready.
- //ADC; // throw it away. // XXX Not sure if the compiler throws this away, but less compiler warnings -HaaTa
- sample = ADC; // throw it away.
+ //sample = getADC();
- for(uint8_t mux=0; mux < 8; ++mux) {
+ PORTC &= ~C_MASK;
+ PORTD &= ~D_MASK;
+ PORTE &= ~E_MASK;
- PORTC &= ~C_MASK;
- PORTD &= ~D_MASK;
- PORTE &= ~E_MASK;
+ PORTF = 0;
+ DDRF = 0;
- SET_FULL_MUX(mux); // our sample will use this
+ recovery(OFF);
+ strobe_w(column);
- for(uint8_t i=0; i < 2; ++i) {
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- //wait for last read to complete.
- while (! (ADCSRA & (1 << ADIF)));
- sample = ADC; // throw away strobe'd value.
- //ADC; // throw away strobe'd value.
- }
+ hold_sample(OFF);
+ SET_FULL_MUX(0);
+ for(uint8_t i=0; i < STROBE_SETTLE; ++i) {
+ sample = getADC();
+ }
+ hold_sample(ON);
+
+#undef MUX_SETTLE
- recovery(0);
- strobe_w(column);
+#if (MUX_SETTLE)
+ for(uint8_t mux=0; mux < 8; ++mux) {
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- //wait for last read to complete.
- while (! (ADCSRA & (1 << ADIF)));
- sample = ADC; // throw away strobe'd value.
- //ADC; // throw away strobe'd value.
+ SET_FULL_MUX(mux); // our sample will use this
+ // wait for mux to settle.
+ for(uint8_t i=0; i < MUX_SETTLE; ++i) {
+ sample = getADC();
+ }
- ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
- while (! (ADCSRA & (1 << ADIF)));
// retrieve current read.
- buffer[mux] = ADC - OFFSET_VOLTAGE;
- recovery(1);
+ buffer[mux] = getADC();// - OFFSET_VOLTAGE;
}
+#else
+ uint8_t mux=0;
+ SET_FULL_MUX(mux);
+ sample = getADC(); // throw away; unknown mux.
+ do {
+ SET_FULL_MUX(mux + 1); // our *next* sample will use this
+
+ // retrieve current read.
+ buffer[mux] = getADC();// - OFFSET_VOLTAGE;
+ mux++;
+
+ } while (mux < 8);
+
+#endif
+ hold_sample(OFF);
+ recovery(ON);
// turn off adc.
ADCSRA &= ~(1 << ADEN);
- // pull all columns' probe-lines low.
+ // pull all columns' strobe-lines low.
+ DDRC |= C_MASK;
+ DDRD |= D_MASK;
+ DDRE |= E_MASK;
+
PORTC &= ~C_MASK;
PORTD &= ~D_MASK;
PORTE &= ~E_MASK;
-// recovery(1);
-
return 0;
}
int sampleColumn(uint8_t column) {
int rval = 0;
- /*
- sampleColumn_i(column, 0x0f, samples+SAMPLE_OFFSET);
- sampleColumn_i(column, 0xf0, samples+SAMPLE_OFFSET + 4 );
-*/
+ //rval = sampleColumn_k(column, samples+SAMPLE_OFFSET);
+ rval = sampleColumn_8x(column, samples+SAMPLE_OFFSET);
- rval = sampleColumn_k(column, samples+SAMPLE_OFFSET);
-
- //for(uint8_t i=0; i<1; ++i) { // TODO REMOVEME
+#if (BUMP_DETECTION)
for(uint8_t i=0; i<8; ++i) {
if(samples[SAMPLE_OFFSET + i] - adc_mux_averages[i] > BUMP_THRESHOLD) {
// was a hump
return rval;
}
}
+#endif
return rval;
}
uint8_t testColumn(uint8_t strobe) {
- uint8_t column = 0;
- uint8_t bit = 1;
- for (uint8_t i=0; i < MUXES_COUNT; ++i) {
+ uint8_t column = 0;
+ uint8_t bit = 1;
+ for (uint8_t i=0; i < MUXES_COUNT; ++i) {
uint16_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + i];
- if ((int16_t)samples[SAMPLE_OFFSET + i] > threshold + delta) {
+ if ((db_sample = samples[SAMPLE_OFFSET + i] >> 1) > (db_threshold = threshold) + (db_delta = delta)) {
column |= bit;
}
bit <<= 1;
}
- return column;
+ return column;
}
void dumpkeys(void) {
//print(" \n");
if(error) {
+ /*
if (count >= WARMUP_LOOPS && error) {
dump();
}
+ */
// Key scan debug
- /*
for (uint8_t i=0; i < STROBE_LINES; ++i) {
printHex(usb_keymap[i]);
print(" ");
printHex(error_data);
error_data = 0;
print(" : " NL);
- */
}
// XXX Will be cleaned up eventually, but this will do for now :P -HaaTa
void dump(void) {
+#define DEBUG_FULL_SAMPLES_AVERAGES
+#ifdef DEBUG_FULL_SAMPLES_AVERAGES
if(!dump_count) { // we don't want to debug-out during the measurements.
// Averages currently set per key
print(" ");
}
print(" ");
- //printHex (keys_averages[(i >> MUXES_COUNT_XSHIFT) + (i & STROBE_LINES_MASK) ]);
printHex (keys_averages[i]);
}
print(" ");
}
print(" ");
- //printHex (keys_averages[(i >> MUXES_COUNT_XSHIFT) + (i & STROBE_LINES_MASK) ]);
- //printHex (keys_averages_acc[i]);
printHex(full_samples[i]);
}
}
+#endif
+#ifdef DEBUG_STROBE_SAMPLES_AVERAGES
// Per strobe information
-// uint8_t cur_strober = 0xe;
uint8_t cur_strober = ze_strober;
print("\n");
printHex(cur_strober);
- //print(": ");
-#if 1
+
// Previously read ADC scans on current strobe
print(" :");
for (uint8_t i=0; i < MUXES_COUNT; ++i) {
// Averages current set on current strobe
print(" :");
-// printHex(threshold);
+
for (uint8_t i=0; i < MUXES_COUNT; ++i) {
print(" ");
printHex(keys_averages[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
}
#endif
- /*
- for (uint8_t i=0; i< SAMPLES; ++i) {
- print(" ");
- printHex(samples[i]);
- //printHex(ADC);
- }*/
- //print(" : ");
- //dPrint((was_active)?" ":"*");
-
- //printHex(keymap[TEST_KEY_STROBE] & TEST_KEY_MASK);
- /*print(" "); */
- //printHex(keymap[TEST_KEY_STROBE]);
-
-
- //print("\n");
- //print(":");
- //printHex(full_av);
- //printHex(count);
- //print(" : ");
+
+#ifdef DEBUG_DELTA_SAMPLE_THRESHOLD
+ print("\n");
+ //uint16_t db_delta = 0;
+ //uint16_t db_sample = 0;
+ //uint16_t db_threshold = 0;
+ printHex( db_delta );
+ print(" ");
+ printHex( db_sample );
+ print(" ");
+ printHex( db_threshold );
+ print(" ");
+ printHex( column );
+#endif
+
+#define DEBUG_USB_KEYMAP
+#ifdef DEBUG_USB_KEYMAP
print("\n ");
// Current keymap values
for (uint8_t i=0; i < STROBE_LINES; ++i) {
printHex(cur_keymap[i]);
print(" ");
-
- //print(" ");
- }
-
-
- //print(": ");
- //printHex(adc_strobe_averages[ze_strober]);
- //print(" ");
-
-
- /* Already printing this above...
- for (uint8_t i=0; i < MUXES_COUNT; ++i) {
- print(" ");
- //printHex(adc_mux_averages[i] + adc_strobe_averages[ze_strober] - full_av);
- //printHex((adc_mux_averages[i] + adc_strobe_averages[ze_strober]) >> 1);
- //printHex((adc_mux_averages[i] * 3 + adc_strobe_averages[ze_strober]) >> 2);
- //printHex(adc_mux_averages[i] + threshold);
- //printHex(gsamples[i + SAMPLE_OFFSET] - (adc_mux_averages[i] + threshold) + 0x100);
- //printHex(keys_averages[(ze_strober << MUXES_COUNT_XSHIFT) + i] + (uint8_t)threshold);
- printHex(keys_averages[(ze_strober << MUXES_COUNT_XSHIFT) + i]);
}
- */
-
- /* Being printed in dumpkeys()
- if(error) {
- print(" ");
- printHex(error);
- print(" ");
- printHex(error_data);
- error = 0;
- error_data = 0;
- }
- //print("\n");
- */
+#endif
ze_strober++;
ze_strober &= 0xf;
-
dump_count++;
dump_count &= 0x0f;
-
-
-
- //ze_strobe = (1 << (ze_strober ) );
-
-
-
- //printHex(ADCSRA);
- //print(" ");
- //print("\n");
}