diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | README | 60 | ||||
-rw-r--r-- | keymap.c | 27 | ||||
-rw-r--r-- | keymap.h | 3 | ||||
-rw-r--r-- | matrix.c | 144 | ||||
-rw-r--r-- | matrix.h | 6 | ||||
-rw-r--r-- | mykey.c | 295 | ||||
-rw-r--r-- | print.c | 9 | ||||
-rw-r--r-- | print.h | 1 |
9 files changed, 336 insertions, 210 deletions
@@ -47,6 +47,7 @@ TARGET = mykey # List C source files here. (C dependencies are automatically generated.) SRC = $(TARGET).c \ keymap.c \ + matrix.c \ usb_keyboard_debug.c \ print.c @@ -0,0 +1,60 @@ +Keyboard Firmware +================= +2010/08/23 noname + + +VERSION +------- +0.1 2010/08/23 + implemented for macway modified. + It works as normal keyboard now. + + +TODO +---- +modulization + clean source +debouncing +anti-ghost +keymap layer + key combination switch + toggle siwtch + HHKB like cursor etc. +setting menu(wizard) + debug console + keymap setting + matrix display +HHKB support +Trackpoint(PS/2) support + Thinkpad keyboard support + + +target board +------------ +Teensy 2.0 +http://www.pjrc.com/teensy + + +projects based on/related to +---------------------------- +PJRC USB Keyboard Example + http://www.pjrc.com/teensy/usb_keyboard.html +kbupgrade + http://github.com/rhomann/kbupgrade + http://geekhack.org/showwiki.php?title=Island:8406 +c64key + http://symlink.dk/projects/c64key/ +rump + http://mg8.org/rump/ + http://github.com/clee/rump +dulcimer + http://www.schatenseite.de/dulcimer.html +humblehacker-keyboard + http://github.com/humblehacker + http://www.humblehacker.com/keyboard/ + http://geekhack.org/showwiki.php?title=Island:6292 +ps2avr + http://sourceforge.net/projects/ps2avr/ + + +EOF @@ -1,28 +1,27 @@ /* - * keymap for modified macway keyboard + * keymap for modified macway keyboarq */ #include <avr/pgmspace.h> #include "keymap.h" -#define MATRIX_ROWS 9 -#define MATRIX_COLS 8 - -static const uint8_t PROGMEM Keymap[MATRIX_COLS][MATRIX_ROWS] = { - { KB_LALT, KB_1, KB_2, KB_3, KB_4, KB_7, KB_8, KB_9, KB_0 }, - { KB_NO, KB_ESCAPE, KB_RALT, KB_NO, KB_5, KB_6, KB_EQUAL, KB_NO, KB_MINUS }, - { KB_BSPACE, KB_TAB, KB_LGUI, KB_RSHIFT, KB_T, KB_Y, KB_RBRACKET, KB_NO, KB_LBRACKET }, - { KB_NO, KB_Q, KB_W, KB_E, KB_R, KB_U, KB_I, KB_O, KB_P }, - { KB_BSLASH, KB_A, KB_S, KB_D, KB_F, KB_J, KB_K, KB_L, KB_SCOLON }, - { KB_NO, KB_LCTRL, KB_NO, KB_UP, KB_G, KB_H, KB_NO, KB_GRAVE, KB_QUOTE }, - { KB_ENTER, KB_Z, KB_X, KB_C, KB_V, KB_M, KB_COMMA, KB_DOWN, KB_NO }, - { KB_SPACE, KB_DOWN, KB_RIGHT, KB_LEFT, KB_B, KB_N, KB_LSHIFT, KB_NO, KB_SLASH } +static const uint8_t PROGMEM Keymap[MATRIX_ROWS][MATRIX_COLS] = { + { KB_LALT, KB_NO, KB_BSPACE, KB_NO, KB_LEFT, KB_NO, KB_ENTER, KB_SPACE }, + { KB_1, KB_ESCAPE, KB_TAB, KB_Q, KB_A, KB_LCTRL, KB_Z, KB_RIGHT }, + { KB_2, KB_RALT, KB_LGUI, KB_W, KB_S, KB_NO, KB_X, KB_UP }, + { KB_3, KB_NO, KB_RSHIFT, KB_E, KB_D, KB_BSLASH, KB_C, KB_DOWN }, + { KB_4, KB_5, KB_T, KB_R, KB_F, KB_G, KB_V, KB_B }, + { KB_7, KB_6, KB_Y, KB_U, KB_J, KB_H, KB_M, KB_N }, + { KB_8, KB_EQUAL, KB_RBRACKET, KB_I, KB_K, KB_NO, KB_COMMA, KB_LSHIFT }, + { KB_9, KB_NO, KB_NO, KB_O, KB_L, KB_GRAVE, KB_DOT, KB_NO }, + { KB_0, KB_MINUS, KB_LBRACKET, KB_P, KB_SCOLON, KB_QUOTE, KB_NO, KB_SLASH } }; + uint8_t get_keycode(uint8_t row, uint8_t col) { if (row >= MATRIX_ROWS) return KB_NO; if (col >= MATRIX_COLS) return KB_NO; - return pgm_read_byte(&Keymap[col][row]); + return pgm_read_byte(&Keymap[row][col]); } @@ -6,4 +6,7 @@ uint8_t get_keycode(uint8_t row, uint8_t col); +#define MATRIX_ROWS 9 +#define MATRIX_COLS 8 + #endif diff --git a/matrix.c b/matrix.c new file mode 100644 index 000000000..fc975a8fc --- /dev/null +++ b/matrix.c @@ -0,0 +1,144 @@ +/* + * scan matrix + */ +#include <avr/io.h> +#include <util/delay.h> +#include "keymap.h" +#include "matrix.h" +#include "print.h" + +uint8_t *matrix; +uint8_t *prev_matrix; +static uint8_t _matrix0[MATRIX_ROWS]; +static uint8_t _matrix1[MATRIX_ROWS]; + +static uint8_t read_col(void); +static void select_row(uint8_t row); + + +void matrix_init(void) +{ + // Column: input w/pullup + DDRB = 0x00; + PORTB = 0xFF; + + // Row: Hi-Z(unselected) + // PD:0,1,2,3,6,7 + // PC:6,7 + // PF:7 + DDRD = 0x00; + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + + for (int i=0; i < MATRIX_ROWS; i++) { + _matrix0[i] = 0xFF; + _matrix1[i] = 0xFF; + } + matrix = _matrix0; + prev_matrix = _matrix1; +} + +uint8_t matrix_scan(void) +{ + uint8_t row, state; + uint8_t *tmp; + + tmp = prev_matrix; + prev_matrix = matrix; + matrix = tmp; + + for (row = 0; row < MATRIX_ROWS; row++) { + select_row(row); + _delay_us(30); // without this wait read unstable value. + state = read_col(); + + matrix[row] = state; + } + return 1; +} + +static uint8_t read_col(void) +{ + return PINB; +} + +static void select_row(uint8_t row) +{ + switch (row) { + case 0: + DDRD = (1<<0); + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 1: + DDRD = (1<<1); + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 2: + DDRD = (1<<2); + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 3: + DDRD = (1<<3); + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 4: + DDRD = (1<<6); + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 5: + DDRD = (1<<7); + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 6: + DDRD = 0x00; + PORTD = 0x00; + DDRC = (1<<6); + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 7: + DDRD = 0x00; + PORTD = 0x00; + DDRC = (1<<7); + PORTC = 0x00; + DDRF = 0x00; + PORTF = 0x00; + break; + case 8: + DDRD = 0x00; + PORTD = 0x00; + DDRC = 0x00; + PORTC = 0x00; + DDRF = (1<<7); + PORTF = 0x00; + break; + } +} diff --git a/matrix.h b/matrix.h new file mode 100644 index 000000000..662421569 --- /dev/null +++ b/matrix.h @@ -0,0 +1,6 @@ + +extern uint8_t *matrix; +extern uint8_t *prev_matrix; + +void matrix_init(void); +uint8_t matrix_scan(void); @@ -1,3 +1,6 @@ +/* 2010/08/23 noname + * keyboard firmware based on PJRC USB keyboard example + */ /* Keyboard example with debug channel, for Teensy USB Development Board * http://www.pjrc.com/teensy/usb_keyboard.html * Copyright (c) 2008 PJRC.COM, LLC @@ -27,211 +30,115 @@ #include <util/delay.h> #include "usb_keyboard_debug.h" #include "print.h" +#include "matrix.h" #include "keymap.h" -#define LED_CONFIG (DDRD |= (1<<6)) -#define LED_ON (PORTD &= ~(1<<6)) -#define LED_OFF (PORTD |= (1<<6)) -#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) +#define LED_CONFIG (DDRD |= (1<<6)) +#define LED_ON (PORTD &= ~(1<<6)) +#define LED_OFF (PORTD |= (1<<6)) +#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) -uint8_t number_keys[10]= - {KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9}; uint16_t idle_count=0; -// -// scan matrix -// -uint8_t MAX_ROW = 9; - -// initialize ports for matrix -void port_setup(void) +int main(void) { - // Column: input w/pullup - DDRB = 0x00; - PORTB = 0xFF; - - // Row: Hi-Z(unselected) - // PD:0,1,2,3,6,7 - // PC:6,7 - // PF:7 - DDRD = 0x00; - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; -} + uint8_t modified = 0; + uint8_t key_index = 0; -// select a row of matrix for read -void select_row(uint8_t row) -{ - switch (row) { - case 0: - DDRD = (1<<0); - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 1: - DDRD = (1<<1); - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 2: - DDRD = (1<<2); - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 3: - DDRD = (1<<3); - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 4: - DDRD = (1<<6); - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 5: - DDRD = (1<<7); - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 6: - DDRD = 0x00; - PORTD = 0x00; - DDRC = (1<<6); - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 7: - DDRD = 0x00; - PORTD = 0x00; - DDRC = (1<<7); - PORTC = 0x00; - DDRF = 0x00; - PORTF = 0x00; - break; - case 8: - DDRD = 0x00; - PORTD = 0x00; - DDRC = 0x00; - PORTC = 0x00; - DDRF = (1<<7); - PORTF = 0x00; - break; - } -} + // set for 16 MHz clock + CPU_PRESCALE(0); -uint8_t read_col(void) -{ - return PINB; -} + matrix_init(); -int main(void) -{ - uint8_t i, reset_idle; - uint8_t prev_state[MAX_ROW]; - for (int i=0; i < MAX_ROW; i++) prev_state[i] = 0xFF; - - // set for 16 MHz clock - CPU_PRESCALE(0); - - port_setup(); - - - // Initialize the USB, and then wait for the host to set configuration. - // If the Teensy is powered without a PC connected to the USB port, - // this will wait forever. - usb_init(); - while (!usb_configured()) /* wait */ ; - - // Wait an extra second for the PC's operating system to load drivers - // and do whatever it does to actually be ready for input - _delay_ms(1000); - - // Configure timer 0 to generate a timer overflow interrupt every - // 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock - // This demonstrates how to use interrupts to implement a simple - // inactivity timeout. - TCCR0A = 0x00; - TCCR0B = 0x05; - TIMSK0 = (1<<TOIE0); - - print("Begin keyboard example program\n"); - print("All Port B or Port D pins are inputs with pullup resistors.\n"); - print("Any connection to ground on Port B or D pins will result in\n"); - print("keystrokes sent to the PC (and debug messages here).\n"); - - uint8_t col; - uint8_t code; - while (1) { - reset_idle = 0; - - for (uint8_t r=0; r < MAX_ROW; r++) { - select_row(r); - - // without this read unstable value. - _delay_us(30); - - col = read_col(); - if (col != prev_state[r]) { - prev_state[r] = col; - phex(r); - print(": "); - pbin(col); - print("\n"); - - for (int c = 0; c < 8; c++) { - if (col & 1<<c) continue; - code = get_keycode(r, c); - phex(code); - print("\n"); - usb_keyboard_press(code, 0); - } - reset_idle = 1; + // Initialize the USB, and then wait for the host to set configuration. + // If the Teensy is powered without a PC connected to the USB port, + // this will wait forever. + usb_init(); + while (!usb_configured()) /* wait */ ; + + // Wait an extra second for the PC's operating system to load drivers + // and do whatever it does to actually be ready for input + _delay_ms(1000); + + // Configure timer 0 to generate a timer overflow interrupt every + // 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock + // This demonstrates how to use interrupts to implement a simple + // inactivity timeout. + TCCR0A = 0x00; + TCCR0B = 0x05; + TIMSK0 = (1<<TOIE0); + + print("keyboard firmware 0.1 for t.m.k.\n"); + + while (1) { + uint8_t row, col, code; + + modified = 0; + + matrix_scan(); + + keyboard_modifier_keys = 0; + for (int i = 0; i < 6; i++) + keyboard_keys[i] = KB_NO; + key_index = 0; + + for (row = 0; row < MATRIX_ROWS; row++) { + if (matrix[row] != prev_matrix[row]) { + modified = 1; + } + + for (col = 0; col < MATRIX_COLS; col++) { + if (matrix[row] & 1<<col) continue; + code = get_keycode(row, col); + + // Modifier keycode: 0xE0-0xE7 + if (KB_LCTRL <= code && code <= KB_RGUI) { + keyboard_modifier_keys |= 1<<(code&0x07); + } else { + if (key_index < 6) { + keyboard_keys[key_index] = code; + } + key_index++; } + } + } + + if (key_index > 6) { + //Rollover + } - // if any keypresses were detected, reset the idle counter - if (reset_idle) { - // variables shared with interrupt routines must be - // accessed carefully so the interrupt routine doesn't - // try to use the variable in the middle of our access - cli(); - idle_count = 0; - sei(); - } - - // now the current pins will be the previous, and - // wait a short delay so we're not highly sensitive - // to mechanical "bounce". - _delay_ms(2); - } + // if any keypresses were detected, reset the idle counter + if (modified) { + print(" 01234567\n"); + for (row = 0; row < MATRIX_ROWS; row++) { + phex(row); print(": "); pbin_reverse(matrix[row]); print("\n"); + } + print("keys: "); + for (int i = 0; i < 6; i++) { phex(keyboard_keys[i]); print(" "); } + print("\n"); + print("mod: "); phex(keyboard_modifier_keys); print("\n"); + usb_keyboard_send(); + + // variables shared with interrupt routines must be + // accessed carefully so the interrupt routine doesn't + // try to use the variable in the middle of our access + cli(); + idle_count = 0; + sei(); + } + + // now the current pins will be the previous, and + // wait a short delay so we're not highly sensitive + // to mechanical "bounce". + _delay_ms(2); + } } // This interrupt routine is run approx 61 times per second. @@ -240,12 +147,10 @@ int main(void) // hid_listen debug message window. ISR(TIMER0_OVF_vect) { - idle_count++; - if (idle_count > 61 * 8) { - idle_count = 0; - print("Timer Event :)\n"); - //usb_keyboard_press(KEY_SPACE, 0); - } + idle_count++; + if (idle_count > 61 * 8) { + idle_count = 0; + //print("Timer Event :)\n"); + //usb_keyboard_press(KEY_SPACE, 0); + } } - - @@ -60,7 +60,14 @@ void phex16(unsigned int i) void pbin(unsigned char c) { - for (int i=7; i>=0; i--) { + for (int i = 7; i >= 0; i--) { + usb_debug_putchar((c & (1<<i)) ? '1' : '0'); + } +} + +void pbin_reverse(unsigned char c) +{ + for (int i = 0; i < 8; i++) { usb_debug_putchar((c & (1<<i)) ? '1' : '0'); } } @@ -13,5 +13,6 @@ void print_P(const char *s); void phex(unsigned char c); void phex16(unsigned int i); void pbin(unsigned char c); +void pbin_reverse(unsigned char c); #endif |