Many changes: added commandhandler module, macro functions, toggle function and
speed settings. Removed key repetition (no idea why it was there).
This commit is contained in:
parent
68abf87a9c
commit
ced5a39988
@ -16,7 +16,7 @@ HWOBJECTS = modelibmmodelm.o
|
|||||||
|
|
||||||
COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega32 -DF_CPU=12000000L $(DEFINES)
|
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:
|
# symbolic targets:
|
||||||
|
187
firmware/commandhandler.c
Normal file
187
firmware/commandhandler.c
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/**
|
||||||
|
* \file commandhandler.c
|
||||||
|
* \brief TODO
|
||||||
|
* \author Ronald Schaten <ronald@schatenseite.de>
|
||||||
|
* \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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
firmware/commandhandler.h
Normal file
12
firmware/commandhandler.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* \file commandhandler.h
|
||||||
|
* \brief TODO
|
||||||
|
* \author Ronald Schaten <ronald@schatenseite.de>
|
||||||
|
* \version $Id$
|
||||||
|
*
|
||||||
|
* License: TODO
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void keypressed(uint8_t* reportbuffer, uint8_t size, uint16_t tickcounter);
|
@ -235,6 +235,7 @@
|
|||||||
#include "keycodes.h"
|
#include "keycodes.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "modelinterface.h"
|
#include "modelinterface.h"
|
||||||
|
#include "commandhandler.h"
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
/* ----------------------------- USB interface ----------------------------- */
|
/* ----------------------------- USB interface ----------------------------- */
|
||||||
@ -341,6 +342,17 @@ uint8_t usbFunctionWrite(uchar *data, uchar len) {
|
|||||||
return 0x01;
|
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
|
* 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.
|
* 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[0] = mode;
|
||||||
repBuffer[2] = key;
|
repBuffer[2] = key;
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
while (!usbInterruptIsReady()) {
|
usbSendReportBuffer(repBuffer, sizeof(repBuffer));
|
||||||
usbPoll();
|
|
||||||
}
|
|
||||||
usbSetInterrupt(repBuffer, sizeof(repBuffer)); // send
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Convert an ASCII-character to the corresponding key-code and modifier-code
|
||||||
* combination.
|
* combination.
|
||||||
@ -574,6 +574,7 @@ int main(void) {
|
|||||||
uint8_t updateNeeded = 0;
|
uint8_t updateNeeded = 0;
|
||||||
uint8_t idleCounter = 0;
|
uint8_t idleCounter = 0;
|
||||||
uint8_t updates = 0;
|
uint8_t updates = 0;
|
||||||
|
uint16_t tickcounter = 0;
|
||||||
wdt_enable(WDTO_2S);
|
wdt_enable(WDTO_2S);
|
||||||
hardwareInit();
|
hardwareInit();
|
||||||
usbInit();
|
usbInit();
|
||||||
@ -595,8 +596,12 @@ int main(void) {
|
|||||||
// check timer if we need periodic reports
|
// check timer if we need periodic reports
|
||||||
if (TIFR & (1 << TOV0)) {
|
if (TIFR & (1 << TOV0)) {
|
||||||
TIFR = (1 << TOV0); // reset flag
|
TIFR = (1 << TOV0); // reset flag
|
||||||
|
if (tickcounter < UINT16_MAX) {
|
||||||
|
tickcounter++;
|
||||||
|
}
|
||||||
calculateSpeed(updates);
|
calculateSpeed(updates);
|
||||||
updates = 0;
|
updates = 0;
|
||||||
|
/*
|
||||||
if (idleRate != 0) { // do we need periodic reports?
|
if (idleRate != 0) { // do we need periodic reports?
|
||||||
if(idleCounter > 4){ // yes, but not yet
|
if(idleCounter > 4){ // yes, but not yet
|
||||||
idleCounter -= 5; // 22ms in units of 4ms
|
idleCounter -= 5; // 22ms in units of 4ms
|
||||||
@ -605,11 +610,13 @@ int main(void) {
|
|||||||
idleCounter = idleRate;
|
idleCounter = idleRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
// if an update is needed, send the report
|
// if an update is needed, send the report
|
||||||
if (updateNeeded && usbInterruptIsReady()) {
|
if (updateNeeded) {
|
||||||
updateNeeded = 0;
|
updateNeeded = 0;
|
||||||
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
keypressed(reportBuffer, sizeof(reportBuffer), tickcounter);
|
||||||
|
tickcounter = 0;
|
||||||
memcpy(oldReportBuffer, reportBuffer, sizeof(oldReportBuffer));
|
memcpy(oldReportBuffer, reportBuffer, sizeof(oldReportBuffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,10 @@ void printMatrix(void) {
|
|||||||
sendString("---");
|
sendString("---");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggle(void) {
|
||||||
|
// not used in this model/version
|
||||||
|
}
|
||||||
|
|
||||||
void setSpeed(uint8_t speed) {
|
void setSpeed(uint8_t speed) {
|
||||||
// not used in this model/version
|
// not used in this model/version
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,11 @@ void hardwareInit(void);
|
|||||||
*/
|
*/
|
||||||
void printMatrix(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
|
* This tells the current writing speed to the keyboard, for whatever it will
|
||||||
* do with the value.
|
* do with the value.
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
uint8_t curmatrix[16]; ///< contains current state of the keyboard
|
uint8_t curmatrix[16]; ///< contains current state of the keyboard
|
||||||
uint8_t oldmatrix[16]; ///< contains old 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 ghostmatrix[16]; ///< contains pressed keys that belong to a ghost-key situation
|
||||||
|
uint8_t backlight = 0;
|
||||||
|
|
||||||
void hardwareInit(void) {
|
void hardwareInit(void) {
|
||||||
// column-port is input
|
// column-port is input
|
||||||
@ -116,10 +117,22 @@ void printMatrix(void) {
|
|||||||
sendString("---");
|
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) {
|
void setSpeed(uint8_t speed) {
|
||||||
uint16_t value = (speed + 1) * (speed + 1) - 1;
|
if (backlight == 1) {
|
||||||
OCR1A = 0xffff - value;
|
OCR1A = 0xffff - ((256 - speed) * (256 - speed) - 1);
|
||||||
OCR1B = value;
|
OCR1B = 0xffff - ((speed + 1) * (speed + 1) - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLeds(uint8_t LEDstate) {
|
void setLeds(uint8_t LEDstate) {
|
||||||
|
@ -93,6 +93,10 @@ void printMatrix(void) {
|
|||||||
sendString("\n");
|
sendString("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void toggle(void) {
|
||||||
|
// not used in this model/version
|
||||||
|
}
|
||||||
|
|
||||||
void setSpeed(uint8_t speed) {
|
void setSpeed(uint8_t speed) {
|
||||||
// not used in this model/version
|
// not used in this model/version
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,16 @@
|
|||||||
#define LED_COMPOSE 0x08 ///< compose LED on a boot-protocol keyboard
|
#define LED_COMPOSE 0x08 ///< compose LED on a boot-protocol keyboard
|
||||||
#define LED_KANA 0x10 ///< kana 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 sendString(char* string);
|
||||||
|
void sendKey(Key keytosend);
|
||||||
|
void usbSendReportBuffer(uint8_t* reportbuffer, uint8_t size);
|
||||||
|
Loading…
Reference in New Issue
Block a user