diff --git a/Firmware/Keyboard/Keyboard.c b/Firmware/Keyboard/Keyboard.c index eb446ff..91273f7 100644 --- a/Firmware/Keyboard/Keyboard.c +++ b/Firmware/Keyboard/Keyboard.c @@ -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); -} - +} \ No newline at end of file diff --git a/Firmware/Keyboard/i2cmaster.S b/Firmware/Keyboard/i2cmaster.S index bb9b6a6..f55da14 100644 --- a/Firmware/Keyboard/i2cmaster.S +++ b/Firmware/Keyboard/i2cmaster.S @@ -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 diff --git a/Firmware/Keyboard/makefile b/Firmware/Keyboard/makefile index 8951038..643de68 100644 --- a/Firmware/Keyboard/makefile +++ b/Firmware/Keyboard/makefile @@ -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