Browse Source

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
simple
Jacob Alexander 10 years ago
parent
commit
15ec4ff71c

+ 4
- 3
CMakeLists.txt View File

@@ -28,8 +28,8 @@ include( AddFileDependencies )
#| "avr" # Teensy++ 2.0
#| "arm" # Teensy 3.0
#| "arm" # Teensy 3.1
set( COMPILER_FAMILY "arm" )
#set( COMPILER_FAMILY "avr" )
#set( COMPILER_FAMILY "arm" )
set( COMPILER_FAMILY "avr" )

message( STATUS "Compiler Family:" )
message( "${COMPILER_FAMILY}" )
@@ -138,9 +138,10 @@ add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
#

#| After Changes Size Information
#| TODO Do lookup on Flash and RAM sizes and do % used
add_custom_target( SizeAfter ALL ${SIZE} --target=${FORMAT} ${TARGET_HEX} ${TARGET_ELF}
DEPENDS ${TARGET_ELF}
COMMENT "Size after generation:"
COMMENT "Size after generation\n\tFlash Usage: data (hex)\n\t RAM Usage: data (elf)"
)



+ 4
- 5
Debug/cli/cli.c View File

@@ -85,15 +85,14 @@ void process_cli()
uint8_t prev_buf_pos = CLILineBufferCurrent;

// Process each character while available
int result = 0;
while ( 1 )
{
// No more characters to process
result = usb_serial_getchar(); // Retrieve from serial module // TODO Make USB agnostic
if ( result == -1 )
if ( output_availablechar() == 0 )
break;

char cur_char = (char)result;
// Retrieve from output module
char cur_char = (char)output_getchar();

// Make sure buffer isn't full
if ( CLILineBufferCurrent >= CLILineBufferMaxSize )
@@ -405,7 +404,7 @@ void cliFunc_reset( char* args )
void cliFunc_restart( char* args )
{
// Trigger an overall software reset
SOFTWARE_RESET();
output_softReset();
}

void cliFunc_version( char* args )

+ 7
- 27
Debug/print/print.c View File

@@ -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 @@ void usb_debug_putstrs( char* first, ... )
while ( !( cur[0] == '\0' && cur[1] == '\0' && cur[2] == '\0' ) )
{
// Print out the given string
usb_debug_putstr( cur );
output_putstr( cur );

// Get the next argument ready
cur = va_arg( ap, char* );
@@ -71,21 +55,17 @@ void usb_debug_putstrs( char* first, ... )
}

// Print a constant string
void _print(const char *s)
void _print( const char* s )
{
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
// Pull string out of flash
char c;

// Acquire the character from flash, and print it, as long as it's not NULL
// Also, if a newline is found, print a carrige return as well
while ( ( c = pgm_read_byte(s++) ) != '\0' )
while ( ( c = pgm_read_byte( s++ ) ) != '\0' )
{
if ( c == '\n' )
usb_debug_putchar('\r');
usb_debug_putchar(c);
output_putchar( c );
}
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
usb_debug_putstr( (char*)s );
output_putstr( (char*)s );
#endif
}


+ 10
- 15
Debug/print/print.h View File

@@ -26,16 +26,12 @@

// Compiler Includes
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)

#include <avr/pgmspace.h>
#include "avr/usb_keyboard_debug.h"

#elif defined(_mk20dx128_) || defined(_mk20dx256_)

#include "arm/usb_serial.h"

#endif

// Project Includes
#include <output_com.h>



// ----- Defines -----
@@ -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

+ 1
- 1
Lib/_buildvars.h View File

@@ -30,7 +30,7 @@

// You can change these to give your code its own name.
#define STR_MANUFACTURER L"@MANUFACTURER@"
#define STR_PRODUCT L"ForceGauge - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@"
#define STR_PRODUCT L"Keyboard - @ScanModule@ @MacroModule@ @OutputModule@ @DebugModule@"
#define STR_SERIAL L"@GitLastCommitDate@"



+ 3
- 2
Output/pjrcUSB/arm/usb_desc.c View File

@@ -1,6 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modified by Jacob Alexander (2013-2014)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -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.

+ 9
- 2
Output/pjrcUSB/arm/usb_desc.h View File

@@ -1,6 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modified by Jacob Alexander (2013-2014)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -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 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define NUM_ENDPOINTS 6
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 4

#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
@@ -98,22 +100,27 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64

#define KEYBOARD_INTERFACE 2 // Keyboard
#define KEYBOARD_ENDPOINT 1
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1

#define MOUSE_INTERFACE 3 // Mouse
#define MOUSE_ENDPOINT 5
#define MOUSE_SIZE 8
#define MOUSE_INTERVAL 2

#define JOYSTICK_INTERFACE 4 // Joystick
#define JOYSTICK_ENDPOINT 6
#define JOYSTICK_SIZE 16
#define JOYSTICK_INTERVAL 1

#define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9)
#define MOUSE_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
#define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
#define CONFIG_DESC_SIZE (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)

#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY

+ 0
- 705
Output/pjrcUSB/avr/usb_keyboard_debug.c View File

@@ -1,705 +0,0 @@
/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
* http://www.pjrc.com/teensy/usb_keyboard.html
* Copyright (c) 2009 PJRC.COM, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

// Version 1.0: Initial Release
// Version 1.1: Add support for Teensy 2.0

#define USB_SERIAL_PRIVATE_INCLUDE
#include "usb_keyboard_debug.h"

/**************************************************************************
*
* Configurable Options
*
**************************************************************************/

// USB devices are supposed to implment a halt feature, which is
// rarely (if ever) used. If you comment this line out, the halt
// code will be removed, saving 102 bytes of space (gcc 4.3.0).
// This is not strictly USB compliant, but works with all major
// operating systems.
#define SUPPORT_ENDPOINT_HALT



/**************************************************************************
*
* Endpoint Buffer Configuration
*
**************************************************************************/

#define ENDPOINT0_SIZE 32

#define KEYBOARD_INTERFACE 0
#define KEYBOARD_ENDPOINT 3
#define KEYBOARD_SIZE 8
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER

#define DEBUG_INTERFACE 1
#define DEBUG_TX_ENDPOINT 4
#define DEBUG_TX_SIZE 32
#define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER

static const uint8_t PROGMEM endpoint_config_table[] = {
0,
0,
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER
};


/**************************************************************************
*
* Descriptor Data
*
**************************************************************************/

// Descriptors are the data that your computer reads when it auto-detects
// this USB device (called "enumeration" in USB lingo). The most commonly
// changed items are editable at the top of this file. Changing things
// in here should only be done by those who've read chapter 9 of the USB
// spec and relevant portions of any USB class specifications!


static const uint8_t PROGMEM device_descriptor[] = {
18, // bLength
1, // bDescriptorType
0x00, 0x02, // bcdUSB
0, // bDeviceClass
0, // bDeviceSubClass
0, // bDeviceProtocol
ENDPOINT0_SIZE, // bMaxPacketSize0
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
0x00, 0x01, // bcdDevice
1, // iManufacturer
2, // iProduct
3, // iSerialNumber
1 // bNumConfigurations
};

// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application),
0x75, 0x01, // Report Size (1),
0x95, 0x08, // Report Count (8),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0xE0, // Usage Minimum (224),
0x29, 0xE7, // Usage Maximum (231),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
0x95, 0x01, // Report Count (1),
0x75, 0x08, // Report Size (8),
0x81, 0x03, // Input (Constant), ;Reserved byte
0x95, 0x05, // Report Count (5),
0x75, 0x01, // Report Size (1),
0x05, 0x08, // Usage Page (LEDs),
0x19, 0x01, // Usage Minimum (1),
0x29, 0x05, // Usage Maximum (5),
0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
0x95, 0x01, // Report Count (1),
0x75, 0x03, // Report Size (3),
0x91, 0x03, // Output (Constant), ;LED report padding
0x95, 0x06, // Report Count (6),
0x75, 0x08, // Report Size (8),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x68, // Logical Maximum(104),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x29, 0x68, // Usage Maximum (104),
0x81, 0x00, // Input (Data, Array),
0xc0 // End Collection
};

static const uint8_t PROGMEM debug_hid_report_desc[] = {
//0x06, 0x30, 0xFF, // Usage Page 0xFF31 (vendor defined)
0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
0x09, 0x74, // Usage 0x74
0xA1, 0x53, // Collection 0x53
0x75, 0x08, // report size = 8 bits
0x15, 0x00, // logical minimum = 0
0x26, 0xFF, 0x00, // logical maximum = 255
0x95, DEBUG_TX_SIZE, // report count
0x09, 0x75, // usage
0x81, 0x02, // Input (array)
0xC0 // end collection
};

#define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7)
#define KEYBOARD_HID_DESC_OFFSET (9+9)
#define DEBUG_HID_DESC_OFFSET (9+9+9+7+9)
static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
9, // bLength;
2, // bDescriptorType;
LSB(CONFIG1_DESC_SIZE), // wTotalLength
MSB(CONFIG1_DESC_SIZE),
2, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0xC0, // bmAttributes
50, // bMaxPower
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
KEYBOARD_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x01, // bInterfaceSubClass (0x01 = Boot)
0x01, // bInterfaceProtocol (0x01 = Keyboard)
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
sizeof(keyboard_hid_report_desc), // wDescriptorLength
0,
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
KEYBOARD_SIZE, 0, // wMaxPacketSize
1, // bInterval
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
DEBUG_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
sizeof(debug_hid_report_desc), // wDescriptorLength
0,
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
DEBUG_TX_SIZE, 0, // wMaxPacketSize
1 // bInterval
};

// If you're desperate for a little extra code memory, these strings
// can be completely removed if iManufacturer, iProduct, iSerialNumber
// in the device desciptor are changed to zeros.
struct usb_string_descriptor_struct {
uint8_t bLength;
uint8_t bDescriptorType;
int16_t wString[];
};
static const struct usb_string_descriptor_struct PROGMEM string0 = {
4,
3,
{0x0409}
};
static const struct usb_string_descriptor_struct PROGMEM string1 = {
sizeof(STR_MANUFACTURER),
3,
STR_MANUFACTURER
};
static const struct usb_string_descriptor_struct PROGMEM string2 = {
sizeof(STR_PRODUCT),
3,
STR_PRODUCT
};
static const struct usb_string_descriptor_struct PROGMEM string3 = {
sizeof(STR_SERIAL),
3,
STR_SERIAL
};

// This table defines which descriptor data is sent for each specific
// request from the host (in wValue and wIndex).
static const struct descriptor_list_struct {
uint16_t wValue;
uint16_t wIndex;
const uint8_t *addr;
uint8_t length;
} PROGMEM descriptor_list[] = {
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
{0x0300, 0x0000, (const uint8_t *)&string0, 4},
{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)},
{0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL)}
};
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))


/**************************************************************************
*
* Variables - these are the only non-stack RAM usage
*
**************************************************************************/

// zero when we are not configured, non-zero when enumerated
static volatile uint8_t usb_configuration=0;

// the time remaining before we transmit any partially full
// packet, or send a zero length packet.
static volatile uint8_t debug_flush_timer=0;


/**************************************************************************
*
* Public Functions - these are the API intended for the user
*
**************************************************************************/


// initialize USB
void usb_init(void)
{
HW_CONFIG();
USB_FREEZE(); // enable USB
PLL_CONFIG(); // config PLL
while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
USB_CONFIG(); // start USB clock
UDCON = 0; // enable attach resistor
usb_configuration = 0;
UDIEN = (1<<EORSTE)|(1<<SOFE);
sei();
}

// return 0 if the USB is not configured, or the configuration
// number selected by the HOST
uint8_t usb_configured(void)
{
return usb_configuration;
}

// send the contents of USBKeys_Array and USBKeys_Modifiers
int8_t usb_keyboard_send(void)
{
uint8_t i, intr_state, timeout;

if (!usb_configuration) return -1;
intr_state = SREG;
cli();
UENUM = KEYBOARD_ENDPOINT;
timeout = UDFNUML + 50;
while (1) {
// are we ready to transmit?
if (UEINTX & (1<<RWAL)) break;
SREG = intr_state;
// has the USB gone offline?
if (!usb_configuration) return -1;
// have we waited too long?
if (UDFNUML == timeout) return -1;
// get ready to try checking again
intr_state = SREG;
cli();
UENUM = KEYBOARD_ENDPOINT;
}
UEDATX = USBKeys_Modifiers;
UEDATX = 0;
for (i=0; i<6; i++) {
UEDATX = USBKeys_Array[i];
}
UEINTX = 0x3A;
USBKeys_Idle_Count = 0;
SREG = intr_state;
return 0;
}

// transmit a character. 0 returned on success, -1 on error
int8_t usb_debug_putchar(uint8_t c)
{
static uint8_t previous_timeout=0;
uint8_t timeout, intr_state;

// if we're not online (enumerated and configured), error
if (!usb_configuration) return -1;
// interrupts are disabled so these functions can be
// used from the main program or interrupt context,
// even both in the same program!
intr_state = SREG;
cli();
UENUM = DEBUG_TX_ENDPOINT;
// if we gave up due to timeout before, don't wait again
if (previous_timeout) {
if (!(UEINTX & (1<<RWAL))) {
SREG = intr_state;
return -1;
}
previous_timeout = 0;
}
// wait for the FIFO to be ready to accept data
timeout = UDFNUML + 4;
while (1) {
// are we ready to transmit?
if (UEINTX & (1<<RWAL)) break;
SREG = intr_state;
// have we waited too long?
if (UDFNUML == timeout) {
previous_timeout = 1;
return -1;
}
// has the USB gone offline?
if (!usb_configuration) return -1;
// get ready to try checking again
intr_state = SREG;
cli();
UENUM = DEBUG_TX_ENDPOINT;
}
// actually write the byte into the FIFO
UEDATX = c;
// if this completed a packet, transmit it now!
if (!(UEINTX & (1<<RWAL))) {
UEINTX = 0x3A;
debug_flush_timer = 0;
} else {
debug_flush_timer = 2;
}
SREG = intr_state;
return 0;
}


// immediately transmit any buffered output.
void usb_debug_flush_output(void)
{
uint8_t intr_state;

intr_state = SREG;
cli();
if (debug_flush_timer) {
UENUM = DEBUG_TX_ENDPOINT;
while ((UEINTX & (1<<RWAL))) {
UEDATX = 0;
}
UEINTX = 0x3A;
debug_flush_timer = 0;
}
SREG = intr_state;
}



/**************************************************************************
*
* Private Functions - not intended for general user consumption....
*
**************************************************************************/



// USB Device Interrupt - handle all device-level events
// the transmit buffer flushing is triggered by the start of frame
//
ISR(USB_GEN_vect)
{
uint8_t intbits, t, i;
static uint8_t div4=0;

intbits = UDINT;
UDINT = 0;
if (intbits & (1<<EORSTI)) {
UENUM = 0;
UECONX = 1;
UECFG0X = EP_TYPE_CONTROL;
UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
UEIENX = (1<<RXSTPE);
usb_configuration = 0;
}
if ((intbits & (1<<SOFI)) && usb_configuration) {
t = debug_flush_timer;
if (t) {
debug_flush_timer = -- t;
if (!t) {
UENUM = DEBUG_TX_ENDPOINT;
while ((UEINTX & (1<<RWAL))) {
UEDATX = 0;
}
UEINTX = 0x3A;
}
}
if (USBKeys_Idle_Config && (++div4 & 3) == 0) {
UENUM = KEYBOARD_ENDPOINT;
if (UEINTX & (1<<RWAL)) {
USBKeys_Idle_Count++;
if (USBKeys_Idle_Count == USBKeys_Idle_Config) {
USBKeys_Idle_Count = 0;
UEDATX = USBKeys_Modifiers;
UEDATX = 0;
for (i=0; i<6; i++) {
UEDATX = USBKeys_Array[i];
}
UEINTX = 0x3A;
}
}
}
}
}



// Misc functions to wait for ready and send/receive packets
static inline void usb_wait_in_ready(void)
{
while (!(UEINTX & (1<<TXINI))) ;
}
static inline void usb_send_in(void)
{
UEINTX = ~(1<<TXINI);
}
static inline void usb_wait_receive_out(void)
{
while (!(UEINTX & (1<<RXOUTI))) ;
}
static inline void usb_ack_out(void)
{
UEINTX = ~(1<<RXOUTI);
}



// USB Endpoint Interrupt - endpoint 0 is handled here. The
// other endpoints are manipulated by the user-callable
// functions, and the start-of-frame interrupt.
//
ISR(USB_COM_vect)
{
uint8_t intbits;
const uint8_t *list;
const uint8_t *cfg;
uint8_t i, n, len, en;
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint16_t desc_val;
const uint8_t *desc_addr;
uint8_t desc_length;

UENUM = 0;
intbits = UEINTX;
if (intbits & (1<<RXSTPI)) {
bmRequestType = UEDATX;
bRequest = UEDATX;
wValue = UEDATX;
wValue |= (UEDATX << 8);
wIndex = UEDATX;
wIndex |= (UEDATX << 8);
wLength = UEDATX;
wLength |= (UEDATX << 8);
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
if (bRequest == GET_DESCRIPTOR) {
list = (const uint8_t *)descriptor_list;
for (i=0; ; i++) {
if (i >= NUM_DESC_LIST) {
UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
return;
}
desc_val = pgm_read_word(list);
if (desc_val != wValue) {
list += sizeof(struct descriptor_list_struct);
continue;
}
list += 2;
desc_val = pgm_read_word(list);
if (desc_val != wIndex) {
list += sizeof(struct descriptor_list_struct)-2;
continue;
}
list += 2;
desc_addr = (const uint8_t *)pgm_read_word(list);
list += 2;
desc_length = pgm_read_byte(list);
break;
}
len = (wLength < 256) ? wLength : 255;
if (len > desc_length) len = desc_length;
do {
// wait for host ready for IN packet
do {
i = UEINTX;
} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
if (i & (1<<RXOUTI)) return; // abort
// send IN packet
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
for (i = n; i; i--) {
UEDATX = pgm_read_byte(desc_addr++);
}
len -= n;
usb_send_in();
} while (len || n == ENDPOINT0_SIZE);
return;
}
if (bRequest == SET_ADDRESS) {
usb_send_in();
usb_wait_in_ready();
UDADDR = wValue | (1<<ADDEN);
return;
}
if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
usb_configuration = wValue;
usb_send_in();
cfg = endpoint_config_table;
for (i=1; i<5; i++) {
UENUM = i;
en = pgm_read_byte(cfg++);
UECONX = en;
if (en) {
UECFG0X = pgm_read_byte(cfg++);
UECFG1X = pgm_read_byte(cfg++);
}
}
UERST = 0x1E;
UERST = 0;
return;
}
if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
usb_wait_in_ready();
UEDATX = usb_configuration;
usb_send_in();
return;
}

if (bRequest == GET_STATUS) {
usb_wait_in_ready();
i = 0;
#ifdef SUPPORT_ENDPOINT_HALT
if (bmRequestType == 0x82) {
UENUM = wIndex;
if (UECONX & (1<<STALLRQ)) i = 1;
UENUM = 0;
}
#endif
UEDATX = i;
UEDATX = 0;
usb_send_in();
return;
}
#ifdef SUPPORT_ENDPOINT_HALT
if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
&& bmRequestType == 0x02 && wValue == 0) {
i = wIndex & 0x7F;
if (i >= 1 && i <= MAX_ENDPOINT) {
usb_send_in();
UENUM = i;
if (bRequest == SET_FEATURE) {
UECONX = (1<<STALLRQ)|(1<<EPEN);
} else {
UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
UERST = (1 << i);
UERST = 0;
}
return;
}
}
#endif
if (wIndex == KEYBOARD_INTERFACE) {
if (bmRequestType == 0xA1) {
if (bRequest == HID_GET_REPORT) {
usb_wait_in_ready();
UEDATX = USBKeys_Modifiers;
UEDATX = 0;
for (i=0; i<6; i++) {
UEDATX = USBKeys_Array[i];
}
usb_send_in();
return;
}
if (bRequest == HID_GET_IDLE) {
usb_wait_in_ready();
UEDATX = USBKeys_Idle_Config;
usb_send_in();
return;
}
if (bRequest == HID_GET_PROTOCOL) {
usb_wait_in_ready();
UEDATX = USBKeys_Protocol;
usb_send_in();
return;
}
}
if (bmRequestType == 0x21) {
if (bRequest == HID_SET_REPORT) {
usb_wait_receive_out();
USBKeys_LEDs = UEDATX;
usb_ack_out();
usb_send_in();
return;
}
if (bRequest == HID_SET_IDLE) {
USBKeys_Idle_Config = (wValue >> 8);
USBKeys_Idle_Count = 0;
//usb_wait_in_ready();
usb_send_in();
return;
}
if (bRequest == HID_SET_PROTOCOL) {
USBKeys_Protocol = wValue;
//usb_wait_in_ready();
usb_send_in();
return;
}
}
}
if (wIndex == DEBUG_INTERFACE) {
if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
len = wLength;
do {
// wait for host ready for IN packet
do {
i = UEINTX;
} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
if (i & (1<<RXOUTI)) return; // abort
// send IN packet
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
for (i = n; i; i--) {
UEDATX = 0;
}
len -= n;
usb_send_in();
} while (len || n == ENDPOINT0_SIZE);
return;
}
}
}
UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
}


+ 0
- 90
Output/pjrcUSB/avr/usb_keyboard_debug.h View File

@@ -1,90 +0,0 @@
#ifndef usb_serial_h__
#define usb_serial_h__

#include <stdint.h>
#include "output_com.h"

void usb_init(void); // initialize everything
uint8_t usb_configured(void); // is the USB port configured

int8_t usb_keyboard_send(void);


int8_t usb_debug_putchar(uint8_t c); // transmit a character
void usb_debug_flush_output(void); // immediately transmit any buffered output
#define USB_DEBUG_HID


// Everything below this point is only intended for usb_serial.c
#ifdef USB_SERIAL_PRIVATE_INCLUDE
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#define EP_TYPE_CONTROL 0x00
#define EP_TYPE_BULK_IN 0x81
#define EP_TYPE_BULK_OUT 0x80
#define EP_TYPE_INTERRUPT_IN 0xC1
#define EP_TYPE_INTERRUPT_OUT 0xC0
#define EP_TYPE_ISOCHRONOUS_IN 0x41
#define EP_TYPE_ISOCHRONOUS_OUT 0x40

#define EP_SINGLE_BUFFER 0x02
#define EP_DOUBLE_BUFFER 0x06

#define EP_SIZE(s) ((s) == 64 ? 0x30 : \
((s) == 32 ? 0x20 : \
((s) == 16 ? 0x10 : \
0x00)))

#define MAX_ENDPOINT 4

#define LSB(n) (n & 255)
#define MSB(n) ((n >> 8) & 255)

#if defined(__AVR_AT90USB162__)
#define HW_CONFIG()
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
#define USB_CONFIG() (USBCON = (1<<USBE))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_ATmega32U4__)
#define HW_CONFIG() (UHWCON = 0x01)
#define PLL_CONFIG() (PLLCSR = 0x12)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_AT90USB646__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x1A)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_AT90USB1286__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x16)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#endif

// standard control endpoint request types
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
// HID (human interface device)
#define HID_GET_REPORT 1
#define HID_GET_IDLE 2
#define HID_GET_PROTOCOL 3
#define HID_SET_REPORT 9
#define HID_SET_IDLE 10
#define HID_SET_PROTOCOL 11
// CDC (communication class device)
#define CDC_SET_LINE_CODING 0x20
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22
#endif
#endif


+ 1126
- 0
Output/pjrcUSB/avr/usb_keyboard_serial.c
File diff suppressed because it is too large
View File


+ 221
- 0
Output/pjrcUSB/avr/usb_keyboard_serial.h View File

@@ -0,0 +1,221 @@
/* USB Keyboard and CDC Serial Device for Teensy USB Development Board
* Copyright (c) 2009 PJRC.COM, LLC
* Modifications by Jacob Alexander (2011-2014)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef usb_keyboard_serial_h__
#define usb_keyboard_serial_h__

// Compiler Includes
#include <stdint.h>

// AVR Includes
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>

// AVR Util Includes
#include <util/delay.h>

// Local Includes
#include "output_com.h"


// ----- Function Declarations -----

// Basic USB Configuration
void usb_init(void); // initialize everything
uint8_t usb_configured(void); // is the USB port configured

// Keyboard HID Functions
int8_t usb_keyboard_send(void);

// Chip Level Functions
void usb_debug_reload(); // Enable firmware reflash mode
void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3"))); // Needed for software reset

// USB Serial CDC Functions
int16_t usb_serial_getchar(void); // receive a character (-1 if timeout/error)
uint8_t usb_serial_available(void); // number of bytes in receive buffer
void usb_serial_flush_input(void); // discard any buffered input

// transmitting data
int8_t usb_serial_putchar(uint8_t c); // transmit a character
int8_t usb_serial_putchar_nowait(uint8_t c); // transmit a character, do not wait
int8_t usb_serial_write(const char *buffer, uint16_t size); // transmit a buffer
void usb_serial_flush_output(void); // immediately transmit any buffered output

// serial parameters
uint32_t usb_serial_get_baud(void); // get the baud rate
uint8_t usb_serial_get_stopbits(void); // get the number of stop bits
uint8_t usb_serial_get_paritytype(void);// get the parity type
uint8_t usb_serial_get_numbits(void); // get the number of data bits
uint8_t usb_serial_get_control(void); // get the RTS and DTR signal state
int8_t usb_serial_set_control(uint8_t signals); // set DSR, DCD, RI, etc



// ----- Macros -----

// Software reset the chip
#define usb_debug_software_reset() do { wdt_enable( WDTO_15MS ); for(;;); } while(0)

#define EP_SIZE(s) ((s) == 64 ? 0x30 : \
((s) == 32 ? 0x20 : \
((s) == 16 ? 0x10 : \
0x00)))

#define LSB(n) (n & 255)
#define MSB(n) ((n >> 8) & 255)



// ----- Defines -----

// constants corresponding to the various serial parameters
#define USB_SERIAL_DTR 0x01
#define USB_SERIAL_RTS 0x02
#define USB_SERIAL_1_STOP 0
#define USB_SERIAL_1_5_STOP 1
#define USB_SERIAL_2_STOP 2
#define USB_SERIAL_PARITY_NONE 0
#define USB_SERIAL_PARITY_ODD 1
#define USB_SERIAL_PARITY_EVEN 2
#define USB_SERIAL_PARITY_MARK 3
#define USB_SERIAL_PARITY_SPACE 4
#define USB_SERIAL_DCD 0x01
#define USB_SERIAL_DSR 0x02
#define USB_SERIAL_BREAK 0x04
#define USB_SERIAL_RI 0x08
#define USB_SERIAL_FRAME_ERR 0x10
#define USB_SERIAL_PARITY_ERR 0x20
#define USB_SERIAL_OVERRUN_ERR 0x40

#define EP_TYPE_CONTROL 0x00
#define EP_TYPE_BULK_IN 0x81
#define EP_TYPE_BULK_OUT 0x80
#define EP_TYPE_INTERRUPT_IN 0xC1
#define EP_TYPE_INTERRUPT_OUT 0xC0
#define EP_TYPE_ISOCHRONOUS_IN 0x41
#define EP_TYPE_ISOCHRONOUS_OUT 0x40

#define EP_SINGLE_BUFFER 0x02
#define EP_DOUBLE_BUFFER 0x06

#define MAX_ENDPOINT 4

#if defined(__AVR_AT90USB162__)
#define HW_CONFIG()
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
#define USB_CONFIG() (USBCON = (1<<USBE))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))

#elif defined(__AVR_ATmega32U4__)
#define HW_CONFIG() (UHWCON = 0x01)
#define PLL_CONFIG() (PLLCSR = 0x12)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))

#elif defined(__AVR_AT90USB646__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x1A)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))

#elif defined(__AVR_AT90USB1286__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x16)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#endif

// standard control endpoint request types
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11

// HID (human interface device)
#define HID_GET_REPORT 1
#define HID_GET_IDLE 2
#define HID_GET_PROTOCOL 3
#define HID_SET_REPORT 9
#define HID_SET_IDLE 10
#define HID_SET_PROTOCOL 11

// CDC (communication class device)
#define CDC_SET_LINE_CODING 0x20
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22



// ----- Endpoint Configuration -----

#define ENDPOINT0_SIZE 32

#define KEYBOARD_INTERFACE 0
#define KEYBOARD_ENDPOINT 2
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1
#define KEYBOARD_HID_BUFFER EP_DOUBLE_BUFFER

#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 1
#define CDC_DATA_INTERFACE 2
#define CDC_ACM_ENDPOINT 3
#define CDC_RX_ENDPOINT 4
#define CDC_TX_ENDPOINT 5
#if defined(__AVR_AT90USB162__)
#define CDC_ACM_SIZE 16
#define CDC_ACM_BUFFER EP_SINGLE_BUFFER
#define CDC_RX_SIZE 32
#define CDC_RX_BUFFER EP_DOUBLE_BUFFER
#define CDC_TX_SIZE 32
#define CDC_TX_BUFFER EP_DOUBLE_BUFFER
#else
#define CDC_ACM_SIZE 16
#define CDC_ACM_BUFFER EP_SINGLE_BUFFER
#define CDC_RX_SIZE 64
#define CDC_RX_BUFFER EP_DOUBLE_BUFFER
#define CDC_TX_SIZE 64
#define CDC_TX_BUFFER EP_DOUBLE_BUFFER
#endif

// Endpoint 0 is reserved for the control endpoint
// Endpoint 1 has a 256 byte buffer
// Endpoints 2-6 have 64 byte buffers
static const uint8_t PROGMEM endpoint_config_table[] = {
0, // 256 byte
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_HID_BUFFER, // 64 byte
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(CDC_ACM_SIZE) | CDC_ACM_BUFFER, // 64 byte
1, EP_TYPE_BULK_OUT, EP_SIZE(CDC_RX_SIZE) | CDC_RX_BUFFER, // 64 byte
1, EP_TYPE_BULK_IN, EP_SIZE(CDC_TX_SIZE) | CDC_TX_BUFFER, // 64 byte
};

#endif // usb_keyboard_serial_h__


+ 124
- 3
Output/pjrcUSB/output_com.c View File

@@ -25,11 +25,13 @@
#include <Lib/OutputLib.h>

// Project Includes
#include <cli.h>
#include <print.h>
#include <scan_loop.h>

// USB Includes
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
#include "avr/usb_keyboard_debug.h"
#include "avr/usb_keyboard_serial.h"
#elif defined(_mk20dx128_) || defined(_mk20dx256_)
#include "arm/usb_keyboard.h"
#include "arm/usb_dev.h"
@@ -40,8 +42,31 @@



// ----- Function Declarations -----

void cliFunc_holdKey ( char* args );
void cliFunc_readLEDs ( char* args );
void cliFunc_releaseKey( char* args );
void cliFunc_sendKey ( char* args );
void cliFunc_setLEDs ( char* args );
void cliFunc_setMod ( char* args );


// ----- Variables -----

// Output Module command dictionary
char* outputCLIDictName = "USB Module Commands";
CLIDictItem outputCLIDict[] = {
{ "holdKey", "Hold a space separated list of USB codes. Ignores already pressed keys.", cliFunc_holdKey },
{ "readLEDs", "Read LED byte. See setLEDs.", cliFunc_readLEDs },
{ "releaseKey", "Release a space separated list of USB codes. Ignores unpressed keys.", cliFunc_releaseKey },
{ "sendKey", "Send a space separated list of USB codes. Press/Release.", cliFunc_sendKey },
{ "setLEDs", "Set LED byte: 1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc.", cliFunc_setLEDs },
{ "setMod", "Set the modfier byte: 1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI", cliFunc_setMod },
{ 0, 0, 0 } // Null entry for dictionary end
};


// which modifier keys are currently pressed
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
@@ -69,7 +94,6 @@ volatile uint8_t USBKeys_LEDs = 0;
uint8_t USBKeys_Idle_Count = 0;



// ----- Functions -----

// USB Module Setup
@@ -81,9 +105,12 @@ inline void output_setup()
usb_init();
while ( !usb_configured() ) /* wait */ ;

// Register USB Output dictionary
registerDictionary_cli( outputCLIDict, outputCLIDictName );

// Wait an extra second for the PC's operating system to load drivers
// and do whatever it does to actually be ready for input
//_delay_ms(1000); // TODO
//_delay_ms(1000); // TODO (is this actually necessary?)
}


@@ -110,8 +137,102 @@ inline void output_send(void)
inline void output_firmwareReload()
{
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
usb_debug_reload();
#elif defined(_mk20dx128_) || defined(_mk20dx256_)
usb_device_reload();
#endif
}


// USB Input buffer available
inline unsigned int output_availablechar()
{
return usb_serial_available();
}


// USB Get Character from input buffer
inline int output_getchar()
{
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
// XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes)
return (int)usb_serial_getchar();
#elif defined(_mk20dx128_) || defined(_mk20dx256_)
return usb_serial_getchar();
#endif
}


// USB Send Character to output buffer
inline int output_putchar( char c )
{
return usb_serial_putchar( c );
}


// USB Send String to output buffer, null terminated
inline int output_putstr( char* str )
{
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
uint16_t count = 0;
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
uint32_t count = 0;
#endif
// Count characters until NULL character, then send the amount counted
while ( str[count] != '\0' )
count++;

return usb_serial_write( str, count );
}


// Soft Chip Reset
inline void output_softReset()
{
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
usb_debug_software_reset();
#elif defined(_mk20dx128_) || defined(_mk20dx256_)
SOFTWARE_RESET();
#endif
}


// ----- CLI Command Functions -----

void cliFunc_holdKey( char* args )
{
// TODO
}


void cliFunc_readLEDs( char* args )
{
// TODO
}


void cliFunc_releaseKey( char* args )
{
// TODO
}


void cliFunc_sendKey( char* args )
{
// TODO Argument handling
USBKeys_Array[0] = 4; // KEY_A
USBKeys_Sent = 1;
}


void cliFunc_setLEDs( char* args )
{
// TODO
}


void cliFunc_setMod( char* args )
{
// TODO
}


+ 8
- 1
Output/pjrcUSB/output_com.h View File

@@ -59,10 +59,17 @@ extern uint8_t USBKeys_Idle_Count;
// ----- Functions -----

void output_setup();

void output_send();

void output_firmwareReload();
void output_softReset();

// Relies on USB serial module
unsigned int output_availablechar();

int output_getchar();
int output_putchar( char c );
int output_putstr( char* str );

#endif


+ 1
- 1
Output/pjrcUSB/setup.cmake View File

@@ -17,7 +17,7 @@ if ( ${COMPILER_FAMILY} MATCHES "avr" )

set( OUTPUT_SRCS
output_com.c
avr/usb_keyboard_debug.c
avr/usb_keyboard_serial.c
)

#| ARM Compiler

+ 17
- 12
README View File

@@ -24,10 +24,12 @@ AVR Specific (Teensy 1.0/++,2.0/++) (try to use something recent, suggested vers
- avr-libc (1.8.0)


ARM Specific (Teensy 3.0) (Sourcery CodeBench Lite for ARM EABI
ARM Specific (Teensy 3.0/3.1) (Sourcery CodeBench Lite for ARM EABI
(http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/)
- arm-none-eabi
- TODO?
OR
- arm-none-eabi-gcc
- arm-none-eaby-binutils



@@ -42,6 +44,7 @@ The options are:
- Teensy 2.0
- Teensy 2.0++
- Teensy 3.0
- Teensy 3.1

Open up CMakeLists.txt in your favourite text editor.
You are looking for:
@@ -57,13 +60,14 @@ You are looking for:
#| "avr" # Teensy++ 1.0
#| "avr" # Teensy++ 2.0
#| "arm" # Teensy 3.0
#| "arm" # Teensy 3.1

set( COMPILER_FAMILY "avr" )


Just change the COMPILER_FAMILY variable to whatever you are trying to build for.

NOTE: If you change this option, you will *may* to delete the build directory that is created in the Building sections below.
NOTE: If you change this option, you will *may* to delete the build directory that is created in the Building sections below.



@@ -102,6 +106,7 @@ You are looking for:
#| type "make clean" after changing this, so all files will be rebuilt
#|
#| "mk20dx128" # Teensy 3.0
#| "mk20dx256" # Teensy 3.1

set( CHIP "mk20dx128" )

@@ -123,7 +128,7 @@ The Kiibohd Controller is designed around a set of 4 types of modules that corre

- Scan Module
- Macro Module
- USB Module
- Output Module
- Debug Module

The Scan Module is where the most interesting stuff happens. These modules take in "keypress data".
@@ -135,11 +140,11 @@ Each Scan Module has it's own default keymap/modifier map. (TODO recommend keyma
Some scan modules have very specialized hardware requirements, each module directory should have at least a link to the needed parts and/or schematics (TODO!).


The Macro Module takes care of the mapping of the key press/release code into a USB scan code.
The Macro Module takes care of the mapping of the key press/release code into an Output (USB) scan code.
Any layering, macros, keypress intelligence/reaction is done here.


The USB Module is the output module of the microcontroller. Currently USB is the only output protocol.
The Output Module is the module dealing with output from the microcontroller. Currently USB is the only output protocol.
Different USB output implementations are available, pjrc being the safest/least featureful one.
Debug capabilities may depend on the module selected.

@@ -161,7 +166,7 @@ Look for:
#| All of the modules must be specified, as they generate the sources list of files to compile
#| Any modifications to this file will cause a complete rebuild of the project

#| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones
#| Please look at the {Scan,Macro,Output,Debug}/module.txt for information on the modules and how to create new ones

##| Deals with acquiring the keypress information and turning it into a key index
set( ScanModule "avr-capsense" )
@@ -170,7 +175,7 @@ Look for:
set( MacroModule "buffer" )

##| Sends the current list of usb key codes through USB HID
set( USBModule "pjrc" )
set( OutputModule "pjrc" )

##| Debugging source to use, each module has it's own set of defines that it sets
set( DebugModule "full" )
@@ -206,8 +211,8 @@ Example output:
Scan/avr-capsense/scan_loop.c
-- Detected Macro Module Source Files:
Macro/buffer/macro.c
-- Detected USB Module Source Files:
USB/pjrc/usb_com.c;USB/pjrc/avr/usb_keyboard_debug.c
-- Detected Output Module Source Files:
Output/pjrc/usb_com.c;Output/pjrc/avr/usb_keyboard_debug.c
-- Detected Debug Module Source Files:
Debug/full/../led/led.c;Debug/full/../print/print.c
-- Configuring done
@@ -218,8 +223,8 @@ Example output:
[ 12%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o
[ 25%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/avr-capsense/scan_loop.c.o
[ 37%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/buffer/macro.c.o
[ 50%] Building C object CMakeFiles/kiibohd.elf.dir/USB/pjrc/usb_com.c.o
[ 62%] Building C object CMakeFiles/kiibohd.elf.dir/USB/pjrc/avr/usb_keyboard_debug.c.o
[ 50%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/usb_com.c.o
[ 62%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/avr/usb_keyboard_debug.c.o
[ 75%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.o
[ 87%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.o
Linking C executable kiibohd.elf

Scan/avr-capsense/scan_loop.c → Scan/DPH/scan_loop.c View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2011-2013 by Joseph Makuch
* Additions by Jacob Alexander (2013)
* 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

Scan/avr-capsense/scan_loop.h → Scan/DPH/scan_loop.h View File


Scan/avr-capsense/setup.cmake → Scan/DPH/setup.cmake View File

@@ -1,6 +1,6 @@
###| CMake Kiibohd Controller Scan Module |###
#
# Written by Jacob Alexander in 2013 for the Kiibohd Controller
# Written by Jacob Alexander in 2013-2014 for the Kiibohd Controller
#
# Released into the Public Domain
#

+ 1
- 1
Scan/SKM67001/setup.cmake View File

@@ -24,7 +24,7 @@ set( SCAN_SRCS
add_definitions( -I${HEAD_DIR}/Keymap )
add_definitions(
-I${HEAD_DIR}/Scan/matrix
)
)

#| Keymap Settings
add_definitions(

+ 4
- 4
Scan/matrix/matrix_scan.c View File

@@ -1,15 +1,15 @@
/* Copyright (C) 2011 by Jacob Alexander
*
/* Copyright (C) 2011,2014 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ 4
- 4
Scan/matrix/matrix_scan.h View File

@@ -1,15 +1,15 @@
/* Copyright (C) 2011 by Jacob Alexander
*
/* Copyright (C) 2011,2014 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ 5
- 5
Scan/matrix/matrix_template.h View File

@@ -1,15 +1,15 @@
/* Copyright (C) 2011 by Jacob Alexander
*
/* Copyright (C) 2011,2014 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -69,7 +69,7 @@ static const uint8_t matrix_pinout[][MAX_ROW_SIZE + 1] = {
// Just layout the matrix by rows and columns
// Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol
// The mode allows for optimization in the kind of scanning algorithms that are done
//
//
// The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0).
// Thus if a row doesn't use all the key positions, you can denote it as 0, which will be ignored/skipped on each scan
// See the keymap.h file for the various preconfigured arrays.

+ 4
- 4
Scan/matrix/scan_loop.c View File

@@ -1,15 +1,15 @@
/* Copyright (C) 2011-2012 by Jacob Alexander
*
/* Copyright (C) 2011-2012,2014 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ 4
- 4
Scan/matrix/scan_loop.h View File

@@ -1,15 +1,15 @@
/* Copyright (C) 2011-2012 by Jacob Alexander
*
/* Copyright (C) 2011-2012,2014 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

+ 14
- 5
avr.cmake View File

@@ -1,6 +1,6 @@
###| CMAKE Kiibohd Controller |###
#
# Jacob Alexander 2011-2013
# Jacob Alexander 2011-2014
# Due to this file's usefulness:
#
# Released into the Public Domain
@@ -37,8 +37,8 @@ set( SIZE "avr-size" )
#| "atmega32u4" # Teensy 2.0
#| "at90usb646" # Teensy++ 1.0
#| "at90usb1286" # Teensy++ 2.0
#set( MCU "atmega32u4" )
set( MCU "at90usb1286" )
set( MCU "atmega32u4" )
#set( MCU "at90usb1286" )

message( STATUS "MCU Selected:" )
message( "${MCU}" )
@@ -51,6 +51,15 @@ set( COMPILER_SRCS
)


#| CPU Type
#| This is only informational for AVR microcontrollers
#| The field can be determined by the microcontroller chip, but currently only one CPU type is used atm
set( CPU "megaAVR" )

message( STATUS "CPU Selected:" )
message( "${CPU}" )


#| USB Defines
set( VENDOR_ID "0x16C0" )
set( PRODUCT_ID "0x047D" )
@@ -66,7 +75,7 @@ set( CSTANDARD "-std=gnu99" )

#| Warning Options
#| -Wall...: warning level
set( WARN "-Wall -Wstrict-prototypes" )
set( WARN "-Wall" )


#| Tuning Options
@@ -75,7 +84,7 @@ set( WARN "-Wall -Wstrict-prototypes" )
set( TUNING "-funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums" )


#| Optimization level, can be [0, 1, 2, 3, s].
#| Optimization level, can be [0, 1, 2, 3, s].
#| 0 = turn off optimization. s = optimize for size.
#| (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
set( OPT "s" )

+ 22
- 36
main.c View File

@@ -139,57 +139,43 @@ int main(void)
{
// Configuring Pins
pinSetup();
init_errorLED();

// Setup Output Module
output_setup();

// Enable CLI
init_cli();

// Setup Output Module
output_setup();

// Setup ISR Timer for flagging a kepress send to USB
usbTimerSetup();

// Setup the scanning module
//scan_setup();

// Main Detection Loop
uint8_t ledTimer = F_CPU / 1000000; // Enable LED for a short time
while ( 1 )
{
// Setup the scanning module
scan_setup();

while ( 1 )
{
// Acquire Key Indices
// Loop continuously until scan_loop returns 0
cli();
while ( scan_loop() );
sei();

// Run Macros over Key Indices and convert to USB Keys
process_macros();

// Send keypresses over USB if the ISR has signalled that it's time
if ( !sendKeypresses )
continue;

// Send USB Data
output_send();
// Process CLI
process_cli();

// Clear sendKeypresses Flag
sendKeypresses = 0;
// Acquire Key Indices
// Loop continuously until scan_loop returns 0
cli();
//while ( scan_loop() );
sei();

// Indicate Error, if valid
errorLED( ledTimer );
// Run Macros over Key Indices and convert to USB Keys
process_macros();

if ( ledTimer > 0 )
ledTimer--;
}
// Send keypresses over USB if the ISR has signalled that it's time
if ( !sendKeypresses )
continue;

// Loop should never get here (indicate error)
ledTimer = 255;
// Send USB Data
output_send();

// HID Debug Error message
erro_print("Detection loop error, this is very bad...bug report!");
// Clear sendKeypresses Flag
sendKeypresses = 0;
}
}


+ 1
- 1
setup.cmake View File

@@ -20,7 +20,7 @@
#| Please look at the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones

##| Deals with acquiring the keypress information and turning it into a key index
set( ScanModule "MBC-55X" )
set( ScanModule "SKM67001" )

##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code
set( MacroModule "buffer" )