changeset 123:0c5d1fe99302

Adding CLI and CDC Serial support for Teensy 2.0 and Teensy 2.0++ - Includes serial putchar and getchar cleanup (overall) - Moved avr-capsense to DPH (renaming) - Basic cleanup for including CLI on the avr architecture
author Jacob Alexander <haata@kiibohd.com>
date Mon, 31 Mar 2014 01:07:48 -0700
parents 2bb16439e6ca
children 2b81083dcaef
files CMakeLists.txt Debug/cli/cli.c Debug/print/print.c Debug/print/print.h Lib/_buildvars.h Output/pjrcUSB/arm/usb_desc.c Output/pjrcUSB/arm/usb_desc.h Output/pjrcUSB/avr/usb_keyboard_debug.c Output/pjrcUSB/avr/usb_keyboard_debug.h Output/pjrcUSB/avr/usb_keyboard_serial.c Output/pjrcUSB/avr/usb_keyboard_serial.h Output/pjrcUSB/output_com.c Output/pjrcUSB/output_com.h Output/pjrcUSB/setup.cmake README Scan/DPH/scan_loop.c Scan/DPH/scan_loop.h Scan/DPH/setup.cmake Scan/SKM67001/setup.cmake Scan/avr-capsense/scan_loop.c Scan/avr-capsense/scan_loop.h Scan/avr-capsense/setup.cmake Scan/matrix/matrix_scan.c Scan/matrix/matrix_scan.h Scan/matrix/matrix_template.h Scan/matrix/scan_loop.c Scan/matrix/scan_loop.h avr.cmake main.c setup.cmake
diffstat 30 files changed, 2724 insertions(+), 2061 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Sat Mar 22 14:32:06 2014 -0700
+++ b/CMakeLists.txt	Mon Mar 31 01:07:48 2014 -0700
@@ -28,8 +28,8 @@
 #| "avr"       # Teensy++ 2.0
 #| "arm"       # Teensy   3.0
 #| "arm"       # Teensy   3.1
-set( COMPILER_FAMILY "arm" )
-#set( COMPILER_FAMILY "avr" )
+#set( COMPILER_FAMILY "arm" )
+set( COMPILER_FAMILY "avr" )
 
 message( STATUS "Compiler Family:" )
 message( "${COMPILER_FAMILY}" )
@@ -138,9 +138,10 @@
 #
 
 #| After Changes Size Information
+#| TODO Do lookup on Flash and RAM sizes and do % used
 add_custom_target( SizeAfter ALL ${SIZE} --target=${FORMAT} ${TARGET_HEX} ${TARGET_ELF}
 	DEPENDS ${TARGET_ELF}
-	COMMENT "Size after generation:"
+	COMMENT "Size after generation\n\tFlash Usage: data (hex)\n\t  RAM Usage: data (elf)"
 )
 
 
--- a/Debug/cli/cli.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/Debug/cli/cli.c	Mon Mar 31 01:07:48 2014 -0700
@@ -85,15 +85,14 @@
 	uint8_t prev_buf_pos = CLILineBufferCurrent;
 
 	// Process each character while available
-	int result = 0;
 	while ( 1 )
 	{
 		// No more characters to process
-		result = usb_serial_getchar(); // Retrieve from serial module // TODO Make USB agnostic
-		if ( result == -1 )
+		if ( output_availablechar() == 0 )
 			break;
 
-		char cur_char = (char)result;
+		// Retrieve from output module
+		char cur_char = (char)output_getchar();
 
 		// Make sure buffer isn't full
 		if ( CLILineBufferCurrent >= CLILineBufferMaxSize )
@@ -405,7 +404,7 @@
 void cliFunc_restart( char* args )
 {
 	// Trigger an overall software reset
-	SOFTWARE_RESET();
+	output_softReset();
 }
 
 void cliFunc_version( char* args )
--- a/Debug/print/print.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/Debug/print/print.c	Mon Mar 31 01:07:48 2014 -0700
@@ -31,24 +31,8 @@
 
 // ----- Functions -----
 
-// USB HID String Output
-void usb_debug_putstr( char* s )
-{
-#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
-	while ( *s != '\0' )
-		usb_debug_putchar( *s++ );
-#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
-	// Count characters until NULL character, then send the amount counted
-	uint32_t count = 0;
-	while ( s[count] != '\0' )
-		count++;
-
-	usb_serial_write( s, count );
-#endif
-}
-
 // Multiple string Output
-void usb_debug_putstrs( char* first, ... )
+void printstrs( char* first, ... )
 {
 	// Initialize the variadic function parameter list
 	va_list ap;
@@ -61,7 +45,7 @@
 	while ( !( cur[0] == '\0' && cur[1] == '\0' && cur[2] == '\0' ) )
 	{
 		// Print out the given string
-		usb_debug_putstr( cur );
+		output_putstr( cur );
 
 		// Get the next argument ready
 		cur = va_arg( ap, char* );
@@ -71,21 +55,17 @@
 }
 
 // Print a constant string
-void _print(const char *s)
+void _print( const char* s )
 {
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
+	// Pull string out of flash
 	char c;
-
-	// Acquire the character from flash, and print it, as long as it's not NULL
-	// Also, if a newline is found, print a carrige return as well
-	while ( ( c = pgm_read_byte(s++) ) != '\0' )
+	while ( ( c = pgm_read_byte( s++ ) ) != '\0' )
 	{
-		if ( c == '\n' )
-			usb_debug_putchar('\r');
-		usb_debug_putchar(c);
+		output_putchar( c );
 	}
 #elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
-	usb_debug_putstr( (char*)s );
+	output_putstr( (char*)s );
 #endif
 }
 
--- a/Debug/print/print.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Debug/print/print.h	Mon Mar 31 01:07:48 2014 -0700
@@ -26,15 +26,11 @@
 
 // Compiler Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
-
 #include <avr/pgmspace.h>
-#include "avr/usb_keyboard_debug.h"
+#endif
 
-#elif defined(_mk20dx128_) || defined(_mk20dx256_)
-
-#include "arm/usb_serial.h"
-
-#endif
+// Project Includes
+#include <output_com.h>
 
 
 
@@ -50,15 +46,15 @@
  */
 
 // Function Aliases
-#define dPrint(c)         usb_debug_putstr(c)
-#define dPrintStr(c)      usb_debug_putstr(c)
-#define dPrintStrs(...)   usb_debug_putstrs(__VA_ARGS__, "\0\0\0")      // Convenience Variadic Macro
-#define dPrintStrNL(c)    dPrintStrs       (c, NL)                      // Appends New Line Macro
-#define dPrintStrsNL(...) usb_debug_putstrs(__VA_ARGS__, NL, "\0\0\0")  // Appends New Line Macro
+#define dPrint(c)         output_putstr(c)
+#define dPrintStr(c)      output_putstr(c)
+#define dPrintStrs(...)   printstrs(__VA_ARGS__, "\0\0\0")      // Convenience Variadic Macro
+#define dPrintStrNL(c)    dPrintStrs       (c, NL)              // Appends New Line Macro
+#define dPrintStrsNL(...) printstrs(__VA_ARGS__, NL, "\0\0\0")  // Appends New Line Macro
 
 // Special Msg Constructs (Uses VT100 tags)
 #define dPrintMsg(colour_code_str,msg,...) \
-                          usb_debug_putstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0")
+                          printstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0")
 #define printMsgNL(colour_code_str,msg,str) \
                           print("\033[" colour_code_str "m" msg "\033[0m - " str NL)
 #define printMsg(colour_code_str,msg,str) \
@@ -89,8 +85,7 @@
 #define print(s) _print(PSTR(s))
 
 void _print(const char *s);
-void usb_debug_putstr( char* s );
-void usb_debug_putstrs( char* first, ... );
+void printstrs( char* first, ... );
 
 
 // Printing numbers
--- a/Lib/_buildvars.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Lib/_buildvars.h	Mon Mar 31 01:07:48 2014 -0700
@@ -30,7 +30,7 @@
 
 // You can change these to give your code its own name.
 #define STR_MANUFACTURER	L"@MANUFACTURER@"
-#define STR_PRODUCT		L"ForceGauge - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@"
+#define STR_PRODUCT		L"Keyboard - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@"
 #define STR_SERIAL              L"@GitLastCommitDate@"
 
 
--- a/Output/pjrcUSB/arm/usb_desc.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/Output/pjrcUSB/arm/usb_desc.c	Mon Mar 31 01:07:48 2014 -0700
@@ -1,6 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
+ * Modified by Jacob Alexander (2013-2014)
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -10,10 +11,10 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * 1. The above copyright notice and this permission notice shall be 
+ * 1. The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * 2. If the Software is incorporated into a build system that allows 
+ * 2. If the Software is incorporated into a build system that allows
  * selection among a list of target devices, then similar target
  * devices manufactured by PJRC.COM must be included in the list of
  * target devices and selectable in the same manner.
--- a/Output/pjrcUSB/arm/usb_desc.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Output/pjrcUSB/arm/usb_desc.h	Mon Mar 31 01:07:48 2014 -0700
@@ -1,6 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
+ * Modified by Jacob Alexander (2013-2014)
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -10,10 +11,10 @@
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
  *
- * 1. The above copyright notice and this permission notice shall be 
+ * 1. The above copyright notice and this permission notice shall be
  * included in all copies or substantial portions of the Software.
  *
- * 2. If the Software is incorporated into a build system that allows 
+ * 2. If the Software is incorporated into a build system that allows
  * selection among a list of target devices, then similar target
  * devices manufactured by PJRC.COM must be included in the list of
  * target devices and selectable in the same manner.
@@ -89,6 +90,7 @@
 #define NUM_ENDPOINTS		6
 #define NUM_USB_BUFFERS	30
 #define NUM_INTERFACE		4
+
 #define CDC_IAD_DESCRIPTOR	1
 #define CDC_STATUS_INTERFACE	0
 #define CDC_DATA_INTERFACE	1	// Serial
@@ -98,22 +100,27 @@
 #define CDC_ACM_SIZE          16
 #define CDC_RX_SIZE           64
 #define CDC_TX_SIZE           64
+
 #define KEYBOARD_INTERFACE    2	// Keyboard
 #define KEYBOARD_ENDPOINT     1
 #define KEYBOARD_SIZE         8
 #define KEYBOARD_INTERVAL     1
+
 #define MOUSE_INTERFACE       3	// Mouse
 #define MOUSE_ENDPOINT        5
 #define MOUSE_SIZE            8
 #define MOUSE_INTERVAL        2
+
 #define JOYSTICK_INTERFACE    4	// Joystick
 #define JOYSTICK_ENDPOINT     6
 #define JOYSTICK_SIZE         16
 #define JOYSTICK_INTERVAL     1
+
 #define KEYBOARD_DESC_OFFSET	(9+8 + 9+5+5+4+5+7+9+7+7 + 9)
 #define MOUSE_DESC_OFFSET	(9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
 #define JOYSTICK_DESC_OFFSET	(9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
 #define CONFIG_DESC_SIZE	(9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)
+
 #define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
 #define ENDPOINT2_CONFIG	ENDPOINT_TRANSIMIT_ONLY
 #define ENDPOINT3_CONFIG	ENDPOINT_RECEIVE_ONLY
--- a/Output/pjrcUSB/avr/usb_keyboard_debug.c	Sat Mar 22 14:32:06 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,705 +0,0 @@
-/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
- * http://www.pjrc.com/teensy/usb_keyboard.html
- * Copyright (c) 2009 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.
- */
-
-// Version 1.0: Initial Release
-// Version 1.1: Add support for Teensy 2.0
-
-#define USB_SERIAL_PRIVATE_INCLUDE
-#include "usb_keyboard_debug.h"
-
-/**************************************************************************
- *
- *  Configurable Options
- *
- **************************************************************************/
-
-// USB devices are supposed to implment a halt feature, which is
-// rarely (if ever) used.  If you comment this line out, the halt
-// code will be removed, saving 102 bytes of space (gcc 4.3.0).
-// This is not strictly USB compliant, but works with all major
-// operating systems.
-#define SUPPORT_ENDPOINT_HALT
-
-
-
-/**************************************************************************
- *
- *  Endpoint Buffer Configuration
- *
- **************************************************************************/
-
-#define ENDPOINT0_SIZE		32
-
-#define KEYBOARD_INTERFACE	0
-#define KEYBOARD_ENDPOINT	3
-#define KEYBOARD_SIZE		8
-#define KEYBOARD_BUFFER		EP_DOUBLE_BUFFER
-
-#define DEBUG_INTERFACE		1
-#define DEBUG_TX_ENDPOINT	4
-#define DEBUG_TX_SIZE		32
-#define DEBUG_TX_BUFFER		EP_DOUBLE_BUFFER
-
-static const uint8_t PROGMEM endpoint_config_table[] = {
-	0,
-	0,
-	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
-	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER
-};
-
-
-/**************************************************************************
- *
- *  Descriptor Data
- *
- **************************************************************************/
-
-// Descriptors are the data that your computer reads when it auto-detects
-// this USB device (called "enumeration" in USB lingo).  The most commonly
-// changed items are editable at the top of this file.  Changing things
-// in here should only be done by those who've read chapter 9 of the USB
-// spec and relevant portions of any USB class specifications!
-
-
-static const uint8_t PROGMEM device_descriptor[] = {
-	18,					// bLength
-	1,					// bDescriptorType
-	0x00, 0x02,				// bcdUSB
-	0,					// bDeviceClass
-	0,					// bDeviceSubClass
-	0,					// bDeviceProtocol
-	ENDPOINT0_SIZE,				// bMaxPacketSize0
-	LSB(VENDOR_ID), MSB(VENDOR_ID),		// idVendor
-	LSB(PRODUCT_ID), MSB(PRODUCT_ID),	// idProduct
-	0x00, 0x01,				// bcdDevice
-	1,					// iManufacturer
-	2,					// iProduct
-	3,					// iSerialNumber
-	1					// bNumConfigurations
-};
-
-// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
-static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
-        0x05, 0x01,          // Usage Page (Generic Desktop),
-        0x09, 0x06,          // Usage (Keyboard),
-        0xA1, 0x01,          // Collection (Application),
-        0x75, 0x01,          //   Report Size (1),
-        0x95, 0x08,          //   Report Count (8),
-        0x05, 0x07,          //   Usage Page (Key Codes),
-        0x19, 0xE0,          //   Usage Minimum (224),
-        0x29, 0xE7,          //   Usage Maximum (231),
-        0x15, 0x00,          //   Logical Minimum (0),
-        0x25, 0x01,          //   Logical Maximum (1),
-        0x81, 0x02,          //   Input (Data, Variable, Absolute), ;Modifier byte
-        0x95, 0x01,          //   Report Count (1),
-        0x75, 0x08,          //   Report Size (8),
-        0x81, 0x03,          //   Input (Constant),                 ;Reserved byte
-        0x95, 0x05,          //   Report Count (5),
-        0x75, 0x01,          //   Report Size (1),
-        0x05, 0x08,          //   Usage Page (LEDs),
-        0x19, 0x01,          //   Usage Minimum (1),
-        0x29, 0x05,          //   Usage Maximum (5),
-        0x91, 0x02,          //   Output (Data, Variable, Absolute), ;LED report
-        0x95, 0x01,          //   Report Count (1),
-        0x75, 0x03,          //   Report Size (3),
-        0x91, 0x03,          //   Output (Constant),                 ;LED report padding
-        0x95, 0x06,          //   Report Count (6),
-        0x75, 0x08,          //   Report Size (8),
-        0x15, 0x00,          //   Logical Minimum (0),
-        0x25, 0x68,          //   Logical Maximum(104),
-        0x05, 0x07,          //   Usage Page (Key Codes),
-        0x19, 0x00,          //   Usage Minimum (0),
-        0x29, 0x68,          //   Usage Maximum (104),
-        0x81, 0x00,          //   Input (Data, Array),
-        0xc0                 // End Collection
-};
-
-static const uint8_t PROGMEM debug_hid_report_desc[] = {
-	//0x06, 0x30, 0xFF,			// Usage Page 0xFF31 (vendor defined)
-	0x06, 0x31, 0xFF,			// Usage Page 0xFF31 (vendor defined)
-	0x09, 0x74,				// Usage 0x74
-	0xA1, 0x53,				// Collection 0x53
-	0x75, 0x08,				// report size = 8 bits
-	0x15, 0x00,				// logical minimum = 0
-	0x26, 0xFF, 0x00,			// logical maximum = 255
-	0x95, DEBUG_TX_SIZE,			// report count
-	0x09, 0x75,				// usage
-	0x81, 0x02,				// Input (array)
-	0xC0					// end collection
-};
-
-#define CONFIG1_DESC_SIZE        (9+9+9+7+9+9+7)
-#define KEYBOARD_HID_DESC_OFFSET (9+9)
-#define DEBUG_HID_DESC_OFFSET    (9+9+9+7+9)
-static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
-	// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
-	9, 					// bLength;
-	2,					// bDescriptorType;
-	LSB(CONFIG1_DESC_SIZE),			// wTotalLength
-	MSB(CONFIG1_DESC_SIZE),
-	2,					// bNumInterfaces
-	1,					// bConfigurationValue
-	0,					// iConfiguration
-	0xC0,					// bmAttributes
-	50,					// bMaxPower
-	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
-	9,					// bLength
-	4,					// bDescriptorType
-	KEYBOARD_INTERFACE,			// bInterfaceNumber
-	0,					// bAlternateSetting
-	1,					// bNumEndpoints
-	0x03,					// bInterfaceClass (0x03 = HID)
-	0x01,					// bInterfaceSubClass (0x01 = Boot)
-	0x01,					// bInterfaceProtocol (0x01 = Keyboard)
-	0,					// iInterface
-	// HID interface descriptor, HID 1.11 spec, section 6.2.1
-	9,					// bLength
-	0x21,					// bDescriptorType
-	0x11, 0x01,				// bcdHID
-	0,					// bCountryCode
-	1,					// bNumDescriptors
-	0x22,					// bDescriptorType
-	sizeof(keyboard_hid_report_desc),	// wDescriptorLength
-	0,
-	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
-	7,					// bLength
-	5,					// bDescriptorType
-	KEYBOARD_ENDPOINT | 0x80,		// bEndpointAddress
-	0x03,					// bmAttributes (0x03=intr)
-	KEYBOARD_SIZE, 0,			// wMaxPacketSize
-	1,					// bInterval
-	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
-	9,					// bLength
-	4,					// bDescriptorType
-	DEBUG_INTERFACE,			// bInterfaceNumber
-	0,					// bAlternateSetting
-	1,					// bNumEndpoints
-	0x03,					// bInterfaceClass (0x03 = HID)
-	0x00,					// bInterfaceSubClass
-	0x00,					// bInterfaceProtocol
-	0,					// iInterface
-	// HID interface descriptor, HID 1.11 spec, section 6.2.1
-	9,					// bLength
-	0x21,					// bDescriptorType
-	0x11, 0x01,				// bcdHID
-	0,					// bCountryCode
-	1,					// bNumDescriptors
-	0x22,					// bDescriptorType
-	sizeof(debug_hid_report_desc),		// wDescriptorLength
-	0,
-	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
-	7,					// bLength
-	5,					// bDescriptorType
-	DEBUG_TX_ENDPOINT | 0x80,		// bEndpointAddress
-	0x03,					// bmAttributes (0x03=intr)
-	DEBUG_TX_SIZE, 0,			// wMaxPacketSize
-	1					// bInterval
-};
-
-// If you're desperate for a little extra code memory, these strings
-// can be completely removed if iManufacturer, iProduct, iSerialNumber
-// in the device desciptor are changed to zeros.
-struct usb_string_descriptor_struct {
-	uint8_t bLength;
-	uint8_t bDescriptorType;
-	int16_t wString[];
-};
-static const struct usb_string_descriptor_struct PROGMEM string0 = {
-	4,
-	3,
-	{0x0409}
-};
-static const struct usb_string_descriptor_struct PROGMEM string1 = {
-	sizeof(STR_MANUFACTURER),
-	3,
-	STR_MANUFACTURER
-};
-static const struct usb_string_descriptor_struct PROGMEM string2 = {
-	sizeof(STR_PRODUCT),
-	3,
-	STR_PRODUCT
-};
-static const struct usb_string_descriptor_struct PROGMEM string3 = {
-	sizeof(STR_SERIAL),
-	3,
-	STR_SERIAL
-};
-
-// This table defines which descriptor data is sent for each specific
-// request from the host (in wValue and wIndex).
-static const struct descriptor_list_struct {
-	uint16_t	wValue;
-	uint16_t	wIndex;
-	const uint8_t	*addr;
-	uint8_t		length;
-} PROGMEM descriptor_list[] = {
-	{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
-	{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
-	{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
-	{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
-	{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
-	{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
-	{0x0300, 0x0000, (const uint8_t *)&string0, 4},
-	{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
-	{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)},
-	{0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)}
-};
-#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
-
-
-/**************************************************************************
- *
- *  Variables - these are the only non-stack RAM usage
- *
- **************************************************************************/
-
-// zero when we are not configured, non-zero when enumerated
-static volatile uint8_t usb_configuration=0;
-
-// the time remaining before we transmit any partially full
-// packet, or send a zero length packet.
-static volatile uint8_t debug_flush_timer=0;
-
-
-/**************************************************************************
- *
- *  Public Functions - these are the API intended for the user
- *
- **************************************************************************/
-
-
-// initialize USB
-void usb_init(void)
-{
-	HW_CONFIG();
-	USB_FREEZE();				// enable USB
-	PLL_CONFIG();				// config PLL
-        while (!(PLLCSR & (1<<PLOCK))) ;	// wait for PLL lock
-        USB_CONFIG();				// start USB clock
-        UDCON = 0;				// enable attach resistor
-	usb_configuration = 0;
-        UDIEN = (1<<EORSTE)|(1<<SOFE);
-	sei();
-}
-
-// return 0 if the USB is not configured, or the configuration
-// number selected by the HOST
-uint8_t usb_configured(void)
-{
-	return usb_configuration;
-}
-
-// send the contents of USBKeys_Array and USBKeys_Modifiers
-int8_t usb_keyboard_send(void)
-{
-	uint8_t i, intr_state, timeout;
-
-	if (!usb_configuration) return -1;
-	intr_state = SREG;
-	cli();
-	UENUM = KEYBOARD_ENDPOINT;
-	timeout = UDFNUML + 50;
-	while (1) {
-		// are we ready to transmit?
-		if (UEINTX & (1<<RWAL)) break;
-		SREG = intr_state;
-		// has the USB gone offline?
-		if (!usb_configuration) return -1;
-		// have we waited too long?
-		if (UDFNUML == timeout) return -1;
-		// get ready to try checking again
-		intr_state = SREG;
-		cli();
-		UENUM = KEYBOARD_ENDPOINT;
-	}
-	UEDATX = USBKeys_Modifiers;
-	UEDATX = 0;
-	for (i=0; i<6; i++) {
-		UEDATX = USBKeys_Array[i];
-	}
-	UEINTX = 0x3A;
-	USBKeys_Idle_Count = 0;
-	SREG = intr_state;
-	return 0;
-}
-
-// transmit a character.  0 returned on success, -1 on error
-int8_t usb_debug_putchar(uint8_t c)
-{
-	static uint8_t previous_timeout=0;
-	uint8_t timeout, intr_state;
-
-	// if we're not online (enumerated and configured), error
-	if (!usb_configuration) return -1;
-	// interrupts are disabled so these functions can be
-	// used from the main program or interrupt context,
-	// even both in the same program!
-	intr_state = SREG;
-	cli();
-	UENUM = DEBUG_TX_ENDPOINT;
-	// if we gave up due to timeout before, don't wait again
-	if (previous_timeout) {
-		if (!(UEINTX & (1<<RWAL))) {
-			SREG = intr_state;
-			return -1;
-		}
-		previous_timeout = 0;
-	}
-	// wait for the FIFO to be ready to accept data
-	timeout = UDFNUML + 4;
-	while (1) {
-		// are we ready to transmit?
-		if (UEINTX & (1<<RWAL)) break;
-		SREG = intr_state;
-		// have we waited too long?
-		if (UDFNUML == timeout) {
-			previous_timeout = 1;
-			return -1;
-		}
-		// has the USB gone offline?
-		if (!usb_configuration) return -1;
-		// get ready to try checking again
-		intr_state = SREG;
-		cli();
-		UENUM = DEBUG_TX_ENDPOINT;
-	}
-	// actually write the byte into the FIFO
-	UEDATX = c;
-	// if this completed a packet, transmit it now!
-	if (!(UEINTX & (1<<RWAL))) {
-		UEINTX = 0x3A;
-		debug_flush_timer = 0;
-	} else {
-		debug_flush_timer = 2;
-	}
-	SREG = intr_state;
-	return 0;
-}
-
-
-// immediately transmit any buffered output.
-void usb_debug_flush_output(void)
-{
-	uint8_t intr_state;
-
-	intr_state = SREG;
-	cli();
-	if (debug_flush_timer) {
-		UENUM = DEBUG_TX_ENDPOINT;
-		while ((UEINTX & (1<<RWAL))) {
-			UEDATX = 0;
-		}
-		UEINTX = 0x3A;
-		debug_flush_timer = 0;
-	}
-	SREG = intr_state;
-}
-
-
-
-/**************************************************************************
- *
- *  Private Functions - not intended for general user consumption....
- *
- **************************************************************************/
-
-
-
-// USB Device Interrupt - handle all device-level events
-// the transmit buffer flushing is triggered by the start of frame
-//
-ISR(USB_GEN_vect)
-{
-	uint8_t intbits, t, i;
-	static uint8_t div4=0;
-
-        intbits = UDINT;
-        UDINT = 0;
-        if (intbits & (1<<EORSTI)) {
-		UENUM = 0;
-		UECONX = 1;
-		UECFG0X = EP_TYPE_CONTROL;
-		UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
-		UEIENX = (1<<RXSTPE);
-		usb_configuration = 0;
-        }
-	if ((intbits & (1<<SOFI)) && usb_configuration) {
-		t = debug_flush_timer;
-		if (t) {
-			debug_flush_timer = -- t;
-			if (!t) {
-				UENUM = DEBUG_TX_ENDPOINT;
-				while ((UEINTX & (1<<RWAL))) {
-					UEDATX = 0;
-				}
-				UEINTX = 0x3A;
-			}
-		}
-		if (USBKeys_Idle_Config && (++div4 & 3) == 0) {
-			UENUM = KEYBOARD_ENDPOINT;
-			if (UEINTX & (1<<RWAL)) {
-				USBKeys_Idle_Count++;
-				if (USBKeys_Idle_Count == USBKeys_Idle_Config) {
-					USBKeys_Idle_Count = 0;
-					UEDATX = USBKeys_Modifiers;
-					UEDATX = 0;
-					for (i=0; i<6; i++) {
-						UEDATX = USBKeys_Array[i];
-					}
-					UEINTX = 0x3A;
-				}
-			}
-		}
-	}
-}
-
-
-
-// Misc functions to wait for ready and send/receive packets
-static inline void usb_wait_in_ready(void)
-{
-	while (!(UEINTX & (1<<TXINI))) ;
-}
-static inline void usb_send_in(void)
-{
-	UEINTX = ~(1<<TXINI);
-}
-static inline void usb_wait_receive_out(void)
-{
-	while (!(UEINTX & (1<<RXOUTI))) ;
-}
-static inline void usb_ack_out(void)
-{
-	UEINTX = ~(1<<RXOUTI);
-}
-
-
-
-// USB Endpoint Interrupt - endpoint 0 is handled here.  The
-// other endpoints are manipulated by the user-callable
-// functions, and the start-of-frame interrupt.
-//
-ISR(USB_COM_vect)
-{
-        uint8_t intbits;
-	const uint8_t *list;
-        const uint8_t *cfg;
-	uint8_t i, n, len, en;
-	uint8_t bmRequestType;
-	uint8_t bRequest;
-	uint16_t wValue;
-	uint16_t wIndex;
-	uint16_t wLength;
-	uint16_t desc_val;
-	const uint8_t *desc_addr;
-	uint8_t	desc_length;
-
-        UENUM = 0;
-	intbits = UEINTX;
-        if (intbits & (1<<RXSTPI)) {
-                bmRequestType = UEDATX;
-                bRequest = UEDATX;
-                wValue = UEDATX;
-                wValue |= (UEDATX << 8);
-                wIndex = UEDATX;
-                wIndex |= (UEDATX << 8);
-                wLength = UEDATX;
-                wLength |= (UEDATX << 8);
-                UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
-                if (bRequest == GET_DESCRIPTOR) {
-			list = (const uint8_t *)descriptor_list;
-			for (i=0; ; i++) {
-				if (i >= NUM_DESC_LIST) {
-					UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
-					return;
-				}
-				desc_val = pgm_read_word(list);
-				if (desc_val != wValue) {
-					list += sizeof(struct descriptor_list_struct);
-					continue;
-				}
-				list += 2;
-				desc_val = pgm_read_word(list);
-				if (desc_val != wIndex) {
-					list += sizeof(struct descriptor_list_struct)-2;
-					continue;
-				}
-				list += 2;
-				desc_addr = (const uint8_t *)pgm_read_word(list);
-				list += 2;
-				desc_length = pgm_read_byte(list);
-				break;
-			}
-			len = (wLength < 256) ? wLength : 255;
-			if (len > desc_length) len = desc_length;
-			do {
-				// wait for host ready for IN packet
-				do {
-					i = UEINTX;
-				} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
-				if (i & (1<<RXOUTI)) return;	// abort
-				// send IN packet
-				n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
-				for (i = n; i; i--) {
-					UEDATX = pgm_read_byte(desc_addr++);
-				}
-				len -= n;
-				usb_send_in();
-			} while (len || n == ENDPOINT0_SIZE);
-			return;
-                }
-		if (bRequest == SET_ADDRESS) {
-			usb_send_in();
-			usb_wait_in_ready();
-			UDADDR = wValue | (1<<ADDEN);
-			return;
-		}
-		if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
-			usb_configuration = wValue;
-			usb_send_in();
-			cfg = endpoint_config_table;
-			for (i=1; i<5; i++) {
-				UENUM = i;
-				en = pgm_read_byte(cfg++);
-				UECONX = en;
-				if (en) {
-					UECFG0X = pgm_read_byte(cfg++);
-					UECFG1X = pgm_read_byte(cfg++);
-				}
-			}
-        		UERST = 0x1E;
-        		UERST = 0;
-			return;
-		}
-		if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
-			usb_wait_in_ready();
-			UEDATX = usb_configuration;
-			usb_send_in();
-			return;
-		}
-
-		if (bRequest == GET_STATUS) {
-			usb_wait_in_ready();
-			i = 0;
-			#ifdef SUPPORT_ENDPOINT_HALT
-			if (bmRequestType == 0x82) {
-				UENUM = wIndex;
-				if (UECONX & (1<<STALLRQ)) i = 1;
-				UENUM = 0;
-			}
-			#endif
-			UEDATX = i;
-			UEDATX = 0;
-			usb_send_in();
-			return;
-		}
-		#ifdef SUPPORT_ENDPOINT_HALT
-		if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
-		  && bmRequestType == 0x02 && wValue == 0) {
-			i = wIndex & 0x7F;
-			if (i >= 1 && i <= MAX_ENDPOINT) {
-				usb_send_in();
-				UENUM = i;
-				if (bRequest == SET_FEATURE) {
-					UECONX = (1<<STALLRQ)|(1<<EPEN);
-				} else {
-					UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
-					UERST = (1 << i);
-					UERST = 0;
-				}
-				return;
-			}
-		}
-		#endif
-		if (wIndex == KEYBOARD_INTERFACE) {
-			if (bmRequestType == 0xA1) {
-				if (bRequest == HID_GET_REPORT) {
-					usb_wait_in_ready();
-					UEDATX = USBKeys_Modifiers;
-					UEDATX = 0;
-					for (i=0; i<6; i++) {
-						UEDATX = USBKeys_Array[i];
-					}
-					usb_send_in();
-					return;
-				}
-				if (bRequest == HID_GET_IDLE) {
-					usb_wait_in_ready();
-					UEDATX = USBKeys_Idle_Config;
-					usb_send_in();
-					return;
-				}
-				if (bRequest == HID_GET_PROTOCOL) {
-					usb_wait_in_ready();
-					UEDATX = USBKeys_Protocol;
-					usb_send_in();
-					return;
-				}
-			}
-			if (bmRequestType == 0x21) {
-				if (bRequest == HID_SET_REPORT) {
-					usb_wait_receive_out();
-					USBKeys_LEDs = UEDATX;
-					usb_ack_out();
-					usb_send_in();
-					return;
-				}
-				if (bRequest == HID_SET_IDLE) {
-					USBKeys_Idle_Config = (wValue >> 8);
-					USBKeys_Idle_Count = 0;
-					//usb_wait_in_ready();
-					usb_send_in();
-					return;
-				}
-				if (bRequest == HID_SET_PROTOCOL) {
-					USBKeys_Protocol = wValue;
-					//usb_wait_in_ready();
-					usb_send_in();
-					return;
-				}
-			}
-		}
-		if (wIndex == DEBUG_INTERFACE) {
-			if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
-				len = wLength;
-				do {
-					// wait for host ready for IN packet
-					do {
-						i = UEINTX;
-					} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
-					if (i & (1<<RXOUTI)) return;	// abort
-					// send IN packet
-					n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
-					for (i = n; i; i--) {
-						UEDATX = 0;
-					}
-					len -= n;
-					usb_send_in();
-				} while (len || n == ENDPOINT0_SIZE);
-				return;
-			}
-		}
-	}
-	UECONX = (1<<STALLRQ) | (1<<EPEN);	// stall
-}
-
--- a/Output/pjrcUSB/avr/usb_keyboard_debug.h	Sat Mar 22 14:32:06 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-#ifndef usb_serial_h__
-#define usb_serial_h__
-
-#include <stdint.h>
-#include "output_com.h"
-
-void usb_init(void);			// initialize everything
-uint8_t usb_configured(void);		// is the USB port configured
-
-int8_t usb_keyboard_send(void);
-
-
-int8_t usb_debug_putchar(uint8_t c);	// transmit a character
-void usb_debug_flush_output(void);	// immediately transmit any buffered output
-#define USB_DEBUG_HID
-
-
-// Everything below this point is only intended for usb_serial.c
-#ifdef USB_SERIAL_PRIVATE_INCLUDE
-#include <avr/io.h>
-#include <avr/pgmspace.h>
-#include <avr/interrupt.h>
-
-#define EP_TYPE_CONTROL			0x00
-#define EP_TYPE_BULK_IN			0x81
-#define EP_TYPE_BULK_OUT		0x80
-#define EP_TYPE_INTERRUPT_IN		0xC1
-#define EP_TYPE_INTERRUPT_OUT		0xC0
-#define EP_TYPE_ISOCHRONOUS_IN		0x41
-#define EP_TYPE_ISOCHRONOUS_OUT		0x40
-
-#define EP_SINGLE_BUFFER		0x02
-#define EP_DOUBLE_BUFFER		0x06
-
-#define EP_SIZE(s)	((s) == 64 ? 0x30 :	\
-			((s) == 32 ? 0x20 :	\
-			((s) == 16 ? 0x10 :	\
-			             0x00)))
-
-#define MAX_ENDPOINT		4
-
-#define LSB(n) (n & 255)
-#define MSB(n) ((n >> 8) & 255)
-
-#if defined(__AVR_AT90USB162__)
-#define HW_CONFIG() 
-#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
-#define USB_CONFIG() (USBCON = (1<<USBE))
-#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
-#elif defined(__AVR_ATmega32U4__)
-#define HW_CONFIG() (UHWCON = 0x01)
-#define PLL_CONFIG() (PLLCSR = 0x12)
-#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
-#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
-#elif defined(__AVR_AT90USB646__)
-#define HW_CONFIG() (UHWCON = 0x81)
-#define PLL_CONFIG() (PLLCSR = 0x1A)
-#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
-#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
-#elif defined(__AVR_AT90USB1286__)
-#define HW_CONFIG() (UHWCON = 0x81)
-#define PLL_CONFIG() (PLLCSR = 0x16)
-#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
-#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
-#endif
-
-// standard control endpoint request types
-#define GET_STATUS			0
-#define CLEAR_FEATURE			1
-#define SET_FEATURE			3
-#define SET_ADDRESS			5
-#define GET_DESCRIPTOR			6
-#define GET_CONFIGURATION		8
-#define SET_CONFIGURATION		9
-#define GET_INTERFACE			10
-#define SET_INTERFACE			11
-// HID (human interface device)
-#define HID_GET_REPORT			1
-#define HID_GET_IDLE			2
-#define HID_GET_PROTOCOL		3
-#define HID_SET_REPORT			9
-#define HID_SET_IDLE			10
-#define HID_SET_PROTOCOL		11
-// CDC (communication class device)
-#define CDC_SET_LINE_CODING		0x20
-#define CDC_GET_LINE_CODING		0x21
-#define CDC_SET_CONTROL_LINE_STATE	0x22
-#endif
-#endif
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Output/pjrcUSB/avr/usb_keyboard_serial.c	Mon Mar 31 01:07:48 2014 -0700
@@ -0,0 +1,1126 @@
+/* USB Keyboard and CDC Serial Device for Teensy USB Development Board
+ * Copyright (c) 2009 PJRC.COM, LLC
+ * Modifications by Jacob Alexander (2011-2014)
+ *
+ * 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.
+ */
+
+
+// Local Includes
+#include "usb_keyboard_serial.h"
+
+
+// ----- Functions -----
+
+// Set the avr into firmware reload mode
+void usb_debug_reload()
+{
+	cli();
+	// Disable watchdog, if enabled
+	// Disable all peripherals
+
+	UDCON = 1;
+	USBCON = (1 << FRZCLK);  // Disable USB
+	UCSR1B = 0;
+	_delay_ms( 5 );
+
+#if defined(__AVR_AT90USB162__)                // Teensy 1.0
+	EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
+	TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
+	DDRB = 0; DDRC = 0; DDRD = 0;
+	PORTB = 0; PORTC = 0; PORTD = 0;
+	asm volatile("jmp 0x3E00");
+#elif defined(__AVR_ATmega32U4__)              // Teensy 2.0
+	EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+	TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
+	DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
+	PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+	asm volatile("jmp 0x7E00");
+#elif defined(__AVR_AT90USB646__)              // Teensy++ 1.0
+	EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+	TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
+	DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
+	PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+	asm volatile("jmp 0xFC00");
+#elif defined(__AVR_AT90USB1286__)             // Teensy++ 2.0
+	EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+	TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
+	DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
+	PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+	asm volatile("jmp 0x1FC00");
+#endif
+}
+
+
+// WDT Setup for software reset the chip
+void wdt_init(void)
+{
+	MCUSR = 0;
+	wdt_disable();
+}
+
+
+/**************************************************************************
+ *
+ *  Configurable Options
+ *
+ **************************************************************************/
+
+// When you write data, it goes into a USB endpoint buffer, which
+// is transmitted to the PC when it becomes full, or after a timeout
+// with no more writes.  Even if you write in exactly packet-size
+// increments, this timeout is used to send a "zero length packet"
+// that tells the PC no more data is expected and it should pass
+// any buffered data to the application that may be waiting.  If
+// you want data sent immediately, call usb_serial_flush_output().
+#define TRANSMIT_FLUSH_TIMEOUT	5   /* in milliseconds */
+
+// If the PC is connected but not "listening", this is the length
+// of time before usb_serial_getchar() returns with an error.  This
+// is roughly equivilant to a real UART simply transmitting the
+// bits on a wire where nobody is listening, except you get an error
+// code which you can ignore for serial-like discard of data, or
+// use to know your data wasn't sent.
+#define TRANSMIT_TIMEOUT	25   /* in milliseconds */
+
+// USB devices are supposed to implment a halt feature, which is
+// rarely (if ever) used.  If you comment this line out, the halt
+// code will be removed, saving 116 bytes of space (gcc 4.3.0).
+// This is not strictly USB compliant, but works with all major
+// operating systems.
+#define SUPPORT_ENDPOINT_HALT
+
+
+
+/**************************************************************************
+ *
+ *  Descriptor Data
+ *
+ **************************************************************************/
+
+// Descriptors are the data that your computer reads when it auto-detects
+// this USB device (called "enumeration" in USB lingo).  The most commonly
+// changed items are editable at the top of this file.  Changing things
+// in here should only be done by those who've read chapter 9 of the USB
+// spec and relevant portions of any USB class specifications!
+
+
+static const uint8_t PROGMEM device_descriptor[] = {
+	18,					// bLength
+	1,					// bDescriptorType
+	0x00, 0x02,				// bcdUSB
+	0,					// bDeviceClass
+	0,					// bDeviceSubClass
+	0,					// bDeviceProtocol
+	ENDPOINT0_SIZE,				// bMaxPacketSize0
+	LSB(VENDOR_ID), MSB(VENDOR_ID),		// idVendor
+	LSB(PRODUCT_ID), MSB(PRODUCT_ID),	// idProduct
+	0x00, 0x01,				// bcdDevice
+	1,					// iManufacturer
+	2,					// iProduct
+	3,					// iSerialNumber
+	1					// bNumConfigurations
+};
+
+// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
+static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
+        0x05, 0x01,          // Usage Page (Generic Desktop),
+        0x09, 0x06,          // Usage (Keyboard),
+        0xA1, 0x01,          // Collection (Application),
+        0x75, 0x01,          //   Report Size (1),
+        0x95, 0x08,          //   Report Count (8),
+        0x05, 0x07,          //   Usage Page (Key Codes),
+        0x19, 0xE0,          //   Usage Minimum (224),
+        0x29, 0xE7,          //   Usage Maximum (231),
+        0x15, 0x00,          //   Logical Minimum (0),
+        0x25, 0x01,          //   Logical Maximum (1),
+        0x81, 0x02,          //   Input (Data, Variable, Absolute), ;Modifier byte
+        0x95, 0x08,          //  Report Count (8),
+        0x75, 0x01,          //  Report Size (1),
+        0x15, 0x00,          //  Logical Minimum (0),
+        0x25, 0x01,          //  Logical Maximum (1),
+        0x05, 0x0C,          //  Usage Page (Consumer),
+        0x09, 0xE9,          //  Usage (Volume Increment),
+        0x09, 0xEA,          //  Usage (Volume Decrement),
+        0x09, 0xE2,          //  Usage (Mute),
+        0x09, 0xCD,          //  Usage (Play/Pause),
+        0x09, 0xB5,          //  Usage (Scan Next Track),
+        0x09, 0xB6,          //  Usage (Scan Previous Track),
+        0x09, 0xB7,          //  Usage (Stop),
+        0x09, 0xB8,          //  Usage (Eject),
+        0x81, 0x02,          //  Input (Data, Variable, Absolute), ;Media keys
+        0x95, 0x05,          //  Report Count (5),
+        0x75, 0x01,          //  Report Size (1),
+        0x05, 0x08,          //  Usage Page (LEDs),
+        0x19, 0x01,          //  Usage Minimum (1),
+        0x29, 0x05,          //  Usage Maximum (5),
+        0x91, 0x02,          //  Output (Data, Variable, Absolute), ;LED report
+        0x95, 0x01,          //  Report Count (1),
+        0x75, 0x03,          //  Report Size (3),
+        0x91, 0x03,          //  Output (Constant),                 ;LED report padding
+        0x95, 0x06,          //  Report Count (6),
+        0x75, 0x08,          //  Report Size (8),
+        0x15, 0x00,          //  Logical Minimum (0),
+        0x25, 0x7F,          //  Logical Maximum(104),
+        0x05, 0x07,          //  Usage Page (Key Codes),
+        0x19, 0x00,          //  Usage Minimum (0),
+        0x29, 0x7F,          //  Usage Maximum (104),
+        0x81, 0x00,          //  Input (Data, Array),                ;Normal keys
+        0xc0                 // End Collection
+};
+
+// <Configuration> + <Keyboard HID> + <Serial CDC>
+#define CONFIG1_DESC_SIZE        (9 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7)
+#define KEYBOARD_HID_DESC_OFFSET (9 + 9)
+#define SERIAL_CDC_DESC_OFFSET   (9 + 9+9+7)
+static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
+// --- Configuration ---
+// - 9 bytes -
+	// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
+	9, 					// bLength;
+	2,					// bDescriptorType;
+	LSB(CONFIG1_DESC_SIZE),			// wTotalLength
+	MSB(CONFIG1_DESC_SIZE),
+	3,					// bNumInterfaces
+	1,					// bConfigurationValue
+	0,					// iConfiguration
+	0xC0,					// bmAttributes
+	50,					// bMaxPower
+
+// --- Keyboard HID ---
+// - 9 bytes -
+	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+	9,					// bLength
+	4,					// bDescriptorType
+	KEYBOARD_INTERFACE,			// bInterfaceNumber
+	0,					// bAlternateSetting
+	1,					// bNumEndpoints
+	0x03,					// bInterfaceClass (0x03 = HID)
+	0x01,					// bInterfaceSubClass (0x01 = Boot)
+	0x01,					// bInterfaceProtocol (0x01 = Keyboard)
+	0,					// iInterface
+// - 9 bytes -
+	// HID interface descriptor, HID 1.11 spec, section 6.2.1
+	9,					// bLength
+	0x21,					// bDescriptorType
+	0x11, 0x01,				// bcdHID
+	0,					// bCountryCode
+	1,					// bNumDescriptors
+	0x22,					// bDescriptorType
+	LSB(sizeof(keyboard_hid_report_desc)),	// wDescriptorLength
+	MSB(sizeof(keyboard_hid_report_desc)),
+// - 7 bytes -
+	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+	7,					// bLength
+	5,					// bDescriptorType
+	KEYBOARD_ENDPOINT | 0x80,		// bEndpointAddress
+	0x03,					// bmAttributes (0x03=intr)
+	KEYBOARD_SIZE, 0,			// wMaxPacketSize
+	KEYBOARD_INTERVAL,			// bInterval
+
+// --- Serial CDC ---
+// - 8 bytes -
+        // interface association descriptor, USB ECN, Table 9-Z
+        8,                                      // bLength
+        11,                                     // bDescriptorType
+        CDC_STATUS_INTERFACE,                   // bFirstInterface
+        2,                                      // bInterfaceCount
+        0x02,                                   // bFunctionClass
+        0x02,                                   // bFunctionSubClass
+        0x01,                                   // bFunctionProtocol
+        4,                                      // iFunction
+// - 9 bytes -
+	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+	9,					// bLength
+	4,					// bDescriptorType
+	CDC_STATUS_INTERFACE,			// bInterfaceNumber
+	0,					// bAlternateSetting
+	1,					// bNumEndpoints
+	0x02,					// bInterfaceClass
+	0x02,					// bInterfaceSubClass
+	0x01,					// bInterfaceProtocol
+	0,					// iInterface
+// - 5 bytes -
+	// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
+	5,					// bFunctionLength
+	0x24,					// bDescriptorType
+	0x00,					// bDescriptorSubtype
+	0x10, 0x01,				// bcdCDC
+// - 5 bytes -
+	// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
+	5,					// bFunctionLength
+	0x24,					// bDescriptorType
+	0x01,					// bDescriptorSubtype
+	0x01,					// bmCapabilities
+	1,					// bDataInterface
+// - 4 bytes -
+	// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
+	4,					// bFunctionLength
+	0x24,					// bDescriptorType
+	0x02,					// bDescriptorSubtype
+	0x06,					// bmCapabilities
+// - 5 bytes -
+	// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
+	5,					// bFunctionLength
+	0x24,					// bDescriptorType
+	0x06,					// bDescriptorSubtype
+	CDC_STATUS_INTERFACE,			// bMasterInterface
+	CDC_DATA_INTERFACE,			// bSlaveInterface0
+// - 7 bytes -
+	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+	7,					// bLength
+	5,					// bDescriptorType
+	CDC_ACM_ENDPOINT | 0x80,		// bEndpointAddress
+	0x03,					// bmAttributes (0x03=intr)
+	CDC_ACM_SIZE, 0,			// wMaxPacketSize
+	64,					// bInterval
+// - 9 bytes -
+	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+	9,					// bLength
+	4,					// bDescriptorType
+	CDC_DATA_INTERFACE,			// bInterfaceNumber
+	0,					// bAlternateSetting
+	2,					// bNumEndpoints
+	0x0A,					// bInterfaceClass
+	0x00,					// bInterfaceSubClass
+	0x00,					// bInterfaceProtocol
+	0,					// iInterface
+// - 7 bytes -
+	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+	7,					// bLength
+	5,					// bDescriptorType
+	CDC_RX_ENDPOINT,			// bEndpointAddress
+	0x02,					// bmAttributes (0x02=bulk)
+	CDC_RX_SIZE, 0,				// wMaxPacketSize
+	0,					// bInterval
+// - 7 bytes -
+	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+	7,					// bLength
+	5,					// bDescriptorType
+	CDC_TX_ENDPOINT | 0x80,			// bEndpointAddress
+	0x02,					// bmAttributes (0x02=bulk)
+	CDC_TX_SIZE, 0,				// wMaxPacketSize
+	0,					// bInterval
+};
+
+// If you're desperate for a little extra code memory, these strings
+// can be completely removed if iManufacturer, iProduct, iSerialNumber
+// in the device desciptor are changed to zeros.
+struct usb_string_descriptor_struct {
+	uint8_t bLength;
+	uint8_t bDescriptorType;
+	int16_t wString[];
+};
+static const struct usb_string_descriptor_struct PROGMEM string0 = {
+	4,
+	3,
+	{0x0409}
+};
+static const struct usb_string_descriptor_struct PROGMEM string1 = {
+	sizeof(STR_MANUFACTURER),
+	3,
+	STR_MANUFACTURER
+};
+static const struct usb_string_descriptor_struct PROGMEM string2 = {
+	sizeof(STR_PRODUCT),
+	3,
+	STR_PRODUCT
+};
+static const struct usb_string_descriptor_struct PROGMEM string3 = {
+	sizeof(STR_SERIAL),
+	3,
+	STR_SERIAL
+};
+
+// This table defines which descriptor data is sent for each specific
+// request from the host (in wValue and wIndex).
+static const struct descriptor_list_struct {
+	uint16_t	wValue;
+	uint16_t	wIndex;
+	const uint8_t	*addr;
+	uint8_t		length;
+} PROGMEM descriptor_list[] = {
+	{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
+	{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
+	{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
+	{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
+	{0x0300, 0x0000, (const uint8_t *)&string0, 4},
+	{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
+	{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)},
+	{0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)}
+};
+#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
+
+
+/**************************************************************************
+ *
+ *  Variables - these are the only non-stack RAM usage
+ *
+ **************************************************************************/
+
+// zero when we are not configured, non-zero when enumerated
+static volatile uint8_t usb_configuration=0;
+
+// the time remaining before we transmit any partially full
+// packet, or send a zero length packet.
+static volatile uint8_t transmit_flush_timer=0;
+static uint8_t transmit_previous_timeout=0;
+
+// serial port settings (baud rate, control signals, etc) set
+// by the PC.  These are ignored, but kept in RAM.
+static uint8_t cdc_line_coding[7]={0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08};
+static uint8_t cdc_line_rtsdtr=0;
+
+
+/**************************************************************************
+ *
+ *  Public Functions - these are the API intended for the user
+ *
+ **************************************************************************/
+
+
+// initialize USB
+void usb_init(void)
+{
+	HW_CONFIG();
+	USB_FREEZE();				// enable USB
+	PLL_CONFIG();				// config PLL
+        while (!(PLLCSR & (1<<PLOCK))) ;	// wait for PLL lock
+        USB_CONFIG();				// start USB clock
+        UDCON = 0;				// enable attach resistor
+	usb_configuration = 0;
+        UDIEN = (1<<EORSTE)|(1<<SOFE);
+	sei();
+
+	// Disable watchdog timer after possible software reset
+	//wdt_init(); // XXX Not working...seems to be ok without this, not sure though
+}
+
+// return 0 if the USB is not configured, or the configuration
+// number selected by the HOST
+uint8_t usb_configured(void)
+{
+	return usb_configuration;
+}
+
+// send the contents of USBKeys_Array and USBKeys_Modifiers
+int8_t usb_keyboard_send(void)
+{
+	uint8_t i, intr_state, timeout;
+
+	if (!usb_configuration) return -1;
+	intr_state = SREG;
+	cli();
+	UENUM = KEYBOARD_ENDPOINT;
+	timeout = UDFNUML + 50;
+	while (1) {
+		// are we ready to transmit?
+		if (UEINTX & (1<<RWAL)) break;
+		SREG = intr_state;
+		// has the USB gone offline?
+		if (!usb_configuration) return -1;
+		// have we waited too long?
+		if (UDFNUML == timeout) return -1;
+		// get ready to try checking again
+		intr_state = SREG;
+		cli();
+		UENUM = KEYBOARD_ENDPOINT;
+	}
+	UEDATX = USBKeys_Modifiers;
+	UEDATX = 0;
+	for (i=0; i<6; i++) {
+		UEDATX = USBKeys_Array[i];
+	}
+	UEINTX = 0x3A;
+	USBKeys_Idle_Count = 0;
+	SREG = intr_state;
+	return 0;
+}
+
+// get the next character, or -1 if nothing received
+int16_t usb_serial_getchar(void)
+{
+	uint8_t c, intr_state;
+
+	// interrupts are disabled so these functions can be
+	// used from the main program or interrupt context,
+	// even both in the same program!
+	intr_state = SREG;
+	cli();
+	if (!usb_configuration) {
+		SREG = intr_state;
+		return -1;
+	}
+	UENUM = CDC_RX_ENDPOINT;
+	retry:
+	c = UEINTX;
+	if (!(c & (1<<RWAL))) {
+		// no data in buffer
+		if (c & (1<<RXOUTI)) {
+			UEINTX = 0x6B;
+			goto retry;
+		}
+		SREG = intr_state;
+		return -2;
+	}
+	// take one byte out of the buffer
+	c = UEDATX;
+	// if buffer completely used, release it
+	if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B;
+	SREG = intr_state;
+	return c;
+}
+
+// number of bytes available in the receive buffer
+uint8_t usb_serial_available(void)
+{
+	uint8_t n=0, i, intr_state;
+
+	intr_state = SREG;
+	cli();
+	if (usb_configuration) {
+		UENUM = CDC_RX_ENDPOINT;
+		n = UEBCLX;
+		if (!n) {
+			i = UEINTX;
+			if (i & (1<<RXOUTI) && !(i & (1<<RWAL))) UEINTX = 0x6B;
+		}
+	}
+	SREG = intr_state;
+	return n;
+}
+
+// discard any buffered input
+void usb_serial_flush_input(void)
+{
+	uint8_t intr_state;
+
+	if (usb_configuration) {
+		intr_state = SREG;
+		cli();
+		UENUM = CDC_RX_ENDPOINT;
+		while ((UEINTX & (1<<RWAL))) {
+			UEINTX = 0x6B;
+		}
+		SREG = intr_state;
+	}
+}
+
+// transmit a character.  0 returned on success, -1 on error
+int8_t usb_serial_putchar(uint8_t c)
+{
+	uint8_t timeout, intr_state;
+
+	// if we're not online (enumerated and configured), error
+	if (!usb_configuration) return -1;
+	// interrupts are disabled so these functions can be
+	// used from the main program or interrupt context,
+	// even both in the same program!
+	intr_state = SREG;
+	cli();
+	UENUM = CDC_TX_ENDPOINT;
+	// if we gave up due to timeout before, don't wait again
+	if (transmit_previous_timeout) {
+		if (!(UEINTX & (1<<RWAL))) {
+			SREG = intr_state;
+			return -1;
+		}
+		transmit_previous_timeout = 0;
+	}
+	// wait for the FIFO to be ready to accept data
+	timeout = UDFNUML + TRANSMIT_TIMEOUT;
+	while (1) {
+		// are we ready to transmit?
+		if (UEINTX & (1<<RWAL)) break;
+		SREG = intr_state;
+		// have we waited too long?  This happens if the user
+		// is not running an application that is listening
+		if (UDFNUML == timeout) {
+			transmit_previous_timeout = 1;
+			return -1;
+		}
+		// has the USB gone offline?
+		if (!usb_configuration) return -1;
+		// get ready to try checking again
+		intr_state = SREG;
+		cli();
+		UENUM = CDC_TX_ENDPOINT;
+	}
+	// actually write the byte into the FIFO
+	UEDATX = c;
+	// if this completed a packet, transmit it now!
+	if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
+	transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
+	SREG = intr_state;
+	return 0;
+}
+
+
+// transmit a character, but do not wait if the buffer is full,
+//   0 returned on success, -1 on buffer full or error
+int8_t usb_serial_putchar_nowait(uint8_t c)
+{
+	uint8_t intr_state;
+
+	if (!usb_configuration) return -1;
+	intr_state = SREG;
+	cli();
+	UENUM = CDC_TX_ENDPOINT;
+	if (!(UEINTX & (1<<RWAL))) {
+		// buffer is full
+		SREG = intr_state;
+		return -2;
+	}
+	// actually write the byte into the FIFO
+	UEDATX = c;
+		// if this completed a packet, transmit it now!
+	if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
+	transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
+	SREG = intr_state;
+	return 0;
+}
+
+// transmit a buffer.
+//  0 returned on success, -1 on error
+// This function is optimized for speed!  Each call takes approx 6.1 us overhead
+// plus 0.25 us per byte.  12 Mbit/sec USB has 8.67 us per-packet overhead and
+// takes 0.67 us per byte.  If called with 64 byte packet-size blocks, this function
+// can transmit at full USB speed using 43% CPU time.  The maximum theoretical speed
+// is 19 packets per USB frame, or 1216 kbytes/sec.  However, bulk endpoints have the
+// lowest priority, so any other USB devices will likely reduce the speed.  Speed
+// can also be limited by how quickly the PC-based software reads data, as the host
+// controller in the PC will not allocate bandwitdh without a pending read request.
+// (thanks to Victor Suarez for testing and feedback and initial code)
+
+int8_t usb_serial_write(const char *buffer, uint16_t size)
+{
+	uint8_t timeout, intr_state, write_size;
+
+	// if we're not online (enumerated and configured), error
+	if (!usb_configuration) return -1;
+	// interrupts are disabled so these functions can be
+	// used from the main program or interrupt context,
+	// even both in the same program!
+	intr_state = SREG;
+	cli();
+	UENUM = CDC_TX_ENDPOINT;
+	// if we gave up due to timeout before, don't wait again
+	/*
+	if (transmit_previous_timeout) {
+		if (!(UEINTX & (1<<RWAL))) {
+			SREG = intr_state;
+			return -2;
+		}
+		transmit_previous_timeout = 0;
+	}
+	*/
+	// each iteration of this loop transmits a packet
+	while (size) {
+		// wait for the FIFO to be ready to accept data
+		timeout = UDFNUML + TRANSMIT_TIMEOUT;
+		while (1) {
+			// are we ready to transmit?
+			if (UEINTX & (1<<RWAL)) break;
+			SREG = intr_state;
+			// have we waited too long?  This happens if the user
+			// is not running an application that is listening
+			if (UDFNUML == timeout) {
+				transmit_previous_timeout = 1;
+				return -3;
+			}
+			// has the USB gone offline?
+			if (!usb_configuration) return -4;
+			// get ready to try checking again
+			intr_state = SREG;
+			cli();
+			UENUM = CDC_TX_ENDPOINT;
+		}
+
+		// compute how many bytes will fit into the next packet
+		write_size = CDC_TX_SIZE - UEBCLX;
+		if (write_size > size) write_size = size;
+		size -= write_size;
+
+		// write the packet
+		switch (write_size) {
+			#if (CDC_TX_SIZE == 64)
+			case 64: UEDATX = *buffer++;
+			case 63: UEDATX = *buffer++;
+			case 62: UEDATX = *buffer++;
+			case 61: UEDATX = *buffer++;
+			case 60: UEDATX = *buffer++;
+			case 59: UEDATX = *buffer++;
+			case 58: UEDATX = *buffer++;
+			case 57: UEDATX = *buffer++;
+			case 56: UEDATX = *buffer++;
+			case 55: UEDATX = *buffer++;
+			case 54: UEDATX = *buffer++;
+			case 53: UEDATX = *buffer++;
+			case 52: UEDATX = *buffer++;
+			case 51: UEDATX = *buffer++;
+			case 50: UEDATX = *buffer++;
+			case 49: UEDATX = *buffer++;
+			case 48: UEDATX = *buffer++;
+			case 47: UEDATX = *buffer++;
+			case 46: UEDATX = *buffer++;
+			case 45: UEDATX = *buffer++;
+			case 44: UEDATX = *buffer++;
+			case 43: UEDATX = *buffer++;
+			case 42: UEDATX = *buffer++;
+			case 41: UEDATX = *buffer++;
+			case 40: UEDATX = *buffer++;
+			case 39: UEDATX = *buffer++;
+			case 38: UEDATX = *buffer++;
+			case 37: UEDATX = *buffer++;
+			case 36: UEDATX = *buffer++;
+			case 35: UEDATX = *buffer++;
+			case 34: UEDATX = *buffer++;
+			case 33: UEDATX = *buffer++;
+			#endif
+			#if (CDC_TX_SIZE >= 32)
+			case 32: UEDATX = *buffer++;
+			case 31: UEDATX = *buffer++;
+			case 30: UEDATX = *buffer++;
+			case 29: UEDATX = *buffer++;
+			case 28: UEDATX = *buffer++;
+			case 27: UEDATX = *buffer++;
+			case 26: UEDATX = *buffer++;
+			case 25: UEDATX = *buffer++;
+			case 24: UEDATX = *buffer++;
+			case 23: UEDATX = *buffer++;
+			case 22: UEDATX = *buffer++;
+			case 21: UEDATX = *buffer++;
+			case 20: UEDATX = *buffer++;
+			case 19: UEDATX = *buffer++;
+			case 18: UEDATX = *buffer++;
+			case 17: UEDATX = *buffer++;
+			#endif
+			#if (CDC_TX_SIZE >= 16)
+			case 16: UEDATX = *buffer++;
+			case 15: UEDATX = *buffer++;
+			case 14: UEDATX = *buffer++;
+			case 13: UEDATX = *buffer++;
+			case 12: UEDATX = *buffer++;
+			case 11: UEDATX = *buffer++;
+			case 10: UEDATX = *buffer++;
+			case  9: UEDATX = *buffer++;
+			#endif
+			case  8: UEDATX = *buffer++;
+			case  7: UEDATX = *buffer++;
+			case  6: UEDATX = *buffer++;
+			case  5: UEDATX = *buffer++;
+			case  4: UEDATX = *buffer++;
+			case  3: UEDATX = *buffer++;
+			case  2: UEDATX = *buffer++;
+			default:
+			case  1: UEDATX = *buffer++;
+			case  0: break;
+		}
+		// if this completed a packet, transmit it now!
+		if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
+		transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
+		SREG = intr_state;
+	}
+	return 0;
+}
+
+// immediately transmit any buffered output.
+// This doesn't actually transmit the data - that is impossible!
+// USB devices only transmit when the host allows, so the best
+// we can do is release the FIFO buffer for when the host wants it
+void usb_serial_flush_output(void)
+{
+	uint8_t intr_state;
+
+	intr_state = SREG;
+	cli();
+	if (transmit_flush_timer) {
+		UENUM = CDC_TX_ENDPOINT;
+		UEINTX = 0x3A;
+		transmit_flush_timer = 0;
+	}
+	SREG = intr_state;
+}
+
+// functions to read the various async serial settings.  These
+// aren't actually used by USB at all (communication is always
+// at full USB speed), but they are set by the host so we can
+// set them properly if we're converting the USB to a real serial
+// communication
+uint32_t usb_serial_get_baud(void)
+{
+	uint32_t *baud = (uint32_t*)cdc_line_coding;
+	return *baud;
+}
+uint8_t usb_serial_get_stopbits(void)
+{
+	return cdc_line_coding[4];
+}
+uint8_t usb_serial_get_paritytype(void)
+{
+	return cdc_line_coding[5];
+}
+uint8_t usb_serial_get_numbits(void)
+{
+	return cdc_line_coding[6];
+}
+uint8_t usb_serial_get_control(void)
+{
+	return cdc_line_rtsdtr;
+}
+
+// write the control signals, DCD, DSR, RI, etc
+// There is no CTS signal.  If software on the host has transmitted
+// data to you but you haven't been calling the getchar function,
+// it remains buffered (either here or on the host) and can not be
+// lost because you weren't listening at the right time, like it
+// would in real serial communication.
+int8_t usb_serial_set_control(uint8_t signals)
+{
+	uint8_t intr_state;
+
+	intr_state = SREG;
+	cli();
+	if (!usb_configuration) {
+		// we're not enumerated/configured
+		SREG = intr_state;
+		return -1;
+	}
+
+	UENUM = CDC_ACM_ENDPOINT;
+	if (!(UEINTX & (1<<RWAL))) {
+		// unable to write
+		// TODO; should this try to abort the previously
+		// buffered message??
+		SREG = intr_state;
+		return -1;
+	}
+	UEDATX = 0xA1;
+	UEDATX = 0x20;
+	UEDATX = 0;
+	UEDATX = 0;
+	UEDATX = 0; // 0 seems to work nicely.  what if this is 1??
+	UEDATX = 0;
+	UEDATX = 1;
+	UEDATX = 0;
+	UEDATX = signals;
+	UEINTX = 0x3A;
+	SREG = intr_state;
+	return 0;
+}
+
+
+
+/**************************************************************************
+ *
+ *  Private Functions - not intended for general user consumption....
+ *
+ **************************************************************************/
+
+
+
+// USB Device Interrupt - handle all device-level events
+// the transmit buffer flushing is triggered by the start of frame
+//
+ISR(USB_GEN_vect)
+{
+	uint8_t intbits, t_cdc, i;
+	static uint8_t div4=0;
+
+        intbits = UDINT;
+        UDINT = 0;
+        if (intbits & (1<<EORSTI)) {
+		UENUM = 0;
+		UECONX = 1;
+		UECFG0X = EP_TYPE_CONTROL;
+		UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
+		UEIENX = (1<<RXSTPE);
+		usb_configuration = 0;
+		cdc_line_rtsdtr = 0;
+        }
+	if ((intbits & (1<<SOFI)) && usb_configuration) {
+		t_cdc = transmit_flush_timer;
+		if (t_cdc) {
+			transmit_flush_timer = --t_cdc;
+			if (!t_cdc) {
+				UENUM = CDC_TX_ENDPOINT;
+				UEINTX = 0x3A;
+			}
+		}
+		if (USBKeys_Idle_Config && (++div4 & 3) == 0) {
+			UENUM = KEYBOARD_ENDPOINT;
+			if (UEINTX & (1<<RWAL)) {
+				USBKeys_Idle_Count++;
+				if (USBKeys_Idle_Count == USBKeys_Idle_Config) {
+					USBKeys_Idle_Count = 0;
+					UEDATX = USBKeys_Modifiers;
+					UEDATX = 0;
+					for (i=0; i<6; i++) {
+						UEDATX = USBKeys_Array[i];
+					}
+					UEINTX = 0x3A;
+				}
+			}
+		}
+	}
+}
+
+
+
+// Misc functions to wait for ready and send/receive packets
+static inline void usb_wait_in_ready(void)
+{
+	while (!(UEINTX & (1<<TXINI))) ;
+}
+static inline void usb_send_in(void)
+{
+	UEINTX = ~(1<<TXINI);
+}
+static inline void usb_wait_receive_out(void)
+{
+	while (!(UEINTX & (1<<RXOUTI))) ;
+}
+static inline void usb_ack_out(void)
+{
+	UEINTX = ~(1<<RXOUTI);
+}
+
+
+
+// USB Endpoint Interrupt - endpoint 0 is handled here.  The
+// other endpoints are manipulated by the user-callable
+// functions, and the start-of-frame interrupt.
+//
+ISR(USB_COM_vect)
+{
+        uint8_t intbits;
+	const uint8_t *list;
+        const uint8_t *cfg;
+	uint8_t i, n, len, en;
+	uint8_t *p;
+	uint8_t bmRequestType;
+	uint8_t bRequest;
+	uint16_t wValue;
+	uint16_t wIndex;
+	uint16_t wLength;
+	uint16_t desc_val;
+	const uint8_t *desc_addr;
+	uint8_t	desc_length;
+
+        UENUM = 0;
+	intbits = UEINTX;
+        if (intbits & (1<<RXSTPI)) {
+                bmRequestType = UEDATX;
+                bRequest = UEDATX;
+                wValue = UEDATX;
+                wValue |= (UEDATX << 8);
+                wIndex = UEDATX;
+                wIndex |= (UEDATX << 8);
+                wLength = UEDATX;
+                wLength |= (UEDATX << 8);
+                UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
+                if (bRequest == GET_DESCRIPTOR) {
+			list = (const uint8_t *)descriptor_list;
+			for (i=0; ; i++) {
+				if (i >= NUM_DESC_LIST) {
+					UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
+					return;
+				}
+				desc_val = pgm_read_word(list);
+				if (desc_val != wValue) {
+					list += sizeof(struct descriptor_list_struct);
+					continue;
+				}
+				list += 2;
+				desc_val = pgm_read_word(list);
+				if (desc_val != wIndex) {
+					list += sizeof(struct descriptor_list_struct)-2;
+					continue;
+				}
+				list += 2;
+				desc_addr = (const uint8_t *)pgm_read_word(list);
+				list += 2;
+				desc_length = pgm_read_byte(list);
+				break;
+			}
+			len = (wLength < 256) ? wLength : 255;
+			if (len > desc_length) len = desc_length;
+			do {
+				// wait for host ready for IN packet
+				do {
+					i = UEINTX;
+				} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
+				if (i & (1<<RXOUTI)) return;	// abort
+				// send IN packet
+				n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
+				for (i = n; i; i--) {
+					UEDATX = pgm_read_byte(desc_addr++);
+				}
+				len -= n;
+				usb_send_in();
+			} while (len || n == ENDPOINT0_SIZE);
+			return;
+                }
+		if (bRequest == SET_ADDRESS) {
+			usb_send_in();
+			usb_wait_in_ready();
+			UDADDR = wValue | (1<<ADDEN);
+			return;
+		}
+		if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
+			usb_configuration = wValue;
+			cdc_line_rtsdtr = 0;
+			transmit_flush_timer = 0;
+			usb_send_in();
+			cfg = endpoint_config_table;
+			for (i=1; i<6; i++) { // 4+1 of 7 endpoints are used // XXX Important to change if more endpoints are used
+				UENUM = i;
+				en = pgm_read_byte(cfg++);
+				UECONX = en;
+				if (en) {
+					UECFG0X = pgm_read_byte(cfg++);
+					UECFG1X = pgm_read_byte(cfg++);
+				}
+			}
+        		UERST = 0x1E;
+        		UERST = 0;
+			return;
+		}
+		if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
+			usb_wait_in_ready();
+			UEDATX = usb_configuration;
+			usb_send_in();
+			return;
+		}
+
+		if (bRequest == CDC_GET_LINE_CODING && bmRequestType == 0xA1) {
+			usb_wait_in_ready();
+			p = cdc_line_coding;
+			for (i=0; i<7; i++) {
+				UEDATX = *p++;
+			}
+			usb_send_in();
+			return;
+		}
+
+		if (bRequest == CDC_SET_LINE_CODING && bmRequestType == 0x21) {
+			usb_wait_receive_out();
+			p = cdc_line_coding;
+			for (i=0; i<7; i++) {
+				*p++ = UEDATX;
+			}
+			usb_ack_out();
+			usb_send_in();
+			return;
+		}
+
+		if (bRequest == CDC_SET_CONTROL_LINE_STATE && bmRequestType == 0x21) {
+			cdc_line_rtsdtr = wValue;
+			usb_wait_in_ready();
+			usb_send_in();
+			return;
+		}
+
+		if (bRequest == GET_STATUS) {
+			usb_wait_in_ready();
+			i = 0;
+			#ifdef SUPPORT_ENDPOINT_HALT
+			if (bmRequestType == 0x82) {
+				UENUM = wIndex;
+				if (UECONX & (1<<STALLRQ)) i = 1;
+				UENUM = 0;
+			}
+			#endif
+			UEDATX = i;
+			UEDATX = 0;
+			usb_send_in();
+			return;
+		}
+
+		#ifdef SUPPORT_ENDPOINT_HALT
+		if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
+		  && bmRequestType == 0x02 && wValue == 0) {
+			i = wIndex & 0x7F;
+			if (i >= 1 && i <= MAX_ENDPOINT) {
+				usb_send_in();
+				UENUM = i;
+				if (bRequest == SET_FEATURE) {
+					UECONX = (1<<STALLRQ)|(1<<EPEN);
+				} else {
+					UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
+					UERST = (1 << i);
+					UERST = 0;
+				}
+				return;
+			}
+		}
+		#endif
+
+		if (wIndex == KEYBOARD_INTERFACE) {
+			if (bmRequestType == 0xA1) {
+				if (bRequest == HID_GET_REPORT) {
+					usb_wait_in_ready();
+					UEDATX = USBKeys_Modifiers;
+					UEDATX = 0;
+					for (i=0; i<6; i++) {
+						UEDATX = USBKeys_Array[i];
+					}
+					usb_send_in();
+					return;
+				}
+				if (bRequest == HID_GET_IDLE) {
+					usb_wait_in_ready();
+					UEDATX = USBKeys_Idle_Config;
+					usb_send_in();
+					return;
+				}
+				if (bRequest == HID_GET_PROTOCOL) {
+					usb_wait_in_ready();
+					UEDATX = USBKeys_Protocol;
+					usb_send_in();
+					return;
+				}
+			}
+			if (bmRequestType == 0x21) {
+				if (bRequest == HID_SET_REPORT) {
+					usb_wait_receive_out();
+					USBKeys_LEDs = UEDATX;
+					usb_ack_out();
+					usb_send_in();
+					return;
+				}
+				if (bRequest == HID_SET_IDLE) {
+					USBKeys_Idle_Config = (wValue >> 8);
+					USBKeys_Idle_Count = 0;
+					//usb_wait_in_ready();
+					usb_send_in();
+					return;
+				}
+				if (bRequest == HID_SET_PROTOCOL) {
+					USBKeys_Protocol = wValue;
+					//usb_wait_in_ready();
+					usb_send_in();
+					return;
+				}
+			}
+		}
+	}
+	UECONX = (1<<STALLRQ) | (1<<EPEN);	// stall
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Output/pjrcUSB/avr/usb_keyboard_serial.h	Mon Mar 31 01:07:48 2014 -0700
@@ -0,0 +1,221 @@
+/* USB Keyboard and CDC Serial Device for Teensy USB Development Board
+ * Copyright (c) 2009 PJRC.COM, LLC
+ * Modifications by Jacob Alexander (2011-2014)
+ *
+ * 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.
+ */
+
+#ifndef usb_keyboard_serial_h__
+#define usb_keyboard_serial_h__
+
+// Compiler Includes
+#include <stdint.h>
+
+// AVR Includes
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+
+// AVR Util Includes
+#include <util/delay.h>
+
+// Local Includes
+#include "output_com.h"
+
+
+// ----- Function Declarations -----
+
+// Basic USB Configuration
+void usb_init(void);			// initialize everything
+uint8_t usb_configured(void);		// is the USB port configured
+
+// Keyboard HID Functions
+int8_t usb_keyboard_send(void);
+
+// Chip Level Functions
+void usb_debug_reload();                // Enable firmware reflash mode
+void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3"))); // Needed for software reset
+
+// USB Serial CDC Functions
+int16_t usb_serial_getchar(void);	// receive a character (-1 if timeout/error)
+uint8_t usb_serial_available(void);	// number of bytes in receive buffer
+void usb_serial_flush_input(void);	// discard any buffered input
+
+// transmitting data
+int8_t usb_serial_putchar(uint8_t c);	// transmit a character
+int8_t usb_serial_putchar_nowait(uint8_t c);  // transmit a character, do not wait
+int8_t usb_serial_write(const char *buffer, uint16_t size); // transmit a buffer
+void usb_serial_flush_output(void);	// immediately transmit any buffered output
+
+// serial parameters
+uint32_t usb_serial_get_baud(void);	// get the baud rate
+uint8_t usb_serial_get_stopbits(void);	// get the number of stop bits
+uint8_t usb_serial_get_paritytype(void);// get the parity type
+uint8_t usb_serial_get_numbits(void);	// get the number of data bits
+uint8_t usb_serial_get_control(void);	// get the RTS and DTR signal state
+int8_t usb_serial_set_control(uint8_t signals); // set DSR, DCD, RI, etc
+
+
+
+// ----- Macros -----
+
+// Software reset the chip
+#define usb_debug_software_reset() do { wdt_enable( WDTO_15MS ); for(;;); } while(0)
+
+#define EP_SIZE(s)	((s) == 64 ? 0x30 :	\
+			((s) == 32 ? 0x20 :	\
+			((s) == 16 ? 0x10 :	\
+			             0x00)))
+
+#define LSB(n) (n & 255)
+#define MSB(n) ((n >> 8) & 255)
+
+
+
+// ----- Defines -----
+
+// constants corresponding to the various serial parameters
+#define USB_SERIAL_DTR			0x01
+#define USB_SERIAL_RTS			0x02
+#define USB_SERIAL_1_STOP		0
+#define USB_SERIAL_1_5_STOP		1
+#define USB_SERIAL_2_STOP		2
+#define USB_SERIAL_PARITY_NONE		0
+#define USB_SERIAL_PARITY_ODD		1
+#define USB_SERIAL_PARITY_EVEN		2
+#define USB_SERIAL_PARITY_MARK		3
+#define USB_SERIAL_PARITY_SPACE		4
+#define USB_SERIAL_DCD			0x01
+#define USB_SERIAL_DSR			0x02
+#define USB_SERIAL_BREAK		0x04
+#define USB_SERIAL_RI			0x08
+#define USB_SERIAL_FRAME_ERR		0x10
+#define USB_SERIAL_PARITY_ERR		0x20
+#define USB_SERIAL_OVERRUN_ERR		0x40
+
+#define EP_TYPE_CONTROL			0x00
+#define EP_TYPE_BULK_IN			0x81
+#define EP_TYPE_BULK_OUT		0x80
+#define EP_TYPE_INTERRUPT_IN		0xC1
+#define EP_TYPE_INTERRUPT_OUT		0xC0
+#define EP_TYPE_ISOCHRONOUS_IN		0x41
+#define EP_TYPE_ISOCHRONOUS_OUT		0x40
+
+#define EP_SINGLE_BUFFER		0x02
+#define EP_DOUBLE_BUFFER		0x06
+
+#define MAX_ENDPOINT		4
+
+#if defined(__AVR_AT90USB162__)
+#define HW_CONFIG()
+#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
+#define USB_CONFIG() (USBCON = (1<<USBE))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+
+#elif defined(__AVR_ATmega32U4__)
+#define HW_CONFIG() (UHWCON = 0x01)
+#define PLL_CONFIG() (PLLCSR = 0x12)
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+
+#elif defined(__AVR_AT90USB646__)
+#define HW_CONFIG() (UHWCON = 0x81)
+#define PLL_CONFIG() (PLLCSR = 0x1A)
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+
+#elif defined(__AVR_AT90USB1286__)
+#define HW_CONFIG() (UHWCON = 0x81)
+#define PLL_CONFIG() (PLLCSR = 0x16)
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+#endif
+
+// standard control endpoint request types
+#define GET_STATUS			0
+#define CLEAR_FEATURE			1
+#define SET_FEATURE			3
+#define SET_ADDRESS			5
+#define GET_DESCRIPTOR			6
+#define GET_CONFIGURATION		8
+#define SET_CONFIGURATION		9
+#define GET_INTERFACE			10
+#define SET_INTERFACE			11
+
+// HID (human interface device)
+#define HID_GET_REPORT			1
+#define HID_GET_IDLE			2
+#define HID_GET_PROTOCOL		3
+#define HID_SET_REPORT			9
+#define HID_SET_IDLE			10
+#define HID_SET_PROTOCOL		11
+
+// CDC (communication class device)
+#define CDC_SET_LINE_CODING		0x20
+#define CDC_GET_LINE_CODING		0x21
+#define CDC_SET_CONTROL_LINE_STATE	0x22
+
+
+
+// ----- Endpoint Configuration -----
+
+#define ENDPOINT0_SIZE		32
+
+#define KEYBOARD_INTERFACE	0
+#define KEYBOARD_ENDPOINT	2
+#define KEYBOARD_SIZE		8
+#define KEYBOARD_INTERVAL	1
+#define KEYBOARD_HID_BUFFER	EP_DOUBLE_BUFFER
+
+#define CDC_IAD_DESCRIPTOR	1
+#define CDC_STATUS_INTERFACE	1
+#define CDC_DATA_INTERFACE	2
+#define CDC_ACM_ENDPOINT	3
+#define CDC_RX_ENDPOINT		4
+#define CDC_TX_ENDPOINT		5
+#if defined(__AVR_AT90USB162__)
+#define CDC_ACM_SIZE		16
+#define CDC_ACM_BUFFER		EP_SINGLE_BUFFER
+#define CDC_RX_SIZE		32
+#define CDC_RX_BUFFER 		EP_DOUBLE_BUFFER
+#define CDC_TX_SIZE		32
+#define CDC_TX_BUFFER		EP_DOUBLE_BUFFER
+#else
+#define CDC_ACM_SIZE		16
+#define CDC_ACM_BUFFER		EP_SINGLE_BUFFER
+#define CDC_RX_SIZE		64
+#define CDC_RX_BUFFER 		EP_DOUBLE_BUFFER
+#define CDC_TX_SIZE		64
+#define CDC_TX_BUFFER		EP_DOUBLE_BUFFER
+#endif
+
+// Endpoint 0 is reserved for the control endpoint
+// Endpoint 1 has a 256 byte buffer
+// Endpoints 2-6 have 64 byte buffers
+static const uint8_t PROGMEM endpoint_config_table[] = {
+	0, // 256 byte
+	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_HID_BUFFER, // 64 byte
+	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(CDC_ACM_SIZE)  | CDC_ACM_BUFFER,      // 64 byte
+	1, EP_TYPE_BULK_OUT,      EP_SIZE(CDC_RX_SIZE)   | CDC_RX_BUFFER,       // 64 byte
+	1, EP_TYPE_BULK_IN,       EP_SIZE(CDC_TX_SIZE)   | CDC_TX_BUFFER,       // 64 byte
+};
+
+#endif // usb_keyboard_serial_h__
+
--- a/Output/pjrcUSB/output_com.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/Output/pjrcUSB/output_com.c	Mon Mar 31 01:07:48 2014 -0700
@@ -25,11 +25,13 @@
 #include <Lib/OutputLib.h>
 
 // Project Includes
+#include <cli.h>
+#include <print.h>
 #include <scan_loop.h>
 
 // USB Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
-#include "avr/usb_keyboard_debug.h"
+#include "avr/usb_keyboard_serial.h"
 #elif defined(_mk20dx128_) || defined(_mk20dx256_)
 #include "arm/usb_keyboard.h"
 #include "arm/usb_dev.h"
@@ -40,8 +42,31 @@
 
 
 
+// ----- Function Declarations -----
+
+void cliFunc_holdKey   ( char* args );
+void cliFunc_readLEDs  ( char* args );
+void cliFunc_releaseKey( char* args );
+void cliFunc_sendKey   ( char* args );
+void cliFunc_setLEDs   ( char* args );
+void cliFunc_setMod    ( char* args );
+
+
 // ----- Variables -----
 
+// Output Module command dictionary
+char*       outputCLIDictName = "USB Module Commands";
+CLIDictItem outputCLIDict[] = {
+	{ "holdKey",    "Hold a space separated list of USB codes. Ignores already pressed keys.", cliFunc_holdKey },
+	{ "readLEDs",   "Read LED byte. See setLEDs.", cliFunc_readLEDs },
+	{ "releaseKey", "Release a space separated list of USB codes. Ignores unpressed keys.", cliFunc_releaseKey },
+	{ "sendKey",    "Send a space separated list of USB codes. Press/Release.", cliFunc_sendKey },
+	{ "setLEDs",    "Set LED byte: 1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_setLEDs },
+	{ "setMod",     "Set the modfier byte: 1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod },
+	{ 0, 0, 0 } // Null entry for dictionary end
+};
+
+
 // which modifier keys are currently pressed
 // 1=left ctrl,    2=left shift,   4=left alt,    8=left gui
 // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
@@ -69,7 +94,6 @@
          uint8_t USBKeys_Idle_Count = 0;
 
 
-
 // ----- Functions -----
 
 // USB Module Setup
@@ -81,9 +105,12 @@
 	usb_init();
 	while ( !usb_configured() ) /* wait */ ;
 
+	// Register USB Output dictionary
+	registerDictionary_cli( outputCLIDict, outputCLIDictName );
+
 	// 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); // TODO
+	//_delay_ms(1000); // TODO (is this actually necessary?)
 }
 
 
@@ -110,8 +137,102 @@
 inline void output_firmwareReload()
 {
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
+	usb_debug_reload();
 #elif defined(_mk20dx128_) || defined(_mk20dx256_)
 	usb_device_reload();
 #endif
 }
 
+
+// USB Input buffer available
+inline unsigned int output_availablechar()
+{
+	return usb_serial_available();
+}
+
+
+// USB Get Character from input buffer
+inline int output_getchar()
+{
+#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
+	// XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes)
+	return (int)usb_serial_getchar();
+#elif defined(_mk20dx128_) || defined(_mk20dx256_)
+	return usb_serial_getchar();
+#endif
+}
+
+
+// USB Send Character to output buffer
+inline int output_putchar( char c )
+{
+	return usb_serial_putchar( c );
+}
+
+
+// USB Send String to output buffer, null terminated
+inline int output_putstr( char* str )
+{
+#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
+	uint16_t count = 0;
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
+	uint32_t count = 0;
+#endif
+	// Count characters until NULL character, then send the amount counted
+	while ( str[count] != '\0' )
+		count++;
+
+	return usb_serial_write( str, count );
+}
+
+
+// Soft Chip Reset
+inline void output_softReset()
+{
+#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
+	usb_debug_software_reset();
+#elif defined(_mk20dx128_) || defined(_mk20dx256_)
+	SOFTWARE_RESET();
+#endif
+}
+
+
+// ----- CLI Command Functions -----
+
+void cliFunc_holdKey( char* args )
+{
+	// TODO
+}
+
+
+void cliFunc_readLEDs( char* args )
+{
+	// TODO
+}
+
+
+void cliFunc_releaseKey( char* args )
+{
+	// TODO
+}
+
+
+void cliFunc_sendKey( char* args )
+{
+	// TODO Argument handling
+	USBKeys_Array[0] = 4; // KEY_A
+	USBKeys_Sent = 1;
+}
+
+
+void cliFunc_setLEDs( char* args )
+{
+	// TODO
+}
+
+
+void cliFunc_setMod( char* args )
+{
+	// TODO
+}
+
--- a/Output/pjrcUSB/output_com.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Output/pjrcUSB/output_com.h	Mon Mar 31 01:07:48 2014 -0700
@@ -59,10 +59,17 @@
 // ----- Functions -----
 
 void output_setup();
-
 void output_send();
 
 void output_firmwareReload();
+void output_softReset();
+
+// Relies on USB serial module
+unsigned int output_availablechar();
+
+int output_getchar();
+int output_putchar( char c );
+int output_putstr( char* str );
 
 #endif
 
--- a/Output/pjrcUSB/setup.cmake	Sat Mar 22 14:32:06 2014 -0700
+++ b/Output/pjrcUSB/setup.cmake	Mon Mar 31 01:07:48 2014 -0700
@@ -17,7 +17,7 @@
 
 	set( OUTPUT_SRCS
 		output_com.c
-		avr/usb_keyboard_debug.c
+		avr/usb_keyboard_serial.c
 	)
 
 #| ARM Compiler
--- a/README	Sat Mar 22 14:32:06 2014 -0700
+++ b/README	Mon Mar 31 01:07:48 2014 -0700
@@ -24,10 +24,12 @@
 - avr-libc     (1.8.0)
 
 
-ARM Specific (Teensy 3.0) (Sourcery CodeBench Lite for ARM EABI
+ARM Specific (Teensy 3.0/3.1) (Sourcery CodeBench Lite for ARM EABI
 (http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/)
 - arm-none-eabi
-- TODO?
+OR
+- arm-none-eabi-gcc
+- arm-none-eaby-binutils
 
 
 
@@ -42,6 +44,7 @@
  - Teensy 2.0
  - Teensy 2.0++
  - Teensy 3.0
+ - Teensy 3.1
 
 Open up CMakeLists.txt in your favourite text editor.
 You are looking for:
@@ -57,13 +60,14 @@
 	#| "avr"       # Teensy++ 1.0
 	#| "avr"       # Teensy++ 2.0
 	#| "arm"       # Teensy   3.0
+	#| "arm"       # Teensy   3.1
 
 	set( COMPILER_FAMILY "avr" )
 
 
 Just change the COMPILER_FAMILY variable to whatever you are trying to build for.
 
-NOTE: If you change this option, you will *may* to delete the build directory that is created in the Building sections below. 
+NOTE: If you change this option, you will *may* to delete the build directory that is created in the Building sections below.
 
 
 
@@ -102,6 +106,7 @@
 	#| type "make clean" after changing this, so all files will be rebuilt
 	#|
 	#| "mk20dx128"        # Teensy   3.0
+	#| "mk20dx256"        # Teensy   3.1
 
 	set( CHIP "mk20dx128" )
 
@@ -123,7 +128,7 @@
 
 - Scan Module
 - Macro Module
-- USB Module
+- Output Module
 - Debug Module
 
 The Scan Module is where the most interesting stuff happens. These modules take in "keypress data".
@@ -135,11 +140,11 @@
 Some scan modules have very specialized hardware requirements, each module directory should have at least a link to the needed parts and/or schematics (TODO!).
 
 
-The Macro Module takes care of the mapping of the key press/release code into a USB scan code.
+The Macro Module takes care of the mapping of the key press/release code into an Output (USB) scan code.
 Any layering, macros, keypress intelligence/reaction is done here.
 
 
-The USB Module is the output module of the microcontroller. Currently USB is the only output protocol.
+The Output Module is the module dealing with output from the microcontroller. Currently USB is the only output protocol.
 Different USB output implementations are available, pjrc being the safest/least featureful one.
 Debug capabilities may depend on the module selected.
 
@@ -161,7 +166,7 @@
 	#| All of the modules must be specified, as they generate the sources list of files to compile
 	#| Any modifications to this file will cause a complete rebuild of the project
 
-	#| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones
+	#| Please look at the {Scan,Macro,Output,Debug}/module.txt for information on the modules and how to create new ones
 
 	##| Deals with acquiring the keypress information and turning it into a key index
 	set(  ScanModule  "avr-capsense" )
@@ -170,7 +175,7 @@
 	set( MacroModule  "buffer"  )
 
 	##| Sends the current list of usb key codes through USB HID
-	set(   USBModule  "pjrc"   )
+	set(   OutputModule  "pjrc"   )
 
 	##| Debugging source to use, each module has it's own set of defines that it sets
 	set( DebugModule  "full"   )
@@ -206,8 +211,8 @@
 	Scan/avr-capsense/scan_loop.c
 	-- Detected Macro Module Source Files:
 	Macro/buffer/macro.c
-	-- Detected USB Module Source Files:
-	USB/pjrc/usb_com.c;USB/pjrc/avr/usb_keyboard_debug.c
+	-- Detected Output Module Source Files:
+	Output/pjrc/usb_com.c;Output/pjrc/avr/usb_keyboard_debug.c
 	-- Detected Debug Module Source Files:
 	Debug/full/../led/led.c;Debug/full/../print/print.c
 	-- Configuring done
@@ -218,8 +223,8 @@
 	[ 12%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o
 	[ 25%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/avr-capsense/scan_loop.c.o
 	[ 37%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/buffer/macro.c.o
-	[ 50%] Building C object CMakeFiles/kiibohd.elf.dir/USB/pjrc/usb_com.c.o
-	[ 62%] Building C object CMakeFiles/kiibohd.elf.dir/USB/pjrc/avr/usb_keyboard_debug.c.o
+	[ 50%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/usb_com.c.o
+	[ 62%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/avr/usb_keyboard_debug.c.o
 	[ 75%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.o
 	[ 87%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.o
 	Linking C executable kiibohd.elf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/DPH/scan_loop.c	Mon Mar 31 01:07:48 2014 -0700
@@ -0,0 +1,1012 @@
+/* Copyright (C) 2011-2013 by Joseph Makuch
+ * Additions by Jacob Alexander (2013-2014)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// ----- Includes -----
+
+// Compiler Includes
+#include <Lib/ScanLib.h>
+
+// Project Includes
+#include <led.h>
+#include <print.h>
+
+// Local Includes
+#include "scan_loop.h"
+
+
+
+// ----- Defines -----
+
+// TODO dfj defines...needs commenting and maybe some cleaning...
+#define MAX_PRESS_DELTA_MV 450 // As measured from the Teensy ADC pin
+#define THRESHOLD_MV (MAX_PRESS_DELTA_MV >> 1)
+//(2560 / (0x3ff/2)) ~= 5
+#define MV_PER_ADC 5
+#define THRESHOLD (THRESHOLD_MV / MV_PER_ADC)
+
+#define STROBE_SETTLE 1
+
+#define TEST_KEY_STROBE (0x05)
+#define TEST_KEY_MASK (1 << 0)
+
+#define ADHSM 7
+
+#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))
+
+// Strobe Masks
+#define D_MASK (0xff)
+#define E_MASK (0x03)
+#define C_MASK (0xff)
+
+// set ADC clock prescale
+#define PRESCALE_MASK ((1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2))
+#define PRESCALE_SHIFT (ADPS0)
+#define PRESCALE 3
+
+// Max number of strobes supported by the hardware
+// Strobe lines are detected at startup, extra strobes cause anomalies like phantom keypresses
+#define MAX_STROBES 18
+
+// Number of consecutive samples required to pass debounce
+#define DEBOUNCE_THRESHOLD 5
+
+#define MUXES_COUNT 8
+#define MUXES_COUNT_XSHIFT 3
+
+#define WARMUP_LOOPS ( 1024 )
+#define WARMUP_STOP (WARMUP_LOOPS - 1)
+
+#define SAMPLE_CONTROL 3
+
+#define KEY_COUNT ((MAX_STROBES) * (MUXES_COUNT))
+
+#define RECOVERY_CONTROL 1
+#define RECOVERY_SOURCE  0
+#define RECOVERY_SINK    2
+
+#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 IDLE_COUNT_SHIFT 8
+
+// 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
+
+
+
+// ----- Macros -----
+
+// Make sure we haven't overflowed the buffer
+#define bufferAdd(byte) \
+		if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
+			KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
+
+// Select mux
+#define SET_FULL_MUX(X) ((ADMUX) = (((ADMUX) & ~(FULL_MUX_MASK)) | ((X) & (FULL_MUX_MASK))))
+
+
+
+// ----- Variables -----
+
+// Buffer used to inform the macro processing module which keys have been detected as pressed
+volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
+volatile uint8_t KeyIndex_BufferUsed;
+
+
+// TODO dfj variables...needs cleaning up and commenting
+
+// Variables used to calculate the starting sense value (averaging)
+uint32_t full_avg = 0;
+uint32_t high_avg = 0;
+uint32_t  low_avg = 0;
+
+uint8_t  high_count = 0;
+uint8_t   low_count = 0;
+
+
+uint8_t ze_strober = 0;
+
+uint16_t samples[MUXES_COUNT];
+
+uint8_t cur_keymap[MAX_STROBES];
+
+uint8_t keymap_change;
+
+uint16_t threshold = THRESHOLD;
+
+uint8_t column = 0;
+
+uint16_t keys_averages_acc[KEY_COUNT];
+uint16_t keys_averages    [KEY_COUNT];
+uint8_t  keys_debounce    [KEY_COUNT]; // Contains debounce statistics
+uint8_t  keys_problem     [KEY_COUNT]; // Marks keys that should be ignored (determined by averaging at startup)
+
+uint8_t full_samples[KEY_COUNT];
+
+// TODO: change this to 'booting', then count down.
+uint16_t boot_count = 0;
+
+uint16_t idle_count = 0;
+uint8_t idle = 1;
+
+uint8_t error = 0;
+uint16_t error_data = 0;
+
+uint8_t total_strobes = MAX_STROBES;
+uint8_t strobe_map[MAX_STROBES];
+
+uint8_t dump_count = 0;
+
+
+
+// ----- Function Declarations -----
+
+void dump( void );
+
+void recovery( uint8_t on );
+
+int sampleColumn( uint8_t column );
+
+void capsense_scan( void );
+
+void setup_ADC( void );
+
+void strobe_w( uint8_t strobe_num );
+
+uint8_t testColumn( uint8_t strobe );
+
+
+
+// ----- Functions -----
+
+// Initial setup for cap sense controller
+inline void scan_setup()
+{
+	// TODO dfj code...needs cleanup + commenting...
+	setup_ADC();
+
+	DDRC  = C_MASK;
+	PORTC = 0;
+	DDRD  = D_MASK;
+	PORTD = 0;
+	DDRE  = E_MASK;
+	PORTE = 0 ;
+
+	// Hardcoded strobes for debugging
+	// Strobes start at 0 and go to 17 (18), not all Model Fs use all of the available strobes
+	// The single row ribbon connector Model Fs only have a max of 16 strobes
+#define KISHSAVER_STROBE
+//#define KISHSAVER_OLD_STROBE
+//#define TERMINAL_6110668_OLD_STROBE
+//#define UNSAVER_OLD_STROBE
+#ifdef KISHSAVER_OLD_STROBE
+	total_strobes = 9;
+
+	strobe_map[0] = 2; // Kishsaver doesn't use strobe 0 and 1
+	strobe_map[1] = 3;
+	strobe_map[2] = 4;
+	strobe_map[3] = 5;
+	strobe_map[4] = 6;
+	strobe_map[5] = 7;
+	strobe_map[6] = 8;
+	strobe_map[7] = 9;
+	strobe_map[8] = 15; // Test point strobe (3 test points, sense 1, 4, 5)
+#elif defined(KISHSAVER_STROBE)
+	total_strobes = 9;
+
+	strobe_map[0] = 15; // Kishsaver doesn't use strobe 0 and 1
+	strobe_map[1] = 14;
+	strobe_map[2] = 13;
+	strobe_map[3] = 12;
+	strobe_map[4] = 11;
+	strobe_map[5] = 10;
+	strobe_map[6] = 9;
+	strobe_map[7] = 8;
+	strobe_map[8] = 2; // Test point strobe (3 test points, sense 1, 4, 5)
+#elif defined(TERMINAL_6110668_OLD_STROBE)
+	total_strobes = 16;
+
+	strobe_map[0] = 0;
+	strobe_map[1] = 1;
+	strobe_map[2] = 2;
+	strobe_map[3] = 3;
+	strobe_map[4] = 4;
+	strobe_map[5] = 5;
+	strobe_map[6] = 6;
+	strobe_map[7] = 7;
+	strobe_map[8] = 8;
+	strobe_map[9] = 9;
+	strobe_map[10] = 10;
+	strobe_map[11] = 11;
+	strobe_map[12] = 12;
+	strobe_map[13] = 13;
+	strobe_map[14] = 14;
+	strobe_map[15] = 15;
+#elif defined(UNSAVER_OLD_STROBE)
+	total_strobes = 14;
+
+	strobe_map[0] = 0;
+	strobe_map[1] = 1;
+	strobe_map[2] = 2;
+	strobe_map[3] = 3;
+	strobe_map[4] = 4;
+	strobe_map[5] = 5;
+	strobe_map[6] = 6;
+	strobe_map[7] = 7;
+	strobe_map[8] = 8;
+	strobe_map[9] = 9;
+	strobe_map[10] = 10;
+	strobe_map[11] = 11;
+	strobe_map[12] = 12;
+	strobe_map[13] = 13;
+#else
+	// Strobe detection
+	// TODO
+#endif
+
+	// TODO all this code should probably be in scan_resetKeyboard
+	for ( int i = 0; i < total_strobes; ++i)
+	{
+		cur_keymap[i] = 0;
+	}
+
+	// Reset debounce table
+	for ( int i = 0; i < KEY_COUNT; ++i )
+	{
+		keys_debounce[i] = 0;
+	}
+
+	// Warm things up a bit before we start collecting data, taking real samples.
+	for ( uint8_t i = 0; i < total_strobes; ++i )
+	{
+		sampleColumn( strobe_map[i] );
+	}
+
+
+	// Reset the keyboard before scanning, we might be in a wierd state
+	// Also sets the KeyIndex_BufferUsed to 0
+	scan_resetKeyboard();
+}
+
+
+// Main Detection Loop
+// This is where the important stuff happens
+inline uint8_t scan_loop()
+{
+	capsense_scan();
+
+	// Error case, should not occur in normal operation
+	if ( error )
+	{
+		erro_msg("Problem detected... ");
+
+		// Keymap scan debug
+		for ( uint8_t i = 0; i < total_strobes; ++i )
+		{
+			printHex(cur_keymap[strobe_map[i]]);
+			print(" ");
+		}
+
+		print(" : ");
+		printHex(error);
+		error = 0;
+		print(" : ");
+		printHex(error_data);
+		error_data = 0;
+
+		// Display keymaps and other debug information if warmup completede
+		if ( boot_count >= WARMUP_LOOPS )
+		{
+			dump();
+		}
+	}
+
+
+	// Return non-zero if macro and USB processing should be delayed
+	// Macro processing will always run if returning 0
+	// USB processing only happens once the USB send timer expires, if it has not, scan_loop will be called
+	//  after the macro processing has been completed
+	return 0;
+}
+
+
+// Reset Keyboard
+void scan_resetKeyboard( void )
+{
+	// Empty buffer, now that keyboard has been reset
+	KeyIndex_BufferUsed = 0;
+}
+
+
+// Send data to keyboard
+// NOTE: Only used for converters, since the scan module shouldn't handle sending data in a controller
+uint8_t scan_sendData( uint8_t dataPayload )
+{
+	return 0;
+}
+
+
+// Reset/Hold keyboard
+// NOTE: Only used for converters, not needed for full controllers
+void scan_lockKeyboard( void )
+{
+}
+
+// NOTE: Only used for converters, not needed for full controllers
+void scan_unlockKeyboard( void )
+{
+}
+
+
+// Signal KeyIndex_Buffer that it has been properly read
+// NOTE: Only really required for implementing "tricks" in converters for odd protocols
+void scan_finishedWithBuffer( uint8_t sentKeys )
+{
+	// Convenient place to clear the KeyIndex_Buffer
+	KeyIndex_BufferUsed = 0;
+	return;
+}
+
+
+// Signal KeyIndex_Buffer that it has been properly read and sent out by the USB module
+// NOTE: Only really required for implementing "tricks" in converters for odd protocols
+void scan_finishedWithUSBBuffer( uint8_t sentKeys )
+{
+	return;
+}
+
+
+inline void capsense_scan()
+{
+	// Accumulated average used for the next scan
+	uint32_t cur_full_avg = 0;
+	uint32_t cur_high_avg = 0;
+
+	// Reset average counters
+	low_avg = 0;
+	low_count = 0;
+
+	high_count = 0;
+
+	// Scan each of the mapped strobes in the matrix
+	for ( uint8_t strober = 0; strober < total_strobes; ++strober )
+	{
+		uint8_t map_strobe = strobe_map[strober];
+
+		uint8_t tries = 1;
+		while ( tries++ && sampleColumn( map_strobe ) ) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+
+		// Only process sense data if warmup is finished
+		if ( boot_count >= WARMUP_LOOPS )
+		{
+			column = testColumn( map_strobe );
+
+			idle |= column; // if column has any pressed keys, then we are not idle.
+
+			// TODO Is this needed anymore? Really only helps debug -HaaTa
+			if( column != cur_keymap[map_strobe] && ( boot_count >= WARMUP_LOOPS ) )
+			{
+				cur_keymap[map_strobe] = column;
+				keymap_change = 1;
+			}
+
+			idle |= keymap_change; // if any keys have changed inc. released, then we are not idle.
+		}
+
+		if ( error == 0x50 )
+		{
+			error_data |= (((uint16_t)map_strobe) << 12);
+		}
+
+		uint8_t strobe_line = map_strobe << MUXES_COUNT_XSHIFT;
+		for ( int i = 0; i < MUXES_COUNT; ++i )
+		{
+			// discard sketchy low bit, and meaningless high bits.
+			uint8_t sample = samples[i] >> 1;
+			full_samples[strobe_line + i] = sample;
+			keys_averages_acc[strobe_line + i] += sample;
+		}
+
+		// Accumulate 3 total averages (used for determining starting average during warmup)
+		//     full_avg - Average of all sampled lines on the previous scan set
+		// cur_full_avg - Average of all sampled lines for this scan set
+		//     high_avg - Average of all sampled lines above full_avg on the previous scan set
+		// cur_high_avg - Average of all sampled lines above full_avg
+		//      low_avg - Average of all sampled lines below or equal to full_avg
+		if ( boot_count < WARMUP_LOOPS )
+		{
+			for ( uint8_t i = 0; i < MUXES_COUNT; ++i )
+			{
+				uint8_t sample = samples[i] >> 1;
+
+				// Sample is high, add it to high avg
+				if ( sample > full_avg )
+				{
+					high_count++;
+					cur_high_avg += sample;
+				}
+				// Sample is low, add it to low avg
+				else
+				{
+					low_count++;
+					low_avg += sample;
+				}
+
+				// If sample is higher than previous high_avg, then mark as "problem key"
+				keys_problem[strobe_line + i] = sample > high_avg ? sample : 0;
+
+				// Prepare for next average
+				cur_full_avg += sample;
+			}
+		}
+	} // for strober
+
+	// Update total sense average (only during warm-up)
+	if ( boot_count < WARMUP_LOOPS )
+	{
+		full_avg = cur_full_avg / (total_strobes * MUXES_COUNT);
+		high_avg = cur_high_avg / high_count;
+		low_avg /= low_count;
+
+		// Update the base average value using the low_avg (best chance of not ignoring a keypress)
+		for ( int i = 0; i < KEY_COUNT; ++i )
+		{
+			keys_averages[i] = low_avg;
+			keys_averages_acc[i] = low_avg;
+		}
+	}
+
+#ifdef VERIFY_TEST_PAD
+	// verify test key is not down.
+	if ( ( cur_keymap[TEST_KEY_STROBE] & TEST_KEY_MASK ) )
+	{
+		error = 0x05;
+		error_data = cur_keymap[TEST_KEY_STROBE] << 8;
+		error_data += full_samples[TEST_KEY_STROBE * 8];
+	}
+#endif
+
+	/** aggregate if booting, or if idle;
+	 * else, if not booting, check for dirty USB.
+	 * */
+
+	idle_count++;
+	idle_count &= IDLE_COUNT_MASK;
+
+	// Warm up voltage references
+	if ( boot_count < WARMUP_LOOPS )
+	{
+		boot_count++;
+
+		switch ( boot_count )
+		{
+		// First loop
+		case 1:
+			// Show msg at first iteration only
+			info_msg("Warming up the voltage references");
+			break;
+		// Middle iterations
+		case 300:
+		case 600:
+		case 900:
+		case 1200:
+			print(".");
+			break;
+		// Last loop
+		case WARMUP_STOP:
+			print("\n");
+			info_msg("Warmup finished using ");
+			printInt16( WARMUP_LOOPS );
+			print(" iterations\n");
+
+			// Display the final calculated averages of all the sensed strobes
+			info_msg("Full average (");
+			printInt8( total_strobes * MUXES_COUNT );
+			print("): ");
+			printHex( full_avg );
+
+			print("  High average (");
+			printInt8( high_count );
+			print("): ");
+			printHex( high_avg );
+
+			print("  Low average (");
+			printInt8( low_count );
+			print("): ");
+			printHex( low_avg );
+			print("\n");
+
+			// Display problem keys, and the sense value at the time
+			for ( uint8_t key = 0; key < KEY_COUNT; key++ )
+			{
+				if ( keys_problem[key] )
+				{
+					warn_msg("Problem key detected: ");
+					printHex( key );
+					print(" (");
+					printHex( keys_problem[key] );
+					print(")\n");
+				}
+			}
+
+			info_print("If problem keys were detected, and were being held down, they will be reset as soon as let go");
+			break;
+		}
+	}
+	else
+	{
+		// Reset accumulators and idle flag/counter
+		if ( keymap_change )
+		{
+			for ( uint8_t c = 0; c < KEY_COUNT; ++c ) { keys_averages_acc[c] = 0; }
+			idle_count = 0;
+			idle = 0;
+
+			keymap_change = 0;
+		}
+
+		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];
+
+					av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
+					av >>= KEYS_AVERAGES_MIX_SHIFT;
+
+					keys_averages[i] = av;
+					keys_averages_acc[i] = 0;
+				}
+			}
+
+			if ( boot_count >= WARMUP_LOOPS )
+			{
+				dump();
+			}
+		}
+
+	}
+}
+
+
+void setup_ADC()
+{
+	// disable adc digital pins.
+	DIDR1 |= (1 << AIN0D) | (1<<AIN1D); // set disable on pins 1,0.
+	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 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 = (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;
+
+	// 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 << ADEN); // ADC enable
+	ADCSRA |= (1 << ADSC); // start conversions q
+}
+
+
+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 )
+	{
+		// 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
+	{
+		PORTB &= ~(1 << RECOVERY_CONTROL);
+		DDRB  &= ~(1 << RECOVERY_SOURCE);
+		PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low
+		DDRB  &= ~(1 << RECOVERY_SINK);	  // SINK high-imp
+	}
+}
+
+
+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);
+	PORTD &= ~(D_MASK);
+	PORTE &= ~(E_MASK);
+
+	// Strobe table
+	// Not all strobes are used depending on which are detected
+	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;
+	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;
+
+	default:
+		break;
+	}
+}
+
+
+inline uint16_t getADC(void)
+{
+	ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
+
+	//wait for last read to complete.
+	while ( !( ADCSRA & (1 << ADIF) ) );
+
+	return ADC; // return sample
+}
+
+
+int sampleColumn_8x( uint8_t column, uint16_t * buffer )
+{
+	// ensure all probe lines are driven low, and chill for recovery delay.
+	ADCSRA |= (1 << ADEN) | (1 << ADSC); // enable and start conversions
+
+	PORTC &= ~C_MASK;
+	PORTD &= ~D_MASK;
+	PORTE &= ~E_MASK;
+
+	PORTF = 0;
+	DDRF  = 0;
+
+	recovery( OFF );
+	strobe_w( column );
+
+	hold_sample( OFF );
+	SET_FULL_MUX( 0 );
+
+	// Allow strobes to settle
+	for ( uint8_t i = 0; i < STROBE_SETTLE; ++i ) { getADC(); }
+
+	hold_sample( ON );
+
+	uint8_t mux = 0;
+	SET_FULL_MUX( mux );
+	getADC(); // throw away; unknown mux.
+	do {
+		SET_FULL_MUX( mux + 1 ); // our *next* sample will use this
+
+		// retrieve current read.
+		buffer[mux] = getADC();
+		mux++;
+
+	} while ( mux < 8 );
+
+	hold_sample( OFF );
+	recovery( ON );
+
+	// turn off adc.
+	ADCSRA &= ~(1 << ADEN);
+
+	// pull all columns' strobe-lines low.
+	DDRC |= C_MASK;
+	DDRD |= D_MASK;
+	DDRE |= E_MASK;
+
+	PORTC &= ~C_MASK;
+	PORTD &= ~D_MASK;
+	PORTE &= ~E_MASK;
+
+	return 0;
+}
+
+
+int sampleColumn( uint8_t column )
+{
+	int rval = 0;
+
+	rval = sampleColumn_8x( column, samples );
+
+	return rval;
+}
+
+
+uint8_t testColumn( uint8_t strobe )
+{
+	uint16_t db_delta = 0;
+	uint8_t  db_sample = 0;
+	uint16_t db_threshold = 0;
+
+	uint8_t column = 0;
+	uint8_t bit = 1;
+
+	for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
+	{
+		uint16_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + mux];
+
+		uint8_t key = (strobe << MUXES_COUNT_XSHIFT) + mux;
+
+		// Check if this is a bad key (e.g. test point, or non-existent key)
+		if ( keys_problem[key] )
+		{
+			// If the sample value of the problem key goes below full_avg (overall initial average)
+			//  re-enable the key
+			if ( (db_sample = samples[mux] >> 1) < full_avg )
+			{
+				info_msg("Re-enabling problem key: ");
+				printHex( key );
+				print("\n");
+
+				keys_problem[key] = 0;
+			}
+			// Otherwise, don't waste any more cycles processing the problem key
+			else
+			{
+				continue;
+			}
+		}
+
+		// Keypress detected
+		//  db_sample (uint8_t), discard meaningless high bit, and garbage low bit
+		if ( (db_sample = samples[mux] >> 1) > (db_threshold = threshold) + (db_delta = delta) )
+		{
+			column |= bit;
+
+			// Only register keypresses once the warmup is complete, or not enough debounce info
+			if ( keys_debounce[key] <= DEBOUNCE_THRESHOLD )
+			{
+				// Add to the Macro processing buffer if debounce criteria met
+				// Automatically handles converting to a USB code and sending off to the PC
+				if ( keys_debounce[key] == DEBOUNCE_THRESHOLD )
+				{
+//#define KEYSCAN_DEBOUNCE_DEBUG
+#ifdef KEYSCAN_DEBOUNCE_DEBUG
+					// Debug message
+					print("0x");
+					printHex_op( key, 2 );
+					print(" ");
+#endif
+
+					// Only add the key to the buffer once
+					// NOTE: Buffer can easily handle multiple adds, just more efficient
+					//        and nicer debug messages :P
+					//bufferAdd( key );
+				}
+
+				keys_debounce[key]++;
+
+#define KEYSCAN_THRESHOLD_DEBUG
+#ifdef KEYSCAN_THRESHOLD_DEBUG
+				// Debug message
+				// <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
+				dbug_msg("0x");
+				printHex_op( key, 2 );
+				print(" [");
+				printInt8( strobe );
+				print(":");
+				printInt8( mux );
+				print("] : ");
+				printHex( db_sample ); // Sense
+				print(" : ");
+				printHex( db_threshold );
+				print("+");
+				printHex( db_delta );
+				print("=");
+				printHex( db_threshold + db_delta ); // Sense compare
+				print(" : ");
+				printHex( db_sample - ( db_threshold + db_delta ) ); // Margin
+				print("\n");
+#endif
+			}
+		}
+		// Clear debounce entry if no keypress detected
+		else
+		{
+			// If the key was previously pressed, remove from the buffer
+			for ( uint8_t c = 0; c < KeyIndex_BufferUsed; c++ )
+                        {
+                                // Key to release found
+                                if ( KeyIndex_Buffer[c] == key )
+                                {
+                                        // Shift keys from c position
+                                        for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
+                                                KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
+
+                                        // Decrement Buffer
+                                        KeyIndex_BufferUsed--;
+
+                                        break;
+                                }
+                        }
+
+
+			// Clear debounce entry
+			keys_debounce[key] = 0;
+		}
+
+		bit <<= 1;
+	}
+	return column;
+}
+
+
+void dump(void) {
+
+#ifdef DEBUG_FULL_SAMPLES_AVERAGES
+	// we don't want to debug-out during the measurements.
+	if ( !dump_count )
+	{
+		// Averages currently set per key
+		for ( int i = 0; i < KEY_COUNT; ++i )
+		{
+			if ( !(i & 0x0f) )
+			{
+				print("\n");
+			}
+			else if ( !(i & 0x07) )
+			{
+				print("  ");
+			}
+
+			print(" ");
+			printHex( keys_averages[i] );
+		}
+
+		print("\n");
+
+		// Previously read full ADC scans?
+		for ( int i = 0; i< KEY_COUNT; ++i)
+		{
+			if ( !(i & 0x0f) )
+			{
+				print("\n");
+			}
+			else if ( !(i & 0x07) )
+			{
+				print("  ");
+			}
+
+			print(" ");
+			printHex(full_samples[i]);
+		}
+	}
+#endif
+
+#ifdef DEBUG_STROBE_SAMPLES_AVERAGES
+	// Per strobe information
+	uint8_t cur_strober = ze_strober;
+	print("\n");
+
+	printHex(cur_strober);
+
+	// Previously read ADC scans on current strobe
+	print(" :");
+	for ( uint8_t i = 0; i < MUXES_COUNT; ++i )
+	{
+		print(" ");
+		printHex(full_samples[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
+	}
+
+	// Averages current set on current strobe
+	print(" :");
+
+	for ( uint8_t i = 0; i < MUXES_COUNT; ++i )
+	{
+		print(" ");
+		printHex(keys_averages[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
+	}
+
+#endif
+
+#ifdef DEBUG_USB_KEYMAP
+	print("\n      ");
+
+	// Current keymap values
+	for ( uint8_t i = 0; i < total_strobes; ++i )
+	{
+		printHex(cur_keymap[i]);
+		print(" ");
+	}
+#endif
+
+	ze_strober++;
+	ze_strober &= 0xf;
+
+	dump_count++;
+	dump_count &= 0x0f;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/DPH/scan_loop.h	Mon Mar 31 01:07:48 2014 -0700
@@ -0,0 +1,64 @@
+/* Copyright (C) 2013 by Jacob Alexander
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SCAN_LOOP_H
+#define __SCAN_LOOP_H
+
+// ----- Includes -----
+
+// Compiler Includes
+#include <stdint.h>
+
+// Local Includes
+
+
+
+// ----- Defines -----
+
+#define KEYBOARD_KEYS 0xFF // TODO Determine max number of keys
+#define KEYBOARD_BUFFER 24 // Max number of key signals to buffer
+                           // This limits the NKRO-ability, so at 24, the keyboard is 24KRO
+                           // The buffer is really only needed for converter modules
+                           // An alternative macro module could be written for matrix modules and still work well
+
+
+
+// ----- Variables -----
+
+extern volatile     uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
+extern volatile     uint8_t KeyIndex_BufferUsed;
+
+
+
+// ----- Functions -----
+
+// Functions used by main.c
+void scan_setup( void );
+uint8_t scan_loop( void );
+
+
+// Functions available to macro.c
+uint8_t scan_sendData( uint8_t dataPayload );
+
+void scan_finishedWithBuffer( uint8_t sentKeys );
+void scan_finishedWithUSBBuffer( uint8_t sentKeys );
+void scan_lockKeyboard( void );
+void scan_unlockKeyboard( void );
+void scan_resetKeyboard( void );
+
+
+#endif // __SCAN_LOOP_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/DPH/setup.cmake	Mon Mar 31 01:07:48 2014 -0700
@@ -0,0 +1,54 @@
+###| CMake Kiibohd Controller Scan Module |###
+#
+# Written by Jacob Alexander in 2013-2014 for the Kiibohd Controller
+#
+# Released into the Public Domain
+#
+###
+
+
+###
+# Module C files
+#
+
+set( SCAN_SRCS
+	scan_loop.c
+)
+
+
+###
+# Module H files
+#
+set( SCAN_HDRS
+	scan_loop.h
+)
+
+
+###
+# File Dependency Setup
+#
+ADD_FILE_DEPENDENCIES( scan_loop.c ${SCAN_HDRS} )
+#add_file_dependencies( scan_loop.c ${SCAN_HDRS} )
+#add_file_dependencies( macro.c keymap.h avrcapsense.h )
+
+
+###
+# Module Specific Options
+#
+add_definitions( -I${HEAD_DIR}/Keymap )
+
+#| Keymap Settings
+add_definitions(
+	-DMODIFIER_MASK=avrcapsense_ModifierMask
+	#-DKEYINDEX_MASK=avrcapsense_ColemakMap
+	-DKEYINDEX_MASK=avrcapsense_DefaultMap
+)
+
+
+###
+# Compiler Family Compatibility
+#
+set( ScanModuleCompatibility
+	avr
+)
+
--- a/Scan/SKM67001/setup.cmake	Sat Mar 22 14:32:06 2014 -0700
+++ b/Scan/SKM67001/setup.cmake	Mon Mar 31 01:07:48 2014 -0700
@@ -24,7 +24,7 @@
 add_definitions( -I${HEAD_DIR}/Keymap )
 add_definitions(
 	-I${HEAD_DIR}/Scan/matrix
-)	
+)
 
 #| Keymap Settings
 add_definitions(
--- a/Scan/avr-capsense/scan_loop.c	Sat Mar 22 14:32:06 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1012 +0,0 @@
-/* Copyright (C) 2011-2013 by Joseph Makuch
- * Additions by Jacob Alexander (2013)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3.0 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-// ----- Includes -----
-
-// Compiler Includes
-#include <Lib/ScanLib.h>
-
-// Project Includes
-#include <led.h>
-#include <print.h>
-
-// Local Includes
-#include "scan_loop.h"
-
-
-
-// ----- Defines -----
-
-// TODO dfj defines...needs commenting and maybe some cleaning...
-#define MAX_PRESS_DELTA_MV 450 // As measured from the Teensy ADC pin
-#define THRESHOLD_MV (MAX_PRESS_DELTA_MV >> 1)
-//(2560 / (0x3ff/2)) ~= 5
-#define MV_PER_ADC 5
-#define THRESHOLD (THRESHOLD_MV / MV_PER_ADC)
-
-#define STROBE_SETTLE 1
-
-#define TEST_KEY_STROBE (0x05)
-#define TEST_KEY_MASK (1 << 0)
-
-#define ADHSM 7
-
-#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))
-
-// Strobe Masks
-#define D_MASK (0xff)
-#define E_MASK (0x03)
-#define C_MASK (0xff)
-
-// set ADC clock prescale
-#define PRESCALE_MASK ((1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2))
-#define PRESCALE_SHIFT (ADPS0)
-#define PRESCALE 3
-
-// Max number of strobes supported by the hardware
-// Strobe lines are detected at startup, extra strobes cause anomalies like phantom keypresses
-#define MAX_STROBES 18
-
-// Number of consecutive samples required to pass debounce
-#define DEBOUNCE_THRESHOLD 5
-
-#define MUXES_COUNT 8
-#define MUXES_COUNT_XSHIFT 3
-
-#define WARMUP_LOOPS ( 1024 )
-#define WARMUP_STOP (WARMUP_LOOPS - 1)
-
-#define SAMPLE_CONTROL 3
-
-#define KEY_COUNT ((MAX_STROBES) * (MUXES_COUNT))
-
-#define RECOVERY_CONTROL 1
-#define RECOVERY_SOURCE  0
-#define RECOVERY_SINK    2
-
-#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 IDLE_COUNT_SHIFT 8
-
-// 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
-
-
-
-// ----- Macros -----
-
-// Make sure we haven't overflowed the buffer
-#define bufferAdd(byte) \
-		if ( KeyIndex_BufferUsed < KEYBOARD_BUFFER ) \
-			KeyIndex_Buffer[KeyIndex_BufferUsed++] = byte
-
-// Select mux
-#define SET_FULL_MUX(X) ((ADMUX) = (((ADMUX) & ~(FULL_MUX_MASK)) | ((X) & (FULL_MUX_MASK))))
-
-
-
-// ----- Variables -----
-
-// Buffer used to inform the macro processing module which keys have been detected as pressed
-volatile uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
-volatile uint8_t KeyIndex_BufferUsed;
-
-
-// TODO dfj variables...needs cleaning up and commenting
-
-// Variables used to calculate the starting sense value (averaging)
-uint32_t full_avg = 0;
-uint32_t high_avg = 0;
-uint32_t  low_avg = 0;
-
-uint8_t  high_count = 0;
-uint8_t   low_count = 0;
-
-
-uint8_t ze_strober = 0;
-
-uint16_t samples[MUXES_COUNT];
-
-uint8_t cur_keymap[MAX_STROBES];
-
-uint8_t keymap_change;
-
-uint16_t threshold = THRESHOLD;
-
-uint8_t column = 0;
-
-uint16_t keys_averages_acc[KEY_COUNT];
-uint16_t keys_averages    [KEY_COUNT];
-uint8_t  keys_debounce    [KEY_COUNT]; // Contains debounce statistics
-uint8_t  keys_problem     [KEY_COUNT]; // Marks keys that should be ignored (determined by averaging at startup)
-
-uint8_t full_samples[KEY_COUNT];
-
-// TODO: change this to 'booting', then count down.
-uint16_t boot_count = 0;
-
-uint16_t idle_count = 0;
-uint8_t idle = 1;
-
-uint8_t error = 0;
-uint16_t error_data = 0;
-
-uint8_t total_strobes = MAX_STROBES;
-uint8_t strobe_map[MAX_STROBES];
-
-uint8_t dump_count = 0;
-
-
-
-// ----- Function Declarations -----
-
-void dump( void );
-
-void recovery( uint8_t on );
-
-int sampleColumn( uint8_t column );
-
-void capsense_scan( void );
-
-void setup_ADC( void );
-
-void strobe_w( uint8_t strobe_num );
-
-uint8_t testColumn( uint8_t strobe );
-
-
-
-// ----- Functions -----
-
-// Initial setup for cap sense controller
-inline void scan_setup()
-{
-	// TODO dfj code...needs cleanup + commenting...
-	setup_ADC();
-
-	DDRC  = C_MASK;
-	PORTC = 0;
-	DDRD  = D_MASK;
-	PORTD = 0;
-	DDRE  = E_MASK;
-	PORTE = 0 ;
-
-	// Hardcoded strobes for debugging
-	// Strobes start at 0 and go to 17 (18), not all Model Fs use all of the available strobes
-	// The single row ribbon connector Model Fs only have a max of 16 strobes
-#define KISHSAVER_STROBE
-//#define KISHSAVER_OLD_STROBE
-//#define TERMINAL_6110668_OLD_STROBE
-//#define UNSAVER_OLD_STROBE
-#ifdef KISHSAVER_OLD_STROBE
-	total_strobes = 9;
-
-	strobe_map[0] = 2; // Kishsaver doesn't use strobe 0 and 1
-	strobe_map[1] = 3;
-	strobe_map[2] = 4;
-	strobe_map[3] = 5;
-	strobe_map[4] = 6;
-	strobe_map[5] = 7;
-	strobe_map[6] = 8;
-	strobe_map[7] = 9;
-	strobe_map[8] = 15; // Test point strobe (3 test points, sense 1, 4, 5)
-#elif defined(KISHSAVER_STROBE)
-	total_strobes = 9;
-
-	strobe_map[0] = 15; // Kishsaver doesn't use strobe 0 and 1
-	strobe_map[1] = 14;
-	strobe_map[2] = 13;
-	strobe_map[3] = 12;
-	strobe_map[4] = 11;
-	strobe_map[5] = 10;
-	strobe_map[6] = 9;
-	strobe_map[7] = 8;
-	strobe_map[8] = 2; // Test point strobe (3 test points, sense 1, 4, 5)
-#elif defined(TERMINAL_6110668_OLD_STROBE)
-	total_strobes = 16;
-
-	strobe_map[0] = 0;
-	strobe_map[1] = 1;
-	strobe_map[2] = 2;
-	strobe_map[3] = 3;
-	strobe_map[4] = 4;
-	strobe_map[5] = 5;
-	strobe_map[6] = 6;
-	strobe_map[7] = 7;
-	strobe_map[8] = 8;
-	strobe_map[9] = 9;
-	strobe_map[10] = 10;
-	strobe_map[11] = 11;
-	strobe_map[12] = 12;
-	strobe_map[13] = 13;
-	strobe_map[14] = 14;
-	strobe_map[15] = 15;
-#elif defined(UNSAVER_OLD_STROBE)
-	total_strobes = 14;
-
-	strobe_map[0] = 0;
-	strobe_map[1] = 1;
-	strobe_map[2] = 2;
-	strobe_map[3] = 3;
-	strobe_map[4] = 4;
-	strobe_map[5] = 5;
-	strobe_map[6] = 6;
-	strobe_map[7] = 7;
-	strobe_map[8] = 8;
-	strobe_map[9] = 9;
-	strobe_map[10] = 10;
-	strobe_map[11] = 11;
-	strobe_map[12] = 12;
-	strobe_map[13] = 13;
-#else
-	// Strobe detection
-	// TODO
-#endif
-
-	// TODO all this code should probably be in scan_resetKeyboard
-	for ( int i = 0; i < total_strobes; ++i)
-	{
-		cur_keymap[i] = 0;
-	}
-
-	// Reset debounce table
-	for ( int i = 0; i < KEY_COUNT; ++i )
-	{
-		keys_debounce[i] = 0;
-	}
-
-	// Warm things up a bit before we start collecting data, taking real samples.
-	for ( uint8_t i = 0; i < total_strobes; ++i )
-	{
-		sampleColumn( strobe_map[i] );
-	}
-
-
-	// Reset the keyboard before scanning, we might be in a wierd state
-	// Also sets the KeyIndex_BufferUsed to 0
-	scan_resetKeyboard();
-}
-
-
-// Main Detection Loop
-// This is where the important stuff happens
-inline uint8_t scan_loop()
-{
-	capsense_scan();
-
-	// Error case, should not occur in normal operation
-	if ( error )
-	{
-		erro_msg("Problem detected... ");
-
-		// Keymap scan debug
-		for ( uint8_t i = 0; i < total_strobes; ++i )
-		{
-			printHex(cur_keymap[strobe_map[i]]);
-			print(" ");
-		}
-
-		print(" : ");
-		printHex(error);
-		error = 0;
-		print(" : ");
-		printHex(error_data);
-		error_data = 0;
-
-		// Display keymaps and other debug information if warmup completede
-		if ( boot_count >= WARMUP_LOOPS )
-		{
-			dump();
-		}
-	}
-
-
-	// Return non-zero if macro and USB processing should be delayed
-	// Macro processing will always run if returning 0
-	// USB processing only happens once the USB send timer expires, if it has not, scan_loop will be called
-	//  after the macro processing has been completed
-	return 0;
-}
-
-
-// Reset Keyboard
-void scan_resetKeyboard( void )
-{
-	// Empty buffer, now that keyboard has been reset
-	KeyIndex_BufferUsed = 0;
-}
-
-
-// Send data to keyboard
-// NOTE: Only used for converters, since the scan module shouldn't handle sending data in a controller
-uint8_t scan_sendData( uint8_t dataPayload )
-{
-	return 0;
-}
-
-
-// Reset/Hold keyboard
-// NOTE: Only used for converters, not needed for full controllers
-void scan_lockKeyboard( void )
-{
-}
-
-// NOTE: Only used for converters, not needed for full controllers
-void scan_unlockKeyboard( void )
-{
-}
-
-
-// Signal KeyIndex_Buffer that it has been properly read
-// NOTE: Only really required for implementing "tricks" in converters for odd protocols
-void scan_finishedWithBuffer( uint8_t sentKeys )
-{
-	// Convenient place to clear the KeyIndex_Buffer
-	KeyIndex_BufferUsed = 0;
-	return;
-}
-
-
-// Signal KeyIndex_Buffer that it has been properly read and sent out by the USB module
-// NOTE: Only really required for implementing "tricks" in converters for odd protocols
-void scan_finishedWithUSBBuffer( uint8_t sentKeys )
-{
-	return;
-}
-
-
-inline void capsense_scan()
-{
-	// Accumulated average used for the next scan
-	uint32_t cur_full_avg = 0;
-	uint32_t cur_high_avg = 0;
-
-	// Reset average counters
-	low_avg = 0;
-	low_count = 0;
-
-	high_count = 0;
-
-	// Scan each of the mapped strobes in the matrix
-	for ( uint8_t strober = 0; strober < total_strobes; ++strober )
-	{
-		uint8_t map_strobe = strobe_map[strober];
-
-		uint8_t tries = 1;
-		while ( tries++ && sampleColumn( map_strobe ) ) { tries &= 0x7; } // don't waste this one just because the last one was poop.
-
-		// Only process sense data if warmup is finished
-		if ( boot_count >= WARMUP_LOOPS )
-		{
-			column = testColumn( map_strobe );
-
-			idle |= column; // if column has any pressed keys, then we are not idle.
-
-			// TODO Is this needed anymore? Really only helps debug -HaaTa
-			if( column != cur_keymap[map_strobe] && ( boot_count >= WARMUP_LOOPS ) )
-			{
-				cur_keymap[map_strobe] = column;
-				keymap_change = 1;
-			}
-
-			idle |= keymap_change; // if any keys have changed inc. released, then we are not idle.
-		}
-
-		if ( error == 0x50 )
-		{
-			error_data |= (((uint16_t)map_strobe) << 12);
-		}
-
-		uint8_t strobe_line = map_strobe << MUXES_COUNT_XSHIFT;
-		for ( int i = 0; i < MUXES_COUNT; ++i )
-		{
-			// discard sketchy low bit, and meaningless high bits.
-			uint8_t sample = samples[i] >> 1;
-			full_samples[strobe_line + i] = sample;
-			keys_averages_acc[strobe_line + i] += sample;
-		}
-
-		// Accumulate 3 total averages (used for determining starting average during warmup)
-		//     full_avg - Average of all sampled lines on the previous scan set
-		// cur_full_avg - Average of all sampled lines for this scan set
-		//     high_avg - Average of all sampled lines above full_avg on the previous scan set
-		// cur_high_avg - Average of all sampled lines above full_avg
-		//      low_avg - Average of all sampled lines below or equal to full_avg
-		if ( boot_count < WARMUP_LOOPS )
-		{
-			for ( uint8_t i = 0; i < MUXES_COUNT; ++i )
-			{
-				uint8_t sample = samples[i] >> 1;
-
-				// Sample is high, add it to high avg
-				if ( sample > full_avg )
-				{
-					high_count++;
-					cur_high_avg += sample;
-				}
-				// Sample is low, add it to low avg
-				else
-				{
-					low_count++;
-					low_avg += sample;
-				}
-
-				// If sample is higher than previous high_avg, then mark as "problem key"
-				keys_problem[strobe_line + i] = sample > high_avg ? sample : 0;
-
-				// Prepare for next average
-				cur_full_avg += sample;
-			}
-		}
-	} // for strober
-
-	// Update total sense average (only during warm-up)
-	if ( boot_count < WARMUP_LOOPS )
-	{
-		full_avg = cur_full_avg / (total_strobes * MUXES_COUNT);
-		high_avg = cur_high_avg / high_count;
-		low_avg /= low_count;
-
-		// Update the base average value using the low_avg (best chance of not ignoring a keypress)
-		for ( int i = 0; i < KEY_COUNT; ++i )
-		{
-			keys_averages[i] = low_avg;
-			keys_averages_acc[i] = low_avg;
-		}
-	}
-
-#ifdef VERIFY_TEST_PAD
-	// verify test key is not down.
-	if ( ( cur_keymap[TEST_KEY_STROBE] & TEST_KEY_MASK ) )
-	{
-		error = 0x05;
-		error_data = cur_keymap[TEST_KEY_STROBE] << 8;
-		error_data += full_samples[TEST_KEY_STROBE * 8];
-	}
-#endif
-
-	/** aggregate if booting, or if idle;
-	 * else, if not booting, check for dirty USB.
-	 * */
-
-	idle_count++;
-	idle_count &= IDLE_COUNT_MASK;
-
-	// Warm up voltage references
-	if ( boot_count < WARMUP_LOOPS )
-	{
-		boot_count++;
-
-		switch ( boot_count )
-		{
-		// First loop
-		case 1:
-			// Show msg at first iteration only
-			info_msg("Warming up the voltage references");
-			break;
-		// Middle iterations
-		case 300:
-		case 600:
-		case 900:
-		case 1200:
-			print(".");
-			break;
-		// Last loop
-		case WARMUP_STOP:
-			print("\n");
-			info_msg("Warmup finished using ");
-			printInt16( WARMUP_LOOPS );
-			print(" iterations\n");
-
-			// Display the final calculated averages of all the sensed strobes
-			info_msg("Full average (");
-			printInt8( total_strobes * MUXES_COUNT );
-			print("): ");
-			printHex( full_avg );
-
-			print("  High average (");
-			printInt8( high_count );
-			print("): ");
-			printHex( high_avg );
-
-			print("  Low average (");
-			printInt8( low_count );
-			print("): ");
-			printHex( low_avg );
-			print("\n");
-
-			// Display problem keys, and the sense value at the time
-			for ( uint8_t key = 0; key < KEY_COUNT; key++ )
-			{
-				if ( keys_problem[key] )
-				{
-					warn_msg("Problem key detected: ");
-					printHex( key );
-					print(" (");
-					printHex( keys_problem[key] );
-					print(")\n");
-				}
-			}
-
-			info_print("If problem keys were detected, and were being held down, they will be reset as soon as let go");
-			break;
-		}
-	}
-	else
-	{
-		// Reset accumulators and idle flag/counter
-		if ( keymap_change )
-		{
-			for ( uint8_t c = 0; c < KEY_COUNT; ++c ) { keys_averages_acc[c] = 0; }
-			idle_count = 0;
-			idle = 0;
-
-			keymap_change = 0;
-		}
-
-		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];
-
-					av = (av << KEYS_AVERAGES_MIX_SHIFT) - av + acc;
-					av >>= KEYS_AVERAGES_MIX_SHIFT;
-
-					keys_averages[i] = av;
-					keys_averages_acc[i] = 0;
-				}
-			}
-
-			if ( boot_count >= WARMUP_LOOPS )
-			{
-				dump();
-			}
-		}
-
-	}
-}
-
-
-void setup_ADC()
-{
-	// disable adc digital pins.
-	DIDR1 |= (1 << AIN0D) | (1<<AIN1D); // set disable on pins 1,0.
-	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 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 = (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;
-
-	// 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 << ADEN); // ADC enable
-	ADCSRA |= (1 << ADSC); // start conversions q
-}
-
-
-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 )
-	{
-		// 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
-	{
-		PORTB &= ~(1 << RECOVERY_CONTROL);
-		DDRB  &= ~(1 << RECOVERY_SOURCE);
-		PORTB &= ~(1 << RECOVERY_SOURCE); // SOURCE low
-		DDRB  &= ~(1 << RECOVERY_SINK);	  // SINK high-imp
-	}
-}
-
-
-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);
-	PORTD &= ~(D_MASK);
-	PORTE &= ~(E_MASK);
-
-	// Strobe table
-	// Not all strobes are used depending on which are detected
-	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;
-	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;
-
-	default:
-		break;
-	}
-}
-
-
-inline uint16_t getADC(void)
-{
-	ADCSRA |= (1 << ADIF); // clear int flag by writing 1.
-
-	//wait for last read to complete.
-	while ( !( ADCSRA & (1 << ADIF) ) );
-
-	return ADC; // return sample
-}
-
-
-int sampleColumn_8x( uint8_t column, uint16_t * buffer )
-{
-	// ensure all probe lines are driven low, and chill for recovery delay.
-	ADCSRA |= (1 << ADEN) | (1 << ADSC); // enable and start conversions
-
-	PORTC &= ~C_MASK;
-	PORTD &= ~D_MASK;
-	PORTE &= ~E_MASK;
-
-	PORTF = 0;
-	DDRF  = 0;
-
-	recovery( OFF );
-	strobe_w( column );
-
-	hold_sample( OFF );
-	SET_FULL_MUX( 0 );
-
-	// Allow strobes to settle
-	for ( uint8_t i = 0; i < STROBE_SETTLE; ++i ) { getADC(); }
-
-	hold_sample( ON );
-
-	uint8_t mux = 0;
-	SET_FULL_MUX( mux );
-	getADC(); // throw away; unknown mux.
-	do {
-		SET_FULL_MUX( mux + 1 ); // our *next* sample will use this
-
-		// retrieve current read.
-		buffer[mux] = getADC();
-		mux++;
-
-	} while ( mux < 8 );
-
-	hold_sample( OFF );
-	recovery( ON );
-
-	// turn off adc.
-	ADCSRA &= ~(1 << ADEN);
-
-	// pull all columns' strobe-lines low.
-	DDRC |= C_MASK;
-	DDRD |= D_MASK;
-	DDRE |= E_MASK;
-
-	PORTC &= ~C_MASK;
-	PORTD &= ~D_MASK;
-	PORTE &= ~E_MASK;
-
-	return 0;
-}
-
-
-int sampleColumn( uint8_t column )
-{
-	int rval = 0;
-
-	rval = sampleColumn_8x( column, samples );
-
-	return rval;
-}
-
-
-uint8_t testColumn( uint8_t strobe )
-{
-	uint16_t db_delta = 0;
-	uint8_t  db_sample = 0;
-	uint16_t db_threshold = 0;
-
-	uint8_t column = 0;
-	uint8_t bit = 1;
-
-	for ( uint8_t mux = 0; mux < MUXES_COUNT; ++mux )
-	{
-		uint16_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + mux];
-
-		uint8_t key = (strobe << MUXES_COUNT_XSHIFT) + mux;
-
-		// Check if this is a bad key (e.g. test point, or non-existent key)
-		if ( keys_problem[key] )
-		{
-			// If the sample value of the problem key goes below full_avg (overall initial average)
-			//  re-enable the key
-			if ( (db_sample = samples[mux] >> 1) < full_avg )
-			{
-				info_msg("Re-enabling problem key: ");
-				printHex( key );
-				print("\n");
-
-				keys_problem[key] = 0;
-			}
-			// Otherwise, don't waste any more cycles processing the problem key
-			else
-			{
-				continue;
-			}
-		}
-
-		// Keypress detected
-		//  db_sample (uint8_t), discard meaningless high bit, and garbage low bit
-		if ( (db_sample = samples[mux] >> 1) > (db_threshold = threshold) + (db_delta = delta) )
-		{
-			column |= bit;
-
-			// Only register keypresses once the warmup is complete, or not enough debounce info
-			if ( keys_debounce[key] <= DEBOUNCE_THRESHOLD )
-			{
-				// Add to the Macro processing buffer if debounce criteria met
-				// Automatically handles converting to a USB code and sending off to the PC
-				if ( keys_debounce[key] == DEBOUNCE_THRESHOLD )
-				{
-//#define KEYSCAN_DEBOUNCE_DEBUG
-#ifdef KEYSCAN_DEBOUNCE_DEBUG
-					// Debug message
-					print("0x");
-					printHex_op( key, 2 );
-					print(" ");
-#endif
-
-					// Only add the key to the buffer once
-					// NOTE: Buffer can easily handle multiple adds, just more efficient
-					//        and nicer debug messages :P
-					//bufferAdd( key );
-				}
-
-				keys_debounce[key]++;
-
-#define KEYSCAN_THRESHOLD_DEBUG
-#ifdef KEYSCAN_THRESHOLD_DEBUG
-				// Debug message
-				// <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
-				dbug_msg("0x");
-				printHex_op( key, 2 );
-				print(" [");
-				printInt8( strobe );
-				print(":");
-				printInt8( mux );
-				print("] : ");
-				printHex( db_sample ); // Sense
-				print(" : ");
-				printHex( db_threshold );
-				print("+");
-				printHex( db_delta );
-				print("=");
-				printHex( db_threshold + db_delta ); // Sense compare
-				print(" : ");
-				printHex( db_sample - ( db_threshold + db_delta ) ); // Margin
-				print("\n");
-#endif
-			}
-		}
-		// Clear debounce entry if no keypress detected
-		else
-		{
-			// If the key was previously pressed, remove from the buffer
-			for ( uint8_t c = 0; c < KeyIndex_BufferUsed; c++ )
-                        {
-                                // Key to release found
-                                if ( KeyIndex_Buffer[c] == key )
-                                {
-                                        // Shift keys from c position
-                                        for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
-                                                KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
-
-                                        // Decrement Buffer
-                                        KeyIndex_BufferUsed--;
-
-                                        break;
-                                }
-                        }
-
-
-			// Clear debounce entry
-			keys_debounce[key] = 0;
-		}
-
-		bit <<= 1;
-	}
-	return column;
-}
-
-
-void dump(void) {
-
-#ifdef DEBUG_FULL_SAMPLES_AVERAGES
-	// we don't want to debug-out during the measurements.
-	if ( !dump_count )
-	{
-		// Averages currently set per key
-		for ( int i = 0; i < KEY_COUNT; ++i )
-		{
-			if ( !(i & 0x0f) )
-			{
-				print("\n");
-			}
-			else if ( !(i & 0x07) )
-			{
-				print("  ");
-			}
-
-			print(" ");
-			printHex( keys_averages[i] );
-		}
-
-		print("\n");
-
-		// Previously read full ADC scans?
-		for ( int i = 0; i< KEY_COUNT; ++i)
-		{
-			if ( !(i & 0x0f) )
-			{
-				print("\n");
-			}
-			else if ( !(i & 0x07) )
-			{
-				print("  ");
-			}
-
-			print(" ");
-			printHex(full_samples[i]);
-		}
-	}
-#endif
-
-#ifdef DEBUG_STROBE_SAMPLES_AVERAGES
-	// Per strobe information
-	uint8_t cur_strober = ze_strober;
-	print("\n");
-
-	printHex(cur_strober);
-
-	// Previously read ADC scans on current strobe
-	print(" :");
-	for ( uint8_t i = 0; i < MUXES_COUNT; ++i )
-	{
-		print(" ");
-		printHex(full_samples[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
-	}
-
-	// Averages current set on current strobe
-	print(" :");
-
-	for ( uint8_t i = 0; i < MUXES_COUNT; ++i )
-	{
-		print(" ");
-		printHex(keys_averages[(cur_strober << MUXES_COUNT_XSHIFT) + i]);
-	}
-
-#endif
-
-#ifdef DEBUG_USB_KEYMAP
-	print("\n      ");
-
-	// Current keymap values
-	for ( uint8_t i = 0; i < total_strobes; ++i )
-	{
-		printHex(cur_keymap[i]);
-		print(" ");
-	}
-#endif
-
-	ze_strober++;
-	ze_strober &= 0xf;
-
-	dump_count++;
-	dump_count &= 0x0f;
-}
-
--- a/Scan/avr-capsense/scan_loop.h	Sat Mar 22 14:32:06 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/* Copyright (C) 2013 by Jacob Alexander
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3.0 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __SCAN_LOOP_H
-#define __SCAN_LOOP_H
-
-// ----- Includes -----
-
-// Compiler Includes
-#include <stdint.h>
-
-// Local Includes
-
-
-
-// ----- Defines -----
-
-#define KEYBOARD_KEYS 0xFF // TODO Determine max number of keys
-#define KEYBOARD_BUFFER 24 // Max number of key signals to buffer
-                           // This limits the NKRO-ability, so at 24, the keyboard is 24KRO
-                           // The buffer is really only needed for converter modules
-                           // An alternative macro module could be written for matrix modules and still work well
-
-
-
-// ----- Variables -----
-
-extern volatile     uint8_t KeyIndex_Buffer[KEYBOARD_BUFFER];
-extern volatile     uint8_t KeyIndex_BufferUsed;
-
-
-
-// ----- Functions -----
-
-// Functions used by main.c
-void scan_setup( void );
-uint8_t scan_loop( void );
-
-
-// Functions available to macro.c
-uint8_t scan_sendData( uint8_t dataPayload );
-
-void scan_finishedWithBuffer( uint8_t sentKeys );
-void scan_finishedWithUSBBuffer( uint8_t sentKeys );
-void scan_lockKeyboard( void );
-void scan_unlockKeyboard( void );
-void scan_resetKeyboard( void );
-
-
-#endif // __SCAN_LOOP_H
-
--- a/Scan/avr-capsense/setup.cmake	Sat Mar 22 14:32:06 2014 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-###| CMake Kiibohd Controller Scan Module |###
-#
-# Written by Jacob Alexander in 2013 for the Kiibohd Controller
-#
-# Released into the Public Domain
-#
-###
-
-
-###
-# Module C files
-#
-
-set( SCAN_SRCS
-	scan_loop.c
-)
-
-
-###
-# Module H files
-#
-set( SCAN_HDRS
-	scan_loop.h
-)
-
-
-###
-# File Dependency Setup
-#
-ADD_FILE_DEPENDENCIES( scan_loop.c ${SCAN_HDRS} )
-#add_file_dependencies( scan_loop.c ${SCAN_HDRS} )
-#add_file_dependencies( macro.c keymap.h avrcapsense.h )
-
-
-###
-# Module Specific Options
-#
-add_definitions( -I${HEAD_DIR}/Keymap )
-
-#| Keymap Settings
-add_definitions(
-	-DMODIFIER_MASK=avrcapsense_ModifierMask
-	#-DKEYINDEX_MASK=avrcapsense_ColemakMap
-	-DKEYINDEX_MASK=avrcapsense_DefaultMap
-)
-
-
-###
-# Compiler Family Compatibility
-#
-set( ScanModuleCompatibility
-	avr
-)
-
--- a/Scan/matrix/matrix_scan.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/Scan/matrix/matrix_scan.c	Mon Mar 31 01:07:48 2014 -0700
@@ -1,15 +1,15 @@
-/* Copyright (C) 2011 by Jacob Alexander
- * 
+/* Copyright (C) 2011,2014 by Jacob Alexander
+ *
  * 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
--- a/Scan/matrix/matrix_scan.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Scan/matrix/matrix_scan.h	Mon Mar 31 01:07:48 2014 -0700
@@ -1,15 +1,15 @@
-/* Copyright (C) 2011 by Jacob Alexander
- * 
+/* Copyright (C) 2011,2014 by Jacob Alexander
+ *
  * 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
--- a/Scan/matrix/matrix_template.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Scan/matrix/matrix_template.h	Mon Mar 31 01:07:48 2014 -0700
@@ -1,15 +1,15 @@
-/* Copyright (C) 2011 by Jacob Alexander
- * 
+/* Copyright (C) 2011,2014 by Jacob Alexander
+ *
  * 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
@@ -69,7 +69,7 @@
 // Just layout the matrix by rows and columns
 // Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol
 // The mode allows for optimization in the kind of scanning algorithms that are done
-// 
+//
 // The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0).
 // Thus if a row doesn't use all the key positions, you can denote it as 0, which will be ignored/skipped on each scan
 // See the keymap.h file for the various preconfigured arrays.
--- a/Scan/matrix/scan_loop.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/Scan/matrix/scan_loop.c	Mon Mar 31 01:07:48 2014 -0700
@@ -1,15 +1,15 @@
-/* Copyright (C) 2011-2012 by Jacob Alexander
- * 
+/* Copyright (C) 2011-2012,2014 by Jacob Alexander
+ *
  * 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
--- a/Scan/matrix/scan_loop.h	Sat Mar 22 14:32:06 2014 -0700
+++ b/Scan/matrix/scan_loop.h	Mon Mar 31 01:07:48 2014 -0700
@@ -1,15 +1,15 @@
-/* Copyright (C) 2011-2012 by Jacob Alexander
- * 
+/* Copyright (C) 2011-2012,2014 by Jacob Alexander
+ *
  * 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
--- a/avr.cmake	Sat Mar 22 14:32:06 2014 -0700
+++ b/avr.cmake	Mon Mar 31 01:07:48 2014 -0700
@@ -1,6 +1,6 @@
 ###| CMAKE Kiibohd Controller |###
 #
-# Jacob Alexander 2011-2013
+# Jacob Alexander 2011-2014
 # Due to this file's usefulness:
 #
 # Released into the Public Domain
@@ -37,8 +37,8 @@
 #| "atmega32u4"       # Teensy   2.0
 #| "at90usb646"       # Teensy++ 1.0
 #| "at90usb1286"      # Teensy++ 2.0
-#set( MCU "atmega32u4" )
-set( MCU "at90usb1286" )
+set( MCU "atmega32u4" )
+#set( MCU "at90usb1286" )
 
 message( STATUS "MCU Selected:" )
 message( "${MCU}" )
@@ -51,6 +51,15 @@
 )
 
 
+#| CPU Type
+#| This is only informational for AVR microcontrollers
+#| The field can be determined by the microcontroller chip, but currently only one CPU type is used atm
+set( CPU "megaAVR" )
+
+message( STATUS "CPU Selected:" )
+message( "${CPU}" )
+
+
 #| USB Defines
 set( VENDOR_ID  "0x16C0" )
 set( PRODUCT_ID "0x047D" )
@@ -66,7 +75,7 @@
 
 #| Warning Options
 #|  -Wall...:     warning level
-set( WARN "-Wall -Wstrict-prototypes" )
+set( WARN "-Wall" )
 
 
 #| Tuning Options
@@ -75,7 +84,7 @@
 set( TUNING "-funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums" )
 
 
-#| Optimization level, can be [0, 1, 2, 3, s]. 
+#| Optimization level, can be [0, 1, 2, 3, s].
 #|     0 = turn off optimization. s = optimize for size.
 #|     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
 set( OPT "s" )
--- a/main.c	Sat Mar 22 14:32:06 2014 -0700
+++ b/main.c	Mon Mar 31 01:07:48 2014 -0700
@@ -139,57 +139,43 @@
 {
 	// Configuring Pins
 	pinSetup();
-	init_errorLED();
+
+	// Enable CLI
+	init_cli();
 
 	// Setup Output Module
 	output_setup();
 
-	// Enable CLI
-	init_cli();
-
 	// Setup ISR Timer for flagging a kepress send to USB
 	usbTimerSetup();
 
+	// Setup the scanning module
+	//scan_setup();
+
 	// Main Detection Loop
-	uint8_t ledTimer = F_CPU / 1000000; // Enable LED for a short time
 	while ( 1 )
 	{
-		// Setup the scanning module
-		scan_setup();
+		// Process CLI
+		process_cli();
 
-		while ( 1 )
-		{
-			// Acquire Key Indices
-			// Loop continuously until scan_loop returns 0
-			cli();
-			while ( scan_loop() );
-			sei();
-
-			// Run Macros over Key Indices and convert to USB Keys
-			process_macros();
-
-			// Send keypresses over USB if the ISR has signalled that it's time
-			if ( !sendKeypresses )
-				continue;
+		// Acquire Key Indices
+		// Loop continuously until scan_loop returns 0
+		cli();
+		//while ( scan_loop() );
+		sei();
 
-			// Send USB Data
-			output_send();
-
-			// Clear sendKeypresses Flag
-			sendKeypresses = 0;
-
-			// Indicate Error, if valid
-			errorLED( ledTimer );
+		// Run Macros over Key Indices and convert to USB Keys
+		process_macros();
 
-			if ( ledTimer > 0 )
-				ledTimer--;
-		}
+		// Send keypresses over USB if the ISR has signalled that it's time
+		if ( !sendKeypresses )
+			continue;
 
-		// Loop should never get here (indicate error)
-		ledTimer = 255;
+		// Send USB Data
+		output_send();
 
-		// HID Debug Error message
-		erro_print("Detection loop error, this is very bad...bug report!");
+		// Clear sendKeypresses Flag
+		sendKeypresses = 0;
 	}
 }
 
--- a/setup.cmake	Sat Mar 22 14:32:06 2014 -0700
+++ b/setup.cmake	Mon Mar 31 01:07:48 2014 -0700
@@ -20,7 +20,7 @@
 #| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones
 
 ##| Deals with acquiring the keypress information and turning it into a key index
-set(  ScanModule  "MBC-55X" )
+set(  ScanModule  "SKM67001" )
 
 ##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code
 set( MacroModule  "buffer"  )