(intermediate checkin: working on new usb code)

(plus a few small aesthetic things in /src/keyboard.  i changed some
function like macros to lower-case, because someday they might be
implemented as real functions... and there's no real reason to
distinguish between functions and function like macros in the main() and
other higher level code.  at least that's what it seems like to me right
now.)
partial-rewrite
Ben Blazak 2012-05-06 18:36:51 -07:00
parent 5c2f6e64f4
commit 1acaaaf5ff
11 changed files with 452 additions and 32 deletions

View File

@ -7,8 +7,8 @@
* ------------------------------------------------------------------------- */
#ifndef _DEFAULTS_h
#define _DEFAULTS_h
#ifndef LAYOUT__DEFAULTS_h
#define LAYOUT__DEFAULTS_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

View File

@ -7,5 +7,11 @@
* ------------------------------------------------------------------------- */
#define KB_LAYERS 1 // must match what's defined in the layout '.c' file
#ifndef LAYOUT_QWERTY_h
#define LAYOUT_QWERTY_h
#define KB_LAYERS 1 // must match what's defined in the layout '.c'
// file
#endif

View File

@ -124,9 +124,9 @@ uint8_t teensy_init(void) {
TCCR1A = 0b10101001; // set and configure fast PWM
TCCR1B = 0b00001001; // set and configure fast PWM
KB_LED1_SET_PERCENT(0.5); KB_LED1_OFF;
KB_LED2_SET_PERCENT(0.5); KB_LED2_OFF;
KB_LED3_SET_PERCENT(0.5); KB_LED3_OFF;
kb_led1_set_percent(0.5); kb_led1_off();
kb_led2_set_percent(0.5); kb_led2_off();
kb_led3_set_percent(0.5); kb_led3_off();
// I2C (TWI)
twi_init(); // on pins D(1,0)

View File

@ -16,18 +16,18 @@
#include "matrix.h"
// LED control
#define KB_LED1_ON (DDRB |= (1<<5))
#define KB_LED1_OFF (DDRB &= ~(1<<5))
#define KB_LED1_SET(n) (OCR1A = (uint8_t)(n))
#define KB_LED1_SET_PERCENT(n) (OCR1A = (uint8_t)((n) * 0xFF))
#define KB_LED2_ON (DDRB |= (1<<6))
#define KB_LED2_OFF (DDRB &= ~(1<<6))
#define KB_LED2_SET(n) (OCR1B = (uint8_t)(n))
#define KB_LED2_SET_PERCENT(n) (OCR1B = (uint8_t)((n) * 0xFF))
#define KB_LED3_ON (DDRB |= (1<<7))
#define KB_LED3_OFF (DDRB &= ~(1<<7))
#define KB_LED3_SET(n) (OCR1C = (uint8_t)(n))
#define KB_LED3_SET_PERCENT(n) (OCR1C = (uint8_t)((n) * 0xFF))
#define kb_led1_on() (DDRB |= (1<<5))
#define kb_led1_off() (DDRB &= ~(1<<5))
#define kb_led1_set(n) (OCR1A = (uint8_t)(n))
#define kb_led1_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
#define kb_led2_on() (DDRB |= (1<<6))
#define kb_led2_off() (DDRB &= ~(1<<6))
#define kb_led2_set(n) (OCR1B = (uint8_t)(n))
#define kb_led2_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
#define kb_led3_on() (DDRB |= (1<<7))
#define kb_led3_off() (DDRB &= ~(1<<7))
#define kb_led3_set(n) (OCR1C = (uint8_t)(n))
#define kb_led3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
#ifdef KEYBOARD_INCLUDE_PRIVATE

View File

@ -350,7 +350,7 @@ int8_t usb_keyboard_send(void)
ISR(USB_GEN_vect)
{
uint8_t intbits, i; // used to declare a variable `t` as well, but it
// wasn't used ::Blazak, 2012::
// wasn't used ::Ben Blazak, 2012::
static uint8_t div4=0;
intbits = UDINT;

View File

@ -0,0 +1,336 @@
/* ----------------------------------------------------------------------------
* Common data structures, macros, and other definitions from the USB spec and
* related documents
*
* - The following document versions were used, unless otherwise noted:
* - USB Specification: revision 2.0
* - HID Usage Tables: version 1.12
* - Device Class Definition for Human Interface Devices (HID): version 1.11
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef USB_DATA_STRUCTURES_h
#define USB_DATA_STRUCTURES_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include "lib/data-types.h"
// - spec sec 9.3 (USB Device Requests)
// - table 9-2 (Format of Setup Data)
struct usb_setup_data {
uint8_t bmRequestType;
// value: bitmap
// - data transfer direction, type, recipient
// (see macros below)
uint8_t bRequest;
// value: value
// - type of request (depending on bmRequestType)
// (see spec table 9-3 (Standard Device Requests))
uint16_t wValue;
// value: value
// - varies according to request; used to pass a request specific
// parameter to the device
uint16_t wIndex;
// value: index or offset
// - varies according to request; often used to specify an endpoint or
// an interface
// (see spec figure 9-2 and 9-3, copied below)
uint16_t wLength;
// value: count
// - number of bytes to transfer if there is a data stage
};
// - table 9-2 (Format of Setup Data)
// - bmRequestType
// --- data transfer direction
#define usb_bmRequestType_hostToDevice(val) (((val) & 0x80) == 0x00)
#define usb_bmRequestType_deviceToHost(val) (((val) & 0x80) == 0x80)
// --- type
#define usb_bmRequestType_standard(val) (((val) & 0x60) == 0x00)
#define usb_bmRequestType_class(val) (((val) & 0x60) == 0x20)
#define usb_bmRequestType_vendor(val) (((val) & 0x60) == 0x40)
#define usb_bmRequestType_reserved(val) (((val) & 0x60) == 0x60)
// --- recipient
#define usb_bmRequestType_device(val) (((val) & 0x1F) == 0x00)
#define usb_bmRequestType_interface(val) (((val) & 0x1F) == 0x01)
#define usb_bmRequestType_endpoint(val) (((val) & 0x1F) == 0x02)
#define usb_bmRequestType_other(val) (((val) & 0x1F) == 0x03)
#define usb_bmRequestType_reserved(val) (((val) & 0x1C) != 0x00)
// - spec sec 9.3.4 (wIndex)
// - figure 9-2 (format when specifying an endpoint)
// .-------------------------------------------------------.
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
// |-------------------------------------------------------|
// | direction | reserved (reset to 0) | endpoint number |
// >-----------------------------------------------------<
// | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
// |-------------------------------------------------------|
// | reserved (reset to 0) |
// '-------------------------------------------------------'
// - direction bit: 0 => out (to device), 1 => in (to host)
#define usb_wIndex_endpoint(direction, endpoint_number) \
( (uint16_t) (((direction) << 7) | (endpoint_number)) )
// - spec sec 9.3.4 (wIndex)
// - figure 9-3 (format when specifying an interface)
// .-------------------------------------------------------.
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
// |-------------------------------------------------------|
// | interface number |
// >-----------------------------------------------------<
// | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
// |-------------------------------------------------------|
// | reserved (reset to 0) |
// '-------------------------------------------------------'
#define usb_wIndex_interface(interface_number) \
( (uint16_t) (interface_number) )
// - spec table 9-4 (Standard Request Codes)
#define USB_GET_STATUS 0
#define USB_CLEAR FEATURE 1
// (reserved for future use): 2
#define USB_SET_FEATURE 3
// (reserved for future use): 4
#define USB_SET_ADDRESS 5
#define USB_GET_DESCRIPTOR 6
#define USB_SET_DESCRIPTOR 7
#define USB_GET_CONFIGURATION 8
#define USB_SET_CONFIGURATION 9
#define USB_GET_INTERFACE 10
#define USB_SET_INTERFACE 11
#define USB_SYNCH_FRAME 12
// - spec table 9-5 (Descriptor Types)
#define USB_DEVICE 1
#define USB_CONFIGURATION 2
#define USB_STRING 3
#define USB_INTERFACE 4
#define USB_ENDPOINT 5
#define USB_DEVICE_QUALIFIER 6
#define USB_OTHER_SPEED_CONFIGURATION 7
#define USB_INTERFACE_POWER 8
// - spec table 9-6 (Standard Feature Selectors)
#define USB_DEVICE_REMOTE_WAKEUP 1 // recipient: device
#define USB_ENDPOINT_HALT 0 // recipient: endpoint
#define USB_TEST_MODE 2 // recipient: device
// - spec sec 9.4.5 (Standard Device Requests / Get Status)
// - figure 9-4 (information returned by a GetStatus() request to a device)
// .------------------------------------------------------------.
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
// |------------------------------------------------------------|
// | reserved (reset to 0) | remote wakeup | self powered |
// >----------------------------------------------------------<
// | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
// |------------------------------------------------------------|
// | reserved (reset to 0) |
// '------------------------------------------------------------'
// - remote wakeup bit: 0 => ability of device to signal remote wakeup disabled
// (default)
// 1 => ability ................................. enabled
// - self powered bit: 0 => device is bus powered, 1=> device is self powered
#define usb_getStatus_device(remote_wakeup, self_powered) \
( (uint16_t) (((remote_wakeup) << 1) | (self_powered)) )
// - spec sec 9.4.5 (Standard Device Requests / Get Status)
// - figure 9-5 (information returned by a GetStatus() request to an
// interface)
// .------------------------------------------------------------.
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
// |------------------------------------------------------------|
// | reserved (reset to 0) |
// >----------------------------------------------------------<
// | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
// |------------------------------------------------------------|
// | reserved (reset to 0) |
// '------------------------------------------------------------'
#define usb_getStatus_interface() ( (uint16_t) 0 )
// - spec sec 9.4.5 (Standard Device Requests / Get Status)
// - figure 9-6 (information returned by a GetStatus() request to an
// endpoint)
// .------------------------------------------------------------.
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
// |------------------------------------------------------------|
// | reserved (reset to 0) | halt |
// >----------------------------------------------------------<
// | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
// |------------------------------------------------------------|
// | reserved (reset to 0) |
// '------------------------------------------------------------'
// - halt bit: 0 => endpoint not currently halted
// 1 => endpoint currently halted
#define usb_getStatus_endpoint(halt) ( (uint16_t) (halt) )
// - spec sec 9.4.9 (Set Feature)
// - table 9-7 (Test Mode Selectors)
// - in the case of a SetFeature(TEST_MODE...):
// - the most significant byte of wIndex is used to specify the test mode
// - the lower byte of wIndex must be zero, because the recipient must be the
// device
// (reserved): (0x0000)
#define USB_TEST_MODE_wIndex_Test_J (0x0100)
#define USB_TEST_MODE_wIndex_Test_K (0x0200)
#define USB_TEST_MODE_wIndex_Test_SE0_NAK (0x0300)
#define USB_TEST_MODE_wIndex_Test_Packet (0x0400)
#define USB_TEST_MODE_wIndex_Test_Force_Enable (0x0500)
// (reserved for standard test selectors): (0x0600)..(0x3F00)
// (reserved): (0x3F00)..(0xBF00)
// (reserved for vendor-specific test modes): (0xC000)..(0xFF00)
// - spec sec 9.6.1 (Standard USB Descriptor Definitions / Device)
// - table 9-8 (Standard Device Descriptor)
struct usb_standard_device_descriptor {
uint8_t bLength;
// value: number
// - size of this descriptor in bytes
uint8_t bDescriptorType;
// value: constant
// - DEVICE Descriptor Type
// - a high speed capable device will set this to 2.0 (0x0200). if the
// device is full-speed or low-speed only, this version number only
// means that it'll send a request error when asked for the
// device_qualifier descriptor
uint16_t bcdUSB;
// value: BCD (binary coded decimal)
// - usb spec release number
// - format: 0xJJMN, where JJ = major version, M = minor version,
// N = sub-minor version; e.g. version 2.1.3 => 0x0213
uint8_t bDeviceClass;
// value: class
// - class code (assigned by the USB-IF)
// - 0x00 => each interface within a configuration specifies its own
// class information and the various interfaces operate independently
// - 0x01..0xFE => the device supports different class specifications
// on different interfaces and the interfaces may not operate
// independently. this value identifies the class definition used
// for the aggregate interfaces
// - 0xFF => the device class is vendor-specific
uint8_t bDeviceSubClass;
// value: subclass
// - subclass code (assigned by the USB-IF)
// - qualified by bDeviceClass
// - if bDeviceClass is reset to 0, this field must be also
// - if bDeviceClass != 0xFF , all values are reserved for assignment
// by the USB-IF
uint8_t bDeviceProtocol;
// value: protocol
// - protocol code (assigned by the USB-IF)
// - qualified by bDeviceClass and bDeviceSubClass
// - if a device supports class-specific protocols on a device basis as
// opposed to an interface basis, this code identifies the protocols
// that the device uses as defined by the specification of the device
// class
// - 0x00 => the device does not use class-specific protocols on a
// device basis. however, it may use class-specific protocols on an
// interface basis
// - 0xFF => the device uses a vendor-specific protocol on a device
// basis
uint8_t bMaxPacketSize0;
// value: number
// - max packet size for endpoint 0
// - only 8, 16, 32, or 64 are valid
// - if operating at high-speed, the value must be 64
uint16_t idVendor;
// value: id
// - vendor ID (assigned by the USB-IF)
uint16_t idProduct;
// value: id
// - product ID (assigned by the manufacturer)
uint16_t bcdDevice;
// value: BCD (binary coded decimal)
// - device release number
uint8_t iManufacturer;
// value: index
// - index of string descriptor describing manufacturer
uint8_t iProduct;
// value: index
// - index of string descriptor describing product
uint8_t iSerialNumber;
// value: index
// - index of string descriptor describing the device's serial number
uint8_t bNumConfigurations;
// value: number
// - number of possible configurations (at the current operating speed)
};
// - spec sec 9.6.2 (Standard USB Descriptor Definitions / Device_Qualifier)
// - table 9-9 (Device_Qualifier Descriptor)
// - required if the device has different device information for full-speed and
// high-speed
// - not valid for a full-speed only device (with a device descriptor version
// number equal to 0x0200); if requested, the device must respond with a
// request error
struct usb_device_qualifier_descriptor {
uint8_t bLength;
// value: number
// - size of descriptor
uint8_t bDescriptorType;
// value: constant
// - device qualifier type
uint16_t bcdUSB;
// value: BCD (binary coded decimal)
// - usb spec release number
// - format: (see note for usb_standard_device_descriptor.bcdUSB)
// - must be at least 2.0 (0x0200) for this descriptor
uint8_t bDeviceClass;
// value: class
uint8_t bDeviceSubClass;
// value: subclass
uint8_t bDeviceProtocol;
// value: protocol
uint8_t bMaxPacketSize0;
// value: number
// - max packet size for other speed
uint8_t bNumConfigurations;
// value: number
// - number of other-speed configurations
uint8_t bReserved;
// value: 0
// - reserved for future use
};
// - spec sec 9.6.4 (Standard USB Descriptor Definitions /
// Other_Speed_Configuration)
// - table 9-10 (Standard Configuration Descriptor)
// TODO
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

44
src/lib/usb/TODO.c Normal file
View File

@ -0,0 +1,44 @@
/* ----------------------------------------------------------------------------
* TODO: not sure where this stuff should be yet. a lot of it (depending on
* what ends up here) will likely be device and application specific.
*
* - The following document versions were used, unless otherwise noted:
* - USB Specification: revision 2.0
* - HID Usage Tables: version 1.12
* - Device Class Definition for Human Interface Devices (HID): version 1.11
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
// TODO: does stuff from spec sec 9.4.* belong directly in an interrupt vector?
// - spec sec 9.4.1 (Standard Device Requests / Clear Feature) (pg 252)
// - spec sec 9.4.2 (Standard Device Requests / Get Configuration) (pg 253)
// - spec sec 9.4.3 (Standard Device Requests / Get Descriptor) (pg 253)
// - spec sec 9.4.4 (Standard Device Requests / Get Interface) (pg 254)
// - spec sec 9.4.5 (Standard Device Requests / Get Status) (pg 254)
// - spec sec 9.4.6 (Standard Device Requests / Set Address) (pg 256)
// - spec sec 9.4.7 (Standard Device Requests / Set Configuration) (pg 257)
// - spec sec 9.4.8 (Standard Device Requests / Set Descriptor) (pg 257)
// - spec sec 9.4.9 (Standard Device Requests / Set Feature) (pg 258)
// - spec sec 9.4.10 (Standard Device Requests / Set Interface) (pg 259)
// - spec sec 9.4.11 (Standard Device Requests / Synch Frame) (pg 260)
// TODO
// - read the hid usage tables .pdf
// - read the hid device class definition .pdf
// - add a note about the variable prefixes (w, b, bcd, ...)

View File

@ -11,6 +11,12 @@
* ------------------------------------------------------------------------- */
#ifndef USB_KEYBOARD_USAGE_PAGE_SHORT_NAMES_h
#define USB_KEYBOARD_USAGE_PAGE_SHORT_NAMES_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include "keyboard-usage-page.h"
@ -298,3 +304,8 @@
#define _memMul_kp KEYPAD_MemoryMultiply
#define _memDiv_kp KEYPAD_MemoryDivide
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -21,6 +21,12 @@
* ------------------------------------------------------------------------- */
#ifndef USB_KEYBOARD_USAGE_PAGE_h
#define USB_KEYBOARD_USAGE_PAGE_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Name ID // PC Mac Unix Boot Keyboard Req.
// --------------------------- ---- -- --- ---- ---------------------
@ -262,3 +268,8 @@
// (Reserved) 0xE8..0xFFFF // - - - -
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -20,6 +20,12 @@
* ------------------------------------------------------------------------- */
#ifndef USB_LED_USAGE_PAGE_h
#define USB_LED_USAGE_PAGE_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Name ID Usage Type Section of HID Tables
// --------------------------- ---- ---------- ----------------------
@ -104,3 +110,9 @@
#define LED_ExternalPowerConnected 0x4D // OOC 11.6
// (Reserved) 0x4E..0xFFFF // - -
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -18,7 +18,7 @@
// note:
// - see your keyswitch specification for the necessary value. for cherry mx
// switches, bounce time should be <= 5ms. it looks like most switches are
// speced between 5 and 8ms.
// speced between 5 and 8 ms.
// - if timing is important, balance this value with the main() loop run time
// (~5ms, last i checked, nearly all of it in the i2c update() function)
#define DEBOUNCE_TIME 5 // in ms
@ -27,17 +27,17 @@
int main(void) {
kb_init(); // does controller initialization too
KB_LED1_ON;
KB_LED2_ON;
KB_LED3_ON;
kb_led1_on();
kb_led2_on();
kb_led3_on();
usb_init();
while (!usb_configured());
_delay_ms(1000); // make sure the OS has had time to load drivers, etc.
KB_LED1_OFF;
KB_LED2_OFF;
KB_LED3_OFF;
kb_led1_off();
kb_led2_off();
kb_led3_off();
for (;;) {
static uint8_t current_layer = 0;
@ -52,7 +52,7 @@ int main(void) {
// call the appropriate function for each key, then send the usb report
// if necessary
// - everything else is the key function's responsibility; see the
// keyboard layout file ("keyboard/ergodox/layout.c") for which key
// keyboard layout file ("keyboard/ergodox/layout/*.c") for which key
// is assigned which function (per layer), and "lib/key-functions.c"
// for their definitions
for (uint8_t row=0; row<KB_ROWS; row++) {
@ -85,12 +85,12 @@ int main(void) {
}
// update LEDs
(keyboard_leds & (1<<0)) ? KB_LED1_ON : KB_LED1_OFF; // num lock
(keyboard_leds & (1<<1)) ? KB_LED2_ON : KB_LED2_OFF; // caps lock
(keyboard_leds & (1<<2)) ? KB_LED3_ON : KB_LED3_OFF; // scroll lock
(keyboard_leds & (1<<0)) ? kb_led1_on() : kb_led1_off(); // num lock
(keyboard_leds & (1<<1)) ? kb_led2_on() : kb_led2_off(); // caps lock
(keyboard_leds & (1<<2)) ? kb_led3_on() : kb_led3_off(); // scroll lock
#if 0 // not implemented right now
(keyboard_leds & (1<<3)) ? KB_LED4_ON : KB_LED4_OFF; // compose
(keyboard_leds & (1<<4)) ? KB_LED5_ON : KB_LED5_OFF; // kana
(keyboard_leds & (1<<3)) ? kb_led4_on() : kb_led4_off(); // compose
(keyboard_leds & (1<<4)) ? kb_led5_on() : kb_led5_off(); // kana
#endif
}