From 43c5c297e83c3977880b1e19ed04f6257efda79a Mon Sep 17 00:00:00 2001 From: Ronald Schaten Date: Sat, 1 Nov 2008 21:20:07 +0000 Subject: [PATCH] implemented new keyboard model: Sun Type 5 --- firmware/Makefile | 2 - firmware/main.c | 7 +- firmware/modelibmmodelm.c | 13 +- firmware/modelsuntype5.c | 294 ++++++++++++++++++++++++++++++++++++++ firmware/tools.h | 6 + 5 files changed, 313 insertions(+), 9 deletions(-) create mode 100644 firmware/modelsuntype5.c diff --git a/firmware/Makefile b/firmware/Makefile index 26d425a..79f9398 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -10,9 +10,7 @@ AVRDUDE = avrdude -p atmega32 -c usbasp # Options: -DEFINES = -DMODELIBMMODELM HWOBJECTS = modelibmmodelm.o -#DEFINES = -DMODELSUNTYPE5 #HWOBJECTS = modelsuntype5.o COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega32 -DF_CPU=12000000L $(DEFINES) diff --git a/firmware/main.c b/firmware/main.c index fedf9c7..2b9a349 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -339,7 +339,10 @@ void usbSendReport(uint8_t mode, uint8_t key) { uint8_t repBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; repBuffer[0] = mode; repBuffer[2] = key; - while (!usbInterruptIsReady()); // wait + wdt_reset(); + while (!usbInterruptIsReady()) { + usbPoll(); + } usbSetInterrupt(repBuffer, sizeof(repBuffer)); // send } @@ -474,6 +477,8 @@ Key charToKey(char character) { case '?': key.mode = MOD_SHIFT_LEFT; key.key = KEY_slash; break; + case '\n': + key.key = KEY_Return; break; } if (key.key == KEY_Reserved) { // still reserved? WTF? return question mark... diff --git a/firmware/modelibmmodelm.c b/firmware/modelibmmodelm.c index 22de8ce..c143b40 100644 --- a/firmware/modelibmmodelm.c +++ b/firmware/modelibmmodelm.c @@ -44,6 +44,7 @@ #define JUMPER2 PD7 ///< address for jumper 2 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 void hardwareInit(void) { @@ -105,12 +106,6 @@ void printMatrix(void) { sendString("---"); } -#define LED_NUM 0x01 ///< num LED on a boot-protocol keyboard -#define LED_CAPS 0x02 ///< caps LED on a boot-protocol keyboard -#define LED_SCROLL 0x04 ///< scroll 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 - void setLeds(uint8_t LEDstate) { if (LEDstate & LED_NUM) { // light up caps lock PORTLEDS &= ~(1 << LEDNUM); @@ -258,6 +253,12 @@ uint8_t scankeys(uint8_t* reportBuffer, uint8_t* oldReportBuffer, uint8_t sizeOf debounce--; } if (debounce == 1) { + /* + if (memcmp(oldmatrix, curmatrix, sizeof(curmatrix)) != 0) { + printMatrix(); + memcpy(oldmatrix, curmatrix, sizeof(curmatrix)); + } + */ // debounce counter expired, create report uint8_t reportIndex = 2; // reportBuffer[0] contains modifiers memset(reportBuffer, 0, sizeOfReportBuffer); // clear report buffer diff --git a/firmware/modelsuntype5.c b/firmware/modelsuntype5.c new file mode 100644 index 0000000..00069e8 --- /dev/null +++ b/firmware/modelsuntype5.c @@ -0,0 +1,294 @@ +/** + * \file firmware/modelsuntype5.c + * \brief Hardware specific part for IBM Model M keyboard + * \author Ronald Schaten + * \version $Id: main.c,v 1.6 2008/07/15 05:16:41 rschaten Exp $ + * + * License: GNU GPL v2 (see License.txt) + */ + +#include +#include +#include +#include +#include + +#include "keycodes.h" +#include "tools.h" +#include "modelinterface.h" +#include "usbdrv.h" + +/* ----------------------- hardware I/O abstraction ------------------------ */ + +#define PORTLEDS PORTB ///< port on which the LEDs are connected +#define PINLEDS PINB ///< port on which the LEDs are connected +#define DDRLEDS DDRB ///< port on which the LEDs are connected +#define LEDSCROLL PINB7 ///< address of the scroll-lock LED +#define LEDNUM PINB6 ///< address of the num-lock LED +#define LEDCOMP PINB5 ///< address of the compose LED +#define LEDCAPS PINB4 ///< address of the caps-lock LED + +#define SRCLOCKON PORTC |= (1 << PC5) +#define SRCLOCKOFF PORTC &= ~(1 << PC5) +#define SRDATAON PORTC |= (1 << PC6) +#define SRDATAOFF PORTC &= ~(1 << PC6) +#define SRSTROBEON PORTC |= (1 << PC7) +#define SRSTROBEOFF PORTC &= ~(1 << PC7) + +uint16_t curmatrix[22]; ///< contains current state of the keyboard +uint16_t oldmatrix[22]; ///< contains old state of the keyboard +uint16_t ghostmatrix[22]; ///< contains pressed keys that belong to a ghost-key situation + +void hardwareInit(void) { + // configure ports + DDRA = 0x00; + PORTA = 0xff; + DDRB = (1 << PB4) |(1 << PB5) | (1 << PB6) | (1 << PB7); + PORTB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3); + DDRC = (1 << PC5) | (1 << PC6) | (1 << PC7); + PORTC = (1 << PC0) | (1 << PC1) | (1 << PC2) | (1 << PC3) | (1 << PC4); + DDRD &= ~((1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7)); + PORTD |= (1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7); + + DDRD |= (1 << PD0) | (1 << PD2); // needed for USB reset + _delay_us(11); // delay >10ms for USB reset + DDRD &= ~((1 << PD0) | (1 << PD2)); // remove USB reset condition + + // configure timer 0 for a rate of 12M/(1024 * 256) = 45.78Hz (~22ms) + TCCR0 = 5; // timer 0 prescaler: 1024 + + // blink, to indicate power-on + PORTLEDS &= ~((1 << LEDNUM) | (1 << LEDCAPS) | (1 << LEDSCROLL) | (1 << LEDCOMP)); + _delay_ms(50); + PORTLEDS |= ((1 << LEDNUM) | (1 << LEDCAPS) | (1 << LEDSCROLL) | (1 << LEDCOMP)); + + // clean shift registers -- set all row lines to 1, except for KEYROW + SRDATAON; + SRSTROBEOFF; + for (uint8_t i = 0; i < 21; i++) { + SRCLOCKON; SRCLOCKOFF; + } + SRSTROBEON; SRSTROBEOFF; +} + +/** + * Print the current state of the keyboard in a readable form. This function + * is used for debug-purposes only. + */ +void printMatrix(void) { + for (uint8_t i = 0; i < 22; i++) { + char buffer[10]; + sprintf(buffer, "%4x", ~(curmatrix[i] | 0xe000)); + for(int j= 0; j < strlen(buffer); j++) { + if(buffer[j] == '0') + buffer[j]= ' '; + } + sendString(buffer); + if (i == 11) { + sendString(":"); + } else { + sendString("."); + } + } + sendString("\n"); +} + +void setLeds(uint8_t LEDstate) { + if (LEDstate & LED_NUM) { // light up caps lock + PORTLEDS &= ~(1 << LEDNUM); + } else { + PORTLEDS |= (1 << LEDNUM); + } + if (LEDstate & LED_CAPS) { // light up caps lock + PORTLEDS &= ~(1 << LEDCAPS); + } else { + PORTLEDS |= (1 << LEDCAPS); + } + if (LEDstate & LED_SCROLL) { // light up caps lock + PORTLEDS &= ~(1 << LEDSCROLL); + } else { + PORTLEDS |= (1 << LEDSCROLL); + } + if (LEDstate & LED_COMPOSE) { // light up compose + PORTLEDS &= ~(1 << LEDCOMP); + } else { + PORTLEDS |= (1 << LEDCOMP); + } +} + +/** + * The keymatrix-array contains positions of keys in the matrix. Here you can + * see which row is connected to which column when a key is pressed. This array + * probably has to be modified if this firmware is ported to a different + * keyboard. + * \sa modmatrix + */ +const uint8_t PROGMEM keymatrix[22][13] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_dot, KEY_F8, KEY_F10, KEY_Reserved, KEY_9, KEY_minus, KEY_P, KEY_K}, // 0 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_slash, KEY_equals, KEY_F11, KEY_Reserved, KEY_0, KEY_lbracket, KEY_semicolon, KEY_L}, // 1 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_LeftArrow, KEY_DownArrow, KEY_grave, KEY_F12, KEY_Reserved, KEY_Euro, KEY_DELETE, KEY_rbracket, KEY_apostroph}, // 2 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_RightArrow, KEY_UpArrow, KEY_Insert, KEY_PrintScreen, KEY_Reserved, KEY_NumLock, KEY_DeleteForward, KEY_Return, KEY_KP4}, // 3 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_KP2, KEY_KP5, KEY_ScrollLock, KEY_Reserved /*mute*/, KEY_Reserved, KEY_KPslash, KEY_Home, KEY_End, KEY_KP7}, // 4 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_KP3, KEY_KP6, KEY_Pause, KEY_Reserved /*vol-*/, KEY_Reserved, KEY_KPasterisk, KEY_PageUp, KEY_PageDown, KEY_KP8}, // 5 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_KPcomma, KEY_KP0, KEY_KPminus, KEY_Reserved /*vol+*/, KEY_Reserved, KEY_KP9, KEY_KPplus, KEY_KPenter, KEY_KP1}, // 6 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 7 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved /*compose*/, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 8 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved /*power*/, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 9 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 10 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 11 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_capslock, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 12 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved /*find*/, KEY_Reserved /*open*/, KEY_ESCAPE, KEY_Reserved /*help*/, KEY_Reserved, KEY_Reserved /*stop*/, KEY_Reserved /*props*/, KEY_Tab, KEY_Reserved /*front*/}, // 13 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 14 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved /*cut*/, KEY_Reserved /*paste*/, KEY_1, KEY_Reserved /*any*/, KEY_Reserved, KEY_Reserved /*again*/, KEY_Reserved /*undo*/ , KEY_Q, KEY_Reserved /*copy*/}, // 15 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Z, KEY_2, KEY_F1, KEY_Reserved, KEY_3, KEY_E, KEY_W, KEY_D}, // 16 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_C, KEY_X, KEY_4, KEY_F2, KEY_Reserved, KEY_5, KEY_R, KEY_F, KEY_A}, // 17 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_V, KEY_N, KEY_F3, KEY_F5, KEY_Reserved, KEY_6, KEY_T, KEY_G, KEY_S}, // 18 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_B, KEY_M, KEY_F4, KEY_F6, KEY_Reserved, KEY_7, KEY_U, KEY_Y, KEY_H}, // 19 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved}, // 20 + {KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Spacebar, KEY_comma, KEY_F7, KEY_F9, KEY_Reserved, KEY_8, KEY_O, KEY_I, KEY_J}, // 21 +}; + +/** + * The modmatrix-array contains positions of the modifier-keys in the matrix. + * It is built in the same way as the keymatrix-array. + * \sa keymatrix + */ +const uint8_t PROGMEM modmatrix[22][13] = { // contains positions of modifiers in the matrix + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 0 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 1 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 2 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 3 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 4 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 5 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 6 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_ALT_RIGHT, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 7 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 8 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 9 + {MOD_NONE, MOD_GUI_RIGHT, MOD_GUI_LEFT, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 10 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_ALT_LEFT, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 11 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 12 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 13 + {MOD_SHIFT_RIGHT, MOD_NONE, MOD_NONE, MOD_SHIFT_LEFT, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 14 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 15 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 16 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 17 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 18 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 19 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_CONTROL_LEFT}, // 20 + {MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE}, // 21 +}; + +/** + * Checks if more than one bit in data is set. + * \param data value to check + * \return true if more than one bit is set + */ +static uint8_t bitcount2(uint16_t data) { + data &= (data - 1); + return data != 0; +} + +/** + * check if reportBuffer contains the key + * \param buffer buffer to check + * \param key key to search + * \return 1 if buffer contains key, 0 otherwise + */ +static uint8_t bufferContains(uint8_t* buffer, uint8_t key) { + for (uint8_t i = 2; i < sizeof(buffer); i++) { + if (buffer[i] == key) { + return 1; + } + } + return 0; +} + +/** + * Scan and debounce keypresses. This is the main worker function for normal + * keyboard operation, the code contains lot of comments. Basically, it first + * scans the keyboard state. If a change is detected, it initializes a counter + * that is decreased each time this function is called. If the counter reaches + * 1, that means that the same scan result has been scanned ten times in a row, + * so we can be pretty sure that the keys are in a certain state (as in: not + * bouncing). Then, the codes for keys and modifiers are searched from the two + * arrays, the USB-message to send the state is prepared. The return value of + * this function indicates if the message has to be sent. + * \return flag to indicate whether something has changed + */ +uint8_t scankeys(uint8_t* reportBuffer, uint8_t* oldReportBuffer, uint8_t sizeOfReportBuffer) { + static uint8_t debounce = 5; + uint8_t retval = 0; + SRDATAOFF; // mark first bit as the active one + SRCLOCKON; SRCLOCKOFF; // trigger clock to shift first bit into the register + SRDATAON; // all further bits will be inactive + for (uint8_t row = 0; row < 22; row++) { + SRSTROBEON; SRSTROBEOFF; // copy current register values to output + _delay_us(30); + uint16_t data = ((PINC & 0x1f) << 8) | PINA; // we need the lower five bits of PINC and PINA + if (data != curmatrix[row]) { + // if a change was detected + debounce = 10; // activate debounce counter + curmatrix[row] = data; // and store the result + ghostmatrix[row] = 0; + } + SRCLOCKON; SRCLOCKOFF; // trigger clock to shift register values + } + if (debounce) { + // Count down, but avoid underflow + debounce--; + } + if (debounce == 1) { + if (memcmp(oldmatrix, curmatrix, sizeof(curmatrix)) != 0) { + // printMatrix(); + memcpy(oldmatrix, curmatrix, sizeof(curmatrix)); + } + // debounce counter expired, create report + uint8_t reportIndex = 2; // reportBuffer[0] contains modifiers + memset(reportBuffer, 0, sizeOfReportBuffer); // clear report buffer + for (uint8_t row = 0; row < 22; row++) { // process all rows for key-codes + uint16_t data = curmatrix[row]; // restore buffer + if (data != 0x1fff) { // anything on this row? - optimization + for (uint8_t col = 0; col < 13; col++) { // check every bit on this row + uint8_t key, modifier, isghostkey; + if (!(data & (1 << col))) { + key = pgm_read_byte(&keymatrix[row][col]); + modifier = pgm_read_byte(&modmatrix[row][col]); + isghostkey = ghostmatrix[row] & (1 << col); + } else { + key = KEY_Reserved; + modifier = MOD_NONE; + isghostkey = 0x00; + } + if (key != KEY_Reserved) { // keycode should be added to report + if (reportIndex >= sizeOfReportBuffer) { // too many keycodes + if (!retval & 0x02) { // Only fill buffer once + memset(reportBuffer+2, KEY_ErrorRollOver, sizeOfReportBuffer-2); + retval |= 0x02; // continue decoding to get modifiers + } + } else { + if (isghostkey) { + // we're in a ghost-key situation + if (bufferContains(oldReportBuffer, key)) { + // this key has been pressed before, so we still send it + reportBuffer[reportIndex] = key; // set next available entry + reportIndex++; + } + } else { + reportBuffer[reportIndex] = key; // set next available entry + reportIndex++; + } + } + } + if (modifier != MOD_NONE) { // modifier should be added to report + reportBuffer[0] |= modifier; + } + } + } + } + retval |= 0x01; // must have been a change at some point, since debounce is done + } + return retval; +} + diff --git a/firmware/tools.h b/firmware/tools.h index b1d7dc3..1372da7 100644 --- a/firmware/tools.h +++ b/firmware/tools.h @@ -7,4 +7,10 @@ * License: TODO */ +#define LED_NUM 0x01 ///< num LED on a boot-protocol keyboard +#define LED_CAPS 0x02 ///< caps LED on a boot-protocol keyboard +#define LED_SCROLL 0x04 ///< scroll 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 + void sendString(char* string);