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)
|
||||
|
||||
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:
|
||||
|
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 "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));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user