# HG changeset patch # User Jacob Alexander # Date 1396253268 25200 # Node ID 0c5d1fe99302bce6c65df1010e2861e883324e7c # Parent 2bb16439e6caa6dea669f525ac14e3619a734db9 Adding CLI and CDC Serial support for Teensy 2.0 and Teensy 2.0++ - Includes serial putchar and getchar cleanup (overall) - Moved avr-capsense to DPH (renaming) - Basic cleanup for including CLI on the avr architecture diff -r 2bb16439e6ca -r 0c5d1fe99302 CMakeLists.txt --- a/CMakeLists.txt Sat Mar 22 14:32:06 2014 -0700 +++ b/CMakeLists.txt Mon Mar 31 01:07:48 2014 -0700 @@ -28,8 +28,8 @@ #| "avr" # Teensy++ 2.0 #| "arm" # Teensy 3.0 #| "arm" # Teensy 3.1 -set( COMPILER_FAMILY "arm" ) -#set( COMPILER_FAMILY "avr" ) +#set( COMPILER_FAMILY "arm" ) +set( COMPILER_FAMILY "avr" ) message( STATUS "Compiler Family:" ) message( "${COMPILER_FAMILY}" ) @@ -138,9 +138,10 @@ # #| After Changes Size Information +#| TODO Do lookup on Flash and RAM sizes and do % used add_custom_target( SizeAfter ALL ${SIZE} --target=${FORMAT} ${TARGET_HEX} ${TARGET_ELF} DEPENDS ${TARGET_ELF} - COMMENT "Size after generation:" + COMMENT "Size after generation\n\tFlash Usage: data (hex)\n\t RAM Usage: data (elf)" ) diff -r 2bb16439e6ca -r 0c5d1fe99302 Debug/cli/cli.c --- a/Debug/cli/cli.c Sat Mar 22 14:32:06 2014 -0700 +++ b/Debug/cli/cli.c Mon Mar 31 01:07:48 2014 -0700 @@ -85,15 +85,14 @@ uint8_t prev_buf_pos = CLILineBufferCurrent; // Process each character while available - int result = 0; while ( 1 ) { // No more characters to process - result = usb_serial_getchar(); // Retrieve from serial module // TODO Make USB agnostic - if ( result == -1 ) + if ( output_availablechar() == 0 ) break; - char cur_char = (char)result; + // Retrieve from output module + char cur_char = (char)output_getchar(); // Make sure buffer isn't full if ( CLILineBufferCurrent >= CLILineBufferMaxSize ) @@ -405,7 +404,7 @@ void cliFunc_restart( char* args ) { // Trigger an overall software reset - SOFTWARE_RESET(); + output_softReset(); } void cliFunc_version( char* args ) diff -r 2bb16439e6ca -r 0c5d1fe99302 Debug/print/print.c --- a/Debug/print/print.c Sat Mar 22 14:32:06 2014 -0700 +++ b/Debug/print/print.c Mon Mar 31 01:07:48 2014 -0700 @@ -31,24 +31,8 @@ // ----- Functions ----- -// USB HID String Output -void usb_debug_putstr( char* s ) -{ -#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR - while ( *s != '\0' ) - usb_debug_putchar( *s++ ); -#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM - // Count characters until NULL character, then send the amount counted - uint32_t count = 0; - while ( s[count] != '\0' ) - count++; - - usb_serial_write( s, count ); -#endif -} - // Multiple string Output -void usb_debug_putstrs( char* first, ... ) +void printstrs( char* first, ... ) { // Initialize the variadic function parameter list va_list ap; @@ -61,7 +45,7 @@ while ( !( cur[0] == '\0' && cur[1] == '\0' && cur[2] == '\0' ) ) { // Print out the given string - usb_debug_putstr( cur ); + output_putstr( cur ); // Get the next argument ready cur = va_arg( ap, char* ); @@ -71,21 +55,17 @@ } // Print a constant string -void _print(const char *s) +void _print( const char* s ) { #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR + // Pull string out of flash char c; - - // Acquire the character from flash, and print it, as long as it's not NULL - // Also, if a newline is found, print a carrige return as well - while ( ( c = pgm_read_byte(s++) ) != '\0' ) + while ( ( c = pgm_read_byte( s++ ) ) != '\0' ) { - if ( c == '\n' ) - usb_debug_putchar('\r'); - usb_debug_putchar(c); + output_putchar( c ); } #elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM - usb_debug_putstr( (char*)s ); + output_putstr( (char*)s ); #endif } diff -r 2bb16439e6ca -r 0c5d1fe99302 Debug/print/print.h --- a/Debug/print/print.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Debug/print/print.h Mon Mar 31 01:07:48 2014 -0700 @@ -26,15 +26,11 @@ // Compiler Includes #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) - #include -#include "avr/usb_keyboard_debug.h" +#endif -#elif defined(_mk20dx128_) || defined(_mk20dx256_) - -#include "arm/usb_serial.h" - -#endif +// Project Includes +#include @@ -50,15 +46,15 @@ */ // Function Aliases -#define dPrint(c) usb_debug_putstr(c) -#define dPrintStr(c) usb_debug_putstr(c) -#define dPrintStrs(...) usb_debug_putstrs(__VA_ARGS__, "\0\0\0") // Convenience Variadic Macro -#define dPrintStrNL(c) dPrintStrs (c, NL) // Appends New Line Macro -#define dPrintStrsNL(...) usb_debug_putstrs(__VA_ARGS__, NL, "\0\0\0") // Appends New Line Macro +#define dPrint(c) output_putstr(c) +#define dPrintStr(c) output_putstr(c) +#define dPrintStrs(...) printstrs(__VA_ARGS__, "\0\0\0") // Convenience Variadic Macro +#define dPrintStrNL(c) dPrintStrs (c, NL) // Appends New Line Macro +#define dPrintStrsNL(...) printstrs(__VA_ARGS__, NL, "\0\0\0") // Appends New Line Macro // Special Msg Constructs (Uses VT100 tags) #define dPrintMsg(colour_code_str,msg,...) \ - usb_debug_putstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0") + printstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0") #define printMsgNL(colour_code_str,msg,str) \ print("\033[" colour_code_str "m" msg "\033[0m - " str NL) #define printMsg(colour_code_str,msg,str) \ @@ -89,8 +85,7 @@ #define print(s) _print(PSTR(s)) void _print(const char *s); -void usb_debug_putstr( char* s ); -void usb_debug_putstrs( char* first, ... ); +void printstrs( char* first, ... ); // Printing numbers diff -r 2bb16439e6ca -r 0c5d1fe99302 Lib/_buildvars.h --- a/Lib/_buildvars.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Lib/_buildvars.h Mon Mar 31 01:07:48 2014 -0700 @@ -30,7 +30,7 @@ // You can change these to give your code its own name. #define STR_MANUFACTURER L"@MANUFACTURER@" -#define STR_PRODUCT L"ForceGauge - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@" +#define STR_PRODUCT L"Keyboard - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@" #define STR_SERIAL L"@GitLastCommitDate@" diff -r 2bb16439e6ca -r 0c5d1fe99302 Output/pjrcUSB/arm/usb_desc.c --- a/Output/pjrcUSB/arm/usb_desc.c Sat Mar 22 14:32:06 2014 -0700 +++ b/Output/pjrcUSB/arm/usb_desc.c Mon Mar 31 01:07:48 2014 -0700 @@ -1,6 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. + * Modified by Jacob Alexander (2013-2014) * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -10,10 +11,10 @@ * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * - * 1. The above copyright notice and this permission notice shall be + * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * - * 2. If the Software is incorporated into a build system that allows + * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. diff -r 2bb16439e6ca -r 0c5d1fe99302 Output/pjrcUSB/arm/usb_desc.h --- a/Output/pjrcUSB/arm/usb_desc.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Output/pjrcUSB/arm/usb_desc.h Mon Mar 31 01:07:48 2014 -0700 @@ -1,6 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. + * Modified by Jacob Alexander (2013-2014) * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -10,10 +11,10 @@ * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * - * 1. The above copyright notice and this permission notice shall be + * 1. The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * - * 2. If the Software is incorporated into a build system that allows + * 2. If the Software is incorporated into a build system that allows * selection among a list of target devices, then similar target * devices manufactured by PJRC.COM must be included in the list of * target devices and selectable in the same manner. @@ -89,6 +90,7 @@ #define NUM_ENDPOINTS 6 #define NUM_USB_BUFFERS 30 #define NUM_INTERFACE 4 + #define CDC_IAD_DESCRIPTOR 1 #define CDC_STATUS_INTERFACE 0 #define CDC_DATA_INTERFACE 1 // Serial @@ -98,22 +100,27 @@ #define CDC_ACM_SIZE 16 #define CDC_RX_SIZE 64 #define CDC_TX_SIZE 64 + #define KEYBOARD_INTERFACE 2 // Keyboard #define KEYBOARD_ENDPOINT 1 #define KEYBOARD_SIZE 8 #define KEYBOARD_INTERVAL 1 + #define MOUSE_INTERFACE 3 // Mouse #define MOUSE_ENDPOINT 5 #define MOUSE_SIZE 8 #define MOUSE_INTERVAL 2 + #define JOYSTICK_INTERFACE 4 // Joystick #define JOYSTICK_ENDPOINT 6 #define JOYSTICK_SIZE 16 #define JOYSTICK_INTERVAL 1 + #define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9) #define MOUSE_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9) #define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9) #define CONFIG_DESC_SIZE (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7) + #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY diff -r 2bb16439e6ca -r 0c5d1fe99302 Output/pjrcUSB/avr/usb_keyboard_debug.c --- a/Output/pjrcUSB/avr/usb_keyboard_debug.c Sat Mar 22 14:32:06 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,705 +0,0 @@ -/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board - * http://www.pjrc.com/teensy/usb_keyboard.html - * Copyright (c) 2009 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// Version 1.0: Initial Release -// Version 1.1: Add support for Teensy 2.0 - -#define USB_SERIAL_PRIVATE_INCLUDE -#include "usb_keyboard_debug.h" - -/************************************************************************** - * - * Configurable Options - * - **************************************************************************/ - -// USB devices are supposed to implment a halt feature, which is -// rarely (if ever) used. If you comment this line out, the halt -// code will be removed, saving 102 bytes of space (gcc 4.3.0). -// This is not strictly USB compliant, but works with all major -// operating systems. -#define SUPPORT_ENDPOINT_HALT - - - -/************************************************************************** - * - * Endpoint Buffer Configuration - * - **************************************************************************/ - -#define ENDPOINT0_SIZE 32 - -#define KEYBOARD_INTERFACE 0 -#define KEYBOARD_ENDPOINT 3 -#define KEYBOARD_SIZE 8 -#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER - -#define DEBUG_INTERFACE 1 -#define DEBUG_TX_ENDPOINT 4 -#define DEBUG_TX_SIZE 32 -#define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER - -static const uint8_t PROGMEM endpoint_config_table[] = { - 0, - 0, - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER -}; - - -/************************************************************************** - * - * Descriptor Data - * - **************************************************************************/ - -// Descriptors are the data that your computer reads when it auto-detects -// this USB device (called "enumeration" in USB lingo). The most commonly -// changed items are editable at the top of this file. Changing things -// in here should only be done by those who've read chapter 9 of the USB -// spec and relevant portions of any USB class specifications! - - -static const uint8_t PROGMEM device_descriptor[] = { - 18, // bLength - 1, // bDescriptorType - 0x00, 0x02, // bcdUSB - 0, // bDeviceClass - 0, // bDeviceSubClass - 0, // bDeviceProtocol - ENDPOINT0_SIZE, // bMaxPacketSize0 - LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor - LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct - 0x00, 0x01, // bcdDevice - 1, // iManufacturer - 2, // iProduct - 3, // iSerialNumber - 1 // bNumConfigurations -}; - -// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 -static const uint8_t PROGMEM keyboard_hid_report_desc[] = { - 0x05, 0x01, // Usage Page (Generic Desktop), - 0x09, 0x06, // Usage (Keyboard), - 0xA1, 0x01, // Collection (Application), - 0x75, 0x01, // Report Size (1), - 0x95, 0x08, // Report Count (8), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0xE0, // Usage Minimum (224), - 0x29, 0xE7, // Usage Maximum (231), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte - 0x95, 0x01, // Report Count (1), - 0x75, 0x08, // Report Size (8), - 0x81, 0x03, // Input (Constant), ;Reserved byte - 0x95, 0x05, // Report Count (5), - 0x75, 0x01, // Report Size (1), - 0x05, 0x08, // Usage Page (LEDs), - 0x19, 0x01, // Usage Minimum (1), - 0x29, 0x05, // Usage Maximum (5), - 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report - 0x95, 0x01, // Report Count (1), - 0x75, 0x03, // Report Size (3), - 0x91, 0x03, // Output (Constant), ;LED report padding - 0x95, 0x06, // Report Count (6), - 0x75, 0x08, // Report Size (8), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x68, // Logical Maximum(104), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0x00, // Usage Minimum (0), - 0x29, 0x68, // Usage Maximum (104), - 0x81, 0x00, // Input (Data, Array), - 0xc0 // End Collection -}; - -static const uint8_t PROGMEM debug_hid_report_desc[] = { - //0x06, 0x30, 0xFF, // Usage Page 0xFF31 (vendor defined) - 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) - 0x09, 0x74, // Usage 0x74 - 0xA1, 0x53, // Collection 0x53 - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 - 0x95, DEBUG_TX_SIZE, // report count - 0x09, 0x75, // usage - 0x81, 0x02, // Input (array) - 0xC0 // end collection -}; - -#define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7) -#define KEYBOARD_HID_DESC_OFFSET (9+9) -#define DEBUG_HID_DESC_OFFSET (9+9+9+7+9) -static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { - // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 - 9, // bLength; - 2, // bDescriptorType; - LSB(CONFIG1_DESC_SIZE), // wTotalLength - MSB(CONFIG1_DESC_SIZE), - 2, // bNumInterfaces - 1, // bConfigurationValue - 0, // iConfiguration - 0xC0, // bmAttributes - 50, // bMaxPower - // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 9, // bLength - 4, // bDescriptorType - KEYBOARD_INTERFACE, // bInterfaceNumber - 0, // bAlternateSetting - 1, // bNumEndpoints - 0x03, // bInterfaceClass (0x03 = HID) - 0x01, // bInterfaceSubClass (0x01 = Boot) - 0x01, // bInterfaceProtocol (0x01 = Keyboard) - 0, // iInterface - // HID interface descriptor, HID 1.11 spec, section 6.2.1 - 9, // bLength - 0x21, // bDescriptorType - 0x11, 0x01, // bcdHID - 0, // bCountryCode - 1, // bNumDescriptors - 0x22, // bDescriptorType - sizeof(keyboard_hid_report_desc), // wDescriptorLength - 0, - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress - 0x03, // bmAttributes (0x03=intr) - KEYBOARD_SIZE, 0, // wMaxPacketSize - 1, // bInterval - // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 9, // bLength - 4, // bDescriptorType - DEBUG_INTERFACE, // bInterfaceNumber - 0, // bAlternateSetting - 1, // bNumEndpoints - 0x03, // bInterfaceClass (0x03 = HID) - 0x00, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0, // iInterface - // HID interface descriptor, HID 1.11 spec, section 6.2.1 - 9, // bLength - 0x21, // bDescriptorType - 0x11, 0x01, // bcdHID - 0, // bCountryCode - 1, // bNumDescriptors - 0x22, // bDescriptorType - sizeof(debug_hid_report_desc), // wDescriptorLength - 0, - // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 7, // bLength - 5, // bDescriptorType - DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress - 0x03, // bmAttributes (0x03=intr) - DEBUG_TX_SIZE, 0, // wMaxPacketSize - 1 // bInterval -}; - -// If you're desperate for a little extra code memory, these strings -// can be completely removed if iManufacturer, iProduct, iSerialNumber -// in the device desciptor are changed to zeros. -struct usb_string_descriptor_struct { - uint8_t bLength; - uint8_t bDescriptorType; - int16_t wString[]; -}; -static const struct usb_string_descriptor_struct PROGMEM string0 = { - 4, - 3, - {0x0409} -}; -static const struct usb_string_descriptor_struct PROGMEM string1 = { - sizeof(STR_MANUFACTURER), - 3, - STR_MANUFACTURER -}; -static const struct usb_string_descriptor_struct PROGMEM string2 = { - sizeof(STR_PRODUCT), - 3, - STR_PRODUCT -}; -static const struct usb_string_descriptor_struct PROGMEM string3 = { - sizeof(STR_SERIAL), - 3, - STR_SERIAL -}; - -// This table defines which descriptor data is sent for each specific -// request from the host (in wValue and wIndex). -static const struct descriptor_list_struct { - uint16_t wValue; - uint16_t wIndex; - const uint8_t *addr; - uint8_t length; -} PROGMEM descriptor_list[] = { - {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, - {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, - {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, - {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, - {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, - {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, - {0x0300, 0x0000, (const uint8_t *)&string0, 4}, - {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, - {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}, - {0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)} -}; -#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) - - -/************************************************************************** - * - * Variables - these are the only non-stack RAM usage - * - **************************************************************************/ - -// zero when we are not configured, non-zero when enumerated -static volatile uint8_t usb_configuration=0; - -// the time remaining before we transmit any partially full -// packet, or send a zero length packet. -static volatile uint8_t debug_flush_timer=0; - - -/************************************************************************** - * - * Public Functions - these are the API intended for the user - * - **************************************************************************/ - - -// initialize USB -void usb_init(void) -{ - HW_CONFIG(); - USB_FREEZE(); // enable USB - PLL_CONFIG(); // config PLL - while (!(PLLCSR & (1<= NUM_DESC_LIST) { - UECONX = (1< desc_length) len = desc_length; - do { - // wait for host ready for IN packet - do { - i = UEINTX; - } while (!(i & ((1<= 1 && i <= MAX_ENDPOINT) { - usb_send_in(); - UENUM = i; - if (bRequest == SET_FEATURE) { - UECONX = (1<> 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< -#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 -#include -#include - -#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< + + +#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< 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<= NUM_DESC_LIST) { + UECONX = (1< desc_length) len = desc_length; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1<= 1 && i <= MAX_ENDPOINT) { + usb_send_in(); + UENUM = i; + if (bRequest == SET_FEATURE) { + UECONX = (1<> 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< + +// AVR Includes +#include +#include +#include +#include + +// AVR Util Includes +#include + +// 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< // Project Includes +#include +#include #include // USB Includes #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) -#include "avr/usb_keyboard_debug.h" +#include "avr/usb_keyboard_serial.h" #elif defined(_mk20dx128_) || defined(_mk20dx256_) #include "arm/usb_keyboard.h" #include "arm/usb_dev.h" @@ -40,8 +42,31 @@ +// ----- Function Declarations ----- + +void cliFunc_holdKey ( char* args ); +void cliFunc_readLEDs ( char* args ); +void cliFunc_releaseKey( char* args ); +void cliFunc_sendKey ( char* args ); +void cliFunc_setLEDs ( char* args ); +void cliFunc_setMod ( char* args ); + + // ----- Variables ----- +// Output Module command dictionary +char* outputCLIDictName = "USB Module Commands"; +CLIDictItem outputCLIDict[] = { + { "holdKey", "Hold a space separated list of USB codes. Ignores already pressed keys.", cliFunc_holdKey }, + { "readLEDs", "Read LED byte. See setLEDs.", cliFunc_readLEDs }, + { "releaseKey", "Release a space separated list of USB codes. Ignores unpressed keys.", cliFunc_releaseKey }, + { "sendKey", "Send a space separated list of USB codes. Press/Release.", cliFunc_sendKey }, + { "setLEDs", "Set LED byte: 1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_setLEDs }, + { "setMod", "Set the modfier byte: 1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod }, + { 0, 0, 0 } // Null entry for dictionary end +}; + + // which modifier keys are currently pressed // 1=left ctrl, 2=left shift, 4=left alt, 8=left gui // 16=right ctrl, 32=right shift, 64=right alt, 128=right gui @@ -69,7 +94,6 @@ uint8_t USBKeys_Idle_Count = 0; - // ----- Functions ----- // USB Module Setup @@ -81,9 +105,12 @@ usb_init(); while ( !usb_configured() ) /* wait */ ; + // Register USB Output dictionary + registerDictionary_cli( outputCLIDict, outputCLIDictName ); + // Wait an extra second for the PC's operating system to load drivers // and do whatever it does to actually be ready for input - //_delay_ms(1000); // TODO + //_delay_ms(1000); // TODO (is this actually necessary?) } @@ -110,8 +137,102 @@ inline void output_firmwareReload() { #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) + usb_debug_reload(); #elif defined(_mk20dx128_) || defined(_mk20dx256_) usb_device_reload(); #endif } + +// USB Input buffer available +inline unsigned int output_availablechar() +{ + return usb_serial_available(); +} + + +// USB Get Character from input buffer +inline int output_getchar() +{ +#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) + // XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes) + return (int)usb_serial_getchar(); +#elif defined(_mk20dx128_) || defined(_mk20dx256_) + return usb_serial_getchar(); +#endif +} + + +// USB Send Character to output buffer +inline int output_putchar( char c ) +{ + return usb_serial_putchar( c ); +} + + +// USB Send String to output buffer, null terminated +inline int output_putstr( char* str ) +{ +#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR + uint16_t count = 0; +#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM + uint32_t count = 0; +#endif + // Count characters until NULL character, then send the amount counted + while ( str[count] != '\0' ) + count++; + + return usb_serial_write( str, count ); +} + + +// Soft Chip Reset +inline void output_softReset() +{ +#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) + usb_debug_software_reset(); +#elif defined(_mk20dx128_) || defined(_mk20dx256_) + SOFTWARE_RESET(); +#endif +} + + +// ----- CLI Command Functions ----- + +void cliFunc_holdKey( char* args ) +{ + // TODO +} + + +void cliFunc_readLEDs( char* args ) +{ + // TODO +} + + +void cliFunc_releaseKey( char* args ) +{ + // TODO +} + + +void cliFunc_sendKey( char* args ) +{ + // TODO Argument handling + USBKeys_Array[0] = 4; // KEY_A + USBKeys_Sent = 1; +} + + +void cliFunc_setLEDs( char* args ) +{ + // TODO +} + + +void cliFunc_setMod( char* args ) +{ + // TODO +} + diff -r 2bb16439e6ca -r 0c5d1fe99302 Output/pjrcUSB/output_com.h --- a/Output/pjrcUSB/output_com.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Output/pjrcUSB/output_com.h Mon Mar 31 01:07:48 2014 -0700 @@ -59,10 +59,17 @@ // ----- Functions ----- void output_setup(); - void output_send(); void output_firmwareReload(); +void output_softReset(); + +// Relies on USB serial module +unsigned int output_availablechar(); + +int output_getchar(); +int output_putchar( char c ); +int output_putstr( char* str ); #endif diff -r 2bb16439e6ca -r 0c5d1fe99302 Output/pjrcUSB/setup.cmake --- a/Output/pjrcUSB/setup.cmake Sat Mar 22 14:32:06 2014 -0700 +++ b/Output/pjrcUSB/setup.cmake Mon Mar 31 01:07:48 2014 -0700 @@ -17,7 +17,7 @@ set( OUTPUT_SRCS output_com.c - avr/usb_keyboard_debug.c + avr/usb_keyboard_serial.c ) #| ARM Compiler diff -r 2bb16439e6ca -r 0c5d1fe99302 README --- a/README Sat Mar 22 14:32:06 2014 -0700 +++ b/README Mon Mar 31 01:07:48 2014 -0700 @@ -24,10 +24,12 @@ - avr-libc (1.8.0) -ARM Specific (Teensy 3.0) (Sourcery CodeBench Lite for ARM EABI +ARM Specific (Teensy 3.0/3.1) (Sourcery CodeBench Lite for ARM EABI (http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/) - arm-none-eabi -- TODO? +OR +- arm-none-eabi-gcc +- arm-none-eaby-binutils @@ -42,6 +44,7 @@ - Teensy 2.0 - Teensy 2.0++ - Teensy 3.0 + - Teensy 3.1 Open up CMakeLists.txt in your favourite text editor. You are looking for: @@ -57,13 +60,14 @@ #| "avr" # Teensy++ 1.0 #| "avr" # Teensy++ 2.0 #| "arm" # Teensy 3.0 + #| "arm" # Teensy 3.1 set( COMPILER_FAMILY "avr" ) Just change the COMPILER_FAMILY variable to whatever you are trying to build for. -NOTE: If you change this option, you will *may* to delete the build directory that is created in the Building sections below. +NOTE: If you change this option, you will *may* to delete the build directory that is created in the Building sections below. @@ -102,6 +106,7 @@ #| type "make clean" after changing this, so all files will be rebuilt #| #| "mk20dx128" # Teensy 3.0 + #| "mk20dx256" # Teensy 3.1 set( CHIP "mk20dx128" ) @@ -123,7 +128,7 @@ - Scan Module - Macro Module -- USB Module +- Output Module - Debug Module The Scan Module is where the most interesting stuff happens. These modules take in "keypress data". @@ -135,11 +140,11 @@ Some scan modules have very specialized hardware requirements, each module directory should have at least a link to the needed parts and/or schematics (TODO!). -The Macro Module takes care of the mapping of the key press/release code into a USB scan code. +The Macro Module takes care of the mapping of the key press/release code into an Output (USB) scan code. Any layering, macros, keypress intelligence/reaction is done here. -The USB Module is the output module of the microcontroller. Currently USB is the only output protocol. +The Output Module is the module dealing with output from the microcontroller. Currently USB is the only output protocol. Different USB output implementations are available, pjrc being the safest/least featureful one. Debug capabilities may depend on the module selected. @@ -161,7 +166,7 @@ #| All of the modules must be specified, as they generate the sources list of files to compile #| Any modifications to this file will cause a complete rebuild of the project - #| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones + #| Please look at the {Scan,Macro,Output,Debug}/module.txt for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index set( ScanModule "avr-capsense" ) @@ -170,7 +175,7 @@ set( MacroModule "buffer" ) ##| Sends the current list of usb key codes through USB HID - set( USBModule "pjrc" ) + set( OutputModule "pjrc" ) ##| Debugging source to use, each module has it's own set of defines that it sets set( DebugModule "full" ) @@ -206,8 +211,8 @@ Scan/avr-capsense/scan_loop.c -- Detected Macro Module Source Files: Macro/buffer/macro.c - -- Detected USB Module Source Files: - USB/pjrc/usb_com.c;USB/pjrc/avr/usb_keyboard_debug.c + -- Detected Output Module Source Files: + Output/pjrc/usb_com.c;Output/pjrc/avr/usb_keyboard_debug.c -- Detected Debug Module Source Files: Debug/full/../led/led.c;Debug/full/../print/print.c -- Configuring done @@ -218,8 +223,8 @@ [ 12%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o [ 25%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/avr-capsense/scan_loop.c.o [ 37%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/buffer/macro.c.o - [ 50%] Building C object CMakeFiles/kiibohd.elf.dir/USB/pjrc/usb_com.c.o - [ 62%] Building C object CMakeFiles/kiibohd.elf.dir/USB/pjrc/avr/usb_keyboard_debug.c.o + [ 50%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/usb_com.c.o + [ 62%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/avr/usb_keyboard_debug.c.o [ 75%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.o [ 87%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.o Linking C executable kiibohd.elf diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/DPH/scan_loop.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/DPH/scan_loop.c Mon Mar 31 01:07:48 2014 -0700 @@ -0,0 +1,1012 @@ +/* Copyright (C) 2011-2013 by Joseph Makuch + * Additions by Jacob Alexander (2013-2014) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include + +// 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<> 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 + // [:] : : : + 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 -r 2bb16439e6ca -r 0c5d1fe99302 Scan/DPH/scan_loop.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/DPH/scan_loop.h Mon Mar 31 01:07:48 2014 -0700 @@ -0,0 +1,64 @@ +/* Copyright (C) 2013 by Jacob Alexander + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __SCAN_LOOP_H +#define __SCAN_LOOP_H + +// ----- Includes ----- + +// Compiler Includes +#include + +// 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 -r 2bb16439e6ca -r 0c5d1fe99302 Scan/DPH/setup.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/DPH/setup.cmake Mon Mar 31 01:07:48 2014 -0700 @@ -0,0 +1,54 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2013-2014 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Module C files +# + +set( SCAN_SRCS + scan_loop.c +) + + +### +# Module H files +# +set( SCAN_HDRS + scan_loop.h +) + + +### +# File Dependency Setup +# +ADD_FILE_DEPENDENCIES( scan_loop.c ${SCAN_HDRS} ) +#add_file_dependencies( scan_loop.c ${SCAN_HDRS} ) +#add_file_dependencies( macro.c keymap.h avrcapsense.h ) + + +### +# Module Specific Options +# +add_definitions( -I${HEAD_DIR}/Keymap ) + +#| Keymap Settings +add_definitions( + -DMODIFIER_MASK=avrcapsense_ModifierMask + #-DKEYINDEX_MASK=avrcapsense_ColemakMap + -DKEYINDEX_MASK=avrcapsense_DefaultMap +) + + +### +# Compiler Family Compatibility +# +set( ScanModuleCompatibility + avr +) + diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/SKM67001/setup.cmake --- a/Scan/SKM67001/setup.cmake Sat Mar 22 14:32:06 2014 -0700 +++ b/Scan/SKM67001/setup.cmake Mon Mar 31 01:07:48 2014 -0700 @@ -24,7 +24,7 @@ add_definitions( -I${HEAD_DIR}/Keymap ) add_definitions( -I${HEAD_DIR}/Scan/matrix -) +) #| Keymap Settings add_definitions( diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/avr-capsense/scan_loop.c --- a/Scan/avr-capsense/scan_loop.c Sat Mar 22 14:32:06 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1012 +0,0 @@ -/* Copyright (C) 2011-2013 by Joseph Makuch - * Additions by Jacob Alexander (2013) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -// ----- Includes ----- - -// Compiler Includes -#include - -// Project Includes -#include -#include - -// 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<> 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 - // [:] : : : - 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 -r 2bb16439e6ca -r 0c5d1fe99302 Scan/avr-capsense/scan_loop.h --- a/Scan/avr-capsense/scan_loop.h Sat Mar 22 14:32:06 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* Copyright (C) 2013 by Jacob Alexander - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - */ - -#ifndef __SCAN_LOOP_H -#define __SCAN_LOOP_H - -// ----- Includes ----- - -// Compiler Includes -#include - -// 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 -r 2bb16439e6ca -r 0c5d1fe99302 Scan/avr-capsense/setup.cmake --- a/Scan/avr-capsense/setup.cmake Sat Mar 22 14:32:06 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -###| CMake Kiibohd Controller Scan Module |### -# -# Written by Jacob Alexander in 2013 for the Kiibohd Controller -# -# Released into the Public Domain -# -### - - -### -# Module C files -# - -set( SCAN_SRCS - scan_loop.c -) - - -### -# Module H files -# -set( SCAN_HDRS - scan_loop.h -) - - -### -# File Dependency Setup -# -ADD_FILE_DEPENDENCIES( scan_loop.c ${SCAN_HDRS} ) -#add_file_dependencies( scan_loop.c ${SCAN_HDRS} ) -#add_file_dependencies( macro.c keymap.h avrcapsense.h ) - - -### -# Module Specific Options -# -add_definitions( -I${HEAD_DIR}/Keymap ) - -#| Keymap Settings -add_definitions( - -DMODIFIER_MASK=avrcapsense_ModifierMask - #-DKEYINDEX_MASK=avrcapsense_ColemakMap - -DKEYINDEX_MASK=avrcapsense_DefaultMap -) - - -### -# Compiler Family Compatibility -# -set( ScanModuleCompatibility - avr -) - diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/matrix/matrix_scan.c --- a/Scan/matrix/matrix_scan.c Sat Mar 22 14:32:06 2014 -0700 +++ b/Scan/matrix/matrix_scan.c Mon Mar 31 01:07:48 2014 -0700 @@ -1,15 +1,15 @@ -/* Copyright (C) 2011 by Jacob Alexander - * +/* Copyright (C) 2011,2014 by Jacob Alexander + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/matrix/matrix_scan.h --- a/Scan/matrix/matrix_scan.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Scan/matrix/matrix_scan.h Mon Mar 31 01:07:48 2014 -0700 @@ -1,15 +1,15 @@ -/* Copyright (C) 2011 by Jacob Alexander - * +/* Copyright (C) 2011,2014 by Jacob Alexander + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/matrix/matrix_template.h --- a/Scan/matrix/matrix_template.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Scan/matrix/matrix_template.h Mon Mar 31 01:07:48 2014 -0700 @@ -1,15 +1,15 @@ -/* Copyright (C) 2011 by Jacob Alexander - * +/* Copyright (C) 2011,2014 by Jacob Alexander + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -69,7 +69,7 @@ // Just layout the matrix by rows and columns // Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol // The mode allows for optimization in the kind of scanning algorithms that are done -// +// // The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0). // Thus if a row doesn't use all the key positions, you can denote it as 0, which will be ignored/skipped on each scan // See the keymap.h file for the various preconfigured arrays. diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/matrix/scan_loop.c --- a/Scan/matrix/scan_loop.c Sat Mar 22 14:32:06 2014 -0700 +++ b/Scan/matrix/scan_loop.c Mon Mar 31 01:07:48 2014 -0700 @@ -1,15 +1,15 @@ -/* Copyright (C) 2011-2012 by Jacob Alexander - * +/* Copyright (C) 2011-2012,2014 by Jacob Alexander + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff -r 2bb16439e6ca -r 0c5d1fe99302 Scan/matrix/scan_loop.h --- a/Scan/matrix/scan_loop.h Sat Mar 22 14:32:06 2014 -0700 +++ b/Scan/matrix/scan_loop.h Mon Mar 31 01:07:48 2014 -0700 @@ -1,15 +1,15 @@ -/* Copyright (C) 2011-2012 by Jacob Alexander - * +/* Copyright (C) 2011-2012,2014 by Jacob Alexander + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE diff -r 2bb16439e6ca -r 0c5d1fe99302 avr.cmake --- a/avr.cmake Sat Mar 22 14:32:06 2014 -0700 +++ b/avr.cmake Mon Mar 31 01:07:48 2014 -0700 @@ -1,6 +1,6 @@ ###| CMAKE Kiibohd Controller |### # -# Jacob Alexander 2011-2013 +# Jacob Alexander 2011-2014 # Due to this file's usefulness: # # Released into the Public Domain @@ -37,8 +37,8 @@ #| "atmega32u4" # Teensy 2.0 #| "at90usb646" # Teensy++ 1.0 #| "at90usb1286" # Teensy++ 2.0 -#set( MCU "atmega32u4" ) -set( MCU "at90usb1286" ) +set( MCU "atmega32u4" ) +#set( MCU "at90usb1286" ) message( STATUS "MCU Selected:" ) message( "${MCU}" ) @@ -51,6 +51,15 @@ ) +#| CPU Type +#| This is only informational for AVR microcontrollers +#| The field can be determined by the microcontroller chip, but currently only one CPU type is used atm +set( CPU "megaAVR" ) + +message( STATUS "CPU Selected:" ) +message( "${CPU}" ) + + #| USB Defines set( VENDOR_ID "0x16C0" ) set( PRODUCT_ID "0x047D" ) @@ -66,7 +75,7 @@ #| Warning Options #| -Wall...: warning level -set( WARN "-Wall -Wstrict-prototypes" ) +set( WARN "-Wall" ) #| Tuning Options @@ -75,7 +84,7 @@ set( TUNING "-funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums" ) -#| Optimization level, can be [0, 1, 2, 3, s]. +#| Optimization level, can be [0, 1, 2, 3, s]. #| 0 = turn off optimization. s = optimize for size. #| (Note: 3 is not always the best optimization level. See avr-libc FAQ.) set( OPT "s" ) diff -r 2bb16439e6ca -r 0c5d1fe99302 main.c --- a/main.c Sat Mar 22 14:32:06 2014 -0700 +++ b/main.c Mon Mar 31 01:07:48 2014 -0700 @@ -139,57 +139,43 @@ { // Configuring Pins pinSetup(); - init_errorLED(); + + // Enable CLI + init_cli(); // Setup Output Module output_setup(); - // Enable CLI - init_cli(); - // Setup ISR Timer for flagging a kepress send to USB usbTimerSetup(); + // Setup the scanning module + //scan_setup(); + // Main Detection Loop - uint8_t ledTimer = F_CPU / 1000000; // Enable LED for a short time while ( 1 ) { - // Setup the scanning module - scan_setup(); + // Process CLI + process_cli(); - while ( 1 ) - { - // Acquire Key Indices - // Loop continuously until scan_loop returns 0 - cli(); - while ( scan_loop() ); - sei(); - - // Run Macros over Key Indices and convert to USB Keys - process_macros(); - - // Send keypresses over USB if the ISR has signalled that it's time - if ( !sendKeypresses ) - continue; + // Acquire Key Indices + // Loop continuously until scan_loop returns 0 + cli(); + //while ( scan_loop() ); + sei(); - // Send USB Data - output_send(); - - // Clear sendKeypresses Flag - sendKeypresses = 0; - - // Indicate Error, if valid - errorLED( ledTimer ); + // Run Macros over Key Indices and convert to USB Keys + process_macros(); - if ( ledTimer > 0 ) - ledTimer--; - } + // Send keypresses over USB if the ISR has signalled that it's time + if ( !sendKeypresses ) + continue; - // Loop should never get here (indicate error) - ledTimer = 255; + // Send USB Data + output_send(); - // HID Debug Error message - erro_print("Detection loop error, this is very bad...bug report!"); + // Clear sendKeypresses Flag + sendKeypresses = 0; } } diff -r 2bb16439e6ca -r 0c5d1fe99302 setup.cmake --- a/setup.cmake Sat Mar 22 14:32:06 2014 -0700 +++ b/setup.cmake Mon Mar 31 01:07:48 2014 -0700 @@ -20,7 +20,7 @@ #| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index -set( ScanModule "MBC-55X" ) +set( ScanModule "SKM67001" ) ##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code set( MacroModule "buffer" )