Fixed clock rates - 1.2ms latency instead of 20ms

This commit is contained in:
William Toohey
2015-11-13 14:14:32 +10:00
parent afccdbe05a
commit 1da318adfd
3 changed files with 166 additions and 108 deletions

View File

@@ -37,30 +37,36 @@
#include "Keyboard.h"
#include "i2cmaster.h"
#define LED_DIR DDRD
#define LED_PORT PORTD
#define DON_LED_PIN 6
#define KAT_LED_PIN 5
#define SET(port, pin) port |= _BV(pin)
#define CLEAR(port, pin) port &= ~_BV(pin)
/** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */
static uint8_t PrevKeyboardHIDReportBuffer[sizeof(USB_KeyboardReport_Data_t)];
void (* BootReset) (void) = 0x0800;
/** LUFA HID Class driver interface configuration and state information. This structure is
* passed to all HID Class driver functions, so that multiple instances of the same class
* within a device can be differentiated from one another.
*/
USB_ClassInfo_HID_Device_t Keyboard_HID_Interface =
{
.Config =
{
.InterfaceNumber = INTERFACE_ID_Keyboard,
.ReportINEndpoint =
{
.Address = KEYBOARD_EPADDR,
.Size = KEYBOARD_EPSIZE,
.Banks = 1,
},
.PrevReportINBuffer = PrevKeyboardHIDReportBuffer,
.PrevReportINBufferSize = sizeof(PrevKeyboardHIDReportBuffer),
},
};
{
.Config =
{
.InterfaceNumber = INTERFACE_ID_Keyboard,
.ReportINEndpoint =
{
.Address = KEYBOARD_EPADDR,
.Size = KEYBOARD_EPSIZE,
.Banks = 1,
},
.PrevReportINBuffer = PrevKeyboardHIDReportBuffer,
.PrevReportINBufferSize = sizeof(PrevKeyboardHIDReportBuffer),
},
};
typedef struct {
@@ -76,35 +82,56 @@ static const uint8_t switch_mapping[] = {HID_KEYBOARD_SC_X,
HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN,
HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK };
static uint8_t switchesChanged = 1;
static uint8_t nunchuckReady = 0;
//todo: neater
#define NUNCHUCK_ADDR 0xA4 // 0x52 << 1
#define NUNCHUCK_ADDR (0x52 << 1)
void Nunchuck_back(void) {
nunchuckReady = 1;
// Turn LEDs on until it returns
CLEAR(LED_PORT, DON_LED_PIN);
CLEAR(LED_PORT, KAT_LED_PIN);
}
void Nunchuck_gone(void) {
nunchuckReady = 0;
// Turn LEDs on until it returns
SET(LED_PORT, DON_LED_PIN);
SET(LED_PORT, KAT_LED_PIN);
}
void Nunchuck_Init(void) {
i2c_init();
// say hello
i2c_start(NUNCHUCK_ADDR + I2C_WRITE);
i2c_write(0xF0);
i2c_write(0x55);
i2c_stop();
i2c_start(NUNCHUCK_ADDR + I2C_WRITE);
i2c_write(0xFB);
i2c_write(0x00);
i2c_stop();
// try to say hello
if(!i2c_start(NUNCHUCK_ADDR | I2C_WRITE)) {
i2c_write(0xF0);
i2c_write(0x55);
i2c_stop();
i2c_start(NUNCHUCK_ADDR | I2C_WRITE);
i2c_write(0xFB);
i2c_write(0x00);
i2c_stop();
Nunchuck_back();
} else {
Nunchuck_gone();
}
}
uint8_t Nunchuck_ReadByte(uint8_t address) {
uint8_t data;
uint8_t data = 0xFF;
if(!nunchuckReady) {
Nunchuck_Init();
}
i2c_start(NUNCHUCK_ADDR + I2C_WRITE);
i2c_write(0x05);
i2c_stop();
//i2c_start(NUNCHUCK_ADDR);
i2c_start(NUNCHUCK_ADDR + I2C_READ);
data = i2c_readNak();
i2c_stop();
if(!i2c_start(NUNCHUCK_ADDR | I2C_WRITE)) {
i2c_write(0x05);
i2c_stop();
i2c_start(NUNCHUCK_ADDR | I2C_READ);
data = i2c_readNak();
i2c_stop();
} else {
Nunchuck_gone();
}
return data;
}
@@ -144,7 +171,6 @@ int main(void)
{
HID_Device_USBTask(&Keyboard_HID_Interface);
USB_USBTask();
update_switches();
}
}
@@ -156,10 +182,81 @@ void SetupHardware()
wdt_disable();
/* Hardware Initialization */
SET(LED_DIR, DON_LED_PIN);
SET(LED_DIR, KAT_LED_PIN);
// Turn them on until we init with the nunchuck
SET(LED_PORT, DON_LED_PIN);
SET(LED_PORT, KAT_LED_PIN);
i2c_init();
Nunchuck_Init();
USB_Init();
}
/** HID class driver callback function for the creation of HID reports to the host.
*
* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
* \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
* \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
* \param[out] ReportData Pointer to a buffer where the created report should be stored
* \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent)
*
* \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
*/
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
uint8_t* const ReportID,
const uint8_t ReportType,
void* ReportData,
uint16_t* const ReportSize)
{
uint8_t i;
USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;
update_switches();
if(!switchesChanged) {
return false;
}
CLEAR(LED_PORT, DON_LED_PIN);
CLEAR(LED_PORT, KAT_LED_PIN);
for(i = 0; i < 4; i++) {
KeyboardReport->KeyCode[i] = switches[i].state ? switch_mapping[i] : 0;
switches[i].lastReport = switches[i].state;
// Update blinkenlights
if(switches[i].state) {
if(i % 2) { // odd indexes are kat, even don
SET(LED_PORT, KAT_LED_PIN);
} else {
SET(LED_PORT, DON_LED_PIN);
}
}
}
*ReportSize = sizeof(USB_KeyboardReport_Data_t);
switchesChanged = 0;
return true;
}
/** HID class driver callback function for the processing of HID reports from the host.
*
* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
* \param[in] ReportID Report ID of the received report from the host
* \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
* \param[in] ReportData Pointer to a buffer where the received report has been stored
* \param[in] ReportSize Size in bytes of the received HID report
*/
void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
const uint8_t ReportID,
const uint8_t ReportType,
const void* ReportData,
const uint16_t ReportSize)
{
}
/** Event handler for the library USB Connection event. */
void EVENT_USB_Device_Connect(void)
{
@@ -192,68 +289,4 @@ void EVENT_USB_Device_ControlRequest(void)
void EVENT_USB_Device_StartOfFrame(void)
{
HID_Device_MillisecondElapsed(&Keyboard_HID_Interface);
}
/** HID class driver callback function for the creation of HID reports to the host.
*
* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
* \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
* \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
* \param[out] ReportData Pointer to a buffer where the created report should be stored
* \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent)
*
* \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
*/
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
uint8_t* const ReportID,
const uint8_t ReportType,
void* ReportData,
uint16_t* const ReportSize)
{
uint8_t i;
USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData;
if(!switchesChanged) {
return false;
}
for(i = 0; i < 4; i++) {
KeyboardReport->KeyCode[i] = switches[i].state ? switch_mapping[i] : 0;
switches[i].lastReport = switches[i].state;
}
*ReportSize = sizeof(USB_KeyboardReport_Data_t);
switchesChanged = 0;
return true;
}
/** HID class driver callback function for the processing of HID reports from the host.
*
* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
* \param[in] ReportID Report ID of the received report from the host
* \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
* \param[in] ReportData Pointer to a buffer where the received report has been stored
* \param[in] ReportSize Size in bytes of the received HID report
*/
void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
const uint8_t ReportID,
const uint8_t ReportType,
const void* ReportData,
const uint16_t ReportSize)
{
// uint8_t LEDMask = LEDS_NO_LEDS;
// uint8_t* LEDReport = (uint8_t*)ReportData;
// if (*LEDReport & HID_KEYBOARD_LED_NUMLOCK)
// LEDMask |= LEDS_LED1;
// if (*LEDReport & HID_KEYBOARD_LED_CAPSLOCK)
// LEDMask |= LEDS_LED3;
// if (*LEDReport & HID_KEYBOARD_LED_SCROLLLOCK)
// LEDMask |= LEDS_LED4;
// LEDs_SetAllLEDs(LEDMask);
}
}

View File

@@ -40,8 +40,8 @@
;***** Adapt these SCA and SCL port and pin definition to your target !!
;
#define SDA 1 // SDA Port D, Pin 4
#define SCL 0 // SCL Port D, Pin 5
#define SDA 4 // SDA Port D, Pin 4
#define SCL 3 // SCL Port D, Pin 3
#define SDA_PORT PORTD // SDA Port D
#define SCL_PORT PORTD // SCL Port D
@@ -72,8 +72,8 @@
.stabs "i2cmaster.S",100,0,0,i2c_delay_T2
.func i2c_delay_T2 ; delay 1.25 microsec with 8 Mhz crystal
i2c_delay_T2: ; 4 cycles
rjmp 1f ; 2 "
1: nop ; 1 "
;rjmp 1f ; 2 "
;1: nop ; 1 "
ret ; 3 "
.endfunc ; total 10 cyles = 1.25 microsec with 8 Mhz crystal

View File

@@ -23,6 +23,9 @@ LUFA_PATH = ../LUFA
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
LD_FLAGS =
AVRDUDE = avrdude -B 8 -c usbasp -p $(MCU)
# Default target
all:
@@ -36,3 +39,25 @@ include $(LUFA_PATH)/Build/lufa_dfu.mk
include $(LUFA_PATH)/Build/lufa_hid.mk
include $(LUFA_PATH)/Build/lufa_avrdude.mk
include $(LUFA_PATH)/Build/lufa_atprogram.mk
init: erase wfuse flashboot
erase:
$(AVRDUDE) -e
rfuse:
$(AVRDUDE) -U hfuse:r:-:h -U lfuse:r:-:h -U efuse:r:-:h
wfuse:
$(AVRDUDE) -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf6:m
# To make this hex, compile HID Bootloader in LUFA
# FLASH_SIZE_KB := 16
# BOOT_SECTION_SIZE_KB := 2
# MCU = atmega16u2
# ARCH = AVR8
flashboot:
$(AVRDUDE) -U flash:w:DFU/BootloaderHID.hex:i
flash: all
python DFU/hid_bootloader_loader.py atmega16u2 Keyboard.hex