]> git.donarmstrong.com Git - kiibohd-controller.git/commitdiff
Adding CLI and CDC Serial support for Teensy 2.0 and Teensy 2.0++
authorJacob Alexander <haata@kiibohd.com>
Mon, 31 Mar 2014 08:07:48 +0000 (01:07 -0700)
committerJacob Alexander <haata@kiibohd.com>
Mon, 31 Mar 2014 08:07:48 +0000 (01:07 -0700)
- Includes serial putchar and getchar cleanup (overall)
- Moved avr-capsense to DPH (renaming)
- Basic cleanup for including CLI on the avr architecture

30 files changed:
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 [deleted file]
Output/pjrcUSB/avr/usb_keyboard_debug.h [deleted file]
Output/pjrcUSB/avr/usb_keyboard_serial.c [new file with mode: 0644]
Output/pjrcUSB/avr/usb_keyboard_serial.h [new file with mode: 0644]
Output/pjrcUSB/output_com.c
Output/pjrcUSB/output_com.h
Output/pjrcUSB/setup.cmake
README
Scan/DPH/scan_loop.c [new file with mode: 0644]
Scan/DPH/scan_loop.h [new file with mode: 0644]
Scan/DPH/setup.cmake [new file with mode: 0644]
Scan/SKM67001/setup.cmake
Scan/avr-capsense/scan_loop.c [deleted file]
Scan/avr-capsense/scan_loop.h [deleted file]
Scan/avr-capsense/setup.cmake [deleted file]
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

index 53cb1400f201d1bc8cbfdf49e338f4e8ec05fb9c..1bc0c56fea233dff24823e5e1fad198212eb950d 100644 (file)
@@ -28,8 +28,8 @@ include( AddFileDependencies )
 #| "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 @@ add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
 #
 
 #| 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)"
 )
 
 
index 07e80ce65f9d1f63602bdb5955fe347fd17ffd2e..11dcbb1b46309043cacf1b22b98bc636a84624c7 100644 (file)
@@ -85,15 +85,14 @@ void process_cli()
        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_reset( char* args )
 void cliFunc_restart( char* args )
 {
        // Trigger an overall software reset
-       SOFTWARE_RESET();
+       output_softReset();
 }
 
 void cliFunc_version( char* args )
index d5eb3fe53a431ed514e8cbcef8080e6e8cf0e867..5c6cb5317e9a0110fedccb867c910f9ef340ae66 100644 (file)
 
 // ----- 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 @@ void usb_debug_putstrs( char* first, ... )
        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 @@ void usb_debug_putstrs( char* first, ... )
 }
 
 // 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
 }
 
index e2498c40c8f17e1be08c7478d399960687850206..8eeee964ba51c55856cf91f46ffad0ff78f1e37b 100644 (file)
 
 // Compiler Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
-
 #include <avr/pgmspace.h>
-#include "avr/usb_keyboard_debug.h"
-
-#elif defined(_mk20dx128_) || defined(_mk20dx256_)
-
-#include "arm/usb_serial.h"
-
 #endif
 
+// Project Includes
+#include <output_com.h>
+
 
 
 // ----- Defines -----
  */
 
 // 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
index 3cf21b526e22449840602a257bb95849466f1fd5..18a3f4f9b76ef53e63553ffabc9a6d98b86bdcaa 100644 (file)
@@ -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@"
 
 
index c5d9982329e6b94bcc0e8fb92fe927c1a8666be6..4d1cdf0298826824bc64fae109f334c525016ae6 100644 (file)
@@ -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
  * 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.
index acebf5f0271a6faf06e7960c5db8c166a8e42a40..ba8d4095b746b62105ab9d29aa934c8ca497950a 100644 (file)
@@ -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
  * 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 @@ let me know?  http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
 #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 @@ let me know?  http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
 #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
diff --git a/Output/pjrcUSB/avr/usb_keyboard_debug.c b/Output/pjrcUSB/avr/usb_keyboard_debug.c
deleted file mode 100644 (file)
index 3a792cf..0000000
+++ /dev/null
@@ -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
-}
-
diff --git a/Output/pjrcUSB/avr/usb_keyboard_debug.h b/Output/pjrcUSB/avr/usb_keyboard_debug.h
deleted file mode 100644 (file)
index 121215d..0000000
+++ /dev/null
@@ -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
-
diff --git a/Output/pjrcUSB/avr/usb_keyboard_serial.c b/Output/pjrcUSB/avr/usb_keyboard_serial.c
new file mode 100644 (file)
index 0000000..6b1c1a6
--- /dev/null
@@ -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
+}
+
diff --git a/Output/pjrcUSB/avr/usb_keyboard_serial.h b/Output/pjrcUSB/avr/usb_keyboard_serial.h
new file mode 100644 (file)
index 0000000..4880c88
--- /dev/null
@@ -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__
+
index c7c7b91ce1fe320ccb5cedc30a9be86738e7eb52..9eaf99f5c653547effd839a00dbdcfc25a51ccde 100644 (file)
 #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"
 
 
 
+// ----- 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 @@ volatile uint8_t USBKeys_LEDs = 0;
          uint8_t USBKeys_Idle_Count = 0;
 
 
-
 // ----- Functions -----
 
 // USB Module Setup
@@ -81,9 +105,12 @@ inline void output_setup()
        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_send(void)
 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
+}
+
index a8a84efd57e3d1542225bef230d5d8635f80d095..fae1197ba06779bbf12e2acd5780c71b6108bcc6 100644 (file)
@@ -59,10 +59,17 @@ extern                       uint8_t USBKeys_Idle_Count;
 // ----- 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
 
index 157dfc2fb12079edf0d8c3a3e21dde3d97ffe439..d982976a4687157e51b9284e0a496221b8b4bfe1 100644 (file)
@@ -17,7 +17,7 @@ if ( ${COMPILER_FAMILY} MATCHES "avr" )
 
        set( OUTPUT_SRCS
                output_com.c
-               avr/usb_keyboard_debug.c
+               avr/usb_keyboard_serial.c
        )
 
 #| ARM Compiler
diff --git a/README b/README
index e521bbcf1e6656be923ca3e076d349fa7817ba7a..0169e504ba2b5cfa14dc265fada9cfa1cb844299 100644 (file)
--- a/README
+++ b/README
@@ -24,10 +24,12 @@ AVR Specific (Teensy 1.0/++,2.0/++) (try to use something recent, suggested vers
 - 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 @@ The options are:
  - 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 @@ You are looking for:
        #| "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 @@ You are looking for:
        #| 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 @@ The Kiibohd Controller is designed around a set of 4 types of modules that corre
 
 - 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 @@ Each Scan Module has it's own default keymap/modifier map. (TODO recommend keyma
 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 @@ Look for:
        #| 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 @@ Look for:
        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 @@ Example output:
        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 @@ Example output:
        [ 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
diff --git a/Scan/DPH/scan_loop.c b/Scan/DPH/scan_loop.c
new file mode 100644 (file)
index 0000000..c8f928e
--- /dev/null
@@ -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;
+}
+
diff --git a/Scan/DPH/scan_loop.h b/Scan/DPH/scan_loop.h
new file mode 100644 (file)
index 0000000..bfad6eb
--- /dev/null
@@ -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
+
diff --git a/Scan/DPH/setup.cmake b/Scan/DPH/setup.cmake
new file mode 100644 (file)
index 0000000..35ec76e
--- /dev/null
@@ -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
+)
+
index 2b71198acbf0306c0ca4b16ac8da29b6bd8f4b9b..c61891936a7b2b42f7b7fe8007c8f765074020b7 100644 (file)
@@ -24,7 +24,7 @@ set( SCAN_SRCS
 add_definitions( -I${HEAD_DIR}/Keymap )
 add_definitions(
        -I${HEAD_DIR}/Scan/matrix
-)      
+)
 
 #| Keymap Settings
 add_definitions(
diff --git a/Scan/avr-capsense/scan_loop.c b/Scan/avr-capsense/scan_loop.c
deleted file mode 100644 (file)
index c8f7f1f..0000000
+++ /dev/null
@@ -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;
-}
-
diff --git a/Scan/avr-capsense/scan_loop.h b/Scan/avr-capsense/scan_loop.h
deleted file mode 100644 (file)
index bfad6eb..0000000
+++ /dev/null
@@ -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
-
diff --git a/Scan/avr-capsense/setup.cmake b/Scan/avr-capsense/setup.cmake
deleted file mode 100644 (file)
index ca7c719..0000000
+++ /dev/null
@@ -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
-)
-
index 77623b3ee050609020365c0df23a829c1a303d61..5987016262c9c0bb95b8c8bc74aa77fc9580a335 100644 (file)
@@ -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
index df5202d3c70fa742078be37f4dbf1eca26650564..2c3a65fc27ed3e78be53ce8633a6913eb74442f3 100644 (file)
@@ -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
index 719fd0a80b285894eece09dc0279a6140af230e6..41ca233db11a396618981e1f76166d1f7d66686b 100644 (file)
@@ -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 @@ static const uint8_t matrix_pinout[][MAX_ROW_SIZE + 1] = {
 // 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.
index 3bca0548de787d2a4b0bacb4a3b114ba0ee3f9eb..e9d8de2bfdc53ae7b1213b0b8126ded8922cacef 100644 (file)
@@ -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
index d3fa133a0eebb96eabde052ec7166a9e35282e32..52591545665d7595ab0c794e6dff6430867bf355 100644 (file)
@@ -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
index c39ed0daa6eb43b11827700eeacca9f9061a0e4f..239563a79cbe365ab6b21d13b876362f2eaa93d2 100644 (file)
--- a/avr.cmake
+++ b/avr.cmake
@@ -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 @@ set( SIZE    "avr-size"    )
 #| "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 @@ set( COMPILER_SRCS
 )
 
 
+#| 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 @@ set( CSTANDARD "-std=gnu99" )
 
 #| Warning Options
 #|  -Wall...:     warning level
-set( WARN "-Wall -Wstrict-prototypes" )
+set( WARN "-Wall" )
 
 
 #| Tuning Options
@@ -75,7 +84,7 @@ set( WARN "-Wall -Wstrict-prototypes" )
 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" )
diff --git a/main.c b/main.c
index 56487b6376c7c64a374f474fd08869d596d8b32b..7412fc6c99de56606dc9ebf8974e1a720bc37843 100644 (file)
--- a/main.c
+++ b/main.c
@@ -139,57 +139,43 @@ int main(void)
 {
        // Configuring Pins
        pinSetup();
-       init_errorLED();
-
-       // Setup Output Module
-       output_setup();
 
        // Enable CLI
        init_cli();
 
+       // Setup Output Module
+       output_setup();
+
        // 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();
-
-               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;
-
-                       // Send USB Data
-                       output_send();
+               // Process CLI
+               process_cli();
 
-                       // Clear sendKeypresses Flag
-                       sendKeypresses = 0;
+               // Acquire Key Indices
+               // Loop continuously until scan_loop returns 0
+               cli();
+               //while ( scan_loop() );
+               sei();
 
-                       // 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;
        }
 }
 
index aa1362d391d5e2b5a28a2a98d57a38b3c7116de7..57b19d22dbcfa196fbda7b41b1beddcbe7bb3e4b 100644 (file)
@@ -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"  )