diff --git a/Firmware/Keyboard/Config.c b/Firmware/Keyboard/Config.c index ba70b17..7e7c36e 100644 --- a/Firmware/Keyboard/Config.c +++ b/Firmware/Keyboard/Config.c @@ -15,7 +15,9 @@ static sdvx_config_t defaults PROGMEM = { HID_KEYBOARD_SC_M, HID_KEYBOARD_SC_ENTER}, .ledsOn = true, - .debounce = 30 + .debounce = 30, + .macroClick = KEYPADPLUS, + .macroPin = {KEYPAD0,KEYPAD0,KEYPAD0,KEYPAD0} }; uint8_t firstRun EEMEM; // init to 255 diff --git a/Firmware/Keyboard/Config.h b/Firmware/Keyboard/Config.h index 2413a83..a1a0660 100644 --- a/Firmware/Keyboard/Config.h +++ b/Firmware/Keyboard/Config.h @@ -18,9 +18,9 @@ typedef struct { uint8_t switches[SWITCH_COUNT]; bool ledsOn; uint8_t debounce; - uint8_t version; - // used to reboot into programming mode - uint8_t reboot; + // When tapping or long-pressing the macro key + uint8_t macroClick; + uint8_t macroPin[4]; } sdvx_config_t; // + 1 for some reason diff --git a/Firmware/Keyboard/Keyboard.c b/Firmware/Keyboard/Keyboard.c index 92e9d66..f969892 100644 --- a/Firmware/Keyboard/Keyboard.c +++ b/Firmware/Keyboard/Keyboard.c @@ -3,6 +3,7 @@ #include "Encoder.h" #include "LED.h" #include "LEDPatterns.h" +#include "Macro.h" #define READ_SWITCH(x) (!(*pins[switches[x].switchPort] & _BV(switches[x].switchPin))) #define MAGIC_BOOT_KEY 0xDEADBE7A @@ -104,25 +105,10 @@ USB_ClassInfo_HID_Device_t LED_HID_Interface = }, }; -// NOTE: atemga16u2 does not have a PORTA -typedef enum { - B = 0, - C, - D -} port_t; - static volatile uint8_t *ports[] = {&PORTB, &PORTC, &PORTD}; static volatile uint8_t *pins[] = {&PINB, &PINC, &PIND}; static volatile uint8_t *ddrs[] = {&DDRB, &DDRC, &DDRD}; -typedef struct { - port_t switchPort; - uint8_t switchPin; - uint8_t state; - uint8_t lastReport; - uint8_t debounce; -} switch_t; - static switch_t switches[SWITCH_COUNT] = { {B, 1}, // A {D, 7}, // B @@ -130,7 +116,8 @@ static switch_t switches[SWITCH_COUNT] = { {D, 4}, // D {B, 0}, // FX L {D, 6}, // FX R - {C, 2} // START + {C, 2}, // START + {C, 1} // Macro key }; static uint8_t switchesChanged = 1; @@ -215,9 +202,11 @@ void SetupHardware() // with internal pullups *ports[switches[i].switchPort] |= _BV(switches[i].switchPin); } + // RESET has its own pullup + *ports[switches[SWITCH_COUNT-1].switchPort] &= ~_BV(switches[SWITCH_COUNT-1].switchPin); - // FX_L held while plugging in - if(READ_SWITCH(4)) { + // RESET held while plugging in + if(READ_SWITCH(SWITCH_COUNT-1)) { RebootToBootloader(); } @@ -250,15 +239,20 @@ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDIn } if (HIDInterfaceInfo == &Keyboard_HID_Interface) { Keyboard_Report_t* KeyboardReport = (Keyboard_Report_t*)ReportData; + + // Only the first 4 bytes are read by bemanitools, so let's use the first + uint8_t macroUpdated = macro_make_report(&KeyboardReport->KeyCode[0]); update_switches(); - if(!switchesChanged) { + if(!switchesChanged && !macroUpdated) { *ReportSize = 0; return false; } - - for(uint8_t i = 0; i < SWITCH_COUNT; i++) { - KeyboardReport->KeyCode[i] = switches[i].state ? sdvxConfig.switches[i] : 0; + + // NOTE: using SWITCH_COUNT-1 so we don't write the report for the macro pin + for(uint8_t i = 0; i < SWITCH_COUNT-1; i++) { + // i+1 to take care of the shift from above + KeyboardReport->KeyCode[i+1] = switches[i].state ? sdvxConfig.switches[i] : 0; switches[i].lastReport = switches[i].state; // Update blinkenlights if(switches[i].state) { @@ -386,6 +380,8 @@ void EVENT_USB_Device_StartOfFrame(void) hidTimeout++; } + macro_on_frame(&switches[SWITCH_COUNT-1]); + for(int i = 0; i < SWITCH_COUNT; i++) { if(switches[i].debounce) { switches[i].debounce--; diff --git a/Firmware/Keyboard/Keyboard.h b/Firmware/Keyboard/Keyboard.h index 0dc0ab9..848a0d0 100644 --- a/Firmware/Keyboard/Keyboard.h +++ b/Firmware/Keyboard/Keyboard.h @@ -48,6 +48,21 @@ #include #include + + // NOTE: atemga16u2 does not have a PORTA + typedef enum { + B = 0, + C, + D + } port_t; + + typedef struct { + port_t switchPort; + uint8_t switchPin; + uint8_t state; + uint8_t lastReport; + uint8_t debounce; + } switch_t; /* Function Prototypes: */ void SetupHardware(void); diff --git a/Firmware/Keyboard/Macro.c b/Firmware/Keyboard/Macro.c new file mode 100644 index 0000000..2e96bab --- /dev/null +++ b/Firmware/Keyboard/Macro.c @@ -0,0 +1,69 @@ +#include + +// in ms +#define KEY_DELAY 30 +#define LONGPRESS_DELAY 500 + +static uint8_t countdown = 0; +static uint16_t longpress = 0; +static uint8_t *data; +static uint8_t dataLen = 0; +static uint8_t position = 0; +static uint8_t liftoff = 0; + +uint8_t macro_make_report(uint8_t* key) { + if(countdown) { + return 0; + } + + if(liftoff) { + liftoff = 0; + countdown = KEY_DELAY; + *key = 0; + return 1; + } else { + if(position >= dataLen) { + return 0; + } + + *key = data[position]; + countdown = KEY_DELAY; + + position++; + liftoff = 1; + return 1; + } +} + +void macro_fire_click(void) { + data = &sdvxConfig.macroClick; + dataLen = 1; + position = 0; +} + +void macro_fire_pin(void) { + data = sdvxConfig.macroPin; + dataLen = 4; + position = 0; +} + +void macro_on_frame(switch_t* macro) { + if(countdown) { + countdown--; + } + + // Rising edge + if(macro->state && !macro->lastReport) { + longpress = 0; + // held high and not triggered longpress yet + } else if(macro->state && macro->lastReport && longpress < LONGPRESS_DELAY) { + longpress++; + if(longpress >= LONGPRESS_DELAY) { + macro_fire_pin(); + } + // falling edge before longpress time + } else if(!macro->state && macro->lastReport && longpress < LONGPRESS_DELAY) { + macro_fire_click(); + } + macro->lastReport = macro->state; +} \ No newline at end of file diff --git a/Firmware/Keyboard/Macro.h b/Firmware/Keyboard/Macro.h new file mode 100644 index 0000000..375ab50 --- /dev/null +++ b/Firmware/Keyboard/Macro.h @@ -0,0 +1,15 @@ +#ifndef MACRO_H_ +#define MACRO_H_ + +#include "Config.h" +#include "asciihid.h" +#include "Keyboard.h" + +extern sdvx_config_t sdvxConfig; + +uint8_t macro_make_report(uint8_t* key); +void macro_on_frame(switch_t* macro); +void macro_fire_click(void); +void macro_fire_pin(void); + +#endif \ No newline at end of file diff --git a/Firmware/Keyboard/asciihid.c b/Firmware/Keyboard/asciihid.c new file mode 100644 index 0000000..4228cec --- /dev/null +++ b/Firmware/Keyboard/asciihid.c @@ -0,0 +1,79 @@ +#include "asciihid.h" + +/**************************************************************************** + * + * ASCII->HID LOOKUP TABLE + * + * Taken from the HID Table definition at + * http://www.usb.org/developers/devclass_docs/Hut1_11.pdf + * + * This array maps the ASCII value of a type-able character to its + * corresponding HID value. + * + * Example: + * 'a' = ASCII value 97 = HID value 0x04 + * HIDTable['a'] = HIDTable[97] = 0x04 + * + * NOTE: + * "Shift Modified" HID values are the same as the non Shift-Modified values + * for any given character, e.g. the HID value for '2' is equal to the + * HID value for '@'. The Shift-Modified value is sent by setting the + * modifier value (buf[0]) to the corresponding modifier value in the + * modifier table. + * + ****************************************************************************/ +const uint8_t PROGMEM HIDTable[] = { + 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x28, // 10 + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, // 30 + 0x00, 0x2c, 0x1e, 0x34, 0x20, 0x21, 0x22, 0x24, 0x34, 0x26, // 40 + 0x27, 0x25, 0x2e, 0x36, 0x2d, 0x37, 0x38, 0x27, 0x1e, 0x1f, // 50 + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x33, 0x33, 0x36, // 60 + 0x2e, 0x37, 0x38, 0x1f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, // 70 + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // 80 + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, // 90 + 0x2f, 0x31, 0x30, 0x23, 0x2d, 0x35, 0x04, 0x05, 0x06, 0x07, // 100 + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // 110 + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, // 120 + 0x1c, 0x1d, 0x2f, 0x31, 0x30, 0x35, 127 // 127 +}; + + +/**************************************************************************** + * + * ASCII->MODIFIER LOOKUP TABLE + * + * Looks up whether or not the HID report should use the SHIFT modifier. + * + * Example: + * The character '2' and the character '@' have different ASCII values but + * the same HID value. This table uses the ASCII value to determine if + * we should hold shift while sending the key. e.g.: + * + * HIDTable['2'] = 0x1f and modifierTable['2'] = 0 + * HIDTable['@'] = 0x1f and modifierTable['@'] = SHIFT + * + * There's probaly a better way to do this, but it's functional. + * + ****************************************************************************/ +const uint8_t PROGMEM modifierTable[] = { + 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 30 + 0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 40 + SHIFT, 0x00, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, SHIFT, 0x00, SHIFT, // 60 + 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 70 + SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 80 + SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 90 + 0x00, 0x00, 0x00, SHIFT, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, // 100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 + 0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, 0x00 // 127 +}; + +const uint8_t PROGMEM numpadTable[] = { + 0x62, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61 // 0-9 on the numpad +}; \ No newline at end of file diff --git a/Firmware/Keyboard/asciihid.h b/Firmware/Keyboard/asciihid.h index 4170e9a..68ef9b2 100644 --- a/Firmware/Keyboard/asciihid.h +++ b/Firmware/Keyboard/asciihid.h @@ -1,4 +1,6 @@ // https://github.com/SFE-Chris/UNO-HIDKeyboard-Library/blob/master/HIDKeyboard.h +#ifndef ASCIIHID_H_ +#define ASCIIHID_H_ #include @@ -69,77 +71,8 @@ #define ALT 0x04 #define GUI 0x08 +extern PROGMEM const uint8_t HIDTable[]; +extern PROGMEM const uint8_t modifierTable[]; +extern PROGMEM const uint8_t numpadTable[]; -/**************************************************************************** - * - * ASCII->HID LOOKUP TABLE - * - * Taken from the HID Table definition at - * http://www.usb.org/developers/devclass_docs/Hut1_11.pdf - * - * This array maps the ASCII value of a type-able character to its - * corresponding HID value. - * - * Example: - * 'a' = ASCII value 97 = HID value 0x04 - * HIDTable['a'] = HIDTable[97] = 0x04 - * - * NOTE: - * "Shift Modified" HID values are the same as the non Shift-Modified values - * for any given character, e.g. the HID value for '2' is equal to the - * HID value for '@'. The Shift-Modified value is sent by setting the - * modifier value (buf[0]) to the corresponding modifier value in the - * modifier table. - * - ****************************************************************************/ -PROGMEM uint8_t HIDTable[] = { - 0x00, // 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x28, // 10 - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, // 30 - 0x00, 0x2c, 0x1e, 0x34, 0x20, 0x21, 0x22, 0x24, 0x34, 0x26, // 40 - 0x27, 0x25, 0x2e, 0x36, 0x2d, 0x37, 0x38, 0x27, 0x1e, 0x1f, // 50 - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x33, 0x33, 0x36, // 60 - 0x2e, 0x37, 0x38, 0x1f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, // 70 - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // 80 - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, // 90 - 0x2f, 0x31, 0x30, 0x23, 0x2d, 0x35, 0x04, 0x05, 0x06, 0x07, // 100 - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // 110 - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, // 120 - 0x1c, 0x1d, 0x2f, 0x31, 0x30, 0x35, 127 // 127 -}; - - -/**************************************************************************** - * - * ASCII->MODIFIER LOOKUP TABLE - * - * Looks up whether or not the HID report should use the SHIFT modifier. - * - * Example: - * The character '2' and the character '@' have different ASCII values but - * the same HID value. This table uses the ASCII value to determine if - * we should hold shift while sending the key. e.g.: - * - * HIDTable['2'] = 0x1f and modifierTable['2'] = 0 - * HIDTable['@'] = 0x1f and modifierTable['@'] = SHIFT - * - * There's probaly a better way to do this, but it's functional. - * - ****************************************************************************/ -PROGMEM uint8_t modifierTable[] = { - 0x00, // 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 30 - 0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 40 - SHIFT, 0x00, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 50 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, SHIFT, 0x00, SHIFT, // 60 - 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 70 - SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 80 - SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 90 - 0x00, 0x00, 0x00, SHIFT, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, // 100 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 110 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 - 0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, 0x00 // 127 -}; \ No newline at end of file +#endif \ No newline at end of file diff --git a/Firmware/Keyboard/makefile b/Firmware/Keyboard/makefile index 43f495a..1c2b2b5 100644 --- a/Firmware/Keyboard/makefile +++ b/Firmware/Keyboard/makefile @@ -18,7 +18,7 @@ F_CPU = 16000000 F_USB = $(F_CPU) OPTIMIZATION = s TARGET = Keyboard -SRC = $(TARGET).c Descriptors.c Config.c Encoder.c LED.c LEDPatterns.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) +SRC = $(TARGET).c asciihid.c Descriptors.c Config.c Encoder.c LED.c LEDPatterns.c Macro.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) LUFA_PATH = ../LUFA CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ LD_FLAGS = @@ -54,7 +54,7 @@ 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 + $(AVRDUDE) -U lfuse:w:0xde:m -U hfuse:w:0x9b:m -U efuse:w:0xf6:m # To make this hex, compile HID Bootloader in LUFA # FLASH_SIZE_KB := 16