diff --git a/firmware/Makefile b/firmware/Makefile index 45f50f2..a1bfa76 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -16,7 +16,7 @@ HWOBJECTS = modelibmmodelm.o COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega32 -DF_CPU=12000000L $(DEFINES) -OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o $(HWOBJECTS) +OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o commandhandler.o $(HWOBJECTS) # symbolic targets: diff --git a/firmware/commandhandler.c b/firmware/commandhandler.c new file mode 100644 index 0000000..299da97 --- /dev/null +++ b/firmware/commandhandler.c @@ -0,0 +1,187 @@ +/** + * \file commandhandler.c + * \brief TODO + * \author Ronald Schaten + * \version $Id$ + * + * License: TODO + */ + +#include "commandhandler.h" +#include "keycodes.h" +#include "tools.h" +#include "modelinterface.h" + +// TODO comment + +typedef enum { + standard, + commandmode, + macrocommand, + macrodefinition, + macrodelete, + complexcommand +} Commandstate; + +static Commandstate commandstate = standard; + +#define MACROCOUNT 10 +#define MACROLENGTH 20 + +// macrodefinitions[][0] is the macro-key +Key macrodefinitions[MACROCOUNT][MACROLENGTH + 1]; +uint8_t macrocountindex = 0; +uint8_t macrodefinitionindex = 0; + + +uint8_t getMacroindex(Key macrokey) { + for (uint8_t i = 0; i < MACROCOUNT; i++) { + if ((macrodefinitions[i][0].mode == macrokey.mode) && (macrodefinitions[i][0].key == macrokey.key)) { + return i; + } + } + return MACROCOUNT; +} + +void deleteMacroindex(Key macrokey) { + for (uint8_t i = 0; i < MACROCOUNT; i++) { + if ((macrodefinitions[i][0].mode == macrokey.mode) && (macrodefinitions[i][0].key == macrokey.key)) { + macrodefinitions[i][0].mode = MOD_NONE; + macrodefinitions[i][0].key = KEY_Reserved; + break; + } + } +} + +void sendMacro(uint8_t index) { + for (uint8_t i = 0; i < MACROLENGTH; i++) { + if(macrodefinitions[index][i+1].key != KEY_Reserved) { + sendKey(macrodefinitions[index][i+1]); + } else { + break; + } + } +} + +uint8_t checkmacrodefinition(uint8_t* reportbuffer) { + if ((reportbuffer[2] != KEY_Reserved) && (reportbuffer[3] == KEY_Reserved)) { + Key macrokey; + macrokey.mode = reportbuffer[0]; + macrokey.key = reportbuffer[2]; + return getMacroindex(macrokey); + } + return MACROCOUNT; +} + +uint8_t setMacroindex(Key macrokey) { + for (uint8_t i = 0; i < MACROCOUNT; i++) { + if ((macrodefinitions[i][0].mode == macrokey.mode) && (macrodefinitions[i][0].key == macrokey.key)) { + macrodefinitions[i][0].mode = MOD_NONE; + macrodefinitions[i][0].key = KEY_Reserved; + break; + } + } + for (uint8_t i = 0; i < MACROCOUNT; i++) { + if ((macrodefinitions[i][0].mode == MOD_NONE) && (macrodefinitions[i][0].key == KEY_Reserved)) { + macrodefinitions[i][0].mode = macrokey.mode; + macrodefinitions[i][0].key = macrokey.key; + return i; + } + } + return MACROCOUNT; +} + +uint8_t iskey(uint8_t* reportbuffer, uint8_t modifier, uint8_t key) { + if ((reportbuffer[0] == modifier) && (reportbuffer[2] == key) && (reportbuffer[3] == KEY_Reserved)) { + return 1; + } else { + return 0; + } +} + +uint8_t ishotkey(uint8_t* reportbuffer) { + return iskey(reportbuffer, (MOD_SHIFT_LEFT | MOD_SHIFT_RIGHT), KEY_D); +} + +void keypressed(uint8_t* reportbuffer, uint8_t size, uint16_t tickcounter) { + switch (commandstate) { + case commandmode: + if (iskey(reportbuffer, (MOD_SHIFT_LEFT | MOD_SHIFT_RIGHT), KEY_Reserved) || + iskey(reportbuffer, MOD_SHIFT_LEFT, KEY_Reserved) || + iskey(reportbuffer, MOD_SHIFT_RIGHT, KEY_Reserved) || + iskey(reportbuffer, MOD_NONE, KEY_Reserved)) { + // ignore pressed shift-keys, probably still pressed from hot + // key usage + } else if (iskey(reportbuffer, MOD_NONE, KEY_T)) { + // toggle function + toggle(); + commandstate = standard; + } else if (iskey(reportbuffer, MOD_NONE, KEY_M)) { + // record macro + commandstate = macrocommand; + } else if (iskey(reportbuffer, MOD_SHIFT_LEFT, KEY_M) || iskey(reportbuffer, MOD_SHIFT_RIGHT, KEY_M)) { + // delete macro + commandstate = macrodelete; + } else { + // command not recognized, return to standard mode + commandstate = standard; + } + break; + case macrocommand: + if (reportbuffer[2] == KEY_Reserved) { + // just modifier pressed => ignore + } else { + Key macrokey; + macrokey.mode = reportbuffer[0]; + macrokey.key = reportbuffer[2]; + macrocountindex = setMacroindex(macrokey); + if (macrocountindex == MACROCOUNT) { + // no space left + commandstate = standard; + } else { + commandstate = macrodefinition; + macrodefinitionindex = 0; + } + } + break; + case macrodefinition: + if (ishotkey(reportbuffer)) { + // macro definition complete + macrodefinitions[macrocountindex][macrodefinitionindex + 1].mode = MOD_NONE; + macrodefinitions[macrocountindex][macrodefinitionindex + 1].key = KEY_Reserved; + commandstate = standard; + } else if (reportbuffer[2] == KEY_Reserved) { + // just modifier pressed => ignore + } else { + macrodefinitions[macrocountindex][macrodefinitionindex + 1].mode = reportbuffer[0]; + macrodefinitions[macrocountindex][macrodefinitionindex + 1].key = reportbuffer[2]; + macrodefinitionindex++; + if (macrodefinitionindex == MACROLENGTH) { + // no space left in this macro + commandstate = standard; + } + } + break; + case macrodelete: + if (reportbuffer[2] == KEY_Reserved) { + // just modifier pressed => ignore + } else { + Key macrokey; + macrokey.mode = reportbuffer[0]; + macrokey.key = reportbuffer[2]; + deleteMacroindex(macrokey); + commandstate = standard; + } + break; + case complexcommand: + break; + default: + if (ishotkey(reportbuffer)) { + commandstate = commandmode; + } else if ((macrocountindex = checkmacrodefinition(reportbuffer)) != MACROCOUNT) { + sendMacro(macrocountindex); + } else { + usbSendReportBuffer(reportbuffer, size); + } + } +} diff --git a/firmware/commandhandler.h b/firmware/commandhandler.h new file mode 100644 index 0000000..4ded178 --- /dev/null +++ b/firmware/commandhandler.h @@ -0,0 +1,12 @@ +/** + * \file commandhandler.h + * \brief TODO + * \author Ronald Schaten + * \version $Id$ + * + * License: TODO + */ + +#include + +void keypressed(uint8_t* reportbuffer, uint8_t size, uint16_t tickcounter); diff --git a/firmware/main.c b/firmware/main.c index 402c365..629cf35 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -235,6 +235,7 @@ #include "keycodes.h" #include "tools.h" #include "modelinterface.h" +#include "commandhandler.h" /* ------------------------------------------------------------------------- */ /* ----------------------------- USB interface ----------------------------- */ @@ -341,6 +342,17 @@ uint8_t usbFunctionWrite(uchar *data, uchar len) { return 0x01; } +/** + * Send a report buffer to the computer. + * \param reportbuffer report buffer + */ +void usbSendReportBuffer(uint8_t* reportbuffer, uint8_t size) { + while (!usbInterruptIsReady()) { + usbPoll(); + } + usbSetInterrupt(reportbuffer, size); // send +} + /** * Send a single report to the computer. This function is not used during * normal typing, it is only used to send non-pressed keys to simulate input. @@ -353,23 +365,11 @@ void usbSendReport(uint8_t mode, uint8_t key) { repBuffer[0] = mode; repBuffer[2] = key; wdt_reset(); - while (!usbInterruptIsReady()) { - usbPoll(); - } - usbSetInterrupt(repBuffer, sizeof(repBuffer)); // send + usbSendReportBuffer(repBuffer, sizeof(repBuffer)); } /* ------------------------------------------------------------------------- */ -/** - * This structure can be used as a container for a single 'key'. It consists of - * the key-code and the modifier-code. - */ -typedef struct { - uint8_t mode; - uint8_t key; -} Key; - /** * Convert an ASCII-character to the corresponding key-code and modifier-code * combination. @@ -574,6 +574,7 @@ int main(void) { uint8_t updateNeeded = 0; uint8_t idleCounter = 0; uint8_t updates = 0; + uint16_t tickcounter = 0; wdt_enable(WDTO_2S); hardwareInit(); usbInit(); @@ -595,8 +596,12 @@ int main(void) { // check timer if we need periodic reports if (TIFR & (1 << TOV0)) { TIFR = (1 << TOV0); // reset flag + if (tickcounter < UINT16_MAX) { + tickcounter++; + } calculateSpeed(updates); updates = 0; + /* if (idleRate != 0) { // do we need periodic reports? if(idleCounter > 4){ // yes, but not yet idleCounter -= 5; // 22ms in units of 4ms @@ -605,11 +610,13 @@ int main(void) { idleCounter = idleRate; } } + */ } // if an update is needed, send the report - if (updateNeeded && usbInterruptIsReady()) { + if (updateNeeded) { updateNeeded = 0; - usbSetInterrupt(reportBuffer, sizeof(reportBuffer)); + keypressed(reportBuffer, sizeof(reportBuffer), tickcounter); + tickcounter = 0; memcpy(oldReportBuffer, reportBuffer, sizeof(oldReportBuffer)); } } diff --git a/firmware/modelibmmodelm.c b/firmware/modelibmmodelm.c index 60d4a54..6f287dd 100644 --- a/firmware/modelibmmodelm.c +++ b/firmware/modelibmmodelm.c @@ -106,6 +106,10 @@ void printMatrix(void) { sendString("---"); } +void toggle(void) { + // not used in this model/version +} + void setSpeed(uint8_t speed) { // not used in this model/version } diff --git a/firmware/modelinterface.h b/firmware/modelinterface.h index d4c24f5..ab1a83a 100644 --- a/firmware/modelinterface.h +++ b/firmware/modelinterface.h @@ -21,6 +21,11 @@ void hardwareInit(void); */ void printMatrix(void); +/** + * Toggle-function is called as a command, doesn't have to be implemented. + */ +void toggle(void); + /** * This tells the current writing speed to the keyboard, for whatever it will * do with the value. diff --git a/firmware/modelmayhem.c b/firmware/modelmayhem.c index a63c5da..d562c49 100644 --- a/firmware/modelmayhem.c +++ b/firmware/modelmayhem.c @@ -41,6 +41,7 @@ uint8_t curmatrix[16]; ///< contains current state of the keyboard uint8_t oldmatrix[16]; ///< contains old state of the keyboard uint8_t ghostmatrix[16]; ///< contains pressed keys that belong to a ghost-key situation +uint8_t backlight = 0; void hardwareInit(void) { // column-port is input @@ -116,10 +117,22 @@ void printMatrix(void) { sendString("---"); } +void toggle(void) { + // switch backlight on or off + if (backlight == 0) { + backlight = 1; + } else { + backlight = 0; + OCR1A = 0xffff; + OCR1B = 0xffff; + } +} + void setSpeed(uint8_t speed) { - uint16_t value = (speed + 1) * (speed + 1) - 1; - OCR1A = 0xffff - value; - OCR1B = value; + if (backlight == 1) { + OCR1A = 0xffff - ((256 - speed) * (256 - speed) - 1); + OCR1B = 0xffff - ((speed + 1) * (speed + 1) - 1); + } } void setLeds(uint8_t LEDstate) { diff --git a/firmware/modelsuntype5.c b/firmware/modelsuntype5.c index 0e710f2..4a356fd 100644 --- a/firmware/modelsuntype5.c +++ b/firmware/modelsuntype5.c @@ -93,6 +93,10 @@ void printMatrix(void) { sendString("\n"); } +void toggle(void) { + // not used in this model/version +} + void setSpeed(uint8_t speed) { // not used in this model/version } diff --git a/firmware/tools.h b/firmware/tools.h index 85aecb9..2681be2 100644 --- a/firmware/tools.h +++ b/firmware/tools.h @@ -13,4 +13,16 @@ #define LED_COMPOSE 0x08 ///< compose LED on a boot-protocol keyboard #define LED_KANA 0x10 ///< kana LED on a boot-protocol keyboard + +/** + * This structure can be used as a container for a single 'key'. It consists of + * the key-code and the modifier-code. + */ +typedef struct { + uint8_t mode; + uint8_t key; +} Key; + void sendString(char* string); +void sendKey(Key keytosend); +void usbSendReportBuffer(uint8_t* reportbuffer, uint8_t size);