added initial V-USB support for HHKB
This commit is contained in:
83
hhkb/Makefile.vusb
Normal file
83
hhkb/Makefile.vusb
Normal file
@@ -0,0 +1,83 @@
|
||||
# Target file name (without extension).
|
||||
TARGET = hhkb_vusb
|
||||
|
||||
# Directory common source filess exist
|
||||
COMMON_DIR = ..
|
||||
|
||||
# Directory keyboard dependent files exist
|
||||
TARGET_DIR = .
|
||||
|
||||
# keyboard dependent files
|
||||
TARGET_SRC = main_vusb.c \
|
||||
keymap.c \
|
||||
matrix.c \
|
||||
led.c
|
||||
|
||||
CONFIG_H = config_vusb.h
|
||||
|
||||
|
||||
# V-USB debug level: To use ps2_usart.c level must be 0
|
||||
# ps2_usart.c requires USART to receive PS/2 signal.
|
||||
OPT_DEFS = -DDEBUG_LEVEL=0
|
||||
|
||||
|
||||
# MCU name, you MUST set this to match the board you are using
|
||||
# type "make clean" after changing this, so all files will be rebuilt
|
||||
#MCU = at90usb162 # Teensy 1.0
|
||||
#MCU = atmega32u4 # Teensy 2.0
|
||||
#MCU = at90usb646 # Teensy++ 1.0
|
||||
#MCU = at90usb1286 # Teensy++ 2.0
|
||||
MCU = atmega168
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# Normally the first thing your program should do is set the clock prescaler,
|
||||
# so your program will run at the correct speed. You should also set this
|
||||
# variable to same clock speed. The _delay_ms() macro uses this, and many
|
||||
# examples use this variable to calculate timings. Do not add a "UL" here.
|
||||
F_CPU = 20000000
|
||||
|
||||
|
||||
# Build Options
|
||||
# comment out to disable the options.
|
||||
#
|
||||
MOUSEKEY_ENABLE = yes # Mouse keys
|
||||
#USB_EXTRA_ENABLE = yes # Enhanced feature for Windows(Audio control and System control)
|
||||
#USB_NKRO_ENABLE = yes # USB Nkey Rollover
|
||||
|
||||
|
||||
|
||||
#---------------- Programming Options --------------------------
|
||||
AVRDUDE = avrdude
|
||||
# Type: avrdude -c ? to get a full listing.
|
||||
AVRDUDE_PROGRAMMER = usbasp
|
||||
AVRDUDE_PORT =
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE_COUNTER = -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_NO_VERIFY = -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_VERBOSE = -v -v
|
||||
|
||||
#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
||||
|
||||
PROGRAM_CMD = $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
|
||||
include $(COMMON_DIR)/Makefile.vusb
|
||||
include $(COMMON_DIR)/Makefile.common
|
120
hhkb/config_vusb.h
Normal file
120
hhkb/config_vusb.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0xC0FE
|
||||
// TODO: share these strings with usbconfig.h
|
||||
// Edit usbconfig.h to change these.
|
||||
#define MANUFACTURER t.m.k.
|
||||
#define PRODUCT HHKB mod
|
||||
#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod
|
||||
|
||||
|
||||
/* matrix size */
|
||||
#define MATRIX_ROWS 8
|
||||
#define MATRIX_COLS 8
|
||||
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() ( \
|
||||
keyboard_report->mods == (BIT_LSHIFT | BIT_RSHIFT) || \
|
||||
keyboard_report->mods == (BIT_LCTRL | BIT_RSHIFT) \
|
||||
)
|
||||
|
||||
|
||||
/* mouse keys */
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
# define MOUSEKEY_DELAY_TIME 255
|
||||
#endif
|
||||
|
||||
|
||||
/* PS/2 lines */
|
||||
#ifdef PS2_MOUSE_ENABLE
|
||||
|
||||
#define PS2_CLOCK_PORT PORTD
|
||||
#define PS2_CLOCK_PIN PIND
|
||||
#define PS2_CLOCK_DDR DDRD
|
||||
#define PS2_CLOCK_BIT 4
|
||||
#define PS2_DATA_PORT PORTD
|
||||
#define PS2_DATA_PIN PIND
|
||||
#define PS2_DATA_DDR DDRD
|
||||
#define PS2_DATA_BIT 0
|
||||
|
||||
|
||||
// Synchronous USART is used to receive data from keyboard.
|
||||
// Use RXD pin for PS/2 DATA line and XCK for PS/2 CLOCK.
|
||||
// NOTE: This is recomended strongly if you use V-USB library.
|
||||
#define PS2_USE_USART
|
||||
|
||||
// External or Pin Change Interrupt is used to receive data from keyboard.
|
||||
// Use INT1 or PCINTxx for PS/2 CLOCK line. see below.
|
||||
//#define PS2_USE_INT
|
||||
|
||||
|
||||
#ifdef PS2_USE_USART
|
||||
// synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge
|
||||
// set DDR of CLOCK as input to be slave
|
||||
#define PS2_USART_INIT() do { \
|
||||
PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \
|
||||
PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \
|
||||
UCSR0C = ((1 << UMSEL00) | \
|
||||
(3 << UPM00) | \
|
||||
(0 << USBS0) | \
|
||||
(3 << UCSZ00) | \
|
||||
(0 << UCPOL0)); \
|
||||
UCSR0A = 0; \
|
||||
UBRR0H = 0; \
|
||||
UBRR0L = 0; \
|
||||
} while (0)
|
||||
#define PS2_USART_RX_INT_ON() do { \
|
||||
UCSR0B = ((1 << RXCIE0) | \
|
||||
(1 << RXEN0)); \
|
||||
} while (0)
|
||||
#define PS2_USART_RX_POLL_ON() do { \
|
||||
UCSR0B = (1 << RXEN0); \
|
||||
} while (0)
|
||||
#define PS2_USART_OFF() do { \
|
||||
UCSR0C = 0; \
|
||||
UCSR0B &= ~((1 << RXEN0) | \
|
||||
(1 << TXEN0)); \
|
||||
} while (0)
|
||||
#define PS2_USART_RX_READY (UCSR0A & (1<<RXC0))
|
||||
#define PS2_USART_RX_DATA UDR0
|
||||
#define PS2_USART_ERROR (UCSR0A & ((1<<FE0) | (1<<DOR0) | (1<<UPE0)))
|
||||
#define PS2_USART_RX_VECT USART_RX_vect
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PS2_USE_INT
|
||||
/* INT1
|
||||
#define PS2_INT_INIT() do { \
|
||||
EICRA |= ((1<<ISC11) | \
|
||||
(0<<ISC10)); \
|
||||
} while (0)
|
||||
#define PS2_INT_ON() do { \
|
||||
EIMSK |= (1<<INT1); \
|
||||
} while (0)
|
||||
#define PS2_INT_OFF() do { \
|
||||
EIMSK &= ~(1<<INT1); \
|
||||
} while (0)
|
||||
#define PS2_INT_VECT INT1_vect
|
||||
*/
|
||||
|
||||
/* PCINT20 */
|
||||
#define PS2_INT_INIT() do { \
|
||||
PCICR |= (1<<PCIE2); \
|
||||
} while (0)
|
||||
#define PS2_INT_ON() do { \
|
||||
PCMSK2 |= (1<<PCINT20); \
|
||||
} while (0)
|
||||
#define PS2_INT_OFF() do { \
|
||||
PCMSK2 &= ~(1<<PCINT20); \
|
||||
PCICR &= ~(1<<PCIE2); \
|
||||
} while (0)
|
||||
#define PS2_INT_VECT PCINT2_vect
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -42,7 +42,7 @@ static const uint8_t PROGMEM fn_layer[] = {
|
||||
2, // Fn2
|
||||
3, // Fn3
|
||||
4, // Fn4
|
||||
5, // Fn5
|
||||
0, // Fn5
|
||||
0, // Fn6
|
||||
0 // Fn7
|
||||
};
|
||||
@@ -54,8 +54,8 @@ static const uint8_t PROGMEM fn_keycode[] = {
|
||||
KB_NO, // Fn1
|
||||
KB_SLSH, // Fn2
|
||||
KB_SCLN, // Fn3
|
||||
KB_RGUI, // Fn4
|
||||
KB_SPC, // Fn5
|
||||
KB_SPC, // Fn4
|
||||
KB_NO, // Fn5
|
||||
KB_NO, // Fn6
|
||||
KB_NO // Fn7
|
||||
};
|
||||
@@ -78,7 +78,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KB_TAB, KB_Q, KB_W, KB_E, KB_R, KB_T, KB_Y, KB_U, KB_I, KB_O, KB_P, KB_LBRC,KB_RBRC,KB_BSPC, \
|
||||
KB_LCTL,KB_A, KB_S, KB_D, KB_F, KB_G, KB_H, KB_J, KB_K, KB_L, KB_FN3, KB_QUOT,KB_ENT, \
|
||||
KB_LSFT,KB_Z, KB_X, KB_C, KB_V, KB_B, KB_N, KB_M, KB_COMM,KB_DOT, KB_FN2, KB_RSFT,KB_FN1, \
|
||||
KB_LGUI,KB_LALT,KB_FN5, KB_RALT,KB_FN4),
|
||||
KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI),
|
||||
|
||||
/* Layer 1: HHKB mode (HHKB Fn)
|
||||
* ,-----------------------------------------------------------.
|
||||
@@ -155,27 +155,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KB_BSPC,KB_P, KB_O, KB_I, KB_U, KB_Y, KB_T, KB_R, KB_E, KB_W, KB_Q, KB_NO, KB_NO, KB_TAB, \
|
||||
KB_LCTL,KB_SCLN,KB_L, KB_K, KB_J, KB_H, KB_G, KB_F, KB_D, KB_S, KB_A, KB_RCTL,KB_RCTL, \
|
||||
KB_LSFT,KB_SLSH,KB_DOT, KB_COMM,KB_M, KB_N, KB_B, KB_V, KB_C, KB_X, KB_Z, KB_RSFT,KB_NO, \
|
||||
KB_LGUI,KB_LALT,KB_SPC, KB_RALT,KB_FN4),
|
||||
|
||||
/* Layer 5: Mouse mode
|
||||
* ,-----------------------------------------------------------.
|
||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Tab |MwL|MwU|McU|MwD|MwR|MwL|MwD|MwU|MwR| | | |Backs|
|
||||
* |-----------------------------------------------------------|
|
||||
* |Contro| |McL|McD|McR| |McL|McD|McU|McR|Mb1| |Return |
|
||||
* |-----------------------------------------------------------|
|
||||
* |Shift |Mb4|Mb5|Mb1|Mb2|Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
|
||||
* `-----------------------------------------------------------'
|
||||
* |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxxx|Alt |Gui|
|
||||
* `--------------------------------------------'
|
||||
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
|
||||
*/
|
||||
KEYMAP(KB_ESC, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_F11, KB_F12, KB_INS, KB_DEL, \
|
||||
KB_TAB, KB_WH_L,KB_WH_U,KB_MS_U,KB_WH_D,KB_WH_R,KB_WH_L,KB_WH_D,KB_WH_U,KB_WH_R,KB_NO, KB_NO, KB_NO, KB_BSPC, \
|
||||
KB_LCTL,KB_NO, KB_MS_L,KB_MS_D,KB_MS_R,KB_NO, KB_MS_L,KB_MS_D,KB_MS_U,KB_MS_R,KB_BTN1,KB_NO, KB_ENT, \
|
||||
KB_LSFT,KB_BTN4,KB_BTN5,KB_BTN1,KB_BTN2,KB_BTN3,KB_BTN2,KB_BTN1,KB_BTN4,KB_BTN5,KB_NO, KB_RSFT,KB_NO, \
|
||||
KB_LGUI,KB_LALT,KB_FN5, KB_RALT,KB_RGUI),
|
||||
KB_LGUI,KB_LALT,KB_FN4, KB_RALT,KB_RGUI)
|
||||
};
|
||||
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "print.h"
|
||||
#include "util.h"
|
||||
@@ -31,29 +32,62 @@ static uint16_t _matrix0[MATRIX_ROWS];
|
||||
static uint16_t _matrix1[MATRIX_ROWS];
|
||||
#endif
|
||||
|
||||
// HHKB has no ghost and no bounce.
|
||||
#ifdef MATRIX_HAS_GHOST
|
||||
static bool matrix_has_ghost_in_row(uint8_t row);
|
||||
#endif
|
||||
|
||||
|
||||
// matrix is active low. (key on: 0/key off: 1)
|
||||
// Matrix I/O ports
|
||||
//
|
||||
// HHKB has no ghost and no bounce.
|
||||
// row: HC4051 select input channel(0-8)
|
||||
// PB0, PB1, PB2(A, B, C)
|
||||
// col: LS145 select low output line(0-8)
|
||||
// PB3, PB4, PB5, PB6(A, B, C, D)
|
||||
// use D as ENABLE: (enable: 0/unenable: 1)
|
||||
// key: KEY: (on: 0/ off:1)
|
||||
// KEY_PREV: (on: 1/ off: 0)
|
||||
// PE6,PE7(KEY, KEY_PREV)
|
||||
#define COL_ENABLE (1<<6)
|
||||
#define KEY_SELELCT(ROW, COL) (PORTB = (PORTB&(1<<7))|COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
|
||||
#define KEY_ENABLE (PORTB &= ~COL_ENABLE)
|
||||
#define KEY_UNABLE (PORTB |= COL_ENABLE)
|
||||
#define KEY_STATE (PINE&(1<<6))
|
||||
#define KEY_PREV_ON (PORTE |= (1<<7))
|
||||
#define KEY_PREV_OFF (PORTE &= ~(1<<7))
|
||||
// row: HC4051[A,B,C] selects scan row0-7
|
||||
// col: LS145[A,B,C,D] selects scan col0-7 and enable(D)
|
||||
// key: on: 0/off: 1
|
||||
// prev: unknown: output previous key state(negated)?
|
||||
|
||||
#ifdef HOST_PJRC
|
||||
// Ports for Teensy
|
||||
// row: PB0-2
|
||||
// col: PB3-5,6
|
||||
// key: PE6(pull-uped)
|
||||
// prev: PE7
|
||||
#define KEY_INIT() do { \
|
||||
DDRB |= 0x7F; \
|
||||
DDRE |= (1<<7); \
|
||||
DDRE &= ~(1<<6); \
|
||||
PORTE |= (1<<6); \
|
||||
} while (0)
|
||||
#define KEY_SELECT(ROW, COL) (PORTB = (PORTB & 0xC0) | \
|
||||
(((COL) & 0x07)<<3) | \
|
||||
((ROW) & 0x07))
|
||||
#define KEY_ENABLE() (PORTB &= ~(1<<6))
|
||||
#define KEY_UNABLE() (PORTB |= (1<<6))
|
||||
#define KEY_STATE() (PINE & (1<<6))
|
||||
#define KEY_PREV_ON() (PORTE |= (1<<7))
|
||||
#define KEY_PREV_OFF() (PORTE &= ~(1<<7))
|
||||
|
||||
#else
|
||||
// Ports for V-USB
|
||||
// key: PB0(pull-uped)
|
||||
// prev: PB1
|
||||
// row: PB2-4
|
||||
// col: PC0-2,3
|
||||
#define KEY_INIT() do { \
|
||||
DDRB |= 0x1E; \
|
||||
DDRB &= ~(1<<0); \
|
||||
PORTB |= (1<<0); \
|
||||
DDRC |= 0x0F; \
|
||||
} while (0)
|
||||
#define KEY_SELECT(ROW, COL) do { \
|
||||
PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \
|
||||
PORTC = (PORTC & 0xF8) | ((COL) & 0x07); \
|
||||
} while (0)
|
||||
#define KEY_ENABLE() (PORTC &= ~(1<<3))
|
||||
#define KEY_UNABLE() (PORTC |= (1<<3))
|
||||
#define KEY_STATE() (PINB & (1<<0))
|
||||
#define KEY_PREV_ON() (PORTB |= (1<<1))
|
||||
#define KEY_PREV_OFF() (PORTB &= ~(1<<1))
|
||||
#endif
|
||||
|
||||
|
||||
inline
|
||||
@@ -70,13 +104,7 @@ uint8_t matrix_cols(void)
|
||||
|
||||
void matrix_init(void)
|
||||
{
|
||||
// row & col output(PB0-6)
|
||||
DDRB = 0xFF;
|
||||
KEY_SELELCT(0, 0);
|
||||
// KEY: input with pullup(PE6)
|
||||
// KEY_PREV: output(PE7)
|
||||
DDRE = 0xBF;
|
||||
PORTE = 0x40;
|
||||
KEY_INIT();
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
|
||||
@@ -95,21 +123,31 @@ uint8_t matrix_scan(void)
|
||||
|
||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||
KEY_SELELCT(row, col);
|
||||
KEY_SELECT(row, col);
|
||||
_delay_us(40); // from logic analyzer chart
|
||||
if (matrix_prev[row] & (1<<col)) {
|
||||
KEY_PREV_ON;
|
||||
KEY_PREV_ON();
|
||||
}
|
||||
_delay_us(7); // from logic analyzer chart
|
||||
KEY_ENABLE;
|
||||
|
||||
#if HOST_VUSB
|
||||
// to avoid V-USB interrupt during read key state
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
#endif
|
||||
KEY_ENABLE();
|
||||
_delay_us(10); // from logic analyzer chart
|
||||
if (KEY_STATE) {
|
||||
if (KEY_STATE()) {
|
||||
matrix[row] &= ~(1<<col);
|
||||
} else {
|
||||
matrix[row] |= (1<<col);
|
||||
}
|
||||
KEY_PREV_OFF;
|
||||
KEY_UNABLE;
|
||||
#if HOST_VUSB
|
||||
SREG = sreg;
|
||||
#endif
|
||||
|
||||
KEY_PREV_OFF();
|
||||
KEY_UNABLE();
|
||||
_delay_us(150); // from logic analyzer chart
|
||||
}
|
||||
}
|
||||
|
378
hhkb/usbconfig.h
Normal file
378
hhkb/usbconfig.h
Normal file
File diff suppressed because it is too large
Load Diff
5
ps2.c
5
ps2.c
@@ -227,8 +227,13 @@ uint8_t ps2_host_recv(void)
|
||||
return pbuf_dequeue();
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0)
|
||||
#define DEBUGP(x) do { PORTC = x; } while (0)
|
||||
#else
|
||||
#define DEBUGP_INIT()
|
||||
#define DEBUGP(x)
|
||||
#endif
|
||||
ISR(PS2_INT_VECT)
|
||||
{
|
||||
static enum {
|
||||
|
@@ -163,8 +163,8 @@ usbRequest_t *rq = (void *)data;
|
||||
if(rq->bRequest == USBRQ_HID_GET_REPORT){
|
||||
debug(" GET_REPORT");
|
||||
/* we only have one report type, so don't look at wValue */
|
||||
usbMsgPtr = (void *)keyboard_report;
|
||||
return sizeof(*keyboard_report);
|
||||
usbMsgPtr = (void *)keyboard_report_prev;
|
||||
return sizeof(*keyboard_report_prev);
|
||||
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){
|
||||
debug(" GET_IDLE: ");
|
||||
debug_hex(idleRate);
|
||||
|
Reference in New Issue
Block a user