t.m.k. Keyboard Firmware | |||||
======================== | |||||
This is keyboard firmware for Teensy(AVR USB MCU) and V-USB board. | |||||
source code repository: | |||||
http://github.com/tmk/tmk_keyboard | |||||
This firmware is used in following projects: | |||||
HHKB mod: http://geekhack.org/showwiki.php?title=Island:12047 | |||||
Macway mod: http://geekhack.org/showwiki.php?title=Island:11930 | |||||
PS2 to USB: http://geekhack.org/showwiki.php?title=Island:14618 | |||||
ADB to USB: http://geekhack.org/showwiki.php?title=Island:14290 | |||||
The project is heavily based on PJRC USB Keyboard/Mouse Example and | |||||
owes a debt to preceding keyboard firmware projects. | |||||
http://www.pjrc.com/teensy | |||||
Features | |||||
-------- | |||||
Mouse key | |||||
control mouse cursor from keyboard. | |||||
System Control Key | |||||
Power Down, Sleep, Wake Up & USB Remote Wake up | |||||
Media Control Key | |||||
Volume Down/Up, Mute | |||||
USB NKRO | |||||
send 120 keys(+ 8 modifiers) at most simultaneously. | |||||
PS/2 mouse support | |||||
integrate PS/2 mouse(TrackPoint) into keyboard as composite device. | |||||
Limitations | |||||
----------- | |||||
Files & Directories | |||||
------------------- | |||||
Target: | |||||
hhkb/ keyboard controller for PFU HHKB pro | |||||
macway/ keyboard controller for Macway mod | |||||
ps2_usb/ PS2 to USB keyboard converter | |||||
adb_usb/ ADB to USB keyboard converter | |||||
USB Protocol Stack: | |||||
pjrc/ PJRC USB stack | |||||
vusb/ V-USB USB stack | |||||
ps2.[ch] PS/2 protocol | |||||
adb.[ch] ADB protocol | |||||
Build | |||||
----- | |||||
To compile needs AVR GCC, AVR Libc and GNU make. | |||||
You can use WinAVR on Windows. http://winavr.sourceforge.net/ | |||||
$ cd <target> | |||||
$ make | |||||
The firmware will be compiled as a file tmk_<target>.hex. | |||||
Build your own firmware | |||||
----------------------- | |||||
Copying exsistent target(macway) is easy way. | |||||
1. Copy contens of macway/ to your own target directory. | |||||
2. Edit Makefile. See next section. | |||||
3. Edit config.h. See next section. | |||||
4. Edit matrix.c. You will need to fix followings at least. | |||||
matrix_init() | |||||
matrix_scan() | |||||
read_col() | |||||
unselect_rows() | |||||
select_row() | |||||
5. Edit keymap.c. NOTE: It is not final design and a bit messy. | |||||
You will need to fix followings at least. | |||||
KEYMAP | |||||
fn_layer[] | |||||
fn_keycode[] | |||||
keymaps[] | |||||
6. Build. | |||||
If you have a build error like following, comment out "--relax" option in Makefile.common. | |||||
(.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12' | |||||
Build Options | |||||
------------- | |||||
<target>/Makefile: | |||||
1. Set target name for your firmware. | |||||
TARGET = tmk_<target> | |||||
2. Choose a MCU and its frequency. | |||||
MCU = atmega32u4 # Teensy 2.0 | |||||
#MCU = at90usb1286 # Teensy++ 2.0 | |||||
F_CPU = 16000000 | |||||
3. Choose optional modules as needed. Comment out to disable optional modules. | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Enhanced feature for Windows(Audio control and System control) | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
<target>/config.h: | |||||
1. USB vendor/product ID and device description | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xBEEF | |||||
/* device description */ | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT Macway mod | |||||
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod | |||||
2. Keyboard matrix configuration | |||||
#define MATRIX_ROWS 8 | |||||
#define MATRIX_COLS 8 | |||||
#define MATRIX_HAS_GHOST | |||||
3. Mouse keys configuration if needed. | |||||
4. PS/2 mouse configuration if needed. | |||||
Debuging & Rescue | |||||
----------------- | |||||
Use PJRC's hid_listen.exe to see debug messages. | |||||
Press <COMMAND> + H to debug menu. | |||||
(see config.h for <COMMAND> key combination.) | |||||
Pressing any 3 keys when connected enables debug output. | |||||
Pressing any 4 keys when connected makes bootloader comes up. | |||||
Projects related | |||||
---------------- | |||||
PJRC USB Keyboard/Mouse Example | |||||
http://www.pjrc.com/teensy/usb_keyboard.html | |||||
http://www.pjrc.com/teensy/usb_mouse.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 |
t.m.k. Keyboard Firmware Collection | |||||
==================================== | |||||
This is a keyboard firmware with some features for Atmel AVR controller. | |||||
Source code is available here: <http://github.com/tmk/tmk_keyboard> | |||||
Features | |||||
-------- | |||||
* Mouse key - Mouse control by keyboard | |||||
* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up | |||||
* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc. | |||||
* USB NKRO - Can send 120 keys(+ 8 modifiers) simultaneously. | |||||
* PS/2 mouse support - integrate PS/2 mouse(TrackPoint) into keyboard as composite device. | |||||
Projects | |||||
-------- | |||||
### converter | |||||
* ps2_usb - PS/2 keyboard to USB | |||||
* adb_usb - ADB keyboard to USB | |||||
* m0110_usb - Machintosh 128K/512K/Plus keyboard to USB | |||||
* terminal_usb - IBM Model M terminal keyboard(PS/2 scancode set3) to USB | |||||
* sony_usb - Sony NEWS keyboard to USB | |||||
* x68k_usb - Sharp X68000 keyboard to USB | |||||
### keyboard | |||||
* hhkb - Happy Hacking Keyboard professional | |||||
* macway - Compact keyboard mod | |||||
* hbk - Happy Buckling sprint keyboard(IBM Model M mod) | |||||
[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930 | |||||
[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047 | |||||
[GH_ps2]: http://geekhack.org/showwiki.php?title=Island:14618 | |||||
[GH_adb]: http://geekhack.org/showwiki.php?title=Island:14290 | |||||
[GH_hhkb_bt]: http://geekhack.org/showwiki.php?title=Island:20851 | |||||
[GH_m0110]: http://geekhack.org/showwiki.php?title=Island:24965 | |||||
[GH_sony]: http://geekhack.org/showwiki.php?title=Island:25759 | |||||
[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272 | |||||
[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060 | |||||
[GH_hbk]: http://geekhack.org/showwiki.php?title=Island:29483 | |||||
Files & Directories | |||||
------------------- | |||||
### Top | |||||
* common/ common codes | |||||
* protocol/ keyboard protocol support | |||||
* keyboard/ keyboard projects | |||||
* converter/ protocol converter projects | |||||
* doc/ documents | |||||
### Keyboard Protocols | |||||
* pjrc/ PJRC USB stack | |||||
* vusb/ Objective Development V-USB | |||||
* iwrap/ Bluetooth HID for Bluegiga iWRAP | |||||
* ps2 PS/2 protocol | |||||
* adb Apple Desktop Bus protocol | |||||
* m0110 Macintosh 128K/512K/Plus keyboard protocol | |||||
* news Sony NEWS keyboard protocol | |||||
* x68k Sharp X68000 keyboard protocol | |||||
Build & Program | |||||
--------------- | |||||
### Build firmware | |||||
To compile you need `AVR GCC`, `AVR Libc` and `GNU make`. | |||||
You can use [WinAVR][1] on Windows and [CrossPack][2] on Mac. | |||||
$ cd <project> | |||||
$ make | |||||
The firmware will be compiled as a file tmk_<project>.hex. | |||||
[1]: http://winavr.sourceforge.net/ | |||||
[2]: http://www.obdev.at/products/crosspack/index.html | |||||
### Program Controller | |||||
If you have proper program command in Makefile just type this. | |||||
$ make program | |||||
As for `Teensy` you can use `PJRC's loader` to program hex file. <http://www.pjrc.com/teensy/loader.html> | |||||
Build Options | |||||
------------- | |||||
### `Makefile` | |||||
#### 1. MCU and Frequency. | |||||
MCU = atmega32u4 # Teensy 2.0 | |||||
#MCU = at90usb1286 # Teensy++ 2.0 | |||||
F_CPU = 16000000 | |||||
#### 2. Features | |||||
Note that ***comment out*** to disable them. | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Enhanced feature for Windows(Audio control and System control) | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#### 3. Programmer | |||||
Set proper command for your controller, bootloader and programmer. | |||||
# for PJRC Teensy | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
# for Atmel AT90USBKEY | |||||
PROGRAM_CMD = dfu-programmer $(MCU) flash $(TARGET).hex | |||||
# avrdude | |||||
PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex | |||||
PROGRAM_CMD = avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex | |||||
PROGRAM_CMD = avrdude -p $(MCU) -c arduino -P COM1 -b 57600 -U flash:w:$(TARGET).hex | |||||
### `config.h` | |||||
#### 1. USB vendor/product ID and device description | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xBEEF | |||||
/* device description */ | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT Macway mod | |||||
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod | |||||
#### 2. Keyboard matrix configuration | |||||
#define MATRIX_ROWS 8 | |||||
#define MATRIX_COLS 8 | |||||
#define MATRIX_HAS_GHOST | |||||
### 3. Mouse keys configuration | |||||
### 4. PS/2 mouse configuration | |||||
Keymap | |||||
------ | |||||
Build your own firmware | |||||
----------------------- | |||||
Debuging | |||||
-------- | |||||
Use PJRC's `hid_listen` to see debug messages and press `<COMMAND> + H` to debug menu. | |||||
See `config.h` for definition of `<COMMAND>` key combination. | |||||
Other Keyboard Projects | |||||
----------------------- | |||||
### PJRC USB Keyboard/Mouse Example | |||||
- <http://www.pjrc.com/teensy/usb_keyboard.html> | |||||
- <http://www.pjrc.com/teensy/usb_mouse.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/> |
# Target file name (without extension). | |||||
TARGET = adb_usb | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
adb.c | |||||
CONFIG_H = config.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
#MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
ADB to USB keyboard converter | |||||
============================= | |||||
http://geekhack.org/showwiki.php?title=Island:14290 | |||||
This firmware converts ADB keyboard protocol to USB. | |||||
Build | |||||
----- | |||||
0. Connect ADB keyboard to Teensy by 3 lines(Vcc, GND, Data). | |||||
You need a external pull-up resistor on DATA line in most case, | |||||
in particular when you want to use a long or coiled cable. | |||||
This converter uses AVR's internal pull-up, but it seems to be too weak. | |||||
The external pull-up resistor is strongly recommended. | |||||
PSW line is optional. See ADB.txt for details. | |||||
1. Define following macros for ADB connection in config.h: | |||||
ADB_PORT | |||||
ADB_PIN | |||||
ADB_DDR | |||||
ADB_DATA_BIT | |||||
ADB_PSW_BIT | |||||
2. make | |||||
3. program Teensy. | |||||
Keymap | |||||
------ | |||||
You can change a keymap by editing code of keymap.c like following. | |||||
This is a keymap for AEK, however, also used for other keyboards. | |||||
How to define the keymap is probably obvious. You can find key | |||||
symbols in usb_keycodes.h. | |||||
If you want to define some keymaps than just one, see hhkb/keymap.c and | |||||
macway/keymap.c as examples. Keymap(layer) switching may needs a bit of | |||||
effort at this time. | |||||
/* Default Layer: plain keymap | |||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' `---' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| | |||||
* |-----------------------------------------------------------| |-----------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -| | |||||
* |-----------------------------------------------------------| `-----------' |---------------| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +| | |||||
* |-----------------------------------------------------------| ,---. |---------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||||
* |Ctrl |Gui |Alt | Space | | | | |Lef|Dow|Rig| | 0| .| | | |||||
* `-----------------------------------------------------------' `-----------' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PMNS, | |||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
Notes | |||||
----- | |||||
Many ADB keyboards has no discrimination between right modifier and left one, | |||||
you will always see left control even if you press right control key. | |||||
Apple Extended Keyboard and Apple Extended Keyboard II are the examples. | |||||
Though ADB protocol itsef has the ability of distinction between right and left. | |||||
And most ADB keyboard has no NKRO functionality, though ADB protocol itsef has that. | |||||
EOF |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x0ADB | |||||
#define DEVICE_VER 0x0101 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT ADB keyboard converter | |||||
#define DESCRIPTION convert ADB keyboard to USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 16 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* Locking Caps Lock support */ | |||||
#define MATRIX_HAS_LOCKING_CAPS | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 192 | |||||
#endif | |||||
/* PS/2 mouse */ | |||||
#ifdef PS2_MOUSE_ENABLE | |||||
# define PS2_CLOCK_PORT PORTF | |||||
# define PS2_CLOCK_PIN PINF | |||||
# define PS2_CLOCK_DDR DDRF | |||||
# define PS2_CLOCK_BIT 0 | |||||
# define PS2_DATA_PORT PORTF | |||||
# define PS2_DATA_PIN PINF | |||||
# define PS2_DATA_DDR DDRF | |||||
# define PS2_DATA_BIT 1 | |||||
#endif | |||||
/* ADB port setting */ | |||||
#define ADB_PORT PORTF | |||||
#define ADB_PIN PINF | |||||
#define ADB_DDR DDRF | |||||
#define ADB_DATA_BIT 0 | |||||
//#define ADB_PSW_BIT 1 // optional | |||||
#endif |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* Keymap for ADB keyboard | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keyboard.h" | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) | |||||
// Convert physical keyboard layout to matrix array. | |||||
// This is a macro to define keymap easily in keyboard layout form. | |||||
/* Apple Extended Keyboard */ | |||||
#define KEYMAP( \ | |||||
K35, K7A,K78,K63,K76, K60,K61,K62,K64, K65,K6D,K67,K6F, K69,K6B,K71, K7F, \ | |||||
K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K72,K73,K74, K47,K51,K4B,K43, \ | |||||
K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, K75,K77,K79, K59,K5B,K5C,K4E, \ | |||||
K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K45, \ | |||||
K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K7B, K3E, K53,K54,K55, \ | |||||
K36,K3A,K37, K31, K3B,K3D,K3C, K52, K41,K4C \ | |||||
) { \ | |||||
{ KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K08, KB_##K09, KB_NO, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | |||||
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_NO, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ | |||||
{ KB_NO, KB_##K41, KB_NO, KB_##K43, KB_NO, KB_##K45, KB_NO, KB_##K47 }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_##K4B, KB_##K4C, KB_NO, KB_##K4E, KB_NO }, \ | |||||
{ KB_NO, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_NO, KB_##K5B, KB_##K5C, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_NO, KB_##K67 }, \ | |||||
{ KB_NO, KB_##K69, KB_NO, KB_##K6B, KB_NO, KB_##K6D, KB_NO, KB_##K6F }, \ | |||||
{ KB_NO, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ | |||||
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_NO, KB_NO, KB_NO, KB_##K7F } \ | |||||
} | |||||
/* plain keymap | |||||
{ | |||||
{ KB_A, KB_S, KB_D, KB_F, KB_H, KB_G, KB_Z, KB_X }, // 00-07 | |||||
{ KB_C, KB_V, KB_NO, KB_B, KB_Q, KB_W, KB_E, KB_R }, // 08-0F | |||||
{ KB_Y, KB_T, KB_1, KB_2, KB_3, KB_4, KB_6, KB_5 }, // 10-17 | |||||
{ KB_EQL, KB_9, KB_7, KB_MINS,KB_8, KB_0, KB_RBRC,KB_O }, // 18-1F | |||||
{ KB_U, KB_LBRC,KB_I, KB_P, KB_ENT, KB_L, KB_J, KB_QUOT}, // 20-27 | |||||
{ KB_K, KB_SCLN,KB_BSLS,KB_COMM,KB_SLSH,KB_N, KB_M, KB_DOT }, // 28-2F | |||||
{ KB_TAB, KB_SPC, KB_GRV, KB_BSPC,KB_NO, KB_ESC, KB_LCTL,KB_LGUI}, // 30-37 | |||||
{ KB_LSFT,KB_CAPS,KB_LALT,KB_LEFT,KB_RGHT,KB_DOWN,KB_UP, KB_NO }, // 38-3F | |||||
{ KB_NO, KB_PDOT,KB_NO, KB_PAST,KB_NO, KB_PPLS,KB_NO, KB_NLCK}, // 40-47 | |||||
{ KB_NO, KB_NO, KB_NO, KB_PSLS,KB_PENT,KB_NO, KB_PMNS,KB_NO }, // 48-4F | |||||
{ KB_NO, KB_PEQL,KB_P0, KB_P1, KB_P2, KB_P3, KB_P4, KB_P5 }, // 50-57 | |||||
{ KB_P6, KB_P7, KB_NO, KB_P8, KB_P9, KB_NO, KB_NO, KB_NO }, // 58-5F | |||||
{ KB_F5, KB_F6, KB_F7, KB_F3, KB_F8, KB_F9, KB_NO, KB_F11 }, // 60-67 | |||||
{ KB_NO, KB_PSCR,KB_NO, KB_SLCK,KB_NO, KB_F10, KB_NO, KB_F12 }, // 68-6F | |||||
{ KB_NO, KB_BRK, KB_INS, KB_HOME,KB_PGUP,KB_DEL, KB_F4, KB_END }, // 70-77 | |||||
{ KB_F2, KB_PGDN,KB_F1, KB_RSFT,KB_NO, KB_NO, KB_NO, KB_PWR }, // 78-7F | |||||
}, | |||||
*/ | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
0, // Fn1 | |||||
0, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_NO, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* Default Layer: plain keymap | |||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' `---' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *| | |||||
* |-----------------------------------------------------------| |-----------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -| | |||||
* |-----------------------------------------------------------| `-----------' |---------------| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +| | |||||
* |-----------------------------------------------------------| ,---. |---------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||||
* |Ctrl |Gui |Alt | Space | | | | |Lef|Dow|Rig| | 0| .| | | |||||
* `-----------------------------------------------------------' `-----------' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PMNS, | |||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return KEYCODE(layer, row, col); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "adb.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
adb_host_kbd_led(~usb_led); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* scan matrix | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "debug.h" | |||||
#include "host.h" | |||||
#include "led.h" | |||||
#include "adb.h" | |||||
#include "matrix.h" | |||||
#if (MATRIX_COLS > 16) | |||||
# error "MATRIX_COLS must not exceed 16" | |||||
#endif | |||||
#if (MATRIX_ROWS > 255) | |||||
# error "MATRIX_ROWS must not exceed 255" | |||||
#endif | |||||
#define CAPS 0x39 | |||||
#define CAPS_UP (CAPS | 0x80) | |||||
#define ROW(key) ((key)>>3&0x0F) | |||||
#define COL(key) ((key)&0x07) | |||||
static bool _matrix_is_modified = false; | |||||
// matrix state buffer(1:on, 0:off) | |||||
#if (MATRIX_COLS <= 8) | |||||
static uint8_t *matrix; | |||||
static uint8_t _matrix0[MATRIX_ROWS]; | |||||
#else | |||||
static uint16_t *matrix; | |||||
static uint16_t _matrix0[MATRIX_ROWS]; | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
static bool matrix_has_ghost_in_row(uint8_t row); | |||||
#endif | |||||
static void _register_key(uint8_t key); | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
adb_host_init(); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | |||||
matrix = _matrix0; | |||||
print_enable = true; | |||||
debug_enable = true; | |||||
debug_matrix = true; | |||||
debug_keyboard = true; | |||||
debug_mouse = true; | |||||
print("debug enabled.\n"); | |||||
return; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
uint16_t codes; | |||||
uint8_t key0, key1; | |||||
_matrix_is_modified = false; | |||||
codes = adb_host_kbd_recv(); | |||||
key0 = codes>>8; | |||||
key1 = codes&0xFF; | |||||
#ifdef MATRIX_HAS_LOCKING_CAPS | |||||
// Send Caps key up event | |||||
if (matrix_is_on(ROW(CAPS), COL(CAPS))) { | |||||
_matrix_is_modified = true; | |||||
_register_key(CAPS_UP); | |||||
} | |||||
#endif | |||||
if (codes == 0) { // no keys | |||||
return 0; | |||||
} else if (key0 == 0xFF && key1 != 0xFF) { // error | |||||
return codes&0xFF; | |||||
} else { | |||||
#ifdef MATRIX_HAS_LOCKING_CAPS | |||||
if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { | |||||
// Ignore LockingCaps key down event when CAPS LOCK is on | |||||
if (key0 == CAPS && (key1 == CAPS || key1 == 0xFF)) return 0; | |||||
if (key0 == CAPS) key0 = key1; | |||||
if (key1 == CAPS) key1 = 0xFF; | |||||
// Convert LockingCaps key up event into down event | |||||
if (key0 == CAPS_UP) key0 = CAPS; | |||||
if (key1 == CAPS_UP) key1 = CAPS; | |||||
} else { | |||||
// CAPS LOCK off: | |||||
// Ignore LockingCaps key up event when CAPS LOCK is off | |||||
if (key0 == CAPS_UP && (key1 == CAPS_UP || key1 == 0xFF)) return 0; | |||||
if (key0 == CAPS_UP) key0 = key1; | |||||
if (key1 == CAPS_UP) key1 = 0xFF; | |||||
} | |||||
#endif | |||||
_matrix_is_modified = true; | |||||
_register_key(key0); | |||||
if (key1 != 0xFF) // key1 is 0xFF when no second key. | |||||
_register_key(key1); | |||||
} | |||||
if (debug_enable) { | |||||
print("adb_host_kbd_recv: "); phex16(codes); print("\n"); | |||||
} | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
return _matrix_is_modified; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
#ifdef MATRIX_HAS_GHOST | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix_has_ghost_in_row(i)) | |||||
return true; | |||||
} | |||||
#endif | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
#if (MATRIX_COLS <= 8) | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
#else | |||||
uint16_t matrix_get_row(uint8_t row) | |||||
#endif | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
#if (MATRIX_COLS <= 8) | |||||
print("\nr/c 01234567\n"); | |||||
#else | |||||
print("\nr/c 0123456789ABCDEF\n"); | |||||
#endif | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
#if (MATRIX_COLS <= 8) | |||||
pbin_reverse(matrix_get_row(row)); | |||||
#else | |||||
pbin_reverse16(matrix_get_row(row)); | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
if (matrix_has_ghost_in_row(row)) { | |||||
print(" <ghost"); | |||||
} | |||||
#endif | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
#if (MATRIX_COLS <= 8) | |||||
count += bitpop(matrix[i]); | |||||
#else | |||||
count += bitpop16(matrix[i]); | |||||
#endif | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | |||||
inline | |||||
static bool matrix_has_ghost_in_row(uint8_t row) | |||||
{ | |||||
// no ghost exists in case less than 2 keys on | |||||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||||
return false; | |||||
// ghost exists in case same state as other row | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
#endif | |||||
inline | |||||
static void _register_key(uint8_t key) | |||||
{ | |||||
uint8_t col, row; | |||||
col = key&0x07; | |||||
row = (key>>3)&0x0F; | |||||
if (key&0x80) { | |||||
matrix[row] &= ~(1<<col); | |||||
} else { | |||||
matrix[row] |= (1<<col); | |||||
} | |||||
} |
# Target file name (without extension). | |||||
TARGET = hbk | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c | |||||
CONFIG_H = config.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
#PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
PROGRAM_CMD = /opt/dfu-programmer-0.5.2/bin/dfu-programmer $(MCU) erase && \ | |||||
/opt/dfu-programmer-0.5.2/bin/dfu-programmer $(MCU) flash $(TARGET).hex && \ | |||||
/opt/dfu-programmer-0.5.2/bin/dfu-programmer $(MCU) start | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xBB00 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT Happy Buckling Keyboard | |||||
#define DESCRIPTION mod version of IBM Model M keyboard | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 12 | |||||
#define MATRIX_COLS 8 | |||||
/* define if matrix has ghost */ | |||||
#define MATRIX_HAS_GHOST | |||||
/* Set 0 if need no debouncing */ | |||||
#define DEBOUNCE 10 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LALT) | MOD_BIT(KB_RALT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 128 | |||||
#endif | |||||
#endif |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef TEENSY_H | |||||
#define TEENSY_H 1 | |||||
// for Teensy/Teensy++ 2.0 | |||||
#undef DEBUG_LED | |||||
#define DEBUG_LED_CONFIG | |||||
#define DEBUG_LED_ON | |||||
#define DEBUG_LED_OFF | |||||
#endif |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* Keymap for Macway mod | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
/* | |||||
* Layout: 59key | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| BS | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| .|Fn2|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Fn4 |Alt | |Fn1 | | |||||
* `-----' `---------------------------------------' `-----' | |||||
* | |||||
* Matrix: 12x8 | |||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |||||
* ---+---------+---------+---------+---------+---------+---------+---------+--------- | |||||
* 0 | | | LCTRL | | | | RCTRL | | |||||
* 1 | | LSHIFT | | | | | RSHIFT | | |||||
* 2 | | Tab | Grave | 1 | Q | A | Z | | |||||
* 3 | | Cpslck | | 2 | W | S | X | | |||||
* 4 | | | | 3 | E | D | C | | |||||
* 5 | G | T | 5 | 4 | R | F | V | B | |||||
* 6 | | Bckspc | | | Key*1 | Bckslsh | Enter | Space | |||||
* 7 | H | Y | 6 | 7 | U | J | M | N | |||||
* 8 | | Rbrckt | Equal | 8 | I | K | Comma | | |||||
* 9 | | | | 9 | O | L | Dot | | |||||
* A | | Lbrckt | Minus | 0 | P | Smcolon | | Slash | |||||
* B | LALT | | | | | | | RALT | |||||
* Key*1 This key locates between Equal and Backspace. | |||||
* | |||||
* Original matrix here: http://geekhack.org/showthread.php?7767-Wireless-Model-M&p=133911&viewfull=1#post133911 | |||||
*/ | |||||
#define KEYMAP( \ | |||||
K22, K23, K33, K43, K53, K52, K72, K73, K83, K93, KA3, KA2, K82, K64, K61, \ | |||||
K21, K24, K34, K44, K54, K51, K71, K74, K84, K94, KA4, KA1, K81, K65, \ | |||||
K31, K25, K35, K45, K55, K50, K70, K75, K85, K95, KA5, KA0, K66, \ | |||||
K11, K26, K36, K46, K56, K57, K77, K76, K86, K96, KA7, K16, \ | |||||
K02, KB0, K67, KB7, K06 \ | |||||
) { \ | |||||
{ KB_NO, KB_NO, KB_##K02, KB_NO, KB_NO, KB_NO, KB_##K06, KB_NO }, \ | |||||
{ KB_NO, KB_##K11, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K16, KB_NO }, \ | |||||
{ KB_NO, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ | |||||
{ KB_NO, KB_##K31, KB_NO, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_NO, KB_##K61, KB_NO, KB_NO, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ | |||||
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ | |||||
{ KB_NO, KB_##K81, KB_##K82, KB_##K83, KB_##K84, KB_##K85, KB_##K86, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_##K93, KB_##K94, KB_##K95, KB_##K96, KB_NO }, \ | |||||
{ KB_##KA0, KB_##KA1, KB_##KA2, KB_##KA3, KB_##KA4, KB_##KA5, KB_NO, KB_##KA7 }, \ | |||||
{ KB_##KB0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KB7 }, \ | |||||
} | |||||
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
1, // Fn1 | |||||
2, // Fn2 | |||||
3, // Fn3 | |||||
4, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_SLSH, // Fn2 | |||||
KB_SCLN, // Fn3 | |||||
KB_SPC, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* Layer 0: Default Layer | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| BS | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| .|Fn2|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Fn4 |Alt | |Fn1 | | |||||
* `-----' `---------------------------------------' `-----' | |||||
*/ | |||||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ | |||||
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,ENT, \ | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, FN1, \ | |||||
LGUI, LALT, FN4, RALT, FN1), | |||||
/* Layer 1: HHKB mode (HHKB Fn) | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||||
* |-----------------------------------------------------------| | |||||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | | | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig| | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | | +| -|End|PgD|Dow|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Space |Alt | |Fn1 | | |||||
* `-----' `---------------------------------------' `-----' | |||||
*/ | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, NO, \ | |||||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,NO, \ | |||||
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,FN1, \ | |||||
LGUI, LALT, SPC, RALT, FN1), | |||||
/* Layer 2: Vi mode (Quote/Rmeta) | |||||
* ,-----------------------------------------------------------. | |||||
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| | | | |||||
* |-----------------------------------------------------------| | |||||
* | \ |Hom|PgD|Up |PgU|End|Hom|PgD|PgU|End| | | | | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | | | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | |Hom|PgD|PgU|End|xxx|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Space |Alt | |Fn1 | | |||||
* `-----' `---------------------------------------' `-----' | |||||
*/ | |||||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, NO, NO, \ | |||||
BSLS,HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, NO, \ | |||||
LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, NO, \ | |||||
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT, \ | |||||
LGUI, LALT, SPC, RALT, NO), | |||||
/* Layer 3: Mouse mode (Semicolon) | |||||
* ,-----------------------------------------------------------. | |||||
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| | | | |||||
* |-----------------------------------------------------------| | |||||
* | \ |MwL|MwD|McU|MwU|MwR|MwL|MwD|MwU|MwR| | | | | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| |McL|McD|McR| |McL|McD|McU|McR|xxx| | | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | |Mb1|Mb2|Mb3|Mb2|Mb1| | | |Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Space |Alt | | | | |||||
* `-----' `---------------------------------------' `-----' | |||||
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel | |||||
*/ | |||||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, NO, NO, \ | |||||
BSLS,WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, NO, \ | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, NO, \ | |||||
LSFT,NO, NO, BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT, \ | |||||
LGUI, LALT, BTN1, RALT, NO), | |||||
/* Layer 4: Matias half keyboard style (Space) | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||||
* |-----------------------------------------------------------| | |||||
* |Backs| P| O| I| U| Y| T| R| E| W| Q| | |Tab | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| ;| L| K| J| H| G| F| D| S| A|Con|Control | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Fn4 |Alt | | | | |||||
* `-----' `---------------------------------------' `-----' | |||||
*/ | |||||
KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, NO, ESC, \ | |||||
BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \ | |||||
LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \ | |||||
LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT, \ | |||||
LGUI, LALT, FN4, RALT, NO), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return KEYCODE(layer, row, col); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "matrix.h" | |||||
/* | |||||
* Happy Buckling Keyboard(IBM Model M mod) | |||||
* | |||||
* Pin usage: | |||||
* COL: PD0-7 | |||||
* ROW: PB0-7, PF4-7 | |||||
*/ | |||||
#if (MATRIX_COLS > 16) | |||||
# error "MATRIX_COLS must not exceed 16" | |||||
#endif | |||||
#if (MATRIX_ROWS > 255) | |||||
# error "MATRIX_ROWS must not exceed 255" | |||||
#endif | |||||
#ifndef DEBOUNCE | |||||
# define DEBOUNCE 0 | |||||
#endif | |||||
static uint8_t debouncing = DEBOUNCE; | |||||
// matrix state buffer(1:on, 0:off) | |||||
#if (MATRIX_COLS <= 8) | |||||
static uint8_t *matrix; | |||||
static uint8_t *matrix_prev; | |||||
static uint8_t _matrix0[MATRIX_ROWS]; | |||||
static uint8_t _matrix1[MATRIX_ROWS]; | |||||
#else | |||||
static uint16_t *matrix; | |||||
static uint16_t *matrix_prev; | |||||
static uint16_t _matrix0[MATRIX_ROWS]; | |||||
static uint16_t _matrix1[MATRIX_ROWS]; | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
static bool matrix_has_ghost_in_row(uint8_t row); | |||||
#endif | |||||
static uint8_t read_col(void); | |||||
static void unselect_rows(void); | |||||
static void select_row(uint8_t row); | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
print_enable = true; | |||||
debug_enable = true; | |||||
debug_matrix = true; | |||||
debug_keyboard = false; | |||||
debug_mouse = false; | |||||
print("debug enabled.\n"); | |||||
// JTAG disable for PORT F. write JTD bit twice within four cycles. | |||||
MCUCR |= (1<<JTD); | |||||
MCUCR |= (1<<JTD); | |||||
// initialize rows | |||||
unselect_rows(); | |||||
// initialize columns to input with pull-up(DDR:0, PORT:1) | |||||
DDRD = 0x00; | |||||
PORTD = 0xFF; | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00; | |||||
matrix = _matrix0; | |||||
matrix_prev = _matrix1; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
if (!debouncing) { | |||||
uint8_t *tmp = matrix_prev; | |||||
matrix_prev = matrix; | |||||
matrix = tmp; | |||||
} | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
unselect_rows(); | |||||
select_row(i); | |||||
_delay_us(30); // without this wait read unstable value. | |||||
if (matrix[i] != (uint8_t)~read_col()) { | |||||
matrix[i] = (uint8_t)~read_col(); | |||||
if (debouncing) { | |||||
debug("bounce!: "); debug_hex(debouncing); print("\n"); | |||||
} | |||||
_delay_ms(1); // TODO: work around. HAHAHAHAHAAHA | |||||
debouncing = DEBOUNCE; | |||||
} | |||||
} | |||||
unselect_rows(); | |||||
if (debouncing) { | |||||
debouncing--; | |||||
} | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
if (debouncing) return false; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix[i] != matrix_prev[i]) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
#ifdef MATRIX_HAS_GHOST | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix_has_ghost_in_row(i)) | |||||
return true; | |||||
} | |||||
#endif | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
#if (MATRIX_COLS <= 8) | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
#else | |||||
uint16_t matrix_get_row(uint8_t row) | |||||
#endif | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
#if (MATRIX_COLS <= 8) | |||||
pbin_reverse(matrix_get_row(row)); | |||||
#else | |||||
pbin_reverse16(matrix_get_row(row)); | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
if (matrix_has_ghost_in_row(row)) { | |||||
print(" <ghost"); | |||||
} | |||||
#endif | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
#if (MATRIX_COLS <= 8) | |||||
count += bitpop(matrix[i]); | |||||
#else | |||||
count += bitpop16(matrix[i]); | |||||
#endif | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | |||||
inline | |||||
static bool matrix_has_ghost_in_row(uint8_t row) | |||||
{ | |||||
// no ghost exists in case less than 2 keys on | |||||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||||
return false; | |||||
// ghost exists in case same state as other row | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
#endif | |||||
inline | |||||
static uint8_t read_col(void) | |||||
{ | |||||
return PIND; | |||||
} | |||||
inline | |||||
static void unselect_rows(void) | |||||
{ | |||||
// Hi-Z(DDR:0, PORT:0) to unselect | |||||
DDRB &= ~0b11111111; | |||||
PORTB &= ~0b11111111; | |||||
DDRF &= ~0b11110000; | |||||
PORTF &= ~0b11110000; | |||||
} | |||||
inline | |||||
static void select_row(uint8_t row) | |||||
{ | |||||
// Output low(DDR:1, PORT:0) to select | |||||
switch (row) { | |||||
case 0: | |||||
case 1: | |||||
case 2: | |||||
case 3: | |||||
case 4: | |||||
case 5: | |||||
case 6: | |||||
case 7: | |||||
DDRB |= (1<<row); | |||||
PORTB &= ~(1<<row); | |||||
break; | |||||
case 8: | |||||
DDRF |= (1<<4); | |||||
PORTF &= ~(1<<4); | |||||
break; | |||||
case 9: | |||||
case 10: | |||||
case 11: | |||||
DDRF |= (1<<(row-4)); | |||||
PORTF &= ~(1<<(row-4)); | |||||
break; | |||||
} | |||||
} |
# | |||||
# Makefile for iWRAP | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = hhkb_iwrap | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c | |||||
CONFIG_H = config_iwrap.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 = atmega168p | |||||
# avrdude doesn't know atmega168p | |||||
AVRDUDE_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 = 12000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#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 $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) | |||||
AVRDUDE_FLAGS = -p $(AVRDUDE_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) | |||||
# Search Path | |||||
VPATH = $(TARGET_DIR) | |||||
include $(TOP_DIR)/protocol/iwrap.mk | |||||
# To be swatchable btween Bluetooth and USB. Comment out if you don't need USB. | |||||
include $(TOP_DIR)/protocol/vusb.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = hhkb_pjrc | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c | |||||
CONFIG_H = config_pjrc.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
# Search Path | |||||
VPATH = $(TARGET_DIR) | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
# | |||||
# Makefile for V-USB | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = hhkb_vusb | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.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 = atmega328p | |||||
# avrdude doesn't know atmega168p | |||||
AVRDUDE_MCU = $(MCU) | |||||
# 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 = 12000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#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 $(AVRDUDE_MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) | |||||
AVRDUDE_FLAGS = -p $(AVRDUDE_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) | |||||
# Search Path | |||||
VPATH = $(TARGET_DIR) | |||||
include $(TOP_DIR)/protocol/vusb.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
Alternative Controller for HHKB | |||||
=============================== | |||||
Feature | |||||
------- | |||||
- Mouse Keys | |||||
- NKRO on USB(PJRC Tennsy only) | |||||
- Keymap Layers | |||||
Customize Keymap | |||||
---------------- | |||||
see keymap.c. | |||||
Build | |||||
===== | |||||
PJRC Teensy | |||||
----------- | |||||
0. Edit matrix.c. | |||||
adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts) | |||||
1. Define macros in config_pjrc.h.(Optional) | |||||
VENDOR_ID, PRODUCT_ID and string descriptor. | |||||
IS_COMMAND | |||||
2. Edit Makefile for MCU setting and build options. | |||||
MCU, F_CPU | |||||
MOUSEKEY_ENABLE, EXTRAKEY_ENABLE, NKRO_ENABLE | |||||
3. Build hex file. | |||||
$ make -f Makefile.pjrc | |||||
4. Program MCU. | |||||
$ make -f Makefile.pjrc program | |||||
V-USB | |||||
----- | |||||
0. Edit matrix.c and usbconfig.h. | |||||
adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts) | |||||
define macros for V-USB in usbconfig.h. | |||||
1. Define macros in config_vusb.h.(Optional) | |||||
IS_COMMAND | |||||
2. Edit Makefile.vusb for MCU setting and build options. | |||||
MCU, F_CPU | |||||
MOUSEKEY_ENABLE, EXTRAKEY_ENABLE | |||||
3. Build hex file. | |||||
$ make -f Makefile.vusb | |||||
4. Program MCU. | |||||
$ make -f Makefile.vusb program | |||||
Using a bootloader to program for convenience is recommended. | |||||
Once program this V-USB bootloader at first, you can program MCU without | |||||
extra programmer. You should have reset switch to start up as bootloader | |||||
mode in this case. | |||||
USBaspLoader: | |||||
http://www.obdev.at/products/vusb/usbasploader.html | |||||
iWRAP | |||||
----- | |||||
0. Edit matrix.c and usbconfig.h. | |||||
adjust scan code to your pin configuration.(see doc/HHKB.txt for pinouts) | |||||
define macros for V-USB in usbconfig.h. | |||||
1. Define macros in config_iwrap.h.(Optional) | |||||
IS_COMMAND | |||||
2. Edit Makefile.iwrap for MCU setting and build options. | |||||
MCU, F_CPU | |||||
MOUSEKEY_ENABLE, EXTRAKEY_ENABLE | |||||
3. Build hex file. | |||||
$ make -f Makefile.iwrap | |||||
4. Program MCU. | |||||
$ make -f Makefile.iwrap program | |||||
Hardware | |||||
======== | |||||
PJRC Teensy | |||||
----------- | |||||
+---------------+ | |||||
| Teensy++ | | |||||
| | | |||||
| | HHKB | |||||
| | ~~~~ | |||||
| PB0-2|------->ROW(6-8) | |||||
| PB3-5|------->COL(9-11) | |||||
| PB6|------->ENABLE(12) | |||||
| PE6|<-------KEY(4) | |||||
| PE7|------->PREV(5) | |||||
| | | |||||
| | | |||||
| | | |||||
+---------------+ | |||||
V-USB | |||||
----- | |||||
+---+ +---------------+ | |||||
USB GND | | ATmega168 | | |||||
~~~ C3 | | | |||||
5V <-------+--------+---|Vcc,AVCC | HHKB | |||||
R1 | | ~~~~ | |||||
D- <----+--+-----R2-----|INT1 PB2-4|------->ROW(6-8) | |||||
D+ <----|---+----R3-----|INT0 PC0-2|------->COL(9-11) | |||||
Z1 Z2 | PC3|------->ENABLE(12) | |||||
GND<----+---+-----------|GND PB0|<-------KEY(4) | |||||
| PB1|------->PREV(5) | |||||
| | | |||||
GND+-C2--+--|XTAL1 RXD|------->Debug Console | |||||
X1 | TXD|<-------Debug Console | |||||
GND+-C3--+--|XTAL2 RST|---SW--+GND | |||||
+---------------+ | |||||
R1: 1.5K Ohm | |||||
R2,R3: 68 Ohm | |||||
Z1,Z2: Zener 3.6V | |||||
C1,C2: 22pF | |||||
C3: 0.1uF | |||||
X1: Crystal 20MHz(16MHz/12MHz) | |||||
SW: Push Switch(Optional for bootloader) | |||||
iWRAP | |||||
----- | |||||
+---------------+ WT12 | |||||
5V | ATmega168 | 5V/3.3V~~~~ | |||||
+-----+---|Vcc,AVCC PC4|---/--->iWRAP(RxD) | |||||
USB | C3 | PC5|<--/----iWRAP(TxD) | |||||
~~~ | + | | | |||||
5V <--BATT + GND | | HHKB | |||||
R1 | | ~~~~ | |||||
D- <----+-----+--R2-----|INT1 PB2-4|------->ROW(6-8) | |||||
D+ <----|---+----R3-----|INT0 PC0-2|------->COL(9-11) | |||||
Z1 Z2 | PC3|------->ENABLE(12) | |||||
GND<----+---+-----------|GND PB0|<-------KEY(4) | |||||
| PB1|------->PREV(5) | |||||
| | | |||||
GND+-C2--+--|XTAL1 RXD|------->Debug Console | |||||
X1 | TXD|<-------Debug Console | |||||
GND+-C3--+--|XTAL2 RST|---SW--+GND | |||||
+---------------+ | |||||
R1: 1.5K Ohm | |||||
R2,R3: 68 Ohm | |||||
Z1,Z2: Zener 3.6V | |||||
C1,C2: 22pF | |||||
C3: 0.1uF | |||||
X1: Crystal 12MHz | |||||
SW: Push Switch(Optional) | |||||
BATT: Li-Po Battery, Battery Charger and Voltage Regulator(5V and 3.3V). | |||||
EOF |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xBEEA | |||||
// 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 == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* pins for Software UART */ | |||||
#define SUART_IN_PIN PINC | |||||
#define SUART_IN_BIT 5 | |||||
#define SUART_OUT_PORT PORTC | |||||
#define SUART_OUT_BIT 4 | |||||
#define DEBUG_LED 1 | |||||
#define DEBUG_LED_CONFIG (DDRD |= (1<<4)) | |||||
#define DEBUG_LED_OFF (PORTD |= (1<<4)) | |||||
#define DEBUG_LED_ON (PORTD &= ~(1<<4)) | |||||
#endif |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xCAFE | |||||
#define DEVICE_VER 0x0101 | |||||
#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 | |||||
/* define if matrix has ghost */ | |||||
//#define MATRIX_HAS_GHOST | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 192 | |||||
#endif | |||||
/* PS/2 mouse */ | |||||
#ifdef PS2_MOUSE_ENABLE | |||||
/* | |||||
# define PS2_CLOCK_PORT PORTF | |||||
# define PS2_CLOCK_PIN PINF | |||||
# define PS2_CLOCK_DDR DDRF | |||||
# define PS2_CLOCK_BIT 0 | |||||
# define PS2_DATA_PORT PORTF | |||||
# define PS2_DATA_PIN PINF | |||||
# define PS2_DATA_DDR DDRF | |||||
# define PS2_DATA_BIT 1 | |||||
*/ | |||||
#endif | |||||
#endif |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#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 == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
#define DEBUG_LED 1 | |||||
#define DEBUG_LED_CONFIG (DDRD |= (1<<4)) | |||||
#define DEBUG_LED_OFF (PORTD |= (1<<4)) | |||||
#define DEBUG_LED_ON (PORTD &= ~(1<<4)) | |||||
#endif |
HHKB Bluetooth mod | |||||
================== | |||||
See this article: | |||||
http://geekhack.org/showwiki.php?title=Island:20851 |
[Picasa] | |||||
name=Bluetooth_img |
Alternative Controller for HHKB pro | |||||
=================================== | |||||
I want to add vi cursor and mouse keys to HHKB. Original HHKB controller is not programmable and | |||||
firmware source code is not open. So, customizing HHKB needs to replace original controller with programmable one. | |||||
I used Teensy++ as alternative controller. Though a Teensy has enough ports to drive HHKB, | |||||
Teensy++ has clean pinout and it makes programing and wiring easier. | |||||
This is just a proof of concept for replacing controller of HHKB, not a complete firmware. | |||||
My prototype firmware source tree is here: | |||||
github(http://github.com/tmk/tmk_keyboard) | |||||
This firmware is a port of my previous project: | |||||
HHKB style Mod(http://geekhack.org/showwiki.php?title=Island:11930) | |||||
PJRC: | |||||
Teensy++/Teensy(http://www.pjrc.com/teensy/) | |||||
Pros: | |||||
* without pattern cutting, case mod and soldering | |||||
* can keep original controller intact | |||||
* can change HHKB behaviour as you like(by C programming) | |||||
Cons: | |||||
* void your warranty | |||||
* unavailability of Teensy++/Teensy(because of PS3 cracking boom?) | |||||
Features: | |||||
* customized keymap | |||||
* more keymap layers | |||||
* mouse keys for minimum mouse operation(never comfortable for normal use) | |||||
* and more...(in the future) | |||||
Any suggestions or ideas are welcome. | |||||
NOTE: | |||||
My HHKB is just "Professional". This means followings may not be applied to "Professional2". | |||||
DISCLAIMER: | |||||
I'm not a professional for electronics and MCU programming. This may damage your HHKB. | |||||
And my English writing is poor, I'm not sure I can convey my notions accurately. | |||||
Teensy++ installation | |||||
--------------------- | |||||
Angled USB mini B adapter is used to install Teensy++ laterally. | |||||
(teensy_install.jpg) | |||||
Bread baord wires are used to connect Teensy++. | |||||
(teensy_wiring.jpg) | |||||
(connector_contact.jpg) | |||||
HHKB internal | |||||
------------- | |||||
HHKB pro has some chips on separate two PCBs. | |||||
Controller PCB: | |||||
M38K07M4 Renesas MCU with USB function | |||||
http://documentation.renesas.com/eng/products/mpumcu/rej03b0192_38k0ds.pdf | |||||
(HHKB_controller.jpg) | |||||
Keyswitch PCB: | |||||
HC4051 Analog Multiplexer: select a row line. | |||||
http://www.alldatasheet.com/datasheet-pdf/pdf/203989/KODENSHI/KK74HC4051A.html | |||||
LS145 BCD Decoder: select a column line. | |||||
http://www.alldatasheet.com/datasheet-pdf/pdf/27373/TI/SN74LS145D.html | |||||
BU9831 Non-volatile electronic potentiometer: for calibration? | |||||
http://www.alldatasheet.com/datasheet-pdf/pdf/36387/ROHM/BU9831.html | |||||
TP1683/4 Capacitive Sensing controller: no datasheet available. | |||||
(HHKB_keyswitch.jpg) | |||||
Topre original chip? | |||||
(HHKB_TP1684.jpg) | |||||
Two PCBs are connected by 15 lines. Vcc and GND use 3 lines each, other 9 lines are for keyboard signaling. | |||||
Keyswitch PCB connector Teensy++ pins | |||||
------------------------------------------------------------------------------- | |||||
1 Vcc(5V) 5V | |||||
2 Vcc(5V) | |||||
3 Vcc(5V) | |||||
4 TP1684 KEY: Low(0) when key pressed PE6 input(with pullup) | |||||
5 TP1684 KEY_PREV: assert previous key state??? PE7 output | |||||
6 HC4051 A(bit0) select 8 rows(0 to 7) PB0 output | |||||
7 HC4051 B(bit1) PB1 output | |||||
8 HC4051 C(bit2) PB2 output | |||||
9 LS145 A(bit0) select 8 columns(0 to 7) PB3 output | |||||
10 LS145 B(bit1) PB4 output | |||||
11 LS145 C(bit2) PB5 output | |||||
12 LS145 D(enable) Low(0) enable selected column PB6 output | |||||
13 GND | |||||
14 GND | |||||
15 GND GND | |||||
(HHKB_connector.jpg) | |||||
Keyswitch matrix | |||||
---------------- | |||||
60 keyswitches in 8*8 matrix. It is ghost-free and bounce-free. | |||||
COL 0 1 2 3 4 5 6 7 | |||||
ROW --------------------------------------------------------------- | |||||
0| 2 q w s a z x c | |||||
1| 3 4 r e d f v b | |||||
2| 5 6 y t g h n _NONE_ | |||||
3| 1 Esc Tab Control LShift LAlt LMeta Space | |||||
4| 7 8 u i k j m _NONE_ | |||||
5| \ ` Delete Return Fn RShift RAlt RMeta | |||||
6| 9 0 o p ; l , _NONE_ | |||||
7| - + ] [ ' / . _NONE_ | |||||
Matrix diagram: | |||||
+-------------------------+-+-+-+-+-+-+-+ Vcc | |||||
|bias control? - - - - - - - - --- | |||||
| 3.9K*8 R R R R R R R R | | |||||
+--------^+ +--------+ - - - - - - - - | | |||||
| 2| | HC4051 <0-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| |capa. | <1-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| TP1684 |sense | <2-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| 11<------| <3-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| | | <4-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| | | <5-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| <-+ | <6-------|-|-|-|-|-|-|-|--|R|-+ | |||||
| 1 4 | | | <7-------|-|-|-|-|-|-|-|--|R|-+ | |||||
+---V---^-+ | +-^-^-^--+ 0 1 2 3 4 5 6 7 33K*8 | |||||
KEY PREV | A B C +-----------------+ | |||||
| | +-^----+ | | | | LS145 | | |||||
Vcc | | |BU9831| | | | +-^--^--^--^------+ | |||||
--- | | +------+ | | | A B C D +------+ | |||||
| | | | | | | | | | | | | |||||
1-3 4 5 6 7 8 9 10 11 12 13-15 | | |||||
+--------------------------------------------------+ | | |||||
| connector | --- | |||||
+--------------------------------------------------+ GND | |||||
to controller | |||||
Signals charts: | |||||
While pressing space bar, watched HHKB original controller signals by logic analyzer. | |||||
Row and column is looping between 0-7 each for selecting a key. | |||||
A key is scaned every about 15ms, so scan rate is 66Hz. | |||||
(HHKB_chart1.jpg) | |||||
Space bar locate at ROW:3 COL:7. A key is selected by HC4051(C,B,A) and LS145(C,B,A). | |||||
Key state can be read on TP1684(4/KEY) while asserting low on LS145(D). | |||||
Usage of TP1684(5) is not clear. Controller seemed to output previous key state on this line. | |||||
However key state can be read without using this signal. | |||||
(HHKB_chart2.jpg) | |||||
Matrix scan pseudo code: | |||||
for (row: 0-7) { | |||||
SELECT_ROW(row); // set HC4051(A,B,C) | |||||
for (col: 0-7) { | |||||
SELECT_COL(col); // set LS145(A,B,C) | |||||
_delay_us(40); | |||||
if (prev_key_state(row, col)) { | |||||
KEY_PREV_ON; | |||||
} | |||||
_delay_us(7); | |||||
ENALBLE_COL(); // set LS145(D) to low | |||||
_delay_us(10); | |||||
if (KEY == 0) { // read TP1684(KEY) | |||||
// key pressed | |||||
} else { | |||||
// not pressed | |||||
} | |||||
KEY_PREV_OFF; | |||||
UNALBLE_COL(); // set LS145(D) to high | |||||
_delay_us(150); | |||||
} | |||||
} | |||||
Keymap layers | |||||
------------- | |||||
Followings are added layers with additional Fn keys. | |||||
see keymap.c | |||||
EOF |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* Keymap for PFU HHKB Pro | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "host.h" | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
// Convert physical keyboard layout to matrix array. | |||||
// This is a macro to define keymap easily in keyboard layout form. | |||||
#define KEYMAP( \ | |||||
K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \ | |||||
K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \ | |||||
K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \ | |||||
K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \ | |||||
K35, K36, K37, K57, K56 \ | |||||
) \ | |||||
{ \ | |||||
{ KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_NO }, \ | |||||
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_NO } \ | |||||
} | |||||
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
1, // Fn1 | |||||
2, // Fn2 | |||||
3, // Fn3 | |||||
3, // Fn4 | |||||
4, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_SLSH, // Fn2 | |||||
KB_SCLN, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_SPC, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* Layer 0: Default Layer | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs| | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| .|Fn2|Shift |Fn1| | |||||
* `-----------------------------------------------------------' | |||||
* |Gui|Alt |Fn5 |Alt |Fn4| | |||||
* `-------------------------------------------' | |||||
*/ | |||||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ | |||||
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,ENT, \ | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ | |||||
LGUI,LALT, FN5, RALT,FN4), | |||||
/* Layer 1: HHKB mode (HHKB Fn) | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||||
* |-----------------------------------------------------------| | |||||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs| | |||||
* |-----------------------------------------------------------| | |||||
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx| | |||||
* `-----------------------------------------------------------' | |||||
* |Gui |Alt |Space |Alt |xxx| | |||||
* `--------------------------------------------' | |||||
*/ | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSPC, \ | |||||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ | |||||
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN1, \ | |||||
LGUI,LALT, SPC, RALT,FN7), | |||||
/* Layer 2: Vi mode (Slash) | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab |Hom|PgD|Up |PgU|End|Hom|PgD|PgUlEnd| | | |Backs| | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | |Hom|PgD|PgUlEnd|xxx|Shift | | | |||||
* `-----------------------------------------------------------' | |||||
* |Gui|Alt |Space |Alt |Gui| | |||||
* `-------------------------------------------' | |||||
*/ | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \ | |||||
LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \ | |||||
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,NO, \ | |||||
LGUI,LALT, SPC, RALT,RGUI), | |||||
/* Layer 3: Mouse mode (Semicolon) | |||||
* ,-----------------------------------------------------------. | |||||
* |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|xxx| |Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift |Mb4|Mb5|Mb1|Mb2|Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | | |||||
* `-----------------------------------------------------------' | |||||
* |Gui |Alt |Mb1 |Alt |Gui| | |||||
* `--------------------------------------------' | |||||
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel | |||||
*/ | |||||
#ifdef HOST_IWRAP | |||||
// iWRAP does not support mouse wheel, use these keycodes to remap as wheel | |||||
#define KB_KPPL KB_KP_PLUS | |||||
#define KB_KPMI KB_KP_MINUS | |||||
#define KB_KPAS KB_KP_ASTERISK | |||||
#define KB_KPSL KB_KP_SLASH | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ | |||||
LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT,NO, \ | |||||
LGUI,LALT, BTN1, RALT,FN4), | |||||
#else | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
TAB, WH_L,WH_U,MS_U,WH_D,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ | |||||
LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ | |||||
LGUI,LALT, BTN1, RALT,FN4), | |||||
#endif | |||||
/* Layer 4: Matias half keyboard style (Space) | |||||
* ,-----------------------------------------------------------. | |||||
* | -| 0| 9| 8| 7| 6| 5| 4| 3| 2| 1| | | |Esc| | |||||
* |-----------------------------------------------------------| | |||||
* |Backs| P| O| I| U| Y| T| R| E| W| Q| | |Tab | | |||||
* |-----------------------------------------------------------| | |||||
* |Contro| ;| L| K| J| H| G| F| D| S| A|Con|Control | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | | | |||||
* `-----------------------------------------------------------' | |||||
* |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxxx|Alt |Gui| | |||||
* `--------------------------------------------' | |||||
*/ | |||||
/* | |||||
KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, NO, ESC, \ | |||||
BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \ | |||||
LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \ | |||||
LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \ | |||||
LGUI,LALT, FN5, RALT,RGUI) | |||||
*/ | |||||
/* Mouse mode (Space) */ | |||||
#ifdef HOST_IWRAP | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ | |||||
LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ | |||||
LGUI,LALT, FN5, RALT,RGUI), | |||||
#else | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ | |||||
TAB, WH_L,WH_U,MS_U,WH_D,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ | |||||
LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ | |||||
LGUI,LALT, FN5, RALT,RGUI), | |||||
#endif | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return KEYCODE(layer, row, col); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "led.h" | |||||
/* HHKB has no LEDs */ | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
} | |||||
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* scan matrix | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "timer.h" | |||||
#include "matrix.h" | |||||
// Timer resolution check | |||||
#if (1000000/TIMER_RAW_FREQ > 20) | |||||
# error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB." | |||||
#endif | |||||
#if (MATRIX_COLS > 16) | |||||
# error "MATRIX_COLS must not exceed 16" | |||||
#endif | |||||
#if (MATRIX_ROWS > 255) | |||||
# error "MATRIX_ROWS must not exceed 255" | |||||
#endif | |||||
// matrix state buffer(1:on, 0:off) | |||||
#if (MATRIX_COLS <= 8) | |||||
static uint8_t *matrix; | |||||
static uint8_t *matrix_prev; | |||||
static uint8_t _matrix0[MATRIX_ROWS]; | |||||
static uint8_t _matrix1[MATRIX_ROWS]; | |||||
#else | |||||
static uint16_t *matrix; | |||||
static uint16_t *matrix_prev; | |||||
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 I/O ports | |||||
// | |||||
// 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)) | |||||
#define KEY_POWER_ON() | |||||
#define KEY_POWER_OFF() | |||||
#else | |||||
// Ports for V-USB | |||||
// key: PB0(pull-uped) | |||||
// prev: PB1 | |||||
// row: PB2-4 | |||||
// col: PC0-2,3 | |||||
// power: PB5(Low:on/Hi-z:off) | |||||
#define KEY_INIT() do { \ | |||||
DDRB |= 0x3E; \ | |||||
DDRB &= ~(1<<0); \ | |||||
PORTB |= 1<<0; \ | |||||
DDRC |= 0x0F; \ | |||||
KEY_UNABLE(); \ | |||||
KEY_PREV_OFF(); \ | |||||
} 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)) | |||||
// Power supply switching | |||||
#define KEY_POWER_ON() do { \ | |||||
KEY_INIT(); \ | |||||
PORTB &= ~(1<<5); \ | |||||
_delay_us(200); \ | |||||
} while (0) | |||||
#define KEY_POWER_OFF() do { \ | |||||
DDRB &= ~0x3F; \ | |||||
PORTB &= ~0x3F; \ | |||||
DDRC &= ~0x0F; \ | |||||
PORTC &= ~0x0F; \ | |||||
} while (0) | |||||
#endif | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
KEY_INIT(); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00; | |||||
matrix = _matrix0; | |||||
matrix_prev = _matrix1; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
uint8_t *tmp; | |||||
tmp = matrix_prev; | |||||
matrix_prev = matrix; | |||||
matrix = tmp; | |||||
KEY_POWER_ON(); | |||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | |||||
for (uint8_t col = 0; col < MATRIX_COLS; col++) { | |||||
KEY_SELECT(row, col); | |||||
_delay_us(40); | |||||
// Not sure this is needed. This just emulates HHKB controller's behaviour. | |||||
if (matrix_prev[row] & (1<<col)) { | |||||
KEY_PREV_ON(); | |||||
} | |||||
_delay_us(7); | |||||
// NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE. | |||||
// If V-USB interrupts in this section we could lose 40us or so | |||||
// and would read invalid value from KEY_STATE. | |||||
uint8_t last = TIMER_RAW; | |||||
KEY_ENABLE(); | |||||
// Wait for KEY_STATE outputs its value. | |||||
// 1us was ok on one HHKB, but not worked on another. | |||||
_delay_us(10); | |||||
if (KEY_STATE()) { | |||||
matrix[row] &= ~(1<<col); | |||||
} else { | |||||
matrix[row] |= (1<<col); | |||||
} | |||||
// Ignore if this code region execution time elapses more than 20us. | |||||
if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) { | |||||
matrix[row] = matrix_prev[row]; | |||||
} | |||||
KEY_PREV_OFF(); | |||||
KEY_UNABLE(); | |||||
// NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE. | |||||
// This takes 25us or more to make sure KEY_STATE returns to idle state. | |||||
_delay_us(150); | |||||
} | |||||
} | |||||
KEY_POWER_OFF(); | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix[i] != matrix_prev[i]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
#ifdef MATRIX_HAS_GHOST | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix_has_ghost_in_row(i)) | |||||
return true; | |||||
} | |||||
#endif | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
#if (MATRIX_COLS <= 8) | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
#else | |||||
uint16_t matrix_get_row(uint8_t row) | |||||
#endif | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
#if (MATRIX_COLS <= 8) | |||||
print("\nr/c 01234567\n"); | |||||
#else | |||||
print("\nr/c 0123456789ABCDEF\n"); | |||||
#endif | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
#if (MATRIX_COLS <= 8) | |||||
pbin_reverse(matrix_get_row(row)); | |||||
#else | |||||
pbin_reverse16(matrix_get_row(row)); | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
if (matrix_has_ghost_in_row(row)) { | |||||
print(" <ghost"); | |||||
} | |||||
#endif | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
#if (MATRIX_COLS <= 8) | |||||
count += bitpop(matrix[i]); | |||||
#else | |||||
count += bitpop16(matrix[i]); | |||||
#endif | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | |||||
inline | |||||
static bool matrix_has_ghost_in_row(uint8_t row) | |||||
{ | |||||
// no ghost exists in case less than 2 keys on | |||||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||||
return false; | |||||
// ghost exists in case same state as other row | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
#endif |
/* Name: usbconfig.h | |||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | |||||
* Author: Christian Starkjohann | |||||
* Creation Date: 2005-04-01 | |||||
* Tabsize: 4 | |||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | |||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | |||||
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $ | |||||
*/ | |||||
#ifndef __usbconfig_h_included__ | |||||
#define __usbconfig_h_included__ | |||||
#include "config_vusb.h" | |||||
/* | |||||
General Description: | |||||
This file is an example configuration (with inline documentation) for the USB | |||||
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is | |||||
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may | |||||
wire the lines to any other port, as long as D+ is also wired to INT0 (or any | |||||
other hardware interrupt, as long as it is the highest level interrupt, see | |||||
section at the end of this file). | |||||
*/ | |||||
/* ---------------------------- Hardware Config ---------------------------- */ | |||||
#define USB_CFG_IOPORTNAME D | |||||
/* This is the port where the USB bus is connected. When you configure it to | |||||
* "B", the registers PORTB, PINB and DDRB will be used. | |||||
*/ | |||||
#define USB_CFG_DMINUS_BIT 3 | |||||
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. | |||||
* This may be any bit in the port. | |||||
*/ | |||||
#define USB_CFG_DPLUS_BIT 2 | |||||
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. | |||||
* This may be any bit in the port. Please note that D+ must also be connected | |||||
* to interrupt pin INT0! [You can also use other interrupts, see section | |||||
* "Optional MCU Description" below, or you can connect D- to the interrupt, as | |||||
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the | |||||
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame | |||||
* markers every millisecond.] | |||||
*/ | |||||
#define USB_CFG_CLOCK_KHZ (F_CPU/1000) | |||||
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, | |||||
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code | |||||
* require no crystal, they tolerate +/- 1% deviation from the nominal | |||||
* frequency. All other rates require a precision of 2000 ppm and thus a | |||||
* crystal! | |||||
* Since F_CPU should be defined to your actual clock rate anyway, you should | |||||
* not need to modify this setting. | |||||
*/ | |||||
#define USB_CFG_CHECK_CRC 0 | |||||
/* Define this to 1 if you want that the driver checks integrity of incoming | |||||
* data packets (CRC checks). CRC checks cost quite a bit of code size and are | |||||
* currently only available for 18 MHz crystal clock. You must choose | |||||
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option. | |||||
*/ | |||||
/* ----------------------- Optional Hardware Config ------------------------ */ | |||||
/* #define USB_CFG_PULLUP_IOPORTNAME D */ | |||||
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of | |||||
* V+, you can connect and disconnect the device from firmware by calling | |||||
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). | |||||
* This constant defines the port on which the pullup resistor is connected. | |||||
*/ | |||||
/* #define USB_CFG_PULLUP_BIT 4 */ | |||||
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined | |||||
* above) where the 1.5k pullup resistor is connected. See description | |||||
* above for details. | |||||
*/ | |||||
/* --------------------------- Functional Range ---------------------------- */ | |||||
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1 | |||||
/* Define this to 1 if you want to compile a version with two endpoints: The | |||||
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint | |||||
* number). | |||||
*/ | |||||
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1 | |||||
/* Define this to 1 if you want to compile a version with three endpoints: The | |||||
* default control endpoint 0, an interrupt-in endpoint 3 (or the number | |||||
* configured below) and a catch-all default interrupt-in endpoint as above. | |||||
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. | |||||
*/ | |||||
#define USB_CFG_EP3_NUMBER 3 | |||||
/* If the so-called endpoint 3 is used, it can now be configured to any other | |||||
* endpoint number (except 0) with this macro. Default if undefined is 3. | |||||
*/ | |||||
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ | |||||
/* The above macro defines the startup condition for data toggling on the | |||||
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. | |||||
* Since the token is toggled BEFORE sending any data, the first packet is | |||||
* sent with the oposite value of this configuration! | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_HALT 0 | |||||
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature | |||||
* for endpoint 1 (interrupt endpoint). Although you may not need this feature, | |||||
* it is required by the standard. We have made it a config option because it | |||||
* bloats the code considerably. | |||||
*/ | |||||
#define USB_CFG_SUPPRESS_INTR_CODE 0 | |||||
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't | |||||
* want to send any data over them. If this macro is defined to 1, functions | |||||
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if | |||||
* you need the interrupt-in endpoints in order to comply to an interface | |||||
* (e.g. HID), but never want to send any data. This option saves a couple | |||||
* of bytes in flash memory and the transmit buffers in RAM. | |||||
*/ | |||||
#define USB_CFG_INTR_POLL_INTERVAL 10 | |||||
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll | |||||
* interval. The value is in milliseconds and must not be less than 10 ms for | |||||
* low speed devices. | |||||
*/ | |||||
#define USB_CFG_IS_SELF_POWERED 0 | |||||
/* Define this to 1 if the device has its own power supply. Set it to 0 if the | |||||
* device is powered from the USB bus. | |||||
*/ | |||||
#define USB_CFG_MAX_BUS_POWER 100 | |||||
/* Set this variable to the maximum USB bus power consumption of your device. | |||||
* The value is in milliamperes. [It will be divided by two since USB | |||||
* communicates power requirements in units of 2 mA.] | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_FN_WRITE 1 | |||||
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out | |||||
* transfers. Set it to 0 if you don't need it and want to save a couple of | |||||
* bytes. | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_FN_READ 0 | |||||
/* Set this to 1 if you need to send control replies which are generated | |||||
* "on the fly" when usbFunctionRead() is called. If you only want to send | |||||
* data from a static buffer, set it to 0 and return the data from | |||||
* usbFunctionSetup(). This saves a couple of bytes. | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0 | |||||
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. | |||||
* You must implement the function usbFunctionWriteOut() which receives all | |||||
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number | |||||
* can be found in 'usbRxToken'. | |||||
*/ | |||||
#define USB_CFG_HAVE_FLOWCONTROL 0 | |||||
/* Define this to 1 if you want flowcontrol over USB data. See the definition | |||||
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in | |||||
* usbdrv.h. | |||||
*/ | |||||
#define USB_CFG_DRIVER_FLASH_PAGE 0 | |||||
/* If the device has more than 64 kBytes of flash, define this to the 64 k page | |||||
* where the driver's constants (descriptors) are located. Or in other words: | |||||
* Define this to 1 for boot loaders on the ATMega128. | |||||
*/ | |||||
#define USB_CFG_LONG_TRANSFERS 0 | |||||
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes | |||||
* in a single control-in or control-out transfer. Note that the capability | |||||
* for long transfers increases the driver size. | |||||
*/ | |||||
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ | |||||
/* This macro is a hook if you want to do unconventional things. If it is | |||||
* defined, it's inserted at the beginning of received message processing. | |||||
* If you eat the received message and don't want default processing to | |||||
* proceed, do a return after doing your things. One possible application | |||||
* (besides debugging) is to flash a status LED on each packet. | |||||
*/ | |||||
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ | |||||
/* This macro is a hook if you need to know when an USB RESET occurs. It has | |||||
* one parameter which distinguishes between the start of RESET state and its | |||||
* end. | |||||
*/ | |||||
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */ | |||||
/* This macro (if defined) is executed when a USB SET_ADDRESS request was | |||||
* received. | |||||
*/ | |||||
#define USB_COUNT_SOF 1 | |||||
/* define this macro to 1 if you need the global variable "usbSofCount" which | |||||
* counts SOF packets. This feature requires that the hardware interrupt is | |||||
* connected to D- instead of D+. | |||||
*/ | |||||
/* #ifdef __ASSEMBLER__ | |||||
* macro myAssemblerMacro | |||||
* in YL, TCNT0 | |||||
* sts timer0Snapshot, YL | |||||
* endm | |||||
* #endif | |||||
* #define USB_SOF_HOOK myAssemblerMacro | |||||
* This macro (if defined) is executed in the assembler module when a | |||||
* Start Of Frame condition is detected. It is recommended to define it to | |||||
* the name of an assembler macro which is defined here as well so that more | |||||
* than one assembler instruction can be used. The macro may use the register | |||||
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages | |||||
* immediately after an SOF pulse may be lost and must be retried by the host. | |||||
* What can you do with this hook? Since the SOF signal occurs exactly every | |||||
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in | |||||
* designs running on the internal RC oscillator. | |||||
* Please note that Start Of Frame detection works only if D- is wired to the | |||||
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! | |||||
*/ | |||||
#define USB_CFG_CHECK_DATA_TOGGLING 0 | |||||
/* define this macro to 1 if you want to filter out duplicate data packets | |||||
* sent by the host. Duplicates occur only as a consequence of communication | |||||
* errors, when the host does not receive an ACK. Please note that you need to | |||||
* implement the filtering yourself in usbFunctionWriteOut() and | |||||
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable | |||||
* for each control- and out-endpoint to check for duplicate packets. | |||||
*/ | |||||
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 | |||||
/* define this macro to 1 if you want the function usbMeasureFrameLength() | |||||
* compiled in. This function can be used to calibrate the AVR's RC oscillator. | |||||
*/ | |||||
#define USB_USE_FAST_CRC 0 | |||||
/* The assembler module has two implementations for the CRC algorithm. One is | |||||
* faster, the other is smaller. This CRC routine is only used for transmitted | |||||
* messages where timing is not critical. The faster routine needs 31 cycles | |||||
* per byte while the smaller one needs 61 to 69 cycles. The faster routine | |||||
* may be worth the 32 bytes bigger code size if you transmit lots of data and | |||||
* run the AVR close to its limit. | |||||
*/ | |||||
/* -------------------------- Device Description --------------------------- */ | |||||
#define USB_CFG_VENDOR_ID (VENDOR_ID & 0xFF), ((VENDOR_ID >> 8) & 0xFF) | |||||
/* USB vendor ID for the device, low byte first. If you have registered your | |||||
* own Vendor ID, define it here. Otherwise you may use one of obdev's free | |||||
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! | |||||
* *** IMPORTANT NOTE *** | |||||
* This template uses obdev's shared VID/PID pair for Vendor Class devices | |||||
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand | |||||
* the implications! | |||||
*/ | |||||
#define USB_CFG_DEVICE_ID (PRODUCT_ID & 0xFF), ((PRODUCT_ID >> 8) & 0xFF) | |||||
/* This is the ID of the product, low byte first. It is interpreted in the | |||||
* scope of the vendor ID. If you have registered your own VID with usb.org | |||||
* or if you have licensed a PID from somebody else, define it here. Otherwise | |||||
* you may use one of obdev's free shared VID/PID pairs. See the file | |||||
* USB-IDs-for-free.txt for details! | |||||
* *** IMPORTANT NOTE *** | |||||
* This template uses obdev's shared VID/PID pair for Vendor Class devices | |||||
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand | |||||
* the implications! | |||||
*/ | |||||
#define USB_CFG_DEVICE_VERSION 0x00, 0x01 | |||||
/* Version number of the device: Minor number first, then major number. | |||||
*/ | |||||
#define USB_CFG_VENDOR_NAME 't', '.', 'm', '.', 'k', '.' | |||||
#define USB_CFG_VENDOR_NAME_LEN 6 | |||||
/* These two values define the vendor name returned by the USB device. The name | |||||
* must be given as a list of characters under single quotes. The characters | |||||
* are interpreted as Unicode (UTF-16) entities. | |||||
* If you don't want a vendor name string, undefine these macros. | |||||
* ALWAYS define a vendor name containing your Internet domain name if you use | |||||
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for | |||||
* details. | |||||
*/ | |||||
#define USB_CFG_DEVICE_NAME 'H', 'H', 'K', 'B', ' ', 'm', 'o', 'd' | |||||
#define USB_CFG_DEVICE_NAME_LEN 8 | |||||
/* Same as above for the device name. If you don't want a device name, undefine | |||||
* the macros. See the file USB-IDs-for-free.txt before you assign a name if | |||||
* you use a shared VID/PID. | |||||
*/ | |||||
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ | |||||
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ | |||||
/* Same as above for the serial number. If you don't want a serial number, | |||||
* undefine the macros. | |||||
* It may be useful to provide the serial number through other means than at | |||||
* compile time. See the section about descriptor properties below for how | |||||
* to fine tune control over USB descriptors such as the string descriptor | |||||
* for the serial number. | |||||
*/ | |||||
#define USB_CFG_DEVICE_CLASS 0 | |||||
#define USB_CFG_DEVICE_SUBCLASS 0 | |||||
/* See USB specification if you want to conform to an existing device class. | |||||
* Class 0xff is "vendor specific". | |||||
*/ | |||||
#define USB_CFG_INTERFACE_CLASS 3 /* HID */ | |||||
#define USB_CFG_INTERFACE_SUBCLASS 1 /* Boot */ | |||||
#define USB_CFG_INTERFACE_PROTOCOL 1 /* Keyboard */ | |||||
/* See USB specification if you want to conform to an existing device class or | |||||
* protocol. The following classes must be set at interface level: | |||||
* HID class is 3, no subclass and protocol required (but may be useful!) | |||||
* CDC class is 2, use subclass 2 and protocol 1 for ACM | |||||
*/ | |||||
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0 | |||||
/* Define this to the length of the HID report descriptor, if you implement | |||||
* an HID device. Otherwise don't define it or define it to 0. | |||||
* If you use this define, you must add a PROGMEM character array named | |||||
* "usbHidReportDescriptor" to your code which contains the report descriptor. | |||||
* Don't forget to keep the array and this define in sync! | |||||
*/ | |||||
/* #define USB_PUBLIC static */ | |||||
/* Use the define above if you #include usbdrv.c instead of linking against it. | |||||
* This technique saves a couple of bytes in flash memory. | |||||
*/ | |||||
/* ------------------- Fine Control over USB Descriptors ------------------- */ | |||||
/* If you don't want to use the driver's default USB descriptors, you can | |||||
* provide our own. These can be provided as (1) fixed length static data in | |||||
* flash memory, (2) fixed length static data in RAM or (3) dynamically at | |||||
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more | |||||
* information about this function. | |||||
* Descriptor handling is configured through the descriptor's properties. If | |||||
* no properties are defined or if they are 0, the default descriptor is used. | |||||
* Possible properties are: | |||||
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched | |||||
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is | |||||
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if | |||||
* you want RAM pointers. | |||||
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found | |||||
* in static memory is in RAM, not in flash memory. | |||||
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), | |||||
* the driver must know the descriptor's length. The descriptor itself is | |||||
* found at the address of a well known identifier (see below). | |||||
* List of static descriptor names (must be declared PROGMEM if in flash): | |||||
* char usbDescriptorDevice[]; | |||||
* char usbDescriptorConfiguration[]; | |||||
* char usbDescriptorHidReport[]; | |||||
* char usbDescriptorString0[]; | |||||
* int usbDescriptorStringVendor[]; | |||||
* int usbDescriptorStringDevice[]; | |||||
* int usbDescriptorStringSerialNumber[]; | |||||
* Other descriptors can't be provided statically, they must be provided | |||||
* dynamically at runtime. | |||||
* | |||||
* Descriptor properties are or-ed or added together, e.g.: | |||||
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) | |||||
* | |||||
* The following descriptors are defined: | |||||
* USB_CFG_DESCR_PROPS_DEVICE | |||||
* USB_CFG_DESCR_PROPS_CONFIGURATION | |||||
* USB_CFG_DESCR_PROPS_STRINGS | |||||
* USB_CFG_DESCR_PROPS_STRING_0 | |||||
* USB_CFG_DESCR_PROPS_STRING_VENDOR | |||||
* USB_CFG_DESCR_PROPS_STRING_PRODUCT | |||||
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER | |||||
* USB_CFG_DESCR_PROPS_HID | |||||
* USB_CFG_DESCR_PROPS_HID_REPORT | |||||
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) | |||||
* | |||||
* Note about string descriptors: String descriptors are not just strings, they | |||||
* are Unicode strings prefixed with a 2 byte header. Example: | |||||
* int serialNumberDescriptor[] = { | |||||
* USB_STRING_DESCRIPTOR_HEADER(6), | |||||
* 'S', 'e', 'r', 'i', 'a', 'l' | |||||
* }; | |||||
*/ | |||||
#define USB_CFG_DESCR_PROPS_DEVICE 0 | |||||
#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC | |||||
//#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 | |||||
#define USB_CFG_DESCR_PROPS_STRINGS 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_0 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 | |||||
#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC | |||||
//#define USB_CFG_DESCR_PROPS_HID 0 | |||||
#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC | |||||
//#define USB_CFG_DESCR_PROPS_HID_REPORT 0 | |||||
#define USB_CFG_DESCR_PROPS_UNKNOWN 0 | |||||
/* ----------------------- Optional MCU Description ------------------------ */ | |||||
/* The following configurations have working defaults in usbdrv.h. You | |||||
* usually don't need to set them explicitly. Only if you want to run | |||||
* the driver on a device which is not yet supported or with a compiler | |||||
* which is not fully supported (such as IAR C) or if you use a differnt | |||||
* interrupt than INT0, you may have to define some of these. | |||||
*/ | |||||
/* #define USB_INTR_CFG MCUCR */ | |||||
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ | |||||
/* #define USB_INTR_CFG_CLR 0 */ | |||||
/* #define USB_INTR_ENABLE GIMSK */ | |||||
/* #define USB_INTR_ENABLE_BIT INT0 */ | |||||
/* #define USB_INTR_PENDING GIFR */ | |||||
/* #define USB_INTR_PENDING_BIT INTF0 */ | |||||
/* #define USB_INTR_VECTOR INT0_vect */ | |||||
/* Set INT1 for D- falling edge to count SOF */ | |||||
/* #define USB_INTR_CFG EICRA */ | |||||
#define USB_INTR_CFG_SET ((1 << ISC11) | (0 << ISC10)) | |||||
/* #define USB_INTR_CFG_CLR 0 */ | |||||
/* #define USB_INTR_ENABLE EIMSK */ | |||||
#define USB_INTR_ENABLE_BIT INT1 | |||||
/* #define USB_INTR_PENDING EIFR */ | |||||
#define USB_INTR_PENDING_BIT INTF1 | |||||
#define USB_INTR_VECTOR INT1_vect | |||||
#endif /* __usbconfig_h_included__ */ |
# Target file name (without extension). | |||||
TARGET = m0110 | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
m0110.c | |||||
CONFIG_H = config.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk | |||||
hasu: EXTRAFLAGS += -DHASU | |||||
hasu: all |
M0110/M0110A to USB keyboard converter | |||||
====================================== | |||||
This firmware converts the protocol of Apple Macintosh keyboard M0110/M0110A into USB. | |||||
Target board of this project is [PJRC Teensy](http://www.pjrc.com/teensy/), though, | |||||
you can use other board with USB AVR like `ATmega32U4` and `AT90USB`. | |||||
![M0110](https://github.com/tmk/tmk_keyboard/raw/master/m0110_usb/doc/m0110.jpg) | |||||
M0110A support was contributed by [skagon@github](https://github.com/skagon). | |||||
Connection | |||||
---------- | |||||
You need 4P4C plug and cable to connect Teensy or other AVR dev board into the keyboard. | |||||
Teensy port `PF0` is assigned for `CLOCK` line and `PF1` for `DATA` by default, | |||||
you can change pin configuration with editing *config.h*. | |||||
You can find 4P4C plugs on telephone handset cable. Note that it is *crossover* connection | |||||
while Macintosh keyboard cable is *straight*. | |||||
[![Conection](http://i.imgur.com/vJoVOm.jpg)](http://i.imgur.com/vJoVO.jpg) | |||||
In this pic: | |||||
1. `GND`(Black) | |||||
2. `CLOCK`(Red) | |||||
3. `DATA`(Green) | |||||
4. `+5V`(Yellow) | |||||
Not that wire colors may vary in your cable. | |||||
### Pinout | |||||
- <http://pinouts.ru/Inputs/MacKeyboard_pinout.shtml> | |||||
- <http://en.wikipedia.org/wiki/Modular_connector#4P4C> | |||||
![Jack fig](http://www.kbdbabel.org/conn/kbd_connector_macplus.png) | |||||
### Pull-up Registor | |||||
You may need pull-up registors on signal lines(`CLOCK`, `DATA`) in particular | |||||
when you have long or coiled cable. 1k-10k Ohm will be OK for this purpose. | |||||
In some cases MCU can't read signal from keyboard correctly without pull-up resistors. | |||||
Building Frimware | |||||
----------------- | |||||
To compile firmware you need AVR GCC. You can use [WinAVR](http://winavr.sourceforge.net/) on Windows. | |||||
You can edit *Makefile* and *config.h* to change compile options and pin configuration. | |||||
$ git clone git://github.com/tmk/tmk_keyboard.git (or download source) | |||||
$ cd m0110_usb | |||||
$ make | |||||
and program your Teensy with [PJRC Teensy loader](http://www.pjrc.com/teensy/loader.html). | |||||
Keymap | |||||
------ | |||||
You can change keymaps by editing *keymap.c*. | |||||
### M0110 | |||||
#### *Default* | |||||
,---------------------------------------------------------. | |||||
| `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| | |||||
|---------------------------------------------------------| | |||||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||||
|---------------------------------------------------------| | |||||
|Fn0 | A| S| D| F| G| H| J| K| L| ;| '|Return| | |||||
|---------------------------------------------------------| | |||||
|Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | | |||||
`---------------------------------------------------------' | |||||
|Ctr|Alt | Space |Gui |Ctr| | |||||
`-----------------------------------------------' | |||||
#### *HHKB/WASD Layer* | |||||
,---------------------------------------------------------. | |||||
|Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delet| | |||||
|---------------------------------------------------------| | |||||
|Caps |Hom| Up|PgU| | | | |Psc|Slk|Pau|Up | |Ins| | |||||
|---------------------------------------------------------| | |||||
|Fn0 |Lef|Dow|Rig| | | | |Hom|PgU|Lef|Rig|Return| | |||||
|---------------------------------------------------------| | |||||
|Shift |End| |PgD| |VoD|VoU|Mut|End|PgD|Dow|Shift | | |||||
`---------------------------------------------------------' | |||||
|Ctr|Alt | Space |Gui |Ctr| | |||||
`-----------------------------------------------' | |||||
### M0110A | |||||
#### *Default* | |||||
,---------------------------------------------------------. ,---------------. | |||||
| `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Gui| =| /| *| | |||||
|---------------------------------------------------------| |---------------| | |||||
|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| | |||||
|-----------------------------------------------------' | |---------------| | |||||
|Fn0 | A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| | |||||
|---------------------------------------------------------| |---------------| | |||||
|Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | | |||||
|---------------------------------------------------------| |-----------|Ent| | |||||
|Ctrl |Alt | Space | \|Lft|Rgt|Dn | | 0| .| | | |||||
`---------------------------------------------------------' `---------------' | |||||
#### *HHKB/WASD/mousekey Layer* | |||||
,---------------------------------------------------------. ,---------------. | |||||
|Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delet| |Nlk|Mb1|Mb3|Mb2| | |||||
|---------------------------------------------------------| |---------------| | |||||
|Caps |Hom| Up|PgU| | | | |Psc|Slk|Pau|Up | | | |MwD|McU|MwU|MwU| | |||||
|-----------------------------------------------------' | |---------------| | |||||
|Fn0 |Lef|Dow|Rig| | | | |Hom|PgU|Lef|Rig|Return| |McL|McD|McR|MwD| | |||||
|---------------------------------------------------------| |---------------| | |||||
|Shift |End| |PgD| |VoD|VoU|Mut|End|PgD|Dow|Shif|Up | |MwL|McD|MwR| | | |||||
|---------------------------------------------------------| |-----------|Mb2| | |||||
|Ctrl |Alt | Space |Ins|Lft|Rgt|Dn | | Mb1|Mb3| | | |||||
`---------------------------------------------------------' `---------------' | |||||
Debug | |||||
----- | |||||
You can use [PJRC HID listen](http://www.pjrc.com/teensy/hid_listen.html) to see debug output. | |||||
The converter has some functions for debug, press `Alt+Gui+H` simultaneously to get help. | |||||
These function is totally undocumented, tentative, inconsistent and buggy. |
/* | |||||
Copyright 2011,2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x0110 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT M0110 keyboard converter | |||||
#define DESCRIPTION convert M0110 keyboard to USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 14 | |||||
#define MATRIX_COLS 8 | |||||
/* Locking Caps Lock support */ | |||||
//#define MATRIX_HAS_LOCKING_CAPS | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 192 | |||||
#endif | |||||
/* ports */ | |||||
#define M0110_CLOCK_PORT PORTF | |||||
#define M0110_CLOCK_PIN PINF | |||||
#define M0110_CLOCK_DDR DDRF | |||||
#define M0110_CLOCK_BIT 0 | |||||
#define M0110_DATA_PORT PORTF | |||||
#define M0110_DATA_PIN PINF | |||||
#define M0110_DATA_DDR DDRF | |||||
#define M0110_DATA_BIT 1 | |||||
#endif |
/* | |||||
Copyright 2011,2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* M0110A Support was contributed by skagon@github */ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keyboard.h" | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) | |||||
#define KEYMAP( \ | |||||
K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K47,K68,K6D,K62, \ | |||||
K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E, K59,K5B,K5C,K4E, \ | |||||
K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K66, \ | |||||
K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K4D, K53,K54,K55,K4C, \ | |||||
K3A,K37, K31, K34,K2A,K46,K42,K48, K52, K41 \ | |||||
) { \ | |||||
{ KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K08, KB_##K09, KB_NO, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | |||||
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_NO, KB_NO, KB_##K37 }, \ | |||||
{ KB_##K38, KB_##K39, KB_##K3A, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_##K41, KB_##K42, KB_NO, KB_NO, KB_NO, KB_##K46, KB_##K47 }, \ | |||||
{ KB_##K48, KB_NO, KB_NO, KB_NO, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_NO, KB_##K5B, KB_##K5C, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_##K62, KB_NO, KB_NO, KB_NO, KB_##K66, KB_NO }, \ | |||||
{ KB_##K68, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K6D, KB_NO, KB_NO }, \ | |||||
} | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
#ifndef HASU | |||||
1, // Fn0 | |||||
0, // Fn1 | |||||
0, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
#else | |||||
1, // Fn0 | |||||
2, // Fn1 | |||||
3, // Fn2 | |||||
1, // Fn3 | |||||
2, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
#endif | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
#ifndef HASU | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_NO, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
#else | |||||
KB_ENTER, // Fn0 | |||||
KB_SCOLON, // Fn1 | |||||
KB_SLASH, // Fn2 | |||||
KB_UP, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
#endif | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* | |||||
* The keymap works with both M0110 and M0110A keyboards. As you can see, the M0110A is a superset | |||||
* of the M0110 keyboard, with only one exception: 'Enter' in M0110 does not exist | |||||
* on the M0110A, but since it generates a unique scan code which is not used for some other key in | |||||
* the M0110A, they are totally interchangeable. In fact, the M0110A is functionally (almost) | |||||
* identical to the combination of the M0110 along with the M0120 keypad. The only difference | |||||
* (which is causing some problems as you will read below) is that the M0110+M0120 don't have | |||||
* dedicated arrow keys, while the M0110A does. However, the M0120 did have arrow keys, which | |||||
* doubled as the [comma], [/], [*] and [+] keys, when used with the [Shift] key. The M0110A has | |||||
* substituted the [comma] key with the [=] key, however its scancode is the same. | |||||
* | |||||
* Default: | |||||
* ,---------------------------------------------------------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Gui| =| /| *| | |||||
* |---------------------------------------------------------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| | |||||
* |-----------------------------------------------------' | |---------------| | |||||
* |Fn0 | A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| | |||||
* |---------------------------------------------------------| |---------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | | |||||
* |---------------------------------------------------------| |-----------|Ent| | |||||
* |Ctrl |Alt | Space |Gui| \|Lft|Rgt|Dn | | 0| .| | | |||||
* `---------------------------------------------------------' `---------------' | |||||
* | |||||
* HHKB/WASD/Mouse Layer(Fn0): | |||||
* ,---------------------------------------------------------. ,---------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delet| |Nlk|Mb1|Mb3|Mb2| | |||||
* |---------------------------------------------------------| |---------------| | |||||
* |Caps |Hom| Up|PgU| | | | |Psc|Slk|Pau|Up |Ins| | |MwD|McU|MwU|MwU| | |||||
* |-----------------------------------------------------' | |---------------| | |||||
* |Fn0 |Lef|Dow|Rig| | | | |Hom|PgU|Lef|Rig|Return| |McL|McD|McR|MwD| | |||||
* |---------------------------------------------------------| |---------------| | |||||
* |Shift |End| |PgD| |VoD|VoU|Mut|End|PgD|Dow|Shif|Up | |MwL|McD|MwR| | | |||||
* |---------------------------------------------------------| |-----------|Mb2| | |||||
* |Ctrl |Alt | Space |Gui | \|Lft|Rgt|Dn | | Mb1|Mb3| | | |||||
* `---------------------------------------------------------' `---------------' | |||||
* Mb: Mouse Button / Mc: Mouse Cursor / Mw: Mouse Wheel | |||||
* | |||||
* NOTE: M0110 has no arrow and keypad keys. | |||||
* NOTE: \ is located next to ] on M0110. | |||||
* NOTE: Gui between Space and \ is Enter on M0110 not exists on M0110A. | |||||
* NOTE: LShift and RShift are logically same key. (M0110, M0110A) | |||||
* NOTE: LOption and ROption are logically same key. (M0110) | |||||
*/ | |||||
#ifndef HASU | |||||
KEYMAP( | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, LGUI,EQL, PSLS,PAST, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, | |||||
FN0, A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, UP, P1, P2, P3, PENT, | |||||
LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT | |||||
), | |||||
// HHKB & WASD | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,BTN1,BTN3,BTN2, | |||||
CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, WH_D,MS_U,WH_U,WH_U, | |||||
FN0, LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, ENT, MS_L,MS_D,MS_R,WH_D, | |||||
LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, UP, WH_L,MS_D,WH_R,BTN2, | |||||
LCTL,LALT, SPC, LGUI,INS, LEFT,RGHT,DOWN, BTN1, BTN3 | |||||
), | |||||
#else | |||||
// hasu's keymap(To enable this use 'make hasu' to add option flag: EXTRAFLAGS=-DHASU) | |||||
KEYMAP( | |||||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, LGUI,EQL, PSLS,PAST, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS, | |||||
LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT, FN0, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, FN3, P1, P2, P3, PENT, | |||||
FN4, LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, LGUI, PDOT | |||||
), | |||||
// HHKB & WASD | |||||
KEYMAP( | |||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,EQL, PSLS,PAST, | |||||
CAPS,HOME,UP, PGUP,NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, P7, P8, P9, PMNS, | |||||
LCTL,LEFT,DOWN,RGHT,NO, NO, NO, NO, HOME,PGUP,LEFT,RGHT, FN0, P4, P5, P6, PPLS, | |||||
LSFT,END, NO, PGDN,NO, VOLD,VOLU,MUTE,END, PGDN,DOWN, FN3, P1, P2, P3, PENT, | |||||
LCTL,LALT, SPC, LGUI,INS, LEFT,RGHT,DOWN, P0, PDOT | |||||
), | |||||
// vi mousekeys | |||||
KEYMAP( | |||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,EQL, PSLS,PAST, | |||||
CAPS,NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, P7, P8, P9, PMNS, | |||||
NO, VOLD,VOLU,MUTE,NO, NO, MS_L,MS_D,MS_U,MS_R,FN1, NO, ENT, P4, P5, P6, PPLS, | |||||
LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,NO, NO, NO, UP, P1, P2, P3, PENT, | |||||
FN4, LALT, BTN1, LGUI,NO, LEFT,RGHT,DOWN, P0, PDOT | |||||
), | |||||
// vi cusorkeys | |||||
KEYMAP( | |||||
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, NLCK,EQL, PSLS,PAST, | |||||
CAPS,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, PSCR,SLCK,PAUS, P7, P8, P9, PMNS, | |||||
NO, NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, | |||||
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, UP, P1, P2, P3, PENT, | |||||
LCTL,LALT, SPC, LGUI,INS, LEFT,RGHT,DOWN, P0, PDOT | |||||
), | |||||
#endif | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return KEYCODE(layer, row, col); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
} |
/* | |||||
Copyright 2011,2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* scan matrix | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "debug.h" | |||||
#include "host.h" | |||||
#include "led.h" | |||||
#include "m0110.h" | |||||
#include "matrix.h" | |||||
#define CAPS 0x39 | |||||
#define CAPS_BREAK (CAPS | 0x80) | |||||
#define ROW(key) ((key)>>3&0x0F) | |||||
#define COL(key) ((key)&0x07) | |||||
static bool is_modified = false; | |||||
// matrix state buffer(1:on, 0:off) | |||||
static uint8_t *matrix; | |||||
static uint8_t _matrix0[MATRIX_ROWS]; | |||||
static void register_key(uint8_t key); | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
print_enable = true; | |||||
debug_enable = true; | |||||
debug_matrix = false; | |||||
debug_keyboard = false; | |||||
debug_mouse = false; | |||||
print("debug enabled.\n"); | |||||
m0110_init(); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | |||||
matrix = _matrix0; | |||||
return; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
uint8_t key; | |||||
is_modified = false; | |||||
key = m0110_recv_key(); | |||||
#ifdef MATRIX_HAS_LOCKING_CAPS | |||||
// Send Caps key up event | |||||
if (matrix_is_on(ROW(CAPS), COL(CAPS))) { | |||||
is_modified = true; | |||||
register_key(CAPS_BREAK); | |||||
} | |||||
#endif | |||||
if (key == M0110_NULL) { | |||||
return 0; | |||||
} else if (key == M0110_ERROR) { | |||||
return 0; | |||||
} else { | |||||
#ifdef MATRIX_HAS_LOCKING_CAPS | |||||
if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) { | |||||
// CAPS LOCK on: | |||||
// Ignore LockingCaps key down event | |||||
if (key == CAPS) return 0; | |||||
// Convert LockingCaps key up event into down event | |||||
if (key == CAPS_BREAK) key = CAPS; | |||||
} else { | |||||
// CAPS LOCK off: | |||||
// Ignore LockingCaps key up event | |||||
if (key == CAPS_BREAK) return 0; | |||||
} | |||||
#endif | |||||
is_modified = true; | |||||
register_key(key); | |||||
} | |||||
if (debug_enable) { | |||||
print("["); phex(key); print("]\n"); | |||||
} | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
return is_modified; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
pbin_reverse(matrix_get_row(row)); | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
count += bitpop(matrix[i]); | |||||
} | |||||
return count; | |||||
} | |||||
inline | |||||
static void register_key(uint8_t key) | |||||
{ | |||||
if (key&0x80) { | |||||
matrix[ROW(key)] &= ~(1<<COL(key)); | |||||
} else { | |||||
matrix[ROW(key)] |= (1<<COL(key)); | |||||
} | |||||
} |
# Target file name (without extension). | |||||
TARGET = macway | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c | |||||
CONFIG_H = config.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# comment out to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0xBEE0 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT Macway mod | |||||
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 9 | |||||
#define MATRIX_COLS 8 | |||||
/* define if matrix has ghost */ | |||||
#define MATRIX_HAS_GHOST | |||||
/* Set 0 if need no debouncing */ | |||||
#define DEBOUNCE 5 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 192 | |||||
#endif | |||||
/* PS/2 mouse */ | |||||
#ifdef PS2_MOUSE_ENABLE | |||||
# define PS2_CLOCK_PORT PORTF | |||||
# define PS2_CLOCK_PIN PINF | |||||
# define PS2_CLOCK_DDR DDRF | |||||
# define PS2_CLOCK_BIT 0 | |||||
# define PS2_DATA_PORT PORTF | |||||
# define PS2_DATA_PIN PINF | |||||
# define PS2_DATA_DDR DDRF | |||||
# define PS2_DATA_BIT 1 | |||||
#endif | |||||
#endif |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* Keymap for Macway mod | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
// Convert physical keyboard layout to matrix array. | |||||
// This is a macro to define keymap easily in keyboard layout form. | |||||
#define KEYMAP( \ | |||||
K11, K10, K20, K30, K40, K41, K51, K50, K60, K70, K80, K81, K61, K02, \ | |||||
K12, K13, K23, K33, K43, K42, K52, K53, K63, K73, K83, K82, K62, \ | |||||
K15, K14, K24, K34, K44, K45, K55, K54, K64, K74, K84, K85, K06, \ | |||||
K67, K16, K26, K36, K46, K47, K57, K56, K66, K76, K87, K32, K35, \ | |||||
K75, K22, K00, K07, K21, K04, K37, K27, K17 \ | |||||
) { \ | |||||
{ KB_##K00, KB_NO, KB_##K02, KB_NO, KB_##K04, KB_NO, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_NO, KB_##K26, KB_##K27 }, \ | |||||
{ KB_##K30, KB_NO, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_NO, KB_##K66, KB_##K67 }, \ | |||||
{ KB_##K70, KB_NO, KB_NO, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_NO }, \ | |||||
{ KB_##K80, KB_##K81, KB_##K82, KB_##K83, KB_##K84, KB_##K85, KB_NO, KB_##K87 } \ | |||||
} | |||||
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
1, // Fn1 | |||||
2, // Fn2 | |||||
3, // Fn3 | |||||
4, // Fn4 | |||||
0, // Fn5 | |||||
2, // Fn6 | |||||
3 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_SLSH, // Fn2 | |||||
KB_SCLN, // Fn3 | |||||
KB_SPC, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* Layer 0: Default Layer | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | |||||
* |-----------------------------------------------------' | | |||||
* |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn1| | |||||
* |-----------------------------------------------------------| | |||||
* |Fn7|Gui |Alt |Fn4 |Alt |Gui|Fn6|Fn6|Ctr| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \ | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, \ | |||||
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,ENT, \ | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ | |||||
FN7, LGUI,LALT,FN4, RALT,BSLS,GRV, FN6, RCTL), | |||||
/* Layer 1: HHKB mode (HHKB Fn) | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||||
* |-----------------------------------------------------------| | |||||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | | | | |||||
* |-----------------------------------------------------' | | |||||
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx| | |||||
* |-----------------------------------------------------------| | |||||
* | |Gui |Alt | |Alt |Gui| | |Ctr| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, \ | |||||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, \ | |||||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ | |||||
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN1, \ | |||||
NO, LGUI,LALT,SPC, RALT,NO, NO, NO, RCTL), | |||||
/* Layer 2: Vi mode (Quote/Rmeta) | |||||
* ,-----------------------------------------------------------. | |||||
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| ` | | |||||
* |-----------------------------------------------------------| | |||||
* | \ |Hom|PgD|Up |PgU|End|Hom|PgD|PgU|End| | | | | | |||||
* |-----------------------------------------------------' | | |||||
* |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | | \ | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | |Hom|PgD|PgU|End|xxx|Shift | | | |||||
* |-----------------------------------------------------------| | |||||
* | |Gui |Alt |Space |Alt |Gui|Fn6|Fn6|Ctr| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, GRV, \ | |||||
BSLS,HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, \ | |||||
LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, BSLS, \ | |||||
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,NO, \ | |||||
NO, LGUI,LALT,SPC, RALT,RGUI,FN6, FN6, RCTL), | |||||
/* Layer 3: Mouse mode (Semicolon) | |||||
* ,-----------------------------------------------------------. | |||||
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| ` | | |||||
* |-----------------------------------------------------------| | |||||
* | \ |MwL|MwD|McU|MwU|MwR|MwL|MwD|MwU|MwR| | | | | | |||||
* |-----------------------------------------------------' | | |||||
* |Contro| |McL|McD|McR| |McL|McD|McU|McR|xxx| | \ | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | |Mb1|Mb2|Mb3|Mb2|Mb1| | | |Shift | | | |||||
* |-----------------------------------------------------------| | |||||
* |xxx|Gui |Alt |Mb1 |Alt | | | | | | |||||
* `-----------------------------------------------------------' | |||||
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel | |||||
*/ | |||||
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, GRV, \ | |||||
BSLS,WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, \ | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, BSLS, \ | |||||
LSFT,NO, NO, BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT,NO, \ | |||||
FN7, LGUI,LALT,BTN1,RALT,NO, NO, NO, NO), | |||||
/* Layer 4: Matias half keyboard style (Space) | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete | | |||||
* |-----------------------------------------------------------| | |||||
* |Backs| P| O| I| U| Y| T| R| E| W| Q|Tab|Tab| | | |||||
* |-----------------------------------------------------' | | |||||
* |Contro| ;| L| K| J| H| G| F| D| S| A|Con|Control | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | | | |||||
* |-----------------------------------------------------------| | |||||
* | |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxx|Alt |Gui| | |Ctr| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, ESC, \ | |||||
BSPC,P, O, I, U, Y, T, R, E, W, Q, TAB, TAB, \ | |||||
LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \ | |||||
LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \ | |||||
NO, LGUI,LALT,FN4, RALT,RGUI,NO, NO, RCTL), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return KEYCODE(layer, row, col); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* scan matrix | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "matrix.h" | |||||
#if (MATRIX_COLS > 16) | |||||
# error "MATRIX_COLS must not exceed 16" | |||||
#endif | |||||
#if (MATRIX_ROWS > 255) | |||||
# error "MATRIX_ROWS must not exceed 255" | |||||
#endif | |||||
#ifndef DEBOUNCE | |||||
# define DEBOUNCE 0 | |||||
#endif | |||||
static uint8_t debouncing = DEBOUNCE; | |||||
// matrix state buffer(1:on, 0:off) | |||||
#if (MATRIX_COLS <= 8) | |||||
static uint8_t *matrix; | |||||
static uint8_t *matrix_prev; | |||||
static uint8_t _matrix0[MATRIX_ROWS]; | |||||
static uint8_t _matrix1[MATRIX_ROWS]; | |||||
#else | |||||
static uint16_t *matrix; | |||||
static uint16_t *matrix_prev; | |||||
static uint16_t _matrix0[MATRIX_ROWS]; | |||||
static uint16_t _matrix1[MATRIX_ROWS]; | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
static bool matrix_has_ghost_in_row(uint8_t row); | |||||
#endif | |||||
static uint8_t read_col(void); | |||||
static void unselect_rows(void); | |||||
static void select_row(uint8_t row); | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
// initialize row and col | |||||
unselect_rows(); | |||||
// Input with pull-up(DDR:0, PORT:1) | |||||
DDRB = 0x00; | |||||
PORTB = 0xFF; | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00; | |||||
matrix = _matrix0; | |||||
matrix_prev = _matrix1; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
if (!debouncing) { | |||||
uint8_t *tmp = matrix_prev; | |||||
matrix_prev = matrix; | |||||
matrix = tmp; | |||||
} | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
unselect_rows(); | |||||
select_row(i); | |||||
_delay_us(30); // without this wait read unstable value. | |||||
if (matrix[i] != (uint8_t)~read_col()) { | |||||
matrix[i] = (uint8_t)~read_col(); | |||||
if (debouncing) { | |||||
debug("bounce!: "); debug_hex(debouncing); print("\n"); | |||||
} | |||||
debouncing = DEBOUNCE; | |||||
} | |||||
} | |||||
unselect_rows(); | |||||
if (debouncing) { | |||||
debouncing--; | |||||
} | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
if (debouncing) return false; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix[i] != matrix_prev[i]) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
#ifdef MATRIX_HAS_GHOST | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix_has_ghost_in_row(i)) | |||||
return true; | |||||
} | |||||
#endif | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
#if (MATRIX_COLS <= 8) | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
#else | |||||
uint16_t matrix_get_row(uint8_t row) | |||||
#endif | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
#if (MATRIX_COLS <= 8) | |||||
pbin_reverse(matrix_get_row(row)); | |||||
#else | |||||
pbin_reverse16(matrix_get_row(row)); | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | |||||
if (matrix_has_ghost_in_row(row)) { | |||||
print(" <ghost"); | |||||
} | |||||
#endif | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
#if (MATRIX_COLS <= 8) | |||||
count += bitpop(matrix[i]); | |||||
#else | |||||
count += bitpop16(matrix[i]); | |||||
#endif | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | |||||
inline | |||||
static bool matrix_has_ghost_in_row(uint8_t row) | |||||
{ | |||||
// no ghost exists in case less than 2 keys on | |||||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||||
return false; | |||||
// ghost exists in case same state as other row | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
#endif | |||||
inline | |||||
static uint8_t read_col(void) | |||||
{ | |||||
return PINB; | |||||
} | |||||
inline | |||||
static void unselect_rows(void) | |||||
{ | |||||
// Hi-Z(DDR:0, PORT:0) to unselect | |||||
DDRC &= ~0b11000000; // PC: 7,6 | |||||
PORTC &= ~0b11000000; | |||||
DDRD &= ~0b11000111; // PD: 7,6,2,1,0 | |||||
PORTD &= ~0b11000111; | |||||
DDRF &= ~0b11000000; // PF: 7,6 | |||||
PORTF &= ~0b11000000; | |||||
} | |||||
inline | |||||
static void select_row(uint8_t row) | |||||
{ | |||||
// Output low(DDR:1, PORT:0) to select | |||||
// row: 0 1 2 3 4 5 6 7 8 | |||||
// pin: PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7 | |||||
switch (row) { | |||||
case 0: | |||||
DDRD |= (1<<0); | |||||
PORTD &= ~(1<<0); | |||||
break; | |||||
case 1: | |||||
DDRC |= (1<<7); | |||||
PORTC &= ~(1<<7); | |||||
break; | |||||
case 2: | |||||
DDRD |= (1<<7); | |||||
PORTD &= ~(1<<7); | |||||
break; | |||||
case 3: | |||||
DDRF |= (1<<6); | |||||
PORTF &= ~(1<<6); | |||||
break; | |||||
case 4: | |||||
DDRD |= (1<<6); | |||||
PORTD &= ~(1<<6); | |||||
break; | |||||
case 5: | |||||
DDRD |= (1<<1); | |||||
PORTD &= ~(1<<1); | |||||
break; | |||||
case 6: | |||||
DDRD |= (1<<2); | |||||
PORTD &= ~(1<<2); | |||||
break; | |||||
case 7: | |||||
DDRC |= (1<<6); | |||||
PORTC &= ~(1<<6); | |||||
break; | |||||
case 8: | |||||
DDRF |= (1<<7); | |||||
PORTF &= ~(1<<7); | |||||
break; | |||||
} | |||||
} |
# Search Path | |||||
VPATH += $(TOP_DIR)/protocol |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = ps2_usb_pjrc | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
ps2.c | |||||
CONFIG_H = config_pjrc.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = ps2_usb_pjrc_usart | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
ps2_usart.c | |||||
CONFIG_H = config_pjrc_usart.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
# | |||||
# Makefile for V-USB | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = ps2_usb_vusb | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
ps2_usart.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 | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
NO_UART = yes # UART is unavailable | |||||
#---------------- 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 $(TOP_DIR)/protocol/vusb.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
PS/2 to USB keyboard converter | |||||
============================== | |||||
This firmware converts PS/2 keyboard protocol to USB and for now supports only Scan Code Set 2. | |||||
This will works on USB AVR(ATMega32U4, AT90USB) or V-USB. | |||||
Features | |||||
-------- | |||||
Mouse keys | |||||
You can emulates mouse move and button click using keyboard. | |||||
System/Media control | |||||
You can sends Power event, Volume down/up and Mute. | |||||
USB NKRO(actually 120KRO+8Modifiers) | |||||
You can tolggles NKRO feature. | |||||
Keymap customization | |||||
You can customize keymaps easily by editing source code. See keymap.c. | |||||
PS/2 signal handling implementations | |||||
------------------------------------ | |||||
Following three methods are used to implement PS/2 signal handling. | |||||
a. Simple and stupid wait & read loop(intensive use of cycles) | |||||
This is implemented with (expected) portable C code for reference. See ps2.c. | |||||
b. Interrupt driven | |||||
See ps2_intr.c | |||||
c. Using USART hardware module(no cycle needed) | |||||
This uses AVR USART function to recevie PS/2 signal and be used in V-USB converter. | |||||
See ps2_usart.c. | |||||
Build Converter | |||||
--------------- | |||||
Connect PS/2 keyboard into Teensy with 4 lines(Vcc, GND, Data, Clock). | |||||
For a. Simple and stupid and b. Interrupt implementaion: | |||||
By default Clock is on PF0 and Data on PF1. | |||||
You can change this pin configuration by editing config_pjrc.h. | |||||
In this photo Vcc is yellow, GND is green, Data is red and Clock is black. | |||||
http://img17.imageshack.us/img17/7243/201101181933.jpg | |||||
For c. USART implementation: | |||||
In case of Teensny(ATMega32u4) CLock is on PD5 and Data on PD2. | |||||
Build Frimware | |||||
-------------- | |||||
1. Edit Makefile for build options and MCU setting. | |||||
Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0. | |||||
2. make | |||||
Just type 'make' in a terminal. | |||||
Use '-f Makefile.pjrc_intr' option to use b. Interrupt. | |||||
Use '-f Makefile.pjrc_usart' option to use c. USART. | |||||
Use '-f Makefile.vusb' option to build V-USB converter. | |||||
3. program with Teensy Loader. | |||||
http://www.pjrc.com/teensy/loader.html | |||||
Demonstration of Features | |||||
------------------------- | |||||
In default configuration, you can try several keymaps, mousekeys and USB NKRO. | |||||
Use following magic key combinations to enable some features. | |||||
keymaps and NKRO: | |||||
Magic+0: Qwerty with mousekeys(default) | |||||
Magic+1: Qwerty without mousekeys | |||||
Magic+2: Colemak | |||||
Magic+3: Dvorak | |||||
Magic+4: Workman | |||||
Magic+N: toggles NKRO/6KRO(6KRO by default) | |||||
Magic+Esc: sends Power Event(Power button) | |||||
where Magic=(LShift+RShift) or (LControl+RShift) | |||||
Fn layer function: | |||||
Fn0+(hjkl): Mousekey move(vi cursor like) | |||||
Fn0+(yuio): Mouse wheel(left,down,up,right) | |||||
Fn0+space: Mouse left button | |||||
Fn0+(mnb): Mouse buttons(m=left, n=right, b=middle) | |||||
Fn0+(zxc): Media control(Volup, Voldown, Mute) | |||||
Fn1+(hjkl): Cursor move(vi cursor like) | |||||
Fn1+(nm,.): Cursor move(Home,PageDown,PageUp,End) | |||||
where Fn0=;, Fn1=/ | |||||
Keymap | |||||
------ | |||||
You can change a keymap by editing code of keymap.c like following. | |||||
How to define the keymap is probably obvious. You can find key symbols in usb_keycodes.h. | |||||
To define keymap layer switching may needs a bit of your effort at this time. | |||||
/* Default Layer: plain keymap | |||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' `-----------' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| /| *| -| | |||||
* |-----------------------------------------------------------| |-----------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | | |||||
* |-----------------------------------------------------------| `-----------' |-----------| +| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| | | |||||
* |-----------------------------------------------------------| ,---. |---------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | | |||||
* `-----------------------------------------------------------' `-----------' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
EOF |
V-USB Support | |||||
============= | |||||
You can also use this converter on ATmega(168/328) with V-USB instead of Teensy. | |||||
The converter on V-USB lacks some features for now: USB NKRO and System/Media control. | |||||
To build a firmware use Makefile.vusb instead of Makefile. | |||||
Circuit | |||||
------- | |||||
+---+ +---------------+ | |||||
USB GND | | ATmega168 | | |||||
=== C3 | | | |||||
5V <-------+--------+---|Vcc,AVCC | PS/2 | |||||
R1 | | ==== | |||||
D- <----+--+-----R2-----|INT1 RXD|------->DATA | |||||
D+ <----|---+----R3-----|INT0 XCK|------->CLOCK | |||||
Z1 Z2 | | ->5V | |||||
GND<----+---+--+--+-----|GND | ->GND | |||||
| | | | | |||||
| C2-+--|XTAL1 | | |||||
| X1 | | | |||||
+--C3-+--|XTAL2 | | |||||
+---------------+ | |||||
R1: 1.5K Ohm | |||||
R2,R3: 68 Ohm | |||||
Z1,Z2: Zenner 3.6V | |||||
C1,C2: 22pF | |||||
C3: 0.1uF | |||||
X1: Crystal 20MHz(16MHz/12MHz) | |||||
This is my V-USB converter on breadboard. | |||||
[IMG]http://i.imgur.com/8jJCZl.jpg[/IMG] | |||||
EOF |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x6512 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT PS/2 keyboard converter | |||||
#define DESCRIPTION convert PS/2 keyboard to USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* PS/2 lines */ | |||||
#define PS2_CLOCK_PORT PORTF | |||||
#define PS2_CLOCK_PIN PINF | |||||
#define PS2_CLOCK_DDR DDRF | |||||
#define PS2_CLOCK_BIT 0 | |||||
#define PS2_DATA_PORT PORTF | |||||
#define PS2_DATA_PIN PINF | |||||
#define PS2_DATA_DDR DDRF | |||||
#define PS2_DATA_BIT 1 | |||||
#endif |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x6513 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT PS/2 keyboard converter(USART) | |||||
#define DESCRIPTION convert PS/2 keyboard to USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* PS/2 lines */ | |||||
#define PS2_CLOCK_PORT PORTD | |||||
#define PS2_CLOCK_PIN PIND | |||||
#define PS2_CLOCK_DDR DDRD | |||||
#define PS2_CLOCK_BIT 5 | |||||
#define PS2_DATA_PORT PORTD | |||||
#define PS2_DATA_PIN PIND | |||||
#define PS2_DATA_DDR DDRD | |||||
#define PS2_DATA_BIT 2 | |||||
// 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); \ | |||||
UCSR1C = ((1 << UMSEL10) | \ | |||||
(3 << UPM10) | \ | |||||
(0 << USBS1) | \ | |||||
(3 << UCSZ10) | \ | |||||
(0 << UCPOL1)); \ | |||||
UCSR1A = 0; \ | |||||
UBRR1H = 0; \ | |||||
UBRR1L = 0; \ | |||||
} while (0) | |||||
#define PS2_USART_RX_INT_ON() do { \ | |||||
UCSR1B = ((1 << RXCIE1) | \ | |||||
(1 << RXEN1)); \ | |||||
} while (0) | |||||
#define PS2_USART_RX_POLL_ON() do { \ | |||||
UCSR1B = (1 << RXEN1); \ | |||||
} while (0) | |||||
#define PS2_USART_OFF() do { \ | |||||
UCSR1C = 0; \ | |||||
UCSR1B &= ~((1 << RXEN1) | \ | |||||
(1 << TXEN1)); \ | |||||
} while (0) | |||||
#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) | |||||
#define PS2_USART_RX_DATA UDR1 | |||||
#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | |||||
#define PS2_USART_RX_VECT USART1_RX_vect | |||||
#endif |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x2233 | |||||
// TODO: share these strings with usbconfig.h | |||||
// Edit usbconfig.h to change these. | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT PS/2 keyboard converter | |||||
#define DESCRIPTION convert PS/2 keyboard to USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 32 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* PS/2 lines */ | |||||
#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 |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
/* | |||||
* Keymap for PS/2 keyboard | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
// Following macros help you to define a keymap with the form of actual keyboard layout. | |||||
/* US layout plus all other various keys */ | |||||
#define KEYMAP_ALL( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | |||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ | |||||
\ | |||||
K61, /* for European ISO */ \ | |||||
K51, K13, K6A, K64, K67, /* for Japanese JIS */ \ | |||||
K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */ \ | |||||
KB7, KBF, KDE, /* System Power, Sleep, Wake */ \ | |||||
KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \ | |||||
KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \ | |||||
KC8, KAB, KC0, /* Mail, Calculator, My Computer */ \ | |||||
K90, KBA, KB8, KB0, /* WWW Search, Home, Back, Forward */ \ | |||||
KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \ | |||||
) { \ | |||||
{ KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_NO }, \ | |||||
{ KB_##K18, KB_NO, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_NO }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ | |||||
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_NO }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \ | |||||
{ KB_##K38, KB_NO, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ | |||||
{ KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ | |||||
{ KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_NO, KB_##K54, KB_##K55, KB_NO, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_NO, KB_##K5D, KB_NO, KB_##K5F }, \ | |||||
{ KB_NO, KB_##K61, KB_NO, KB_NO, KB_##K64, KB_NO, KB_##K66, KB_##K67 }, \ | |||||
{ KB_NO, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ | |||||
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_##K83, KB_NO, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_##K90, KB_##K91, KB_NO, KB_NO, KB_##K94, KB_##K95, KB_NO, KB_NO }, \ | |||||
{ KB_##K98, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K9F }, \ | |||||
{ KB_##KA0, KB_##KA1, KB_NO, KB_##KA3, KB_NO, KB_NO, KB_NO, KB_##KA7 }, \ | |||||
{ KB_##KA8, KB_NO, KB_NO, KB_##KAB, KB_NO, KB_NO, KB_NO, KB_##KAF }, \ | |||||
{ KB_##KB0, KB_NO, KB_##KB2, KB_NO, KB_##KB4, KB_NO, KB_NO, KB_##KB7 }, \ | |||||
{ KB_##KB8, KB_NO, KB_##KBA, KB_##KBB, KB_NO, KB_NO, KB_NO, KB_##KBF }, \ | |||||
{ KB_##KC0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_##KC8, KB_NO, KB_##KCA, KB_NO, KB_NO, KB_##KCD, KB_NO, KB_NO }, \ | |||||
{ KB_##KD0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_##KDA, KB_NO, KB_NO, KB_NO, KB_##KDE, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_##KE9, KB_NO, KB_##KEB, KB_##KEC, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_##KF0, KB_##KF1, KB_##KF2, KB_NO, KB_##KF4, KB_##KF5, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \ | |||||
} | |||||
/* US layout */ | |||||
#define KEYMAP( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | |||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ | |||||
) \ | |||||
KEYMAP_ALL( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | |||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ | |||||
\ | |||||
NUBS, \ | |||||
RO, KANA, JYEN, HENK, MHEN, \ | |||||
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ | |||||
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ | |||||
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ | |||||
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ | |||||
MAIL, CALCULATOR, MY_COMPUTER, \ | |||||
WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ | |||||
WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ | |||||
) | |||||
/* ISO layout */ | |||||
#define KEYMAP_ISO( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A, K6B,K73,K74,K79, \ | |||||
K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ | |||||
) \ | |||||
KEYMAP_ALL( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | |||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ | |||||
\ | |||||
K61, \ | |||||
RO, KANA, JYEN, HENK, MHEN, \ | |||||
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ | |||||
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ | |||||
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ | |||||
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ | |||||
MAIL, CALCULATOR, MY_COMPUTER, \ | |||||
WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ | |||||
WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ | |||||
) | |||||
/* JIS layout */ | |||||
#define KEYMAP_JIS( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D, K5A, K6B,K73,K74,K79, \ | |||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K67,K29,K64,K13, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \ | |||||
) \ | |||||
KEYMAP_ALL( \ | |||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \ | |||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \ | |||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ | |||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ | |||||
\ | |||||
NUBS, \ | |||||
K51, K13, K6A, K64, K67, \ | |||||
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \ | |||||
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ | |||||
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ | |||||
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ | |||||
MAIL, CALCULATOR, MY_COMPUTER, \ | |||||
WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \ | |||||
WWW_STOP, WWW_REFRESH, WWW_FAVORITES \ | |||||
) | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
5, // Fn0 | |||||
6, // Fn1 | |||||
0, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_SCLN, // Fn0 | |||||
KB_SLSH, // Fn1 | |||||
KB_NO, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
// The keymap is a 32*8 byte array which convert a PS/2 scan code into a USB keycode. | |||||
// See usb_keycodes.h for USB keycodes. You should omit a 'KB_' prefix of USB keycodes in keymap macro. | |||||
// Use KEYMAP_ISO() or KEYMAP_JIS() instead of KEYMAP() if your keyboard is ISO or JIS. | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* 0: default | |||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|Slp|Wak| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' `-----------' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| /| *| -| | |||||
* |-----------------------------------------------------------| |-----------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | | |||||
* |-----------------------------------------------------------| `-----------' |-----------| +| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| | | |||||
* |-----------------------------------------------------------| ,---. |---------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| |Lef|Dow|Rig| | 0| .| | | |||||
* `-----------------------------------------------------------' `-----------' `---------------' | |||||
* ; = Fn0(to Layer 5) | |||||
* / = Fn1(to Layer 6) | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
CAPS,A, S, D, F, G, H, J, K, L, FN0, QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN1, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
/* 1: plain Qwerty without layer switching | |||||
* ,-----------------------------------------------------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | |||||
* |-----------------------------------------------------------| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
/* 2: Colemak http://colemak.com | |||||
* ,-----------------------------------------------------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| W| F| P| G| J| L| U| Y| ;| [| ]| \| | |||||
* |-----------------------------------------------------------| | |||||
* |BackSp| A| R| S| T| D| H| N| E| I| O| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| C| V| B| K| M| ,| ,| /|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| | |||||
* `----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, W, F, P, G, J, L, U, Y, SCLN,LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
BSPC,A, R, S, T, D, H, N, E, I, O, QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, C, V, B, K, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
/* 3: Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard | |||||
* ,-----------------------------------------------------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| [| ]|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | '| ,| .| P| Y| F| G| C| R| L| /| =| \| | |||||
* |-----------------------------------------------------------| | |||||
* |BackSp| A| O| E| U| I| D| H| T| N| S| -|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | ;| Q| J| K| X| B| M| Wl V| Z|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4, P5, P6, PPLS, | |||||
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
/* 4: Workman http://viralintrospection.wordpress.com/2010/09/06/a-different-philosophy-in-designing-keyboard-layouts/ | |||||
* ,-----------------------------------------------------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab | Q| D| R| W| B| J| F| U| P| ;| [| ]| \| | |||||
* |-----------------------------------------------------------| | |||||
* |CapsLo| A| S| H| T| G| Y| N| E| O| I| '|Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | Z| X| M| C| V| K| L| ,| ,| /|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, D, R, W, B, J, F, U, P, SCLN,LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
BSPC,A, S, H, T, G, Y, N, E, O, I, QUOT, ENT, P4, P5, P6, PPLS, | |||||
LSFT,Z, X, M, C, V, K, L, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
/* 5: Mouse keys | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab |MwL|MwU|McU|WwU|WwR|MwL|MwD|MwU|MwR| | | | \| | |||||
* |-----------------------------------------------------------| | |||||
* |CapsLo| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift |VoD|VoU|Mut|Mb2|Mb3|Mb2|Mb1|VoD|VoU|Mut|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl |Gui |Alt | Mb1 |Alt |Gui |Menu|Ctrl| | |||||
* `-----------------------------------------------------------' | |||||
* Mc = mouse cursor, Mw = mouse wheel, Mb = mouse button | |||||
* Vo = Volume, Mut = Mute | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
CAPS,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, P4, P5, P6, PPLS, | |||||
LSFT,VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, BTN1, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
/* 6: Cursor keys | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab |Hom|PgU| Up|PgU|End|Hom|PgD|PgU|End| | | | \| | |||||
* |-----------------------------------------------------------| | |||||
* |CapsLo| |Lef|Dow|Rig| |Lef|Dow| Up|Rig| | |Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | |Hom|PgD|PgU|End|Fn1|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl |Gui |Alt | Space |Alt |Gui |Menu|Ctrl| | |||||
* `-----------------------------------------------------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, | |||||
CAPS,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS, | |||||
LSFT,VOLD,VOLU,MUTE,NO, NO, HOME,PGDN,PGUP,END, FN1, RSFT, UP, P1, P2, P3, | |||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT | |||||
), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "ps2.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
uint8_t ps2_led = 0; | |||||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_SCROLL_LOCK); | |||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_NUM_LOCK); | |||||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_CAPS_LOCK); | |||||
ps2_host_set_led(ps2_led); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "debug.h" | |||||
#include "ps2.h" | |||||
#include "matrix.h" | |||||
static void matrix_make(uint8_t code); | |||||
static void matrix_break(uint8_t code); | |||||
#ifdef MATRIX_HAS_GHOST | |||||
static bool matrix_has_ghost_in_row(uint8_t row); | |||||
#endif | |||||
/* | |||||
* Matrix Array usage: | |||||
* 'Scan Code Set 2' is assigned into 256(32x8)cell matrix. | |||||
* Hmm, it is very sparse and not efficient :( | |||||
* | |||||
* Notes: | |||||
* Both 'Hanguel/English'(F1) and 'Hanja'(F2) collide with 'Delete'(E0 71) and 'Down'(E0 72). | |||||
* These two Korean keys need exceptional handling and are not supported for now. Sorry. | |||||
* | |||||
* 8bit wide | |||||
* +---------+ | |||||
* 0| | | |||||
* :| XX | 00-7F for normal codes(without E0-prefix) | |||||
* f|_________| | |||||
* 10| | | |||||
* :| E0 YY | 80-FF for E0-prefixed codes | |||||
* 1f| | (<YY>|0x80) is used as matrix position. | |||||
* +---------+ | |||||
* | |||||
* Exceptions: | |||||
* 0x83: F7(0x83) This is a normal code but beyond 0x7F. | |||||
* 0xFC: PrintScreen | |||||
* 0xFE: Pause | |||||
*/ | |||||
static uint8_t matrix[MATRIX_ROWS]; | |||||
#define ROW(code) (code>>3) | |||||
#define COL(code) (code&0x07) | |||||
// matrix positions for exceptional keys | |||||
#define F7 (0x83) | |||||
#define PRINT_SCREEN (0xFC) | |||||
#define PAUSE (0xFE) | |||||
static bool is_modified = false; | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
ps2_host_init(); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||||
return; | |||||
} | |||||
/* | |||||
* PS/2 Scan Code Set 2: Exceptional Handling | |||||
* | |||||
* There are several keys to be handled exceptionally. | |||||
* The scan code for these keys are varied or prefix/postfix'd | |||||
* depending on modifier key state. | |||||
* | |||||
* Keyboard Scan Code Specification: | |||||
* http://www.microsoft.com/whdc/archive/scancode.mspx | |||||
* http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc | |||||
* | |||||
* | |||||
* 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left | |||||
* a) when Num Lock is off | |||||
* modifiers | make | break | |||||
* ----------+---------------------------+---------------------- | |||||
* Ohter | <make> | <break> | |||||
* LShift | E0 F0 12 <make> | <break> E0 12 | |||||
* RShift | E0 F0 59 <make> | <break> E0 59 | |||||
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 | |||||
* | |||||
* b) when Num Lock is on | |||||
* modifiers | make | break | |||||
* ----------+---------------------------+---------------------- | |||||
* Other | E0 12 <make> | <break> E0 F0 12 | |||||
* Shift'd | <make> | <break> | |||||
* | |||||
* Handling: These prefix/postfix codes are ignored. | |||||
* | |||||
* | |||||
* 2) Keypad / | |||||
* modifiers | make | break | |||||
* ----------+---------------------------+---------------------- | |||||
* Ohter | <make> | <break> | |||||
* LShift | E0 F0 12 <make> | <break> E0 12 | |||||
* RShift | E0 F0 59 <make> | <break> E0 59 | |||||
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 | |||||
* | |||||
* Handling: These prefix/postfix codes are ignored. | |||||
* | |||||
* | |||||
* 3) PrintScreen | |||||
* modifiers | make | break | |||||
* ----------+--------------+----------------------------------- | |||||
* Other | E0 12 E0 7C | E0 F0 7C E0 F0 12 | |||||
* Shift'd | E0 7C | E0 F0 7C | |||||
* Control'd | E0 7C | E0 F0 7C | |||||
* Alt'd | 84 | F0 84 | |||||
* | |||||
* Handling: These prefix/postfix codes are ignored, and both scan codes | |||||
* 'E0 7C' and 84 are seen as PrintScreen. | |||||
* | |||||
* 4) Pause | |||||
* modifiers | make(no break code) | |||||
* ----------+-------------------------------------------------- | |||||
* Other | E1 14 77 E1 F0 14 F0 77 | |||||
* Control'd | E0 7E E0 F0 7E | |||||
* | |||||
* Handling: Both code sequences are treated as a whole. | |||||
* And we need a ad hoc 'pseudo break code' hack to get the key off | |||||
* because it has no break code. | |||||
* | |||||
*/ | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
// scan code reading states | |||||
static enum { | |||||
INIT, | |||||
F0, | |||||
E0, | |||||
E0_F0, | |||||
// Pause | |||||
E1, | |||||
E1_14, | |||||
E1_14_77, | |||||
E1_14_77_E1, | |||||
E1_14_77_E1_F0, | |||||
E1_14_77_E1_F0_14, | |||||
E1_14_77_E1_F0_14_F0, | |||||
// Control'd Pause | |||||
E0_7E, | |||||
E0_7E_E0, | |||||
E0_7E_E0_F0, | |||||
} state = INIT; | |||||
is_modified = false; | |||||
// 'pseudo break code' hack | |||||
if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) { | |||||
matrix_break(PAUSE); | |||||
} | |||||
uint8_t code; | |||||
while ((code = ps2_host_recv())) { | |||||
switch (state) { | |||||
case INIT: | |||||
switch (code) { | |||||
case 0xE0: | |||||
state = E0; | |||||
break; | |||||
case 0xF0: | |||||
state = F0; | |||||
break; | |||||
case 0xE1: | |||||
state = E1; | |||||
break; | |||||
case 0x83: // F7 | |||||
matrix_make(F7); | |||||
state = INIT; | |||||
break; | |||||
case 0x84: // Alt'd PrintScreen | |||||
matrix_make(PRINT_SCREEN); | |||||
state = INIT; | |||||
break; | |||||
default: // normal key make | |||||
if (code < 0x80) { | |||||
matrix_make(code); | |||||
} else { | |||||
debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E0: // E0-Prefixed | |||||
switch (code) { | |||||
case 0x12: // to be ignored | |||||
case 0x59: // to be ignored | |||||
state = INIT; | |||||
break; | |||||
case 0x7E: // Control'd Pause | |||||
state = E0_7E; | |||||
break; | |||||
case 0xF0: | |||||
state = E0_F0; | |||||
break; | |||||
default: | |||||
if (code < 0x80) { | |||||
matrix_make(code|0x80); | |||||
} else { | |||||
debug("unexpected scan code at E0: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case F0: // Break code | |||||
switch (code) { | |||||
case 0x83: // F7 | |||||
matrix_break(F7); | |||||
state = INIT; | |||||
break; | |||||
case 0x84: // Alt'd PrintScreen | |||||
matrix_break(PRINT_SCREEN); | |||||
state = INIT; | |||||
break; | |||||
default: | |||||
if (code < 0x80) { | |||||
matrix_break(code); | |||||
} else { | |||||
debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E0_F0: // Break code of E0-prefixed | |||||
switch (code) { | |||||
case 0x12: // to be ignored | |||||
case 0x59: // to be ignored | |||||
state = INIT; | |||||
break; | |||||
default: | |||||
if (code < 0x80) { | |||||
matrix_break(code|0x80); | |||||
} else { | |||||
debug("unexpected scan code at E0_F0: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
} | |||||
break; | |||||
// following are states of Pause | |||||
case E1: | |||||
switch (code) { | |||||
case 0x14: | |||||
state = E1_14; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E1_14: | |||||
switch (code) { | |||||
case 0x77: | |||||
state = E1_14_77; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E1_14_77: | |||||
switch (code) { | |||||
case 0xE1: | |||||
state = E1_14_77_E1; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E1_14_77_E1: | |||||
switch (code) { | |||||
case 0xF0: | |||||
state = E1_14_77_E1_F0; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E1_14_77_E1_F0: | |||||
switch (code) { | |||||
case 0x14: | |||||
state = E1_14_77_E1_F0_14; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E1_14_77_E1_F0_14: | |||||
switch (code) { | |||||
case 0xF0: | |||||
state = E1_14_77_E1_F0_14_F0; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
case E1_14_77_E1_F0_14_F0: | |||||
switch (code) { | |||||
case 0x77: | |||||
matrix_make(PAUSE); | |||||
state = INIT; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
break; | |||||
// Following are states of Control'd Pause | |||||
case E0_7E: | |||||
if (code == 0xE0) | |||||
state = E0_7E_E0; | |||||
else | |||||
state = INIT; | |||||
break; | |||||
case E0_7E_E0: | |||||
if (code == 0xF0) | |||||
state = E0_7E_E0_F0; | |||||
else | |||||
state = INIT; | |||||
break; | |||||
case E0_7E_E0_F0: | |||||
if (code == 0x7E) | |||||
matrix_make(PAUSE); | |||||
state = INIT; | |||||
break; | |||||
default: | |||||
state = INIT; | |||||
} | |||||
phex(code); | |||||
} | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
return is_modified; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
#ifdef MATRIX_HAS_GHOST | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix_has_ghost_in_row(i)) | |||||
return true; | |||||
} | |||||
#endif | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
pbin_reverse(matrix_get_row(row)); | |||||
#ifdef MATRIX_HAS_GHOST | |||||
if (matrix_has_ghost_in_row(row)) { | |||||
print(" <ghost"); | |||||
} | |||||
#endif | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
count += bitpop(matrix[i]); | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | |||||
inline | |||||
static bool matrix_has_ghost_in_row(uint8_t row) | |||||
{ | |||||
// no ghost exists in case less than 2 keys on | |||||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||||
return false; | |||||
// ghost exists in case same state as other row | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
#endif | |||||
inline | |||||
static void matrix_make(uint8_t code) | |||||
{ | |||||
if (!matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] |= 1<<COL(code); | |||||
is_modified = true; | |||||
} | |||||
} | |||||
inline | |||||
static void matrix_break(uint8_t code) | |||||
{ | |||||
if (matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||||
is_modified = true; | |||||
} | |||||
} |
/* Name: usbconfig.h | |||||
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers | |||||
* Author: Christian Starkjohann | |||||
* Creation Date: 2005-04-01 | |||||
* Tabsize: 4 | |||||
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH | |||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | |||||
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $ | |||||
*/ | |||||
#ifndef __usbconfig_h_included__ | |||||
#define __usbconfig_h_included__ | |||||
#include "config_vusb.h" | |||||
/* | |||||
General Description: | |||||
This file is an example configuration (with inline documentation) for the USB | |||||
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is | |||||
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may | |||||
wire the lines to any other port, as long as D+ is also wired to INT0 (or any | |||||
other hardware interrupt, as long as it is the highest level interrupt, see | |||||
section at the end of this file). | |||||
*/ | |||||
/* ---------------------------- Hardware Config ---------------------------- */ | |||||
#define USB_CFG_IOPORTNAME D | |||||
/* This is the port where the USB bus is connected. When you configure it to | |||||
* "B", the registers PORTB, PINB and DDRB will be used. | |||||
*/ | |||||
#define USB_CFG_DMINUS_BIT 3 | |||||
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. | |||||
* This may be any bit in the port. | |||||
*/ | |||||
#define USB_CFG_DPLUS_BIT 2 | |||||
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. | |||||
* This may be any bit in the port. Please note that D+ must also be connected | |||||
* to interrupt pin INT0! [You can also use other interrupts, see section | |||||
* "Optional MCU Description" below, or you can connect D- to the interrupt, as | |||||
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the | |||||
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame | |||||
* markers every millisecond.] | |||||
*/ | |||||
#define USB_CFG_CLOCK_KHZ (F_CPU/1000) | |||||
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, | |||||
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code | |||||
* require no crystal, they tolerate +/- 1% deviation from the nominal | |||||
* frequency. All other rates require a precision of 2000 ppm and thus a | |||||
* crystal! | |||||
* Since F_CPU should be defined to your actual clock rate anyway, you should | |||||
* not need to modify this setting. | |||||
*/ | |||||
#define USB_CFG_CHECK_CRC 0 | |||||
/* Define this to 1 if you want that the driver checks integrity of incoming | |||||
* data packets (CRC checks). CRC checks cost quite a bit of code size and are | |||||
* currently only available for 18 MHz crystal clock. You must choose | |||||
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option. | |||||
*/ | |||||
/* ----------------------- Optional Hardware Config ------------------------ */ | |||||
/* #define USB_CFG_PULLUP_IOPORTNAME D */ | |||||
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of | |||||
* V+, you can connect and disconnect the device from firmware by calling | |||||
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). | |||||
* This constant defines the port on which the pullup resistor is connected. | |||||
*/ | |||||
/* #define USB_CFG_PULLUP_BIT 4 */ | |||||
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined | |||||
* above) where the 1.5k pullup resistor is connected. See description | |||||
* above for details. | |||||
*/ | |||||
/* --------------------------- Functional Range ---------------------------- */ | |||||
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1 | |||||
/* Define this to 1 if you want to compile a version with two endpoints: The | |||||
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint | |||||
* number). | |||||
*/ | |||||
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1 | |||||
/* Define this to 1 if you want to compile a version with three endpoints: The | |||||
* default control endpoint 0, an interrupt-in endpoint 3 (or the number | |||||
* configured below) and a catch-all default interrupt-in endpoint as above. | |||||
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. | |||||
*/ | |||||
#define USB_CFG_EP3_NUMBER 3 | |||||
/* If the so-called endpoint 3 is used, it can now be configured to any other | |||||
* endpoint number (except 0) with this macro. Default if undefined is 3. | |||||
*/ | |||||
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ | |||||
/* The above macro defines the startup condition for data toggling on the | |||||
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. | |||||
* Since the token is toggled BEFORE sending any data, the first packet is | |||||
* sent with the oposite value of this configuration! | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_HALT 0 | |||||
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature | |||||
* for endpoint 1 (interrupt endpoint). Although you may not need this feature, | |||||
* it is required by the standard. We have made it a config option because it | |||||
* bloats the code considerably. | |||||
*/ | |||||
#define USB_CFG_SUPPRESS_INTR_CODE 0 | |||||
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't | |||||
* want to send any data over them. If this macro is defined to 1, functions | |||||
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if | |||||
* you need the interrupt-in endpoints in order to comply to an interface | |||||
* (e.g. HID), but never want to send any data. This option saves a couple | |||||
* of bytes in flash memory and the transmit buffers in RAM. | |||||
*/ | |||||
#define USB_CFG_INTR_POLL_INTERVAL 10 | |||||
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll | |||||
* interval. The value is in milliseconds and must not be less than 10 ms for | |||||
* low speed devices. | |||||
*/ | |||||
#define USB_CFG_IS_SELF_POWERED 0 | |||||
/* Define this to 1 if the device has its own power supply. Set it to 0 if the | |||||
* device is powered from the USB bus. | |||||
*/ | |||||
#define USB_CFG_MAX_BUS_POWER 100 | |||||
/* Set this variable to the maximum USB bus power consumption of your device. | |||||
* The value is in milliamperes. [It will be divided by two since USB | |||||
* communicates power requirements in units of 2 mA.] | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_FN_WRITE 1 | |||||
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out | |||||
* transfers. Set it to 0 if you don't need it and want to save a couple of | |||||
* bytes. | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_FN_READ 0 | |||||
/* Set this to 1 if you need to send control replies which are generated | |||||
* "on the fly" when usbFunctionRead() is called. If you only want to send | |||||
* data from a static buffer, set it to 0 and return the data from | |||||
* usbFunctionSetup(). This saves a couple of bytes. | |||||
*/ | |||||
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0 | |||||
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. | |||||
* You must implement the function usbFunctionWriteOut() which receives all | |||||
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number | |||||
* can be found in 'usbRxToken'. | |||||
*/ | |||||
#define USB_CFG_HAVE_FLOWCONTROL 0 | |||||
/* Define this to 1 if you want flowcontrol over USB data. See the definition | |||||
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in | |||||
* usbdrv.h. | |||||
*/ | |||||
#define USB_CFG_DRIVER_FLASH_PAGE 0 | |||||
/* If the device has more than 64 kBytes of flash, define this to the 64 k page | |||||
* where the driver's constants (descriptors) are located. Or in other words: | |||||
* Define this to 1 for boot loaders on the ATMega128. | |||||
*/ | |||||
#define USB_CFG_LONG_TRANSFERS 0 | |||||
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes | |||||
* in a single control-in or control-out transfer. Note that the capability | |||||
* for long transfers increases the driver size. | |||||
*/ | |||||
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ | |||||
/* This macro is a hook if you want to do unconventional things. If it is | |||||
* defined, it's inserted at the beginning of received message processing. | |||||
* If you eat the received message and don't want default processing to | |||||
* proceed, do a return after doing your things. One possible application | |||||
* (besides debugging) is to flash a status LED on each packet. | |||||
*/ | |||||
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ | |||||
/* This macro is a hook if you need to know when an USB RESET occurs. It has | |||||
* one parameter which distinguishes between the start of RESET state and its | |||||
* end. | |||||
*/ | |||||
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */ | |||||
/* This macro (if defined) is executed when a USB SET_ADDRESS request was | |||||
* received. | |||||
*/ | |||||
#define USB_COUNT_SOF 0 | |||||
/* define this macro to 1 if you need the global variable "usbSofCount" which | |||||
* counts SOF packets. This feature requires that the hardware interrupt is | |||||
* connected to D- instead of D+. | |||||
*/ | |||||
/* #ifdef __ASSEMBLER__ | |||||
* macro myAssemblerMacro | |||||
* in YL, TCNT0 | |||||
* sts timer0Snapshot, YL | |||||
* endm | |||||
* #endif | |||||
* #define USB_SOF_HOOK myAssemblerMacro | |||||
* This macro (if defined) is executed in the assembler module when a | |||||
* Start Of Frame condition is detected. It is recommended to define it to | |||||
* the name of an assembler macro which is defined here as well so that more | |||||
* than one assembler instruction can be used. The macro may use the register | |||||
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages | |||||
* immediately after an SOF pulse may be lost and must be retried by the host. | |||||
* What can you do with this hook? Since the SOF signal occurs exactly every | |||||
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in | |||||
* designs running on the internal RC oscillator. | |||||
* Please note that Start Of Frame detection works only if D- is wired to the | |||||
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! | |||||
*/ | |||||
#define USB_CFG_CHECK_DATA_TOGGLING 0 | |||||
/* define this macro to 1 if you want to filter out duplicate data packets | |||||
* sent by the host. Duplicates occur only as a consequence of communication | |||||
* errors, when the host does not receive an ACK. Please note that you need to | |||||
* implement the filtering yourself in usbFunctionWriteOut() and | |||||
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable | |||||
* for each control- and out-endpoint to check for duplicate packets. | |||||
*/ | |||||
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 | |||||
/* define this macro to 1 if you want the function usbMeasureFrameLength() | |||||
* compiled in. This function can be used to calibrate the AVR's RC oscillator. | |||||
*/ | |||||
#define USB_USE_FAST_CRC 0 | |||||
/* The assembler module has two implementations for the CRC algorithm. One is | |||||
* faster, the other is smaller. This CRC routine is only used for transmitted | |||||
* messages where timing is not critical. The faster routine needs 31 cycles | |||||
* per byte while the smaller one needs 61 to 69 cycles. The faster routine | |||||
* may be worth the 32 bytes bigger code size if you transmit lots of data and | |||||
* run the AVR close to its limit. | |||||
*/ | |||||
/* -------------------------- Device Description --------------------------- */ | |||||
#define USB_CFG_VENDOR_ID (VENDOR_ID & 0xFF), ((VENDOR_ID >> 8) & 0xFF) | |||||
/* USB vendor ID for the device, low byte first. If you have registered your | |||||
* own Vendor ID, define it here. Otherwise you may use one of obdev's free | |||||
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! | |||||
* *** IMPORTANT NOTE *** | |||||
* This template uses obdev's shared VID/PID pair for Vendor Class devices | |||||
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand | |||||
* the implications! | |||||
*/ | |||||
#define USB_CFG_DEVICE_ID (PRODUCT_ID & 0xFF), ((PRODUCT_ID >> 8) & 0xFF) | |||||
/* This is the ID of the product, low byte first. It is interpreted in the | |||||
* scope of the vendor ID. If you have registered your own VID with usb.org | |||||
* or if you have licensed a PID from somebody else, define it here. Otherwise | |||||
* you may use one of obdev's free shared VID/PID pairs. See the file | |||||
* USB-IDs-for-free.txt for details! | |||||
* *** IMPORTANT NOTE *** | |||||
* This template uses obdev's shared VID/PID pair for Vendor Class devices | |||||
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand | |||||
* the implications! | |||||
*/ | |||||
#define USB_CFG_DEVICE_VERSION 0x00, 0x01 | |||||
/* Version number of the device: Minor number first, then major number. | |||||
*/ | |||||
#define USB_CFG_VENDOR_NAME 't', '.', 'm', '.', 'k', '.' | |||||
#define USB_CFG_VENDOR_NAME_LEN 6 | |||||
/* These two values define the vendor name returned by the USB device. The name | |||||
* must be given as a list of characters under single quotes. The characters | |||||
* are interpreted as Unicode (UTF-16) entities. | |||||
* If you don't want a vendor name string, undefine these macros. | |||||
* ALWAYS define a vendor name containing your Internet domain name if you use | |||||
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for | |||||
* details. | |||||
*/ | |||||
#define USB_CFG_DEVICE_NAME 'P', 'S', '/', '2', ' ', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', ' ', 'c', 'o', 'n', 'v', 'e', 'r', 't', 'e', 'r' | |||||
#define USB_CFG_DEVICE_NAME_LEN 23 | |||||
/* Same as above for the device name. If you don't want a device name, undefine | |||||
* the macros. See the file USB-IDs-for-free.txt before you assign a name if | |||||
* you use a shared VID/PID. | |||||
*/ | |||||
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */ | |||||
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */ | |||||
/* Same as above for the serial number. If you don't want a serial number, | |||||
* undefine the macros. | |||||
* It may be useful to provide the serial number through other means than at | |||||
* compile time. See the section about descriptor properties below for how | |||||
* to fine tune control over USB descriptors such as the string descriptor | |||||
* for the serial number. | |||||
*/ | |||||
#define USB_CFG_DEVICE_CLASS 0 | |||||
#define USB_CFG_DEVICE_SUBCLASS 0 | |||||
/* See USB specification if you want to conform to an existing device class. | |||||
* Class 0xff is "vendor specific". | |||||
*/ | |||||
#define USB_CFG_INTERFACE_CLASS 3 /* HID */ | |||||
#define USB_CFG_INTERFACE_SUBCLASS 1 /* Boot */ | |||||
#define USB_CFG_INTERFACE_PROTOCOL 1 /* Keyboard */ | |||||
/* See USB specification if you want to conform to an existing device class or | |||||
* protocol. The following classes must be set at interface level: | |||||
* HID class is 3, no subclass and protocol required (but may be useful!) | |||||
* CDC class is 2, use subclass 2 and protocol 1 for ACM | |||||
*/ | |||||
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0 | |||||
/* Define this to the length of the HID report descriptor, if you implement | |||||
* an HID device. Otherwise don't define it or define it to 0. | |||||
* If you use this define, you must add a PROGMEM character array named | |||||
* "usbHidReportDescriptor" to your code which contains the report descriptor. | |||||
* Don't forget to keep the array and this define in sync! | |||||
*/ | |||||
/* #define USB_PUBLIC static */ | |||||
/* Use the define above if you #include usbdrv.c instead of linking against it. | |||||
* This technique saves a couple of bytes in flash memory. | |||||
*/ | |||||
/* ------------------- Fine Control over USB Descriptors ------------------- */ | |||||
/* If you don't want to use the driver's default USB descriptors, you can | |||||
* provide our own. These can be provided as (1) fixed length static data in | |||||
* flash memory, (2) fixed length static data in RAM or (3) dynamically at | |||||
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more | |||||
* information about this function. | |||||
* Descriptor handling is configured through the descriptor's properties. If | |||||
* no properties are defined or if they are 0, the default descriptor is used. | |||||
* Possible properties are: | |||||
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched | |||||
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is | |||||
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if | |||||
* you want RAM pointers. | |||||
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found | |||||
* in static memory is in RAM, not in flash memory. | |||||
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), | |||||
* the driver must know the descriptor's length. The descriptor itself is | |||||
* found at the address of a well known identifier (see below). | |||||
* List of static descriptor names (must be declared PROGMEM if in flash): | |||||
* char usbDescriptorDevice[]; | |||||
* char usbDescriptorConfiguration[]; | |||||
* char usbDescriptorHidReport[]; | |||||
* char usbDescriptorString0[]; | |||||
* int usbDescriptorStringVendor[]; | |||||
* int usbDescriptorStringDevice[]; | |||||
* int usbDescriptorStringSerialNumber[]; | |||||
* Other descriptors can't be provided statically, they must be provided | |||||
* dynamically at runtime. | |||||
* | |||||
* Descriptor properties are or-ed or added together, e.g.: | |||||
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) | |||||
* | |||||
* The following descriptors are defined: | |||||
* USB_CFG_DESCR_PROPS_DEVICE | |||||
* USB_CFG_DESCR_PROPS_CONFIGURATION | |||||
* USB_CFG_DESCR_PROPS_STRINGS | |||||
* USB_CFG_DESCR_PROPS_STRING_0 | |||||
* USB_CFG_DESCR_PROPS_STRING_VENDOR | |||||
* USB_CFG_DESCR_PROPS_STRING_PRODUCT | |||||
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER | |||||
* USB_CFG_DESCR_PROPS_HID | |||||
* USB_CFG_DESCR_PROPS_HID_REPORT | |||||
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) | |||||
* | |||||
* Note about string descriptors: String descriptors are not just strings, they | |||||
* are Unicode strings prefixed with a 2 byte header. Example: | |||||
* int serialNumberDescriptor[] = { | |||||
* USB_STRING_DESCRIPTOR_HEADER(6), | |||||
* 'S', 'e', 'r', 'i', 'a', 'l' | |||||
* }; | |||||
*/ | |||||
#define USB_CFG_DESCR_PROPS_DEVICE 0 | |||||
#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC | |||||
//#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 | |||||
#define USB_CFG_DESCR_PROPS_STRINGS 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_0 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 | |||||
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 | |||||
//#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC | |||||
#define USB_CFG_DESCR_PROPS_HID 0 | |||||
#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC | |||||
//#define USB_CFG_DESCR_PROPS_HID_REPORT 0 | |||||
#define USB_CFG_DESCR_PROPS_UNKNOWN 0 | |||||
/* ----------------------- Optional MCU Description ------------------------ */ | |||||
/* The following configurations have working defaults in usbdrv.h. You | |||||
* usually don't need to set them explicitly. Only if you want to run | |||||
* the driver on a device which is not yet supported or with a compiler | |||||
* which is not fully supported (such as IAR C) or if you use a differnt | |||||
* interrupt than INT0, you may have to define some of these. | |||||
*/ | |||||
/* #define USB_INTR_CFG MCUCR */ | |||||
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ | |||||
/* #define USB_INTR_CFG_CLR 0 */ | |||||
/* #define USB_INTR_ENABLE GIMSK */ | |||||
/* #define USB_INTR_ENABLE_BIT INT0 */ | |||||
/* #define USB_INTR_PENDING GIFR */ | |||||
/* #define USB_INTR_PENDING_BIT INTF0 */ | |||||
/* #define USB_INTR_VECTOR INT0_vect */ | |||||
#endif /* __usbconfig_h_included__ */ |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = news_usb_pjrc | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
news.c | |||||
CONFIG_H = config_pjrc.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x5021 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT SONY NEWS keyboard converter | |||||
#define DESCRIPTION converts SONY NEWS protocol into USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 16 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* Asynchronous USART | |||||
* 8-data bit, non parity, 1-stop bit, no flow control | |||||
*/ | |||||
#ifdef __AVR_ATmega32U4__ | |||||
# define NEWS_KBD_RX_VECT USART1_RX_vect | |||||
# define NEWS_KBD_RX_DATA UDR1 | |||||
# define NEWS_KBD_RX_BAUD 9600 | |||||
# define NEWS_KBD_RX_UBBR ((F_CPU/(16UL*NEWS_KBD_RX_BAUD))-1) | |||||
# define NEWS_KBD_RX_INIT() do { \ | |||||
UBRR1L = (uint8_t) NEWS_KBD_RX_UBBR; \ | |||||
UBRR1H = (uint8_t) (NEWS_KBD_RX_UBBR>>8); \ | |||||
UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); \ | |||||
} while(0) | |||||
#else | |||||
# error "USART configuration is needed." | |||||
#endif | |||||
#endif |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
// Following macros help you to define a keymap with the form of actual keyboard layout. | |||||
/* SONY NEWS NWP-5461 */ | |||||
#define KEYMAP( \ | |||||
K7A, K01,K02,K03,K04,K05, K06,K07,K08,K09,K0A, K68,K69, K64,K65,K52, \ | |||||
K0B,K0C,K0D,K0E,K0F,K10,K11,K12,K13,K14,K15,K16,K17,K18,K19, K6A, K4B,K4C,K4D,K4E, \ | |||||
K1A,K1B,K1C,K1D,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27, K6B, K4F,K50,K51,K56, \ | |||||
K28,K29,K2A,K2B,K2C,K2D,K2E,K2F,K30,K31,K32,K33,K34, K35, K6C, K53,K54,K55,K5A, \ | |||||
K36,K37,K38,K39,K3A,K3B,K3C,K3D,K3E,K3F,K40,K41, K42, K6D, K57,K59,K58, \ | |||||
K43,K44,K45, K46, K47, K48,K49,K4A, K6E, K66,K5B,K5C,K5D \ | |||||
) { \ | |||||
{ KB_NO, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | |||||
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ | |||||
{ KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ | |||||
{ KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_NO, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_##K64, KB_##K65, KB_##K66, KB_NO }, \ | |||||
{ KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_##K6D, KB_##K6E, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, }, \ | |||||
{ KB_NO, KB_NO, KB_##K7A, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO } \ | |||||
} | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
0, // Fn1 | |||||
0, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_NO, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* 0: default | |||||
* ,---. ,------------------------, ,------------------------. ,---------. | |||||
* |Pow| | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10| | F11| F12| ,-----------. | |||||
* `---' `------------------------' `------------------------' `---------' | *| /| +| | |||||
* ,-------------------------------------------------------------. ,---. ,---------------| | |||||
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| BS | |Hlp| | 7| 8| 9| -| | |||||
* |-------------------------------------------------------------| |---| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Del| | |Ins| | 4| 5| 6| ,| | |||||
* |---------------------------------------------------------' | |---| |---------------| | |||||
* |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| `|Return| |Clr| | 1| 2| 3| | | |||||
* |-------------------------------------------------------------| |---| |-----------|Ent| | |||||
* |Shift | Z| X| C| V| B| N| M| ,| ,| /| |Shift | |PgU| | 0| .| Up| | | |||||
* |-------------------------------------------------------------| |---| |---------------| | |||||
* |Alt |Gui |Alt | Space | |Gui|App|Ctrl | |PgD| |Tab|Lef|Dow|Rig| | |||||
* `-------------------------------------------------------------' `---' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PAST,PSLS,PPLS, | |||||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, HELP, P7, P8, P9, PMNS, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,DEL, INS, P4, P5, P6, PCMM, | |||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,GRV, ENT, CLR, P1, P2, P3, PENT, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RO, RSFT, PGUP, P0, PDOT,UP, | |||||
LCTL,LGUI,LALT, SPC, ERAS, RALT,RGUI,RCTL, PGDN, TAB, LEFT,DOWN,RGHT | |||||
), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "news.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
// not supported now | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "news.h" | |||||
#include "matrix.h" | |||||
/* | |||||
* Matrix Array usage: | |||||
* | |||||
* ROW: 16 | |||||
* COL:8 | |||||
* | |||||
* 8bit wide | |||||
* +---------+ | |||||
* 0|00 ... 07| | |||||
* 1|08 ... 0F| | |||||
* :| ... | | |||||
* :| ... | | |||||
* E|70 ... 77| | |||||
* F|78 ... 7F| | |||||
* +---------+ | |||||
* | |||||
*/ | |||||
static uint8_t matrix[MATRIX_ROWS]; | |||||
#define ROW(code) ((code>>3)&0xF) | |||||
#define COL(code) (code&0x07) | |||||
static bool is_modified = false; | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
news_init(); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||||
return; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
is_modified = false; | |||||
uint8_t code; | |||||
code = news_recv(); | |||||
if (code == 0) { | |||||
return 0; | |||||
} | |||||
phex(code); print(" "); | |||||
if (code&0x80) { | |||||
// break code | |||||
if (matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||||
is_modified = true; | |||||
} | |||||
} else { | |||||
// make code | |||||
if (!matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] |= (1<<COL(code)); | |||||
is_modified = true; | |||||
} | |||||
} | |||||
return code; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
return is_modified; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
pbin_reverse(matrix_get_row(row)); | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
count += bitpop(matrix[i]); | |||||
} | |||||
return count; | |||||
} |
/* | |||||
Copyright 2012 Jun WAKO <[email protected]> | |||||
This software is licensed with a Modified BSD License. | |||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | |||||
GPL-compatible, and OK to use in both free and proprietary applications. | |||||
Additions and corrections to this file are welcome. | |||||
Redistribution and use in source and binary forms, with or without | |||||
modification, are permitted provided that the following conditions are met: | |||||
* Redistributions of source code must retain the above copyright | |||||
notice, this list of conditions and the following disclaimer. | |||||
* Redistributions in binary form must reproduce the above copyright | |||||
notice, this list of conditions and the following disclaimer in | |||||
the documentation and/or other materials provided with the | |||||
distribution. | |||||
* Neither the name of the copyright holders nor the names of | |||||
contributors may be used to endorse or promote products derived | |||||
from this software without specific prior written permission. | |||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||||
POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | |||||
#include "news.h" | |||||
void news_init(void) | |||||
{ | |||||
NEWS_KBD_RX_INIT(); | |||||
} | |||||
// RX ring buffer | |||||
#define RBUF_SIZE 8 | |||||
static uint8_t rbuf[RBUF_SIZE]; | |||||
static uint8_t rbuf_head = 0; | |||||
static uint8_t rbuf_tail = 0; | |||||
uint8_t news_recv(void) | |||||
{ | |||||
uint8_t data = 0; | |||||
if (rbuf_head == rbuf_tail) { | |||||
return 0; | |||||
} | |||||
data = rbuf[rbuf_tail]; | |||||
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE; | |||||
return data; | |||||
} | |||||
// USART RX complete interrupt | |||||
ISR(NEWS_KBD_RX_VECT) | |||||
{ | |||||
uint8_t next = (rbuf_head + 1) % RBUF_SIZE; | |||||
if (next != rbuf_tail) { | |||||
rbuf[rbuf_head] = NEWS_KBD_RX_DATA; | |||||
rbuf_head = next; | |||||
} | |||||
} | |||||
/* | |||||
SONY NEWS Keyboard Protocol | |||||
=========================== | |||||
Resources | |||||
--------- | |||||
Mouse protocol of NWA-5461(Japanese) | |||||
http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d | |||||
SONY NEWS Info(Japanese) | |||||
http://katsu.watanabe.name/doc/sonynews/ | |||||
Pinouts | |||||
------- | |||||
EIA 232 male connector from NWP-5461 | |||||
------------- | |||||
\ 1 2 3 4 5 / | |||||
\ 6 7 8 9 / | |||||
--------- | |||||
1 VCC | |||||
2 BZ(Speaker) | |||||
3 Keyboard Data(from keyboard MCU TxD) | |||||
4 NC | |||||
5 FG | |||||
6 Unknown Input(to keyboard MCU RxD via schmitt trigger) | |||||
7 Mouse Data(from Mouse Ext connector) | |||||
8 Unknown Input(to Keyboard MCU Input via diode and buffer) | |||||
9 GND | |||||
NOTE: Two LED on keyboard are controlled by pin 6,8? | |||||
EIA 232 male connector from NWP-411A | |||||
------------- | |||||
\ 1 2 3 4 5 / | |||||
\ 6 7 8 9 / | |||||
--------- | |||||
1 VCC | |||||
2 BZ(Speaker) | |||||
3 Keyboard Data(from keyboard MCU TxD) | |||||
4 NC | |||||
5 FG | |||||
6 NC | |||||
7 Mouse Data(from Mouse Ext connector) | |||||
8 NC | |||||
9 GND | |||||
NOTE: These are just from my guess and not confirmed. | |||||
Signaling | |||||
--------- | |||||
~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~ | |||||
Idle Start LSB MSB Stop Idle | |||||
Idle: High | |||||
Start bit: Low | |||||
Stop bit: High | |||||
Bit order: LSB first | |||||
Baud rate: 9600 | |||||
Interface: TTL level(5V) UART | |||||
NOTE: This is observed on NWP-5461 with its DIP switch all OFF. | |||||
Format | |||||
------ | |||||
MSB LSB | |||||
7 6 5 4 3 2 1 0 bit | |||||
| | | | | | | | | |||||
| +-+-+-+-+-+-+-- scan code(00-7F) | |||||
+---------------- break flag: sets when released | |||||
Scan Codes | |||||
---------- | |||||
SONY NEWS NWP-5461 | |||||
,---. ,------------------------, ,------------------------. ,---------. | |||||
| 7A| | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------. | |||||
`---' `------------------------' `------------------------' `---------' | 64| 65| 52| | |||||
,-------------------------------------------------------------. ,---. ,---------------| | |||||
| 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19 | | 6A| | 4B| 4C| 4D| 4E| | |||||
|-------------------------------------------------------------| |---| |---------------| | |||||
| 1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| | | 6B| | 4F| 50| 51| 56| | |||||
|---------------------------------------------------------' | |---| |---------------| | |||||
| 28 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35 | | 6C| | 53| 54| 55| | | |||||
|-------------------------------------------------------------| |---| |-----------| 5A| | |||||
| 36 | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41| 42 | | 6D| | 57| 59| 58| | | |||||
|-------------------------------------------------------------| |---| |---------------| | |||||
| 43 | 44 | 45 | 46 | 47 | 48| 49| 4A | | 6E| | 66| 5B| 5C| 5D| | |||||
`-------------------------------------------------------------' `---' `---------------' | |||||
*/ |
/* | |||||
Copyright 2012 Jun WAKO <[email protected]> | |||||
This software is licensed with a Modified BSD License. | |||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | |||||
GPL-compatible, and OK to use in both free and proprietary applications. | |||||
Additions and corrections to this file are welcome. | |||||
Redistribution and use in source and binary forms, with or without | |||||
modification, are permitted provided that the following conditions are met: | |||||
* Redistributions of source code must retain the above copyright | |||||
notice, this list of conditions and the following disclaimer. | |||||
* Redistributions in binary form must reproduce the above copyright | |||||
notice, this list of conditions and the following disclaimer in | |||||
the documentation and/or other materials provided with the | |||||
distribution. | |||||
* Neither the name of the copyright holders nor the names of | |||||
contributors may be used to endorse or promote products derived | |||||
from this software without specific prior written permission. | |||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||||
POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#ifndef NEWS_H | |||||
#define NEWS_H | |||||
/* | |||||
* Primitive PS/2 Library for AVR | |||||
*/ | |||||
/* host role */ | |||||
void news_init(void); | |||||
uint8_t news_recv(void); | |||||
/* device role */ | |||||
#endif |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = terminal_usb_102_pjrc | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap_102.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
ps2.c | |||||
CONFIG_H = config_102_pjrc.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = terminal_usb_122_pjrc | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap_122.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
ps2.c | |||||
CONFIG_H = config_122_pjrc.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
#MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
PS/2 to USB keyboard converter for IBM terminal keyboard | |||||
========================================================= | |||||
It supports PS/2 Scan Code Set 3 and runs on Teensy, Teensy++ and boards withATMega32u4/AT90USB. | |||||
I tested the converter only on Teensy with 1392595(102keys terminal keyboard), | |||||
though, I think it will also work with 122keys boards. | |||||
http://geekhack.org/showwiki.php?title=Island:27272 | |||||
CONNECTION | |||||
---------- | |||||
Data: PD0 | |||||
Clock: PD1 | |||||
VCC and GND, of course. | |||||
It is the same as Soarer's converter pin configuration. | |||||
See RESOURCE for keyboard connector pin assign. | |||||
BUILD | |||||
----- | |||||
Get source: | |||||
$ git clone https://github.com/tmk/tmk_keyboard.git | |||||
$ cd terminal_usb | |||||
For 102keys: | |||||
$ make -f Makefile.102_pjrc | |||||
For 122keys(not tested): | |||||
$ make -f Makefile.122_pjrc | |||||
I used WinAVR 20100110 to develop and build. | |||||
RESOURCE | |||||
-------- | |||||
Soarer's Converter: http://geekhack.org/showwiki.php?title=Island:17458 | |||||
102keys(1392595): http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M | |||||
122keys(1390876): http://www.seasip.info/VintagePC/ibm_1390876.html | |||||
KbdBabel: http://www.kbdbabel.org/ | |||||
RJ45 Connector: http://www.kbdbabel.org/conn/kbd_connector_ibmterm.png | |||||
DIN Connector: http://www.kbdbabel.org/conn/kbd_connector_ibm3179_318x_319x.png | |||||
WinAVR: http://winavr.sourceforge.net/ | |||||
EOF |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x6531 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT PS/2(Set3)-USB Keyboard converter(IBM 102keys) | |||||
#define DESCRIPTION USB converter for IBM Terminal Keyboard 102keys | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 17 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_RALT) | MOD_BIT(KB_RCTL)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* PS/2 lines */ | |||||
#define PS2_CLOCK_PORT PORTD | |||||
#define PS2_CLOCK_PIN PIND | |||||
#define PS2_CLOCK_DDR DDRD | |||||
#define PS2_CLOCK_BIT 1 | |||||
#define PS2_DATA_PORT PORTD | |||||
#define PS2_DATA_PIN PIND | |||||
#define PS2_DATA_DDR DDRD | |||||
#define PS2_DATA_BIT 0 | |||||
#endif |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x6532 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT PS/2(Set3)-USB Keyboard converter(IBM 122keys) | |||||
#define DESCRIPTION USB converter for IBM Terminal Keyboard 122keys | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 17 // keycode bit: 3-0 | |||||
#define MATRIX_COLS 8 // keycode bit: 6-4 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_RALT) | MOD_BIT(KB_RCTL)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* PS/2 lines */ | |||||
#define PS2_CLOCK_PORT PORTD | |||||
#define PS2_CLOCK_PIN PIND | |||||
#define PS2_CLOCK_DDR DDRD | |||||
#define PS2_CLOCK_BIT 1 | |||||
#define PS2_DATA_PORT PORTD | |||||
#define PS2_DATA_PIN PIND | |||||
#define PS2_DATA_DDR DDRD | |||||
#define PS2_DATA_BIT 0 | |||||
#endif |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
/* | |||||
* IBM Terminal keyboard 1392595(102keys) | |||||
* http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M | |||||
* http://www.seasip.info/VintagePC/ibm_1391406.html | |||||
* | |||||
* Keymap array: | |||||
* 8 bytes | |||||
* +---------+ | |||||
* 0| | | |||||
* :| | 0x00-0x87 | |||||
* ;| | | |||||
* 17| | | |||||
* +---------+ | |||||
*/ | |||||
#define KEYMAP( \ | |||||
K08, K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, K57,K5F,K62, \ | |||||
\ | |||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K5D,K66, K67,K6E,K6F, K76,K77,K7E,K84, \ | |||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, K5C, K64,K65,K6D, K6C,K75,K7D,K7C, \ | |||||
K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K53,K5A, K6B,K73,K74,K7B, \ | |||||
K12,K13,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K51,K59, K63, K69,K72,K7A,K79, \ | |||||
K11, K19, K29, K39, K58, K61,K60,K6A, K68,K70,K71,K78 \ | |||||
) { \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K07 }, \ | |||||
{ KB_##K08, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K0D, KB_##K0E, KB_##K0F }, \ | |||||
{ KB_NO, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_NO, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | |||||
{ KB_NO, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | |||||
{ KB_NO, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | |||||
{ KB_NO, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_NO, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ | |||||
{ KB_NO, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ | |||||
{ KB_NO, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ | |||||
{ KB_NO, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_##K5E, KB_##K5F }, \ | |||||
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ | |||||
{ KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_##K6D, KB_##K6E, KB_##K6F }, \ | |||||
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ | |||||
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_##K84, KB_NO, KB_NO, KB_NO, }, \ | |||||
} | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
1, // Fn0 | |||||
2, // Fn1 | |||||
3, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_SCLN, // Fn0 | |||||
KB_SLSH, // Fn1 | |||||
KB_ESC, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* 0: default | |||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \|BS | |Ins|Hom|PgU| |NmL| /| *| -| | |||||
* |-----------------------------------------------------------| |-----------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | | |||||
* |-----------------------------------------------------------| `-----------' |-----------| +| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #|Retu| | 4| 5| 6| | | |||||
* |-----------------------------------------------------------| ,---. |---------------| | |||||
* |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||||
* |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 0| .| | | |||||
* `----' `---------------------------------------' `----' `-----------' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, | |||||
LCTL,A, S, D, F, G, H, J, K, L, FN0, QUOT, NUHS,ENT, P4, P5, P6, PCMM, | |||||
LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, FN1, RO, FN2, UP, P1, P2, P3, PENT, | |||||
LGUI, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO | |||||
), | |||||
/* 1: Mouse keys | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab |MwL|MwU|McU|WwU|WwR|MwL|MwD|MwU|MwR| | | | \| | |||||
* |-----------------------------------------------------------| | |||||
* |CapsLo| |McL|McD|McR| |McL|McD|McU|McR|Fn0| |Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift |VoD|VoU|Mut|Mb2|Mb3|Mb2|Mb1|VoD|VoU|Mut|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Mb1 |Alt | |Ctrl| | |||||
* `-----' `--------------------------------------' `----' | |||||
* Mc = mouse cursor, Mw = mouse wheel, Mb = mouse button | |||||
* Vo = Volume, Mut = Mute | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, | |||||
LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, NO, ENT, P4, P5, P6, PCMM, | |||||
LSFT,NO, VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE, NO, RSFT, UP, P1, P2, P3, PENT, | |||||
LGUI, LALT, BTN1, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO | |||||
), | |||||
/* 2: Cursor keys | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backspa| | |||||
* |-----------------------------------------------------------| | |||||
* |Tab |Hom|PgU| Up|PgU|End|Hom|PgD|PgU|End| | | | \| | |||||
* |-----------------------------------------------------------| | |||||
* |CapsLo| |Lef|Dow|Rig| |Lef|Dow| Up|Rig| | |Return | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | |Hom|PgD|PgU|End|Fn1|Shift | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Space |Alt | |Ctrl| | |||||
* `-----' `--------------------------------------' `----' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9, PMNS, | |||||
LCTL,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, NO, ENT, P4, P5, P6, PCMM, | |||||
LSFT,NO, VOLD,VOLU,MUTE,NO, NO, HOME,PGDN,PGUP,END, FN1, NO, RSFT, UP, P1, P2, P3, PENT, | |||||
LGUI, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO | |||||
), | |||||
/* 3: HHKB | |||||
* ,-----------------------------------------------------------. | |||||
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| | |||||
* |-----------------------------------------------------------| | |||||
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs| | |||||
* |-----------------------------------------------------------| | |||||
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | | |||||
* |-----------------------------------------------------------| | |||||
* |Shift | | | | | | +| -|End|PgD|Dow|Fn2 | | |||||
* |-----------------------------------------------------------| | |||||
* |Ctrl | |Alt | Space |Alt | |Ctrl| | |||||
* `-----' `--------------------------------------' `----' | |||||
*/ | |||||
KEYMAP( | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, | |||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, NO, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, | |||||
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT, NO, ENT, P4, P5, P6, PCMM, | |||||
LSFT,NO, NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN, NO, FN2, UP, P1, P2, P3, PENT, | |||||
LGUI, LALT, SPC, RALT, RCTL, LEFT,DOWN,RGHT, NO, P0, PDOT,NO | |||||
), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
/* | |||||
* IBM Terminal keyboard 1392595(102keys) | |||||
* http://geekhack.org/showthread.php?10737-What-Can-I-Do-With-a-Terminal-Model-M | |||||
* http://www.seasip.info/VintagePC/ibm_1391406.html | |||||
* | |||||
* Keymap array: | |||||
* 8 bytes | |||||
* +---------+ | |||||
* 0| | | |||||
* :| | 0x00-0x87 | |||||
* ;| | | |||||
* 17| | | |||||
* +---------+ | |||||
*/ | |||||
#define KEYMAP( \ | |||||
K08,K10,K18,K20,K28,K30,K38,K40,K48,K50,K57,K5F, \ | |||||
K07,K0F,K17,K1F,K27,K2F,K37,K3F,K47,K4F,K56,K5E, \ | |||||
\ | |||||
K05,K06, K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K5D,K66, K67,K6E,K6F, K76,K77,K7E,K84, \ | |||||
K04,K0C, K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, K5C, K64,K65,K6D, K6C,K75,K7D,K7C, \ | |||||
K03,K0B, K14,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K53,K5A, K63, K6B,K73,K74,K7B, \ | |||||
K83,K0A, K12,K13,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K51,K59, K61,K62,K6A, K69,K72,K7A,K79, \ | |||||
K01,K09, K11, K19, K29, K39, K58, K60, K68,K70,K71,K78 \ | |||||
) { \ | |||||
{ KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | |||||
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ | |||||
{ KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ | |||||
{ KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_##K5E, KB_##K5F }, \ | |||||
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ | |||||
{ KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_##K6D, KB_##K6E, KB_##K6F }, \ | |||||
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ | |||||
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_##K83, KB_##K84, KB_NO, KB_NO, KB_NO, }, \ | |||||
} | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
0, // Fn1 | |||||
0, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_NO, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* 0: default | |||||
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. | |||||
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| | |||||
* `---' `---------------' `---------------' `---------------' `-----------' | |||||
* ,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \|BS | |Ins|Hom|PgU| |NmL| /| *| -| | |||||
* |-----------------------------------------------------------| |-----------| |---------------| | |||||
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| | | |||||
* |-----------------------------------------------------------| `-----------' |-----------| +| | |||||
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '| #|Retu| | 4| 5| 6| | | |||||
* |-----------------------------------------------------------| ,---. |---------------| | |||||
* |Shif| \| Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| | | |||||
* |-----------------------------------------------------------| ,-----------. |-----------|Ent| | |||||
* |Ctrl| |Alt | Space |Alt | |Ctrl| |Lef|Dow|Rig| | 0| .| | | |||||
* `----' `---------------------------------------' `----' `-----------' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, | |||||
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, | |||||
PSCR,ESC, GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
SLCK,INT4, TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, BSLS, DEL, END, PGDN, P7, P8, P9, PPLS, | |||||
PAUS,INT5, CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, NUHS,ENT, UP, P4, P5, P6, PCMM, | |||||
APP, INT6, LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RO, RSFT, LEFT,INT2,RGHT, P1, P2, P3, PENT, | |||||
RGUI,LGUI, LCTL, LALT, SPC, RALT, RCTL, DOWN, NO, P0, PDOT,NO | |||||
), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "ps2.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
uint8_t ps2_led = 0; | |||||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_SCROLL_LOCK); | |||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_NUM_LOCK); | |||||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_CAPS_LOCK); | |||||
ps2_host_set_led(ps2_led); | |||||
} |
/* | |||||
Copyright 2011 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "debug.h" | |||||
#include "ps2.h" | |||||
#include "matrix.h" | |||||
static void matrix_make(uint8_t code); | |||||
static void matrix_break(uint8_t code); | |||||
#ifdef MATRIX_HAS_GHOST | |||||
static bool matrix_has_ghost_in_row(uint8_t row); | |||||
#endif | |||||
/* | |||||
* Matrix Array usage: | |||||
* 'Scan Code Set 3' is assigned into 17x8 cell matrix. | |||||
* | |||||
* 8bit wide | |||||
* +---------+ | |||||
* 0| | | |||||
* :| | 0x00-0x87 | |||||
* ;| | | |||||
* 17| | | |||||
* +---------+ | |||||
*/ | |||||
static uint8_t matrix[MATRIX_ROWS]; | |||||
#define ROW(code) (code>>3) | |||||
#define COL(code) (code&0x07) | |||||
static bool is_modified = false; | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
print_enable = true; | |||||
debug_enable = true; | |||||
//debug_matrix = true; | |||||
//debug_keyboard = true; | |||||
//debug_mouse = false; | |||||
ps2_host_init(); | |||||
// Make and Break code without Typematic | |||||
while (ps2_host_send(0xF8) != 0xFA) { | |||||
debug("send F8: failed\n"); | |||||
_delay_ms(500); | |||||
} | |||||
debug("send F8: OK\n"); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||||
return; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
// scan code reading states | |||||
static enum { | |||||
INIT, | |||||
F0, | |||||
} state = INIT; | |||||
is_modified = false; | |||||
uint8_t code; | |||||
while ((code = ps2_host_recv())) { | |||||
debug_hex(code); | |||||
switch (state) { | |||||
case INIT: | |||||
switch (code) { | |||||
case 0xF0: | |||||
state = F0; | |||||
debug(" "); | |||||
break; | |||||
default: // normal key make | |||||
if (code < 0x88) { | |||||
matrix_make(code); | |||||
} else { | |||||
debug("unexpected scan code at INIT: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
debug("\n"); | |||||
} | |||||
break; | |||||
case F0: // Break code | |||||
switch (code) { | |||||
default: | |||||
if (code < 0x88) { | |||||
matrix_break(code); | |||||
} else { | |||||
debug("unexpected scan code at F0: "); debug_hex(code); debug("\n"); | |||||
} | |||||
state = INIT; | |||||
debug("\n"); | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
return 1; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
return is_modified; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
#ifdef MATRIX_HAS_GHOST | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
if (matrix_has_ghost_in_row(i)) | |||||
return true; | |||||
} | |||||
#endif | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
pbin_reverse(matrix_get_row(row)); | |||||
#ifdef MATRIX_HAS_GHOST | |||||
if (matrix_has_ghost_in_row(row)) { | |||||
print(" <ghost"); | |||||
} | |||||
#endif | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
count += bitpop(matrix[i]); | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | |||||
inline | |||||
static bool matrix_has_ghost_in_row(uint8_t row) | |||||
{ | |||||
// no ghost exists in case less than 2 keys on | |||||
if (((matrix[row] - 1) & matrix[row]) == 0) | |||||
return false; | |||||
// ghost exists in case same state as other row | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
#endif | |||||
inline | |||||
static void matrix_make(uint8_t code) | |||||
{ | |||||
if (!matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] |= 1<<COL(code); | |||||
is_modified = true; | |||||
} | |||||
} | |||||
inline | |||||
static void matrix_break(uint8_t code) | |||||
{ | |||||
if (matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||||
is_modified = true; | |||||
} | |||||
} |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = x68k_usb_pjrc | |||||
# Directory common source filess exist | |||||
TOP_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
SRC = main.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c \ | |||||
x68k.c | |||||
CONFIG_H = config_pjrc.h | |||||
# 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 | |||||
# 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 = 16000000 | |||||
# Build Options | |||||
# *Comment out* to disable the options. | |||||
# | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
EXTRAKEY_ENABLE = yes # Audio control and System control | |||||
NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#---------------- Programming Options -------------------------- | |||||
AVRDUDE = avrdude | |||||
# Type: avrdude -c ? to get a full listing. | |||||
AVRDUDE_PROGRAMMER = avr109 | |||||
AVRDUDE_PORT = /dev/ttyACM0 | |||||
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) | |||||
#PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex | |||||
PROGRAM_CMD = dfu-programmer atmega32u4 flash $(TARGET).hex | |||||
include $(TOP_DIR)/protocol/pjrc.mk | |||||
include $(TOP_DIR)/protocol.mk | |||||
include $(TOP_DIR)/common.mk | |||||
include $(TOP_DIR)/rules.mk |
X68000 to USB keyboard protocol converter | |||||
========================================= | |||||
SHARP X68000 is a hobby computer released in Japan.(1987-93) | |||||
http://en.wikipedia.org/wiki/Sharp_X68000 | |||||
X68000 keyboard has ALPS linear switches. | |||||
- DSETK0016CE01 green linear | |||||
- DSETK0023CE03 yellow linear | |||||
Hardware | |||||
-------- | |||||
Target MCU is ATMega32u4 but other USB capable AVR will also work. | |||||
You can use PJRC Teensy as dev board. | |||||
http://www.pjrc.com/teensy/ | |||||
Wiring: | |||||
Mini-DIN Teensy | |||||
----------------------------------------------------- | |||||
pin1 +5V VCC | |||||
pin2 MOUSE - | |||||
pin3 RXD PD2(RXD) | |||||
pin4 TXD PD3(TXD) NOTE: Not supported yet. | |||||
pin5 READY - | |||||
pin6 REMOTE - | |||||
pin7 GND GND | |||||
Firmware | |||||
-------- | |||||
Build: | |||||
$ cd x68k_usb | |||||
$ make | |||||
And load the binary to MCU with your favorite programmer. | |||||
If you use Teensy you can load with PJRC Teensy Loader tool. | |||||
http://www.pjrc.com/teensy/loader.html | |||||
* * * * * * * * * * * * * * * * * * | |||||
X68000 Keyboard Protocol | |||||
======================== | |||||
http://kyoutan.jpn.org/uts/pc/pic/x68key/ | |||||
Connector | |||||
--------- | |||||
Mini DIN 7pin(female connector on computer side) | |||||
7 6 5 | |||||
o o o | |||||
4 o = o 3 | |||||
o o | |||||
2 1 | |||||
Mini-DIN | |||||
------------- | |||||
pin1 +5V | |||||
pin2 MOUSE | |||||
pin3 RXD | |||||
pin4 TXD | |||||
pin5 READY | |||||
pin6 REMOTE | |||||
pin7 GND | |||||
Signaling | |||||
--------- | |||||
- TXD,RXD | |||||
Asynchronous, 2400baud, 1-startbit(L), 8-databit, 1-stopbit(H) | |||||
- READY | |||||
ready/not ready(1/0) | |||||
Data from keyboard | |||||
------------------ | |||||
bit 7 make/break flag(0/1) | |||||
bit 6-0 following scan code | |||||
Data from computer | |||||
------------------ | |||||
- LED contorol ON/OFF(0/1) | |||||
bit 7 1(fixed) | |||||
bit 6 全角 | |||||
bit 5 ひらがな | |||||
bit 4 INS | |||||
bit 3 CAPS | |||||
bit 2 コード入力 | |||||
bit 1 ローマ字 | |||||
bit 0 かな | |||||
- Repeat delay | |||||
bit 7 0(fixed) | |||||
bit 6 1(fixed) | |||||
bit 5 1(fixed) | |||||
bit 4 0(fixed) | |||||
bit 3-0 delay | |||||
REPEAT_DELAY = 200+delay*100 ms | |||||
default: 500ms | |||||
- Repeat time | |||||
bit 7 0(fixed) | |||||
bit 6 1(fixed) | |||||
bit 5 1(fixed) | |||||
bit 4 1(fixed) | |||||
bit 3-0 time | |||||
REPEAT_TIME = 30+time^2*5 ms | |||||
default: 110ms | |||||
Scan Codes | |||||
---------- | |||||
,---. ,---. ,-------------------, ,-------------------. ,-----------. ,---------------. | |||||
| 61| | 62| | 63| 64| 65| 66| 67| | 68| 69| 6A| 6B| 6C| | 5A| 5B| 5C| | 5D| 52| 53| 54| | |||||
`---' `---' `-------------------' `-------------------' `-----------' `---------------' | |||||
,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
| 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| 0F| | 36| 5E| 37| | 3F| 40| 41| 42| | |||||
|-----------------------------------------------------------| |------------ |---------------| | |||||
| 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| | | 38| 39| 3A| | 43| 44| 45| 46| | |||||
|------------------------------------------------------. 1D | `---=====---' |---------------| | |||||
| 71 | 1E| 1F| 20| 21| 2l| 23| 24| 25| 26| 27| 28| 29| | ___| 3C|___ | 47| 48| 49| 4A| | |||||
|-----------------------------------------------------------| | 3B|---| 3D| |-----------|---| | |||||
| 70 | 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 70 | `---| 3E|---' | 4B| 4C| 4D| | | |||||
`-----------------------------------------------------------| .---=====---. |-----------| 4E| | |||||
| 5F| 55 | 56 | 35 | 57 | 58 | 59 | 60| | 72 | 73 | | 4F| 50| 51| | | |||||
`---------------------------------------------' `-----------' `---------------' |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef CONFIG_H | |||||
#define CONFIG_H | |||||
/* controller configuration */ | |||||
#include "controller_teensy.h" | |||||
#define VENDOR_ID 0xFEED | |||||
#define PRODUCT_ID 0x6800 | |||||
#define MANUFACTURER t.m.k. | |||||
#define PRODUCT SHARP X68000 keyboard converter | |||||
#define DESCRIPTION converts SHARP X68000 keyboard protocol into USB | |||||
/* matrix size */ | |||||
#define MATRIX_ROWS 16 | |||||
#define MATRIX_COLS 8 | |||||
/* key combination for command */ | |||||
#define IS_COMMAND() ( \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LALT) | MOD_BIT(KB_RALT)) || \ | |||||
keyboard_report->mods == (MOD_BIT(KB_LCTRL) | MOD_BIT(KB_RSHIFT)) \ | |||||
) | |||||
/* mouse keys */ | |||||
#ifdef MOUSEKEY_ENABLE | |||||
# define MOUSEKEY_DELAY_TIME 255 | |||||
#endif | |||||
/* USART configuration | |||||
* asynchronous, 2400baud, 8-data bit, non parity, 1-stop bit, no flow control | |||||
*/ | |||||
#ifdef __AVR_ATmega32U4__ | |||||
# define KBD_RX_VECT USART1_RX_vect | |||||
# define KBD_RX_DATA UDR1 | |||||
# define KBD_RX_BAUD 2400 | |||||
# define KBD_RX_UBBR ((F_CPU/(16UL*KBD_RX_BAUD))-1) | |||||
# define KBD_RX_INIT() do { \ | |||||
UBRR1L = (uint8_t) KBD_RX_UBBR; \ | |||||
UBRR1H = (uint8_t) (KBD_RX_UBBR>>8); \ | |||||
UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); \ | |||||
} while(0) | |||||
#else | |||||
# error "USART configuration is needed." | |||||
#endif | |||||
#endif |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "util.h" | |||||
#include "keymap.h" | |||||
// Following macros help you to define a keymap with the form of actual keyboard layout. | |||||
/* X68000 Keyboard Scan codes | |||||
,---. ,---. ,-------------------, ,-------------------. ,-----------. ,---------------. | |||||
| 61| | 62| | 63| 64| 65| 66| 67| | 68| 69| 6A| 6B| 6C| | 5A| 5B| 5C| | 5D| 52| 53| 54| | |||||
`---' `---' `-------------------' `-------------------' `-----------' `---------------' | |||||
,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
| 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| 0F| | 36| 5E| 37| | 3F| 40| 41| 42| | |||||
|-----------------------------------------------------------| |------------ |---------------| | |||||
| 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| | | 38| 39| 3A| | 43| 44| 45| 46| | |||||
|------------------------------------------------------. 1D | `---=====---' |---------------| | |||||
| 71 | 1E| 1F| 20| 21| 2l| 23| 24| 25| 26| 27| 28| 29| | ___| 3C|___ | 47| 48| 49| 4A| | |||||
|-----------------------------------------------------------| | 3B|---| 3D| |-----------|---| | |||||
| 70 | 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 70 | `---| 3E|---' | 4B| 4C| 4D| | | |||||
`-----------------------------------------------------------| .---=====---. |-----------| 4E| | |||||
| 5F| 55 | 56 | 35 | 57 | 58 | 59 | 60| | 72 | 73 | | 4F| 50| 51| | | |||||
`---------------------------------------------' `-----------' `---------------' | |||||
*/ | |||||
#define KEYMAP( \ | |||||
K61,K62, K63,K64,K65,K66,K67, K68,K69,K6A,K6B,K6C, K5A,K5B,K5C, K5D,K52,K53,K54, \ | |||||
K01,K02,K03,K04,K05,K06,K07,K08,K09,K0A,K0B,K0C,K0D,K0E,K0F, K36,K5E,K37, K3F,K40,K41,K42, \ | |||||
K10,K11,K12,K13,K14,K15,K16,K17,K18,K19,K1A,K1B,K1C, K1D, K38,K39,K3A, K43,K44,K45,K46, \ | |||||
K71,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27,K28,K29, K3C, K47,K48,K49,K4A, \ | |||||
K70,K2A,K2B,K2C,K2D,K2E,K2F,K30,K31,K32,K33,K34, K3B,K3E,K3D, K4B,K4C,K4D,K4E, \ | |||||
K5F,K55,K56, K35, K57,K58,K59,K60, K72, K73, K4F,K50,K51 \ | |||||
) { \ | |||||
{ KB_NO, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ | |||||
{ KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ | |||||
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ | |||||
{ KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ | |||||
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ | |||||
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ | |||||
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_##K37 }, \ | |||||
{ KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_##K3F }, \ | |||||
{ KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_##K47 }, \ | |||||
{ KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_##K4F }, \ | |||||
{ KB_##K50, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \ | |||||
{ KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_##K5C, KB_##K5D, KB_##K5E, KB_##K5F }, \ | |||||
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_##K66, KB_##K67 }, \ | |||||
{ KB_##K68, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \ | |||||
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_NO, KB_NO, KB_NO, KB_NO, }, \ | |||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO } \ | |||||
} | |||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. | |||||
static const uint8_t PROGMEM fn_layer[] = { | |||||
0, // Fn0 | |||||
0, // Fn1 | |||||
0, // Fn2 | |||||
0, // Fn3 | |||||
0, // Fn4 | |||||
0, // Fn5 | |||||
0, // Fn6 | |||||
0 // Fn7 | |||||
}; | |||||
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. | |||||
// See layer.c for details. | |||||
static const uint8_t PROGMEM fn_keycode[] = { | |||||
KB_NO, // Fn0 | |||||
KB_NO, // Fn1 | |||||
KB_NO, // Fn2 | |||||
KB_NO, // Fn3 | |||||
KB_NO, // Fn4 | |||||
KB_NO, // Fn5 | |||||
KB_NO, // Fn6 | |||||
KB_NO // Fn7 | |||||
}; | |||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | |||||
/* X68000 Keyboard Scan codes | |||||
,---. ,---. ,-------------------, ,-------------------. ,-----------. ,---------------. | |||||
| 61| | 62| | 63| 64| 65| 66| 67| | 68| 69| 6A| 6B| 6C| | 5A| 5B| 5C| | 5D| 52| 53| 54| | |||||
`---' `---' `-------------------' `-------------------' `-----------' `---------------' | |||||
,-----------------------------------------------------------. ,-----------. ,---------------. | |||||
| 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| 0F| | 36| 5E| 37| | 3F| 40| 41| 42| | |||||
|-----------------------------------------------------------| |------------ |---------------| | |||||
| 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| | | 38| 39| 3A| | 43| 44| 45| 46| | |||||
|------------------------------------------------------. 1D | `---=====---' |---------------| | |||||
| 71 | 1E| 1F| 20| 21| 2l| 23| 24| 25| 26| 27| 28| 29| | ___| 3C|___ | 47| 48| 49| 4A| | |||||
|-----------------------------------------------------------| | 3B|---| 3D| |-----------|---| | |||||
| 70 | 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 70 | `---| 3E|---' | 4B| 4C| 4D| | | |||||
`-----------------------------------------------------------| .---=====---. |-----------| 4E| | |||||
| 5F| 55 | 56 | 35 | 57 | 58 | 59 | 60| | 72 | 73 | | 4F| 50| 51| | | |||||
`---------------------------------------------' `-----------' `---------------' | |||||
*/ | |||||
KEYMAP( | |||||
NO, NO, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, PSCR,SLCK,PAUS, CAPS,NO, NO, NO, | |||||
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS, | |||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, ENT, DEL, END, PGDN, P7, P8, P9, PPLS, | |||||
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, UP, P4, P5, P6, PEQL, | |||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,GRV, LEFT,DOWN,RGHT, P1, P2, P3, PENT, | |||||
LGUI,LALT,NO, SPC, RALT,RGUI,RCTL,APP, NO, NO, P0, PCMM,PDOT | |||||
), | |||||
}; | |||||
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) | |||||
{ | |||||
return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); | |||||
} | |||||
uint8_t keymap_fn_layer(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_layer[biton(fn_bits)]); | |||||
} | |||||
uint8_t keymap_fn_keycode(uint8_t fn_bits) | |||||
{ | |||||
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "stdint.h" | |||||
#include "x68k.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
// not supported now | |||||
} |
/* | |||||
Copyright 2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <util/delay.h> | |||||
#include "print.h" | |||||
#include "util.h" | |||||
#include "x68k.h" | |||||
#include "matrix.h" | |||||
/* | |||||
* Matrix Array usage: | |||||
* | |||||
* ROW: 16(4bits) | |||||
* COL: 8(3bits) | |||||
* | |||||
* 8bit wide | |||||
* +---------+ | |||||
* 0|00 ... 07| | |||||
* 1|08 ... 0F| | |||||
* :| ... | | |||||
* :| ... | | |||||
* E|70 ... 77| | |||||
* F|78 ... 7F| | |||||
* +---------+ | |||||
* | |||||
*/ | |||||
static uint8_t matrix[MATRIX_ROWS]; | |||||
#define ROW(code) ((code>>3)&0xF) | |||||
#define COL(code) (code&0x07) | |||||
static bool is_modified = false; | |||||
inline | |||||
uint8_t matrix_rows(void) | |||||
{ | |||||
return MATRIX_ROWS; | |||||
} | |||||
inline | |||||
uint8_t matrix_cols(void) | |||||
{ | |||||
return MATRIX_COLS; | |||||
} | |||||
void matrix_init(void) | |||||
{ | |||||
x68k_init(); | |||||
// initialize matrix state: all keys off | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00; | |||||
return; | |||||
} | |||||
uint8_t matrix_scan(void) | |||||
{ | |||||
is_modified = false; | |||||
uint8_t code; | |||||
code = x68k_recv(); | |||||
if (code == 0) { | |||||
return 0; | |||||
} | |||||
phex(code); print(" "); | |||||
if (code&0x80) { | |||||
// break code | |||||
if (matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] &= ~(1<<COL(code)); | |||||
is_modified = true; | |||||
} | |||||
} else { | |||||
// make code | |||||
if (!matrix_is_on(ROW(code), COL(code))) { | |||||
matrix[ROW(code)] |= (1<<COL(code)); | |||||
is_modified = true; | |||||
} | |||||
} | |||||
return code; | |||||
} | |||||
bool matrix_is_modified(void) | |||||
{ | |||||
return is_modified; | |||||
} | |||||
inline | |||||
bool matrix_has_ghost(void) | |||||
{ | |||||
return false; | |||||
} | |||||
inline | |||||
bool matrix_is_on(uint8_t row, uint8_t col) | |||||
{ | |||||
return (matrix[row] & (1<<col)); | |||||
} | |||||
inline | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
{ | |||||
return matrix[row]; | |||||
} | |||||
void matrix_print(void) | |||||
{ | |||||
print("\nr/c 01234567\n"); | |||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | |||||
phex(row); print(": "); | |||||
pbin_reverse(matrix_get_row(row)); | |||||
print("\n"); | |||||
} | |||||
} | |||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
count += bitpop(matrix[i]); | |||||
} | |||||
return count; | |||||
} |
/* | |||||
Copyright 2012 Jun WAKO <[email protected]> | |||||
This software is licensed with a Modified BSD License. | |||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | |||||
GPL-compatible, and OK to use in both free and proprietary applications. | |||||
Additions and corrections to this file are welcome. | |||||
Redistribution and use in source and binary forms, with or without | |||||
modification, are permitted provided that the following conditions are met: | |||||
* Redistributions of source code must retain the above copyright | |||||
notice, this list of conditions and the following disclaimer. | |||||
* Redistributions in binary form must reproduce the above copyright | |||||
notice, this list of conditions and the following disclaimer in | |||||
the documentation and/or other materials provided with the | |||||
distribution. | |||||
* Neither the name of the copyright holders nor the names of | |||||
contributors may be used to endorse or promote products derived | |||||
from this software without specific prior written permission. | |||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||||
POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#include <stdbool.h> | |||||
#include <avr/io.h> | |||||
#include <avr/interrupt.h> | |||||
#include "x68k.h" | |||||
void x68k_init(void) | |||||
{ | |||||
KBD_RX_INIT(); | |||||
} | |||||
// RX ring buffer | |||||
#define RBUF_SIZE 8 | |||||
static uint8_t rbuf[RBUF_SIZE]; | |||||
static uint8_t rbuf_head = 0; | |||||
static uint8_t rbuf_tail = 0; | |||||
uint8_t x68k_recv(void) | |||||
{ | |||||
uint8_t data = 0; | |||||
if (rbuf_head == rbuf_tail) { | |||||
return 0; | |||||
} | |||||
data = rbuf[rbuf_tail]; | |||||
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE; | |||||
return data; | |||||
} | |||||
// USART RX complete interrupt | |||||
ISR(KBD_RX_VECT) | |||||
{ | |||||
uint8_t next = (rbuf_head + 1) % RBUF_SIZE; | |||||
if (next != rbuf_tail) { | |||||
rbuf[rbuf_head] = KBD_RX_DATA; | |||||
rbuf_head = next; | |||||
} | |||||
} |
/* | |||||
Copyright 2012 Jun WAKO <[email protected]> | |||||
This software is licensed with a Modified BSD License. | |||||
All of this is supposed to be Free Software, Open Source, DFSG-free, | |||||
GPL-compatible, and OK to use in both free and proprietary applications. | |||||
Additions and corrections to this file are welcome. | |||||
Redistribution and use in source and binary forms, with or without | |||||
modification, are permitted provided that the following conditions are met: | |||||
* Redistributions of source code must retain the above copyright | |||||
notice, this list of conditions and the following disclaimer. | |||||
* Redistributions in binary form must reproduce the above copyright | |||||
notice, this list of conditions and the following disclaimer in | |||||
the documentation and/or other materials provided with the | |||||
distribution. | |||||
* Neither the name of the copyright holders nor the names of | |||||
contributors may be used to endorse or promote products derived | |||||
from this software without specific prior written permission. | |||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||||
POSSIBILITY OF SUCH DAMAGE. | |||||
*/ | |||||
#ifndef X68K_H | |||||
#define X68K_H | |||||
/* host role */ | |||||
void x68k_init(void); | |||||
uint8_t x68k_recv(void); | |||||
/* device role */ | |||||
#endif |