new hardware support: IBM Host keyboard
This commit is contained in:
		@@ -10,9 +10,10 @@
 | 
				
			|||||||
AVRDUDE = avrdude -p atmega32 -c usbasp
 | 
					AVRDUDE = avrdude -p atmega32 -c usbasp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Options:
 | 
					# Options:
 | 
				
			||||||
HWOBJECTS = modelibmmodelm.o
 | 
					#HWOBJECTS = modelibmmodelm.o
 | 
				
			||||||
#HWOBJECTS = modelmayhem.o
 | 
					#HWOBJECTS = modelmayhem.o
 | 
				
			||||||
#HWOBJECTS = modelsuntype5.o
 | 
					#HWOBJECTS = modelsuntype5.o
 | 
				
			||||||
 | 
					HWOBJECTS = modelibmhost.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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										313
									
								
								firmware/modelibmhost.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								firmware/modelibmhost.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,313 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \file firmware/modelibmmodelm.c
 | 
				
			||||||
 | 
					 * \brief Hardware specific part for IBM Host keyboard
 | 
				
			||||||
 | 
					 * \author Ronald Schaten <ronald@schatenseite.de>
 | 
				
			||||||
 | 
					 * \version $Id: modelibmmodelm.c 173 2009-02-14 21:11:43Z rschaten $
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * License: GNU GPL v2 (see License.txt)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <avr/io.h>
 | 
				
			||||||
 | 
					#include <avr/pgmspace.h>
 | 
				
			||||||
 | 
					#include <util/delay.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "keycodes.h"
 | 
				
			||||||
 | 
					#include "tools.h"
 | 
				
			||||||
 | 
					#include "modelinterface.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ----------------------- hardware I/O abstraction ------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PORTCOLUMNS PORTB  ///< port on which we read the state of the columns
 | 
				
			||||||
 | 
					#define PINCOLUMNS  PINB   ///< port on which we read the state of the columns
 | 
				
			||||||
 | 
					#define DDRCOLUMNS  DDRB   ///< port on which we read the state of the columns
 | 
				
			||||||
 | 
					#define PORTROWS1   PORTA  ///< first port connected to the matrix rows
 | 
				
			||||||
 | 
					#define PINROWS1    PINA   ///< first port connected to the matrix rows
 | 
				
			||||||
 | 
					#define DDRROWS1    DDRA   ///< first port connected to the matrix rows
 | 
				
			||||||
 | 
					#define PORTROWS2   PORTC  ///< second port connected to the matrix rows
 | 
				
			||||||
 | 
					#define PINROWS2    PINC   ///< second port connected to the matrix rows
 | 
				
			||||||
 | 
					#define DDRROWS2    DDRC   ///< second port connected to the matrix rows
 | 
				
			||||||
 | 
					#define PORTROWS3   PORTD  ///< third port connected to the matrix rows
 | 
				
			||||||
 | 
					#define PINROWS3    PIND   ///< third port connected to the matrix rows
 | 
				
			||||||
 | 
					#define DDRROWS3    DDRD   ///< third port connected to the matrix rows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t curmatrix[20];  ///< contains current state of the keyboard
 | 
				
			||||||
 | 
					uint8_t oldmatrix[20];  ///< contains old state of the keyboard
 | 
				
			||||||
 | 
					uint8_t ghostmatrix[20]; ///< contains pressed keys that belong to a ghost-key situation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void hardwareInit(void) {
 | 
				
			||||||
 | 
					    // column-port is input
 | 
				
			||||||
 | 
					    PORTCOLUMNS = 0xff;
 | 
				
			||||||
 | 
					    DDRCOLUMNS  = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // row-ports are output
 | 
				
			||||||
 | 
					    PORTROWS1   = 0xff;
 | 
				
			||||||
 | 
					    DDRROWS1    = 0x00;
 | 
				
			||||||
 | 
					    PORTROWS2   = 0xff;
 | 
				
			||||||
 | 
					    DDRROWS2    = 0x00;
 | 
				
			||||||
 | 
					    PORTROWS3   |= ((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					    DDRROWS3    &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // port D contains USB (D0, D2),
 | 
				
			||||||
 | 
					    //             and keyboard rows (D4, D5, D6, D7).
 | 
				
			||||||
 | 
					    // so we call it PORTD instead of PORTJUMPERS or PORTLEDS
 | 
				
			||||||
 | 
					    PORTD       &= ~((1 << PIND0) | (1 << PIND2)); // deactivate pull-ups on USB-lines
 | 
				
			||||||
 | 
					    DDRD        |= ((1 << PIND0) | (1 << PIND2)); // set reset USB condition.
 | 
				
			||||||
 | 
					                        // USB reset by device only required on watchdog reset
 | 
				
			||||||
 | 
					    _delay_us(11);      // delay >10us for USB reset
 | 
				
			||||||
 | 
					    DDRD        &= ~((1 << PIND0) | (1 << PIND2)); // remove USB reset condition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // configure timer 0 for a rate of 12M/(1024 * 256) = 45.78Hz (~22ms)
 | 
				
			||||||
 | 
					    TCCR0 = 5;          // timer 0 prescaler: 1024
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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 <= 19; i++) {
 | 
				
			||||||
 | 
					        char buffer[10];
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					        sprintf(buffer, "%d%d%d%d%d%d%d%d.",
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 0) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 1) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 2) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 3) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 4) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 5) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 6) ? 1 : 0),
 | 
				
			||||||
 | 
					                (curmatrix[i] & (1 << 7) ? 1 : 0));
 | 
				
			||||||
 | 
					                */
 | 
				
			||||||
 | 
					        sprintf(buffer, "%2x", curmatrix[i]);
 | 
				
			||||||
 | 
					        sendString(buffer);
 | 
				
			||||||
 | 
					        if ((i == 7) || (i == 15)) {
 | 
				
			||||||
 | 
					            sendString(":");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            sendString(".");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    sendString("---");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void toggle(void) {
 | 
				
			||||||
 | 
					    // not used in this model/version
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setSpeed(uint8_t speed) {
 | 
				
			||||||
 | 
					    // not used in this model/version
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setLeds(uint8_t LEDstate) {
 | 
				
			||||||
 | 
					    // do nothing, since we don't have fancy lights on this hardware
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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[20][8] = {
 | 
				
			||||||
 | 
					  // 0 / 0x01       1 / 0x02       2 / 0x04      3 / 0x08      4 / 0x10      5 / 0x20         6 / 0x40           7 / 0x80
 | 
				
			||||||
 | 
					    {KEY_KPenter,   KEY_Reserved,  KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved,    KEY_RightArrow,    KEY_Application }, //  0
 | 
				
			||||||
 | 
					    {KEY_KPcomma,   KEY_KP3,       KEY_Reserved, KEY_KP9,      KEY_Reserved, KEY_KPslash,     KEY_KP6,           KEY_Reserved    }, //  1
 | 
				
			||||||
 | 
					    {KEY_KP0,       KEY_KP2,       KEY_Reserved, KEY_KP8,      KEY_Home,     KEY_KPequals,    KEY_KP5,           KEY_Reserved    }, //  2
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_Reserved,  KEY_End,      KEY_PageDown, KEY_Insert,   KEY_PageUp,      KEY_DeleteForward, KEY_UpArrow     }, //  3
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_Return,    KEY_Reserved, KEY_KP7,      KEY_DELETE,   KEY_KPBackspace, KEY_KP4,           KEY_DownArrow   }, //  4
 | 
				
			||||||
 | 
					    {KEY_slash,     KEY_hash,      KEY_lbracket, KEY_P,        KEY_minus,    KEY_0,           KEY_semicolon,     KEY_apostroph   }, //  5
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_dot,       KEY_Reserved, KEY_O,        KEY_Reserved, KEY_9,           KEY_L,             KEY_Reserved    }, //  6
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_comma,     KEY_rbracket, KEY_I,        KEY_equals,   KEY_8,           KEY_K,             KEY_Reserved    }, //  7
 | 
				
			||||||
 | 
					    {KEY_F12,       KEY_F11,       KEY_F9,       KEY_F8,       KEY_F6,       KEY_F5,          KEY_F3,            KEY_F2          }, //  8
 | 
				
			||||||
 | 
					    {KEY_F24,       KEY_F10,       KEY_F21,      KEY_F7,       KEY_F18,      KEY_F4,          KEY_F15,           KEY_F1          }, //  9
 | 
				
			||||||
 | 
					    {KEY_F23,       KEY_F22,       KEY_F20,      KEY_F19,      KEY_F17,      KEY_F16,         KEY_F14,           KEY_F13         }, // 10
 | 
				
			||||||
 | 
					    {KEY_N,         KEY_M,         KEY_Z,        KEY_U,        KEY_6,        KEY_7,           KEY_J,             KEY_H           }, // 11
 | 
				
			||||||
 | 
					    {KEY_B,         KEY_V,         KEY_T,        KEY_R,        KEY_5,        KEY_4,           KEY_F,             KEY_G           }, // 12
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_C,         KEY_Reserved, KEY_E,        KEY_Reserved, KEY_3,           KEY_D,             KEY_Reserved    }, // 13
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_X,         KEY_Reserved, KEY_W,        KEY_Reserved, KEY_2,           KEY_S,             KEY_Reserved    }, // 14
 | 
				
			||||||
 | 
					    {KEY_Euro,      KEY_Y,         KEY_Reserved, KEY_Q,        KEY_grave,    KEY_1,           KEY_A,             KEY_Reserved    }, // 15
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_Reserved,  KEY_Reserved, KEY_Reserved, KEY_Reserved, KEY_Reserved,    KEY_Reserved,      KEY_Reserved    }, // 16
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_capslock,  KEY_Copy,     KEY_Tab,      KEY_Again,    KEY_Reserved,    KEY_Paste,         KEY_Find        }, // 17
 | 
				
			||||||
 | 
					    {KEY_Spacebar,  KEY_KP1,       KEY_Execute,  KEY_Undo,     KEY_Stop,     KEY_Menu,        KEY_Select,        KEY_Cut         }, // 18
 | 
				
			||||||
 | 
					    {KEY_Reserved,  KEY_LeftArrow, KEY_Reserved, KEY_KPminus,  KEY_Reserved, KEY_KPasterisk,  KEY_KPplus,        KEY_Reserved    }, // 19
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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[20][8] = { // contains positions of modifiers in the matrix
 | 
				
			||||||
 | 
					  // 0                  1                2         3         4         5         6         7
 | 
				
			||||||
 | 
					    {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         }, //  1
 | 
				
			||||||
 | 
					    {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         }, //  3
 | 
				
			||||||
 | 
					    {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         }, //  5
 | 
				
			||||||
 | 
					    {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_NONE, MOD_NONE, MOD_NONE         }, //  7
 | 
				
			||||||
 | 
					    {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         }, //  9
 | 
				
			||||||
 | 
					    {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_NONE, MOD_NONE, MOD_NONE, MOD_NONE         }, // 11
 | 
				
			||||||
 | 
					    {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         }, // 13
 | 
				
			||||||
 | 
					    {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         }, // 15
 | 
				
			||||||
 | 
					    {MOD_SHIFT_LEFT,    MOD_SHIFT_RIGHT, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_ALT_RIGHT    }, // 16
 | 
				
			||||||
 | 
					    {MOD_CONTROL_RIGHT, 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         }, // 18
 | 
				
			||||||
 | 
					    {MOD_ALT_LEFT,      MOD_NONE,        MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_NONE, MOD_CONTROL_LEFT }, // 19
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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;
 | 
				
			||||||
 | 
					    for (uint8_t row = 0; row <= 19; row++) {
 | 
				
			||||||
 | 
					        if (row <= 7) {
 | 
				
			||||||
 | 
					            DDRROWS1  = (1 << row);
 | 
				
			||||||
 | 
					            PORTROWS1 = ~(1 << row);
 | 
				
			||||||
 | 
					            DDRROWS2  = 0x00;
 | 
				
			||||||
 | 
					            PORTROWS2 = 0xff;
 | 
				
			||||||
 | 
					            PORTROWS3 |= ((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					            DDRROWS3  &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					        } else if (row <= 15) {
 | 
				
			||||||
 | 
					            DDRROWS1  = 0x00;
 | 
				
			||||||
 | 
					            PORTROWS1 = 0xff;
 | 
				
			||||||
 | 
					            // (15 - row) looks a bit weird, you would expect (row - 8) here.
 | 
				
			||||||
 | 
					            // This is because pins on PORTC are ordered in the other direction
 | 
				
			||||||
 | 
					            // than on PORTA. With (15 - row), we have the bytes in the
 | 
				
			||||||
 | 
					            // resulting matrix matching the pins of the keyboard connector.
 | 
				
			||||||
 | 
					            DDRROWS2  = (1 << (15 - row));
 | 
				
			||||||
 | 
					            PORTROWS2 = ~(1 << (15 - row));
 | 
				
			||||||
 | 
					            PORTROWS3 |= ((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					            DDRROWS3  &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            DDRROWS1  = 0x00;
 | 
				
			||||||
 | 
					            PORTROWS1 = 0xff;
 | 
				
			||||||
 | 
					            DDRROWS2  = 0x00;
 | 
				
			||||||
 | 
					            PORTROWS2 = 0xff;
 | 
				
			||||||
 | 
					            // As if the case above wasn't difficult enough, on PORTD we have
 | 
				
			||||||
 | 
					            // to make sure that the scanning doesn't affect USB
 | 
				
			||||||
 | 
					            // communications, which occur on PIND0 and PIND2.
 | 
				
			||||||
 | 
					            PORTROWS3 |= ((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					            DDRROWS3  &= ~((1 << PIND4) | (1 << PIND5) | (1 << PIND6) | (1 << PIND7));
 | 
				
			||||||
 | 
					            DDRROWS3  |= (1 << (19 - row + 4));
 | 
				
			||||||
 | 
					            PORTROWS3 &= ~(1 << (19 - row + 4));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _delay_us(30);
 | 
				
			||||||
 | 
					        uint8_t data = ~PINCOLUMNS;
 | 
				
			||||||
 | 
					        // check if we have to prevent ghost-keys
 | 
				
			||||||
 | 
					        uint16_t rows = (PINROWS1 << 8) | PINROWS2; // TODO
 | 
				
			||||||
 | 
					        if (bitcount2(~rows) && bitcount2(data)) {
 | 
				
			||||||
 | 
					            // ghost-key situation detected
 | 
				
			||||||
 | 
					            ghostmatrix[row] = data;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ghostmatrix[row] = 0x00;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (data != curmatrix[row]) {
 | 
				
			||||||
 | 
					            // if a change was detected
 | 
				
			||||||
 | 
					            debounce = 10; // activate debounce counter
 | 
				
			||||||
 | 
					            curmatrix[row] = data; // and store the result
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (debounce) {
 | 
				
			||||||
 | 
					        // Count down, but avoid underflow
 | 
				
			||||||
 | 
					        debounce--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (debounce == 1) {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					        if (memcmp(oldmatrix, curmatrix, sizeof(curmatrix)) != 0) {
 | 
				
			||||||
 | 
					            printMatrix();
 | 
				
			||||||
 | 
					            memcpy(oldmatrix, curmatrix, sizeof(curmatrix));
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        // 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 <= 19; row++) { // process all rows for key-codes
 | 
				
			||||||
 | 
					            uint8_t data = curmatrix[row]; // restore buffer
 | 
				
			||||||
 | 
					            if (data != 0xff) { // anything on this row? - optimization
 | 
				
			||||||
 | 
					                for (uint8_t col = 0; col <= 7; 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)) != 0;
 | 
				
			||||||
 | 
					                    } 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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user