changeset 83:62069d39b09d

rsync'd over the changes
author Jo Makuch <jmakuch@kvack.org>
date Wed, 10 Apr 2013 14:06:10 -0400
parents 4c267d3734eb
children fcef1286ab60
files Scan/avr-capsense/scan_loop.c Scan/avr-capsense/setup.cmake cmake_install.cmake winbuild.sh
diffstat 4 files changed, 1498 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/avr-capsense/scan_loop.c	Wed Apr 10 14:06:10 2013 -0400
@@ -0,0 +1,1391 @@
+/* Keyboard example with debug channel, for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2008 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "usb_keyboard_debug.h"
+#include "print.h"
+
+#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 THRESHOLD 0x0a
+#define BUMP_THRESHOLD 0x50
+//((THRESHOLD) * 3)
+#define BUMP_REST_US 1200
+
+#define HYST 1
+#define HYST_T 0x10
+
+#define TEST_KEY_STROBE (0x05)
+#define TEST_KEY_MASK (1 << 0)
+
+#define ADHSM 7
+
+/** Whether to use all of D and C, vs using E0, E1 instead of D6, D7,
+ * or alternately all of D, and E0,E1 and C0,..5 */
+//#define ALL_D_C
+//#define SHORT_D
+#define SHORT_C
+
+// rough offset voltage: one diode drop, about 50mV = 0x3ff * 50/3560 = 20
+//#define OFFSET_VOLTAGE 0x14
+#define OFFSET_VOLTAGE 0x28
+
+volatile uint8_t idle_count=1;
+
+uint8_t blink=0;
+
+volatile uint16_t full_av = 0;
+
+#define RIGHT_JUSTIFY 0
+#define LEFT_JUSTIFY (0xff)
+
+// set left or right justification here:
+#define JUSTIFY_ADC RIGHT_JUSTIFY
+
+#define ADLAR_MASK (1 << ADLAR)
+#ifdef JUSTIFY_ADC
+#define ADLAR_BITS ((ADLAR_MASK) & (JUSTIFY_ADC))
+#else // defaults to right justification.
+#define ADLAR_BITS 0
+#endif
+
+
+// full muxmask
+#define FULL_MUX_MASK ((1 << MUX0) | (1 << MUX1) | (1 << MUX2) | (1 << MUX3) | (1 << MUX4))
+
+// 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
+
+
+	// set ADC clock prescale
+#define PRESCALE_MASK ((1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2))
+#define PRESCALE_SHIFT (ADPS0)
+#define PRESCALE 3
+
+
+/**/ uint8_t ze_strober = 0;
+
+#ifdef EXTENDED_STROBE
+
+#define STROBE_LINES 18
+
+#else
+
+#define STROBE_LINES 16
+
+#endif
+
+#define STROBE_LINES_XSHIFT 4
+#define STROBE_LINES_MASK 0x0f
+#define MUXES_COUNT 8
+#define MUXES_COUNT_XSHIFT 3
+#define MUXES_MASK 0x7
+
+#define WARMUP_LOOPS ( 1024 )
+
+#define RECOVERY_US 6
+
+#define SAMPLES 10
+int16_t samples [SAMPLES];
+
+//int16_t gsamples [SAMPLES];
+
+#define SAMPLE_OFFSET ((SAMPLES) - MUXES_COUNT)
+//#define SAMPLE_OFFSET 9
+#define STROBE_OFFSET 0
+
+/**/ int16_t adc_mux_averages[MUXES_COUNT];
+/**/ int16_t adc_strobe_averages[STROBE_LINES];
+
+
+/**/ uint8_t cur_keymap[STROBE_LINES];
+// /**/ int8_t last_keymap[STROBE_LINES];
+/**/ uint8_t usb_keymap[STROBE_LINES];
+uint8_t dirty;
+uint8_t unstable;
+uint8_t usb_dirty;
+
+int16_t threshold = THRESHOLD;
+uint16_t tests = 0;
+
+uint8_t col_a=0;
+uint8_t col_b=0;
+uint8_t col_c=0;
+
+uint8_t column=0;
+
+#define KEY_COUNT ((STROBE_LINES) * (MUXES_COUNT))
+
+int16_t keys_averages_acc[KEY_COUNT];
+uint16_t keys_averages[KEY_COUNT];
+
+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
+*/
+
+/*** 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
+ */
+
+/*volatile*/ uint16_t count = 0;
+
+
+
+/*volatile*/ uint8_t error = 0;
+uint16_t error_data = 0;
+
+void dump(void);
+void dumpkeys(void);
+
+static const uint8_t PROGMEM matrix122F_to_set3[] = {
+0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x84, // (), npenter, np3, (), np+, np9, np*, np-
+0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // np0, np., np2, np5, np6, np8, numlck, np/
+0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, //
+0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+0x00, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // 0x50 vanishes - is test key.
+0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, // 0x48 vanishes - else roll back.
+0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
+0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+0x01, 0x83, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 0x02 is replaced with 0x83.
+};
+
+#define LX2FX
+
+static const uint8_t PROGMEM page3_2_USB[133] = {
+0x0,		// 00   00  // no key.
+
+#ifndef LX2FX
+
+0xe3,		// 01       Enl   Help -> windows. (e3)
+0x0,		// 02		// no key.
+0x80,	// 03   A4  ExSel SetUp print, -> paste 7d -> vol up 80
+0x46,	// 04   A3  CrSel       Properties -> copy 7c -> mute 7f-> prt-scrn
+0x29,	// 05   9A  Attn  SysRq // good place fer escape. (29)
+0x47,		// 06   9C  Clear -> kp / 54 -> scroll-lock (47)
+0x3a,		// 07   3A  F1
+0x68,		// 08   68  F13
+0x65,		// 09       Ctrl	// record/pause // -> kb application (65)
+0x74,		// 0A       Copy  Test // play/test -> execute 74 -> kp + 57
+0x75,		// 0B      // no key. help (75) -> kp - 56
+0x48,		// 0C       Pause ErInp erase input. -> cut 7b -> kp * 55 -> pause 48
+
+#else
+
+/*
+0x42,		// 01       L9
+0x0,		// 02		// no key.
+0x3e,		// 03		L5
+0x3c,		// 04		L3
+0x3a,		// 05      	L1
+0x3b,		// 06      	L2
+0x3a,		// 07   3A  F1
+0x68,		// 08   68  F13
+0x43,		// 09      	L10
+0x41,		// 0A      	L8
+0x3f,		// 0B      	L6
+0x3d,		// 0C      	L4
+*/
+0x61,		// 01       L9 -> num 9  0x61
+0x0,		// 02		// no key.
+0x5d,		// 03		L5 -> num 5  0x5d
+0x5b,		// 04		L3 -> num 3  0x5b
+0x59,		// 05      	L1 -> num 1  0x59
+0x5a,		// 06      	L2 -> num 2  0x5a
+0x3a,		// 07   3A  F1
+0x68,		// 08   68  F13
+0x62,		// 09      	L10 -> num 0 0x62
+0x60,		// 0A      	L8 -> num 8 0x60
+0x5e,		// 0B      	L6 -> num 6 0x5e
+0x5c,		// 0C      	L4 -> num 4 0x5c
+#endif
+
+
+0x2b,		// 0D   2B  Tab
+0x29,		// 0E   35  ~ ` -> escape 29
+0x3b,		// 0F   3B  F2
+0x69,		// 10   69  F14
+0xe0,		// 11   E0  Ctrl L
+0xe1,		// 12   E1  Shift L
+0xe1,		// 13   64  left of z. -> l shift e1
+0x39,		// 14   39  Caps Lock
+0x14,		// 15   14  Q
+0x1e,		// 16   1E  ! 1
+0x3c,		// 17   3C  F3
+0x6a,		// 18   6A  F15
+0xe2,		// 19   E2  Alt L
+0x1d,		// 1A   1D  Z
+0x16,		// 1B   16  S
+0x04,		// 1C   04  A
+0x1a,		// 1D   1A  W
+0x1f,		// 1E   1F  @ 2
+0x3d,		// 1F   3D  F4
+0x6b,		// 20   6B  F16
+0x06,		// 21   06  C
+0x1b,		// 22   1B  X
+0x07,		// 23   07  D
+0x08,		// 24   08  E
+0x21,		// 25   21  $ 4
+0x20,		// 26   20  # 3
+0x3e,		// 27   3E  F5
+0x6c,		// 28   6C  F17
+0x2c,		// 29   2C  Space
+0x19,		// 2A   19  V
+0x09,		// 2B   09  F
+0x17,		// 2C   17  T
+0x15,		// 2D   15  R
+0x22,		// 2E   22  % 5
+0x3f,		// 2F   3F  F6
+0x6d,		// 30   6D  F18
+0x11,		// 31   11  N
+0x05,		// 32   05  B
+0x0b,		// 33   0B  H
+0x0a,		// 34   0A  G
+0x1c,		// 35   1C  Y
+0x23,		// 36   23  ^ 6
+0x40,		// 37   40  F7
+0x6e,		// 38   6E  F19
+0xe6,		// 39   E6  Alt R
+0x10,		// 3A   10  M
+0x0d,		// 3B   0D  J
+0x18,		// 3C   18  U
+0x24,		// 3D   24  & 7
+0x25,		// 3E   25  * 8
+0x41,		// 3F   41  F8
+0x6f,		// 40   6F  F20
+0x36,		// 41   36  < ,
+0x0e,		// 42   0E  K
+0x0c,		// 43   0C  I
+0x12,		// 44   12  O
+0x27,		// 45   27  ) 0
+0x26,		// 46   26  ( 9
+0x42,		// 47   42  F9
+0x70,		// 48   70  F21
+0x37,		// 49   37  > .
+0x38,		// 4A   38  ? /
+0x0f,		// 4B   0F  L
+0x33,		// 4C   33  : ;
+0x13,		// 4D   13  P
+0x2d,		// 4E   2D  _ -
+0x43,		// 4F   43  F10
+0x71,		// 50   71  F22
+0xe5,		// 51   87  likely a shift - e.g. kp shift -> e5
+0x34,		// 52   34  " '
+0x31,		// 53      (INT 2) -> keypad enter. 58 -> |/\ (31)
+0x2f,		// 54   2F  { [
+0x2e,		// 55   2E  + =
+0x44,		// 56   44  F11
+0x72,		// 57   72  F23  -> vol up.
+0xe4,		// 58   E4  Ctrl R
+0xe5,		// 59   E5  Shift R
+0x28,		// 5A   28  Enter
+0x30,		// 5B   30  } ]
+0x31,		// 5C   31  | '\'
+0x35,		// 5D   -> kp = 67 -> ~` 35
+0x45,		// 5E   45  F12
+0x73,		// 5F   73  F24 -> vol down.
+0x51,		// 60   51  Down CP
+0x50,		// 61   50  Left CP
+0x51, //0x0,// 62       Rule // centre cp.  //62   48  Pause/Bk
+0x52,		// 63   52  Up CP
+0x4c,		// 64   4C  Del CP
+0x4d,		// 65   4D  End CP
+0x2a,		// 66   2A  Back Space
+0x49,		// 67   49  Ins CP
+0x48,		// 68		// under kp0 => kp 0 (62) 48 -> pause (48)
+0x59,		// 69   59  1 End KP
+0x4f,		// 6A   4F  Right CP
+0x5c,		// 6B   5C  4 Left KP
+0x5f,		// 6C   5F  7 Home KP
+0x4e,		// 6D   4E  PgDn CP
+0x4a,		// 6E   4A  Home CP
+0x4b,		// 6F   4B  PgUp CP
+0x62,		// 70   62  0 Ins KP -> pause (+48) -> kp-0 (62)
+0x63,		// 71   63  . Del KP
+0x5a,		// 72   5A  2 Down KP
+0x5d,		// 73   97  5 KP
+0x5e,		// 74   5E  6 Right KP
+0x60,		// 75   60  8 Up KP
+0x53,		// 76   53  Num Lock
+0x54,		// 77   54  / KP
+0x47,		// 78       Undo // under enter -> scroll-lock 47
+0x58,		// 79   58  Enter KP ->  enter kp
+0x5b,		// 7A   5B  3 PgDn KP
+0x46,		// 7B       (INT 5) // under + -> print screen (46
+0x57,		// 7C   57  + KP
+0x61,		// 7D   61  9 PgUp KP
+0x55,		// 7E   55  * KP
+0x0,		// 7F			no such key?
+0x0,		// 80           no such key
+0x0,		// 81              Paste?
+0x0,		// 82              Find?
+#ifndef LX2FX
+0x81,		// 83   Print Ident -> undo 7a -> vol down 81
+#else
+//0x40,		// 83   L7 (f1) 3a
+0x5f,		// 83   L7 (f1) 3a -> num 7 0x5f
+#endif
+0x56		// 84   56  - KP
+};
+
+void
+_delay_loop(uint8_t __count)
+{
+	__asm__ volatile (
+		"1: dec %0" "\n\t"
+		"brne 1b"
+		: "=r" (__count)
+		: "0" (__count)
+	);
+}
+
+
+void setup_ADC (void) {
+	// disable adc digital pins.
+	DIDR1 |= (1 << AIN0D) | (1<<AIN1D); // set disable on pins 1,0.
+	//DIDR0 = 0xff; // disable all. (port F, usually). - testing w/o disable.
+	DDRF = 0x0;
+	PORTF = 0x0;
+	uint8_t mux = 0 & 0x1f; // 0 == first. // 0x1e = 1.1V ref.
+
+	// 0 = external aref 1,1 = 2.56V internal ref
+	uint8_t aref = ((1 << REFS1) | (1 << REFS0)) & ((1 << REFS1) | (1 << REFS0));
+//	uint8_t adlar = 0xff & (1 << ADLAR); // 1 := left justify bits, 0 := right
+	uint8_t adate = (1 << ADATE) & (1 << ADATE); // trigger enable
+	uint8_t trig = 0 & ((1 << ADTS0) | (1 << ADTS1) | (1 << ADTS2)); // 0 = free running
+	// ps2, ps1 := /64 ( 2^6 ) ps2 := /16 (2^4), ps1 := 4, ps0 :=2, PS1,PS0 := 8 (2^8)
+	uint8_t prescale = ( ((PRESCALE) << PRESCALE_SHIFT) & PRESCALE_MASK ); // 001 == 2^1 == 2
+	uint8_t hispeed = (1 << ADHSM);
+	uint8_t en_mux = (1 << ACME);
+
+	//ADCSRA = (ADCSRA & ~PRESCALES) | ((1 << ADPS1) | (1 << ADPS2)); // 2, 1 := /64 ( 2^6 )
+	//ADCSRA = (ADCSRA & ~PRESCALES) | ((1 << ADPS0) | (1 << ADPS2)); // 2, 0 := /32 ( 2^5 )
+	//ADCSRA = (ADCSRA & ~PRESCALES) | ((1 << ADPS2)); // 2 := /16 ( 2^4 )
+
+	ADCSRA = (1 << ADEN) | prescale; // ADC enable
+
+	// select ref.
+	//ADMUX |= ((1 << REFS1) | (1 << REFS0)); // 2.56 V internal.
+	//ADMUX |= ((1 << REFS0) ); // Vcc with external cap.
+	//ADMUX &= ~((1 << REFS1) | (1 << REFS0)); // 0,0 : aref.
+	ADMUX = aref | mux | ADLAR_BITS;
+
+	// enable MUX
+	// ADCSRB |= (1 << ACME); 	// enable
+	// ADCSRB &= ~(1 << ADEN); // ?
+
+	// select first mux.
+	//ADMUX = (ADMUX & ~MUXES); // start at 000 = ADC0
+
+	// clear adlar to left justify data
+	//ADMUX = ~();
+
+	// set adlar to right justify data
+	//ADMUX |= (1 << ADLAR);
+
+
+	// set free-running
+	ADCSRA |= adate; // trigger enable
+	ADCSRB  = en_mux | hispeed | trig | (ADCSRB & ~((1 << ADTS0) | (1 << ADTS1) | (1 << ADTS2))); // trigger select free running
+
+//	ADCSRA |= (1 << ADATE); // tiggger enable
+
+	ADCSRA |= (1 << ADEN); // ADC enable
+	ADCSRA |= (1 << ADSC); // start conversions q
+
+}
+
+
+#define RECOVERY_CONTROL 1
+
+#define RECOVERY_SOURCE 0
+#define RECOVERY_SINK 2
+#define RECOVERY_MASK 0x03
+
+void recovery(uint8_t on) {
+	DDRB |= (1 << RECOVERY_CONTROL);
+
+	PORTB &= ~(1 << RECOVERY_SINK);    // SINK always zero
+	DDRB &= ~(1 << RECOVERY_SOURCE);  // SOURCE high imp
+
+	if(on) {
+		DDRB |= (1 << RECOVERY_SINK);	// SINK pull
+
+
+		PORTB |= (1 << RECOVERY_CONTROL);
+
+		PORTB |= (1 << RECOVERY_SOURCE); // SOURCE high
+		DDRB |= (1 << RECOVERY_SOURCE);
+	} else {
+		_delay_loop(10);
+		PORTB &= ~(1 << RECOVERY_CONTROL);
+
+		DDRB &= ~(1 << RECOVERY_SOURCE);
+		PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low
+		DDRB &= ~(1 << RECOVERY_SINK);	// SINK high-imp
+
+		//DDRB &= ~(1 << RECOVERY_SINK);
+	}
+}
+
+void strobe_w(uint8_t strobe_num) {
+
+#ifdef ALL_D_C
+
+#define D_MASK (0xff)
+#define D_SHIFT 0
+
+#define E_MASK (0x00)
+#define E_SHIFT 0
+
+#define C_MASK (0xff)
+#define C_SHIFT 8
+
+#else
+#if defined(SHORT_D)
+
+#define D_MASK (0x3f)
+#define D_SHIFT 0
+
+#define E_MASK (0x03)
+#define E_SHIFT 6
+
+#define C_MASK (0xff)
+#define C_SHIFT 8
+
+#else
+#if defined(SHORT_C)
+
+#define D_MASK (0xff)
+#define D_SHIFT 0
+
+#define E_MASK (0x03)
+#define E_SHIFT 6
+
+#define C_MASK (0xff)
+#define C_SHIFT 8
+#endif
+#endif
+#endif
+
+
+
+#define STROBE_CASE(SC_CASE, SC_REG_A) case (SC_CASE): PORT##SC_REG_A = \
+	(( (PORT##SC_REG_A) & ~(1 << (SC_CASE - SC_REG_A##_SHIFT)) ) | (1 << (SC_CASE - SC_REG_A##_SHIFT)))
+
+	PORTC &= ~(D_MASK);
+	PORTD &= ~(D_MASK);
+	PORTE &= ~(E_MASK);
+
+#ifdef SHORT_C
+	strobe_num = 15 - strobe_num;
+#endif
+
+	switch(strobe_num) {
+
+	case 0: PORTD |= (1 << 0); break;
+	case 1: PORTD |= (1 << 1); break;
+	case 2: PORTD |= (1 << 2); break;
+	case 3: PORTD |= (1 << 3); break;
+	case 4: PORTD |= (1 << 4); break;
+	case 5: PORTD |= (1 << 5); break;
+
+#ifdef ALL_D
+
+	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;
+
+	case 16: PORTE |= (1 << 0); break;
+	case 17: PORTE |= (1 << 1); break;
+
+#else
+#ifdef SHORT_D
+
+	case 6: PORTE |= (1 << 0); break;
+	case 7: PORTE |= (1 << 1); 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;
+
+#else
+#ifdef SHORT_C
+
+	case 6: PORTD |= (1 << 6); break;
+	case 7: PORTD |= (1 << 7); break;
+
+	case 8: PORTE |= (1 << 0); break;
+	case 9: PORTE |= (1 << 1); break;
+
+	case 10:  PORTC |= (1 << 0); break;
+	case 11:  PORTC |= (1 << 1); break;
+	case 12: PORTC |= (1 << 2); break;
+	case 13: PORTC |= (1 << 3); break;
+	case 14: PORTC |= (1 << 4); break;
+	case 15: PORTC |= (1 << 5); break;
+
+	case 16: PORTC |= (1 << 6); break;
+	case 17: PORTC |= (1 << 7); break;
+
+#endif
+#endif
+#endif
+
+	default:
+		break;
+	}
+
+}
+
+
+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;
+
+	for (uint8_t i=0; i<8; ++i) {
+		if(muxes & (1 << i)) {
+			buffer[index++] = i;
+		}
+	}
+
+	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.
+
+	uint16_t sample;
+
+	while (! (ADCSRA & (1 << ADIF))); // wait until ready.
+	sample = ADC; // 1st sample, icky.
+
+	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
+	 *
+	 * */
+
+
+	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.
+
+#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) {
+
+		// setup i'th read.
+		SET_FULL_MUX(buffer[i]); // _next_ read will use this.
+
+		ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+		while (! (ADCSRA & (1 << ADIF)));
+		sample = ADC; // throw away warmup value.
+
+
+
+		/*
+		ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+		while (! (ADCSRA & (1 << ADIF)));
+		sample = ADC; // throw away warmup value.
+*/
+
+		ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+		while (! (ADCSRA & (1 << ADIF)));
+
+		// retrieve current read.
+		buffer[i] = ADC - OFFSET_VOLTAGE;
+
+
+	}
+#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;
+
+}
+
+int sampleColumn_k(uint8_t column, int16_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.
+	sample = ADC; // throw it away.
+
+	for(uint8_t mux=0; mux < 8; ++mux) {
+
+		PORTC &= ~C_MASK;
+		PORTD &= ~D_MASK;
+		PORTE &= ~E_MASK;
+
+		SET_FULL_MUX(mux); // our sample will use this
+
+		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.
+		}
+
+		recovery(0);
+		strobe_w(column);
+
+		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.
+
+		ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+		while (! (ADCSRA & (1 << ADIF)));
+
+		// retrieve current read.
+		buffer[mux] = ADC - OFFSET_VOLTAGE;
+		recovery(1);
+
+	}
+
+	// turn off adc.
+	ADCSRA &= ~(1 << ADEN);
+
+	// pull all columns' probe-lines low.
+	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);
+
+	for(uint8_t i=0; i<8; ++i) {
+		if(samples[SAMPLE_OFFSET + i] - adc_mux_averages[i] > BUMP_THRESHOLD) {
+			// was a hump
+
+			_delay_us(BUMP_REST_US);
+			rval++;
+			error = 0x50;
+			error_data = samples[SAMPLE_OFFSET +i]; //  | ((uint16_t)i << 8);
+			return rval;
+		}
+	}
+
+	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) {
+		uint16_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + i];
+		if ((int16_t)samples[SAMPLE_OFFSET + i] > threshold + delta) {
+			column |= bit;
+		}
+		bit <<= 1;
+	}
+    return column;
+}
+
+int main(void) {
+	// set for 16 MHz clock
+	CPU_PRESCALE(0);
+
+	// Initialize the USB, and then wait for the host to set configuration.
+	// If the Teensy is powered without a PC connected to the USB port,
+	// this will wait forever.
+	usb_init();
+	while (!usb_configured()) /* wait */ ;
+
+	// Wait an extra second for the PC's operating system to load drivers
+	// and do whatever it does to actually be ready for input
+	_delay_ms(1000);
+
+	LED_CONFIG;
+
+	setup_ADC();
+
+	// Configure timer 0 to generate a timer overflow interrupt every
+	// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
+	// This demonstrates how to use interrupts to implement a simple
+	// inactivity timeout.
+	//TCCR0A = 0x00;
+	//TCCR0B = 0x05;
+	//TIMSK0 = (1<<TOIE0);
+
+	DDRC = C_MASK;
+	PORTC = 0;
+	DDRD = D_MASK;
+	PORTD = 0;
+	DDRE = E_MASK;
+	PORTE = 0 ;
+
+	//DDRC |= (1 << 6);
+	//PORTC &= ~(1<< 6);
+
+	//uint16_t strobe = 1;
+
+
+	uint8_t strober = 0;
+	uint32_t full_av_acc = 0;
+
+	for (int i=0; i< STROBE_LINES; ++i) {
+		cur_keymap[i] = 0;
+		//last_keymap[i] = 0;
+		usb_keymap[i] = 0;
+	}
+
+	int16_t mux_averages[MUXES_COUNT];
+	for(int i=0; i < MUXES_COUNT; ++i) {
+		adc_mux_averages[i] = 0x20; // experimentally determined.
+	}
+	int16_t strobe_averages[STROBE_LINES];
+	for(int i=0; i < STROBE_LINES; ++i) {
+		adc_strobe_averages[i] = 0x20; // yup.
+	}
+
+	for(int i=0; i< KEY_COUNT; ++i) {
+		keys_averages[i] = 0x40;
+		keys_averages_acc[i] = (0x400);
+	}
+
+	/** warm things up a bit before we start collecting data, taking real samples. */
+	for(uint8_t i = 0; i< STROBE_LINES; ++i) {
+		sampleColumn(i);
+	}
+
+	while(1) {
+
+		for (strober = 0; strober < STROBE_LINES; ++strober) {
+
+			uint8_t tries;
+			tries = 1;
+			while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+			column = testColumn(strober);
+
+			if( column != cur_keymap[strober] && (count >= WARMUP_LOOPS) ) {
+				tests++;
+
+				tries = 1;
+				while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+				col_a = testColumn(strober);
+
+				tries = 1;
+				while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+				col_b = testColumn(strober);
+
+				tries = 1;
+				while (tries++ && sampleColumn(strober)) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+				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;
+				}
+			}
+
+			if(error == 0x50) {
+				error_data |= (((uint16_t)strober) << 12);
+			}
+
+			for(int i=0; i<MUXES_COUNT; ++i) {
+				full_samples[(strober << MUXES_COUNT_XSHIFT) + i] = samples[SAMPLE_OFFSET + i];
+			}
+
+			strobe_averages[strober] = 0;
+			for (uint8_t i = SAMPLE_OFFSET; i < (SAMPLE_OFFSET + MUXES_COUNT); ++i) {
+				//samples[i] -= samples[i-SAMPLE_OFFSET]; // av; // + full_av); // -something.
+				//samples[i] -= OFFSET_VOLTAGE; // moved to sampleColumn.
+
+				full_av_acc += (samples[i]);
+				mux_averages[i - SAMPLE_OFFSET] += samples[i];
+				strobe_averages[strober] += samples[i];
+				//samples[i] -= (full_av - HYST_T);
+
+				//++count;
+			}
+			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
+					>= 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];
+			}
+
+		} // for strober
+
+		if (count < WARMUP_LOOPS) {
+			error = 0x0C;
+			error_data = count;
+			count++;
+		}
+
+		// verify test key is not down.
+		if((cur_keymap[TEST_KEY_STROBE] & TEST_KEY_MASK) ) {
+			//count=0;
+			error = 0x05;
+			error_data = cur_keymap[TEST_KEY_STROBE] << 8;
+			error_data += full_samples[TEST_KEY_STROBE * 8];
+			//threshold++;
+		}
+
+		// calc mux averages.
+		if (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) {
+
+// mix in 1/4 of the current average to the running average. -> (@mux_mix = 2)
+#define 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;
+			}
+
+		}
+
+#define IDLE_COUNT_MASK 0xff
+#define MAX_ICS 8
+
+#define IDLE_COUNT_SHIFT 4
+#define KEYS_AVERAGES_MIX 2
+
+		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];
+			}
+
+			dumpkeys();
+			usb_dirty=0;
+			_delay_ms(2);
+		}
+
+		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];
+
+				av = av + av + av + acc;
+				av >>= 2;
+
+				keys_averages[i] = av;
+				keys_averages_acc[i] = 0;
+			}
+		}
+
+
+		if(!idle_count) {
+
+			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.
+		}
+	}
+}
+
+
+void debug_println() {
+	usb_debug_putchar('\r');
+	usb_debug_putchar('\n');
+}
+
+
+// This interrupt routine is run approx 61 times per second.
+// A very simple inactivity timeout is implemented, where we
+// will send a space character and print a message to the
+// hid_listen debug message window.
+ISR(TIMER0_OVF_vect) {
+	//idle_count++;
+	/*
+	if (idle_count > 61) {
+		idle_count = 0;
+	}*/
+
+}
+
+void dumpkeys(void) {
+	//print(" \n");
+	if(error) {
+		for (uint8_t i=0; i < STROBE_LINES; ++i) {
+				phex(usb_keymap[i]);
+				usb_debug_putchar(' ');
+
+				//print(" ");
+		}
+		if (count >= WARMUP_LOOPS && error) {
+			dump();
+		}
+
+		print(" : ");
+		phex(error);
+		error = 0;
+		print(" : ");
+		phex16(error_data);
+		error_data = 0;
+		print(" : ");
+		debug_println();
+	}
+
+
+	for(uint8_t i = 0; i < 6; ++i) {
+		keyboard_keys[i] = 0;
+	}
+	keyboard_modifier_keys = 0;
+	uint8_t usbkeycount = 0;
+	for (uint8_t i=0; i < STROBE_LINES; ++i) {
+		for(uint8_t j=0; j<MUXES_COUNT; ++j) {
+			if ( usb_keymap[i] & (1 << j) ) {
+				uint8_t key = pgm_read_byte(matrix122F_to_set3 + ( (i << MUXES_COUNT_XSHIFT) + j) );
+				if(usb_dirty) phex( key );
+				if(usbkeycount < 6) {
+					uint8_t usbkey = pgm_read_byte(page3_2_USB + key);
+
+					if ((usbkey >= 0xe0) && (usbkey <= 0xe7)) { // metas
+						keyboard_modifier_keys |= (1 << (usbkey & 0x07));
+					} else {
+						keyboard_keys[usbkeycount++] =  usbkey;
+					}
+				}
+				if (usb_dirty) usb_debug_putchar(' ');
+			}
+		}
+	}
+	if(usb_dirty) {
+		debug_println();
+	}
+
+	/** shall we send actual keyboard events? */
+#if 0
+	usb_keyboard_send();
+#endif
+
+}
+
+// taken from the datasheet.
+uint8_t readEE(uint16_t offset) {
+	/* Wait for completion of previous write */
+	while(EECR & (1<<EEPE))
+	;
+	/* Set up address register */
+	EEAR = offset;
+	/* Start eeprom read by writing EERE */
+	EECR |= (1<<EERE);
+	/* Return data from Data Register */
+	return EEDR;
+}
+
+// taken from the datasheet - note: writing is very slow. >1ms/byte.
+void writeEE(uint16_t offset, uint8_t data) {
+	/* Wait for completion of previous write */
+	while(EECR & (1<<EEPE))
+	;
+	/* Set up address and Data Registers */
+	EEAR = offset;
+	EEDR = data;
+	/* Write logical one to EEMPE */
+	EECR |= (1<<EEMPE);
+	/* Start eeprom write by setting EEPE */
+	EECR |= (1<<EEPE);
+}
+
+uint8_t dump_count = 0;
+void dump(void) {
+
+#if 0
+	static char once = 0;
+	uint8_t eb;
+
+	if(!once) {
+		print("\nwriting ee");
+		eb = readEE(0x10);
+		eb++;
+		writeEE(0x10, eb);
+
+		once++;
+	}
+
+
+	print("\n ee: ");
+	for(uint16_t i=0x10; i< 0x18; ++i) {
+		phex(readEE(i));
+		pchar(0x20);
+	}
+#endif
+
+	if(!dump_count) {  // we don't want to debug-out during the measurements.
+
+		for(int i =0; i< KEY_COUNT; ++i) {
+			if(!(i & 0x0f)) {
+				print("\n");
+			} else if (!(i & 0x07)) {
+				print("  ");
+			}
+			usb_debug_putchar(' ');
+			//phex16 (keys_averages[(i >> MUXES_COUNT_XSHIFT) + (i & STROBE_LINES_MASK) ]);
+			phex (keys_averages[i]);
+		}
+
+		print("\n");
+
+		for(int i =0; i< KEY_COUNT; ++i) {
+			if(!(i & 0x0f)) {
+				print("\n");
+			} else if (!(i & 0x07)) {
+				print("  ");
+			}
+			usb_debug_putchar(' ');
+			//phex16 (keys_averages[(i >> MUXES_COUNT_XSHIFT) + (i & STROBE_LINES_MASK) ]);
+			//phex16 (keys_averages_acc[i]);
+			phex(full_samples[i]);
+		}
+	}
+
+
+	//}
+
+//	uint8_t cur_strober = 0xe;
+	uint8_t cur_strober = ze_strober;
+	print("\n");
+
+	phex(cur_strober);
+	//print(":         ");
+	print(": ");
+#if 1
+	print("\n");
+	for (uint8_t i=0; i < MUXES_COUNT; ++i) {
+		usb_debug_putchar(' ');
+		phex16(full_samples[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
+	}
+
+	print("\n");
+//	phex(threshold);
+//	print(": ");
+
+	for (uint8_t i=0; i < MUXES_COUNT; ++i) {
+		usb_debug_putchar(' ');
+		phex16(keys_averages[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
+	}
+
+#endif
+	/*
+	for (uint8_t i=0; i< SAMPLES; ++i) {
+		print(" ");
+		phex16(samples[i]);
+		//phex16(ADC);
+	}*/
+	//print(" : ");
+	//usb_debug_putchar((was_active)?' ':'*');
+
+	//phex16(keymap[TEST_KEY_STROBE] & TEST_KEY_MASK);
+	/*print(" "); */
+	//phex(keymap[TEST_KEY_STROBE]);
+
+
+	//print("\n");
+	//print(":");
+	//phex(full_av);
+	//phex16(count);
+	//print(" : ");
+	print("\n");
+
+	for (uint8_t i=0; i < STROBE_LINES; ++i) {
+		phex(cur_keymap[i]);
+		usb_debug_putchar(' ');
+
+		//print(" ");
+	}
+
+
+	//print(": ");
+	//phex(adc_strobe_averages[ze_strober]);
+	//usb_debug_putchar(' ');
+
+
+
+	for (uint8_t i=0; i < MUXES_COUNT; ++i) {
+		usb_debug_putchar(' ');
+		//phex16(adc_mux_averages[i] + adc_strobe_averages[ze_strober] - full_av);
+		//phex16((adc_mux_averages[i] + adc_strobe_averages[ze_strober]) >> 1);
+		//phex16((adc_mux_averages[i] * 3  + adc_strobe_averages[ze_strober]) >> 2);
+		//phex16(adc_mux_averages[i] + threshold);
+		//phex16(gsamples[i + SAMPLE_OFFSET] - (adc_mux_averages[i] + threshold) + 0x100);
+		//phex16(keys_averages[(ze_strober << MUXES_COUNT_XSHIFT) + i] + (uint8_t)threshold);
+		phex16(keys_averages[(ze_strober << MUXES_COUNT_XSHIFT) + i]);
+	}
+
+	if(error) {
+		usb_debug_putchar(' ');
+		phex (error);
+		usb_debug_putchar(' ');
+		phex16(error_data);
+		error = 0;
+		error_data = 0;
+	}
+	//print("\n");
+
+	ze_strober++;
+	ze_strober &= 0xf;
+
+
+	dump_count++;
+	dump_count &= 0x0f;
+
+
+
+	//ze_strobe = (1 << (ze_strober ) );
+
+
+
+	//phex(ADCSRA);
+	//print(" ");
+			//print("\n");
+	//usb_keyboard_press(KEY_SPACE, 0);
+
+//		if(blink) {
+//			LED_ON;
+//		} else {
+//			LED_OFF;
+//		}
+//		blink ^= 1;
+}
+
+
+/*
+int oldmain(void) {
+	uint8_t b, d, mask, i, reset_idle;
+	uint8_t b_prev=0xFF, d_prev=0xFF;
+
+	// set for 16 MHz clock
+	CPU_PRESCALE(0);
+
+	// Configure all port B and port D pins as inputs with pullup resistors.
+	// See the "Using I/O Pins" page for details.
+	// http://www.pjrc.com/teensy/pins.html
+	DDRD = 0x00;
+	DDRB = 0x00;
+	PORTB = 0xFF;
+	PORTD = 0xFF;
+
+	// Initialize the USB, and then wait for the host to set configuration.
+	// If the Teensy is powered without a PC connected to the USB port,
+	// this will wait forever.
+	usb_init();
+	while (!usb_configured())  ;
+
+	// Wait an extra second for the PC's operating system to load drivers
+	// and do whatever it does to actually be ready for input
+	_delay_ms(1000);
+
+	// Configure timer 0 to generate a timer overflow interrupt every
+	// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
+	// This demonstrates how to use interrupts to implement a simple
+	// inactivity timeout.
+	TCCR0A = 0x00;
+	TCCR0B = 0x05;
+	TIMSK0 = (1<<TOIE0);
+
+	print("Begin keyboard example program\n");
+	print("All Port B or Port D pins are inputs with pullup resistors.\n");
+	print("Any connection to ground on Port B or D pins will result in\n");
+	print("keystrokes sent to the PC (and debug messages here).\n");
+	while (1) {
+		// read all port B and port D pins
+		b = PINB;
+		d = PIND;
+		// check if any pins are low, but were high previously
+		mask = 1;
+		reset_idle = 0;
+		for (i=0; i<8; i++) {
+			if (((b & mask) == 0) && (b_prev & mask) != 0) {
+				usb_keyboard_press(KEY_B, KEY_SHIFT);
+				usb_keyboard_press(number_keys[i], 0);
+				print("Port B, bit ");
+				phex(i);
+				print("\n");
+				reset_idle = 1;
+			}
+			if (((d & mask) == 0) && (d_prev & mask) != 0) {
+				usb_keyboard_press(KEY_D, KEY_SHIFT);
+				usb_keyboard_press(number_keys[i], 0);
+				print("Port D, bit ");
+				phex(i);
+				print("\n");
+				reset_idle = 1;
+			}
+			mask = mask << 1;
+		}
+		// if any keypresses were detected, reset the idle counter
+		if (reset_idle) {
+			// variables shared with interrupt routines must be
+			// accessed carefully so the interrupt routine doesn't
+			// try to use the variable in the middle of our access
+			cli();
+			idle_count = 0;
+			sei();
+		}
+		// now the current pins will be the previous, and
+		// wait a short delay so we're not highly sensitive
+		// to mechanical "bounce".
+		b_prev = b;
+		d_prev = d;
+		_delay_ms(2);
+	}
+}
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/avr-capsense/setup.cmake	Wed Apr 10 14:06:10 2013 -0400
@@ -0,0 +1,43 @@
+###| CMake Kiibohd Controller Scan Module |###
+#
+# Written by Jacob Alexander in 2011 for the Kiibohd Controller
+#
+# Released into the Public Domain
+#
+###
+
+
+###
+# Module C files
+#
+
+#| XXX Requires the ../ due to how the paths are constructed
+set( SCAN_SRCS
+	../matrix/matrix_scan.c
+	../matrix/scan_loop.c
+)
+
+
+###
+# Module Specific Options
+#
+add_definitions( -I${HEAD_DIR}/Keymap )
+add_definitions(
+	-I${HEAD_DIR}/Scan/matrix
+)	
+
+#| Keymap Settings
+add_definitions(
+	-DMODIFIER_MASK=budkeypad_ModifierMask
+	#-DKEYINDEX_MASK=budkeypad_TheProfosistMap
+	-DKEYINDEX_MASK=budkeypad_DefaultMap
+)
+
+
+###
+# Compiler Family Compatibility
+#
+set( ScanModuleCompatibility
+	avr
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake_install.cmake	Wed Apr 10 14:06:10 2013 -0400
@@ -0,0 +1,39 @@
+# Install script for directory: L:/haata/kiibohd
+
+# Set the install prefix
+IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
+  SET(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/kiibohd_controller")
+ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
+STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+  IF(BUILD_TYPE)
+    STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+           CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+  ELSE(BUILD_TYPE)
+    SET(CMAKE_INSTALL_CONFIG_NAME "")
+  ENDIF(BUILD_TYPE)
+  MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+
+# Set the component getting installed.
+IF(NOT CMAKE_INSTALL_COMPONENT)
+  IF(COMPONENT)
+    MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
+    SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+  ELSE(COMPONENT)
+    SET(CMAKE_INSTALL_COMPONENT)
+  ENDIF(COMPONENT)
+ENDIF(NOT CMAKE_INSTALL_COMPONENT)
+
+IF(CMAKE_INSTALL_COMPONENT)
+  SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
+ELSE(CMAKE_INSTALL_COMPONENT)
+  SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
+ENDIF(CMAKE_INSTALL_COMPONENT)
+
+FILE(WRITE "L:/haata/kiibohd/${CMAKE_INSTALL_MANIFEST}" "")
+FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})
+  FILE(APPEND "L:/haata/kiibohd/${CMAKE_INSTALL_MANIFEST}" "${file}\n")
+ENDFOREACH(file)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/winbuild.sh	Wed Apr 10 14:06:10 2013 -0400
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+#temp jo
+#export PATH="/c/WinAVR-20100110/bin:/c/Program Files (x86)/CMake 2.8/bin:${PATH}"
+#echo $PATH
+export PATH="/c/WinAVR-20100110/bin:/c/Program Files (x86)/CMake 2.8/bin:/usr/local/bin:/usr/bin:/bin:/c/Windows/system32"
+echo $PATH
+
+
+which cmake.exe
+which -a cmake.exe
+which avr-gcc
+which make
+#alias cmake="cmake.exe"
+#alias make="avr-nm"
+
+#cd build
+cmake -G "Unix Makefiles" -D \
+CMAKE_C_COMPILER="C:/WinAVR-20100110/bin/avr-gcc.exe" \
+-D CMAKE_CXX_COMPILER="C:/WinAVR-20100110/bin/avr-g++.exe" .
+#cd ..
+make
+#nm
+
+#./buildall.bash