Codes are released under each license. See heading of each file for details. | |||||
Modified BSD license: | |||||
ps2.c | |||||
ps2.h | |||||
adb.c | |||||
adb.h | |||||
GPLv2 or later: | |||||
other codes | |||||
PJRC's license: | |||||
print.c | |||||
print.h | |||||
pjrc/ | |||||
GPLv2 or GPLv3 or OBJECTIVE DEVELOPMENT's commercial license: | |||||
vusb/ | |||||
This software includes following codes from other parties. | |||||
- V-USB from OBJECTIVE DEVELOPMENT | |||||
http://www.obdev.at/products/vusb/index.html | |||||
- Teensy example codes from PJRC | |||||
http://www.pjrc.com/teensy/ |
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][c1] - [PS/2 keyboard to USB][GH_ps2] | |||||
* [adb_usb][c2] - [ADB keyboard to USB][GH_adb] | |||||
* [m0110_usb][c3] - [Machintosh 128K/512K/Plus keyboard to USB][GH_m0110] | |||||
* [terminal_usb][c4] - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal] | |||||
* [news_usb][c5] - [Sony NEWS keyboard to USB][GH_news] | |||||
* [x68k_usb][c6] - [Sharp X68000 keyboard to USB][GH_x68k] | |||||
### keyboard | |||||
* [hhkb][k1] - [Happy Hacking Keyboard professional][GH_hhkb] | |||||
* [macway][k2] - [Compact keyboard mod][GH_macway] | |||||
* [hbkb][k3] - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb] | |||||
[c1]: converter/ps2_usb/ | |||||
[c2]: converter/adb_usb/ | |||||
[c3]: converter/m0110_usb/ | |||||
[c4]: converter/terminal_usb/ | |||||
[c5]: converter/news_usb/ | |||||
[c6]: converter/x68k_usb/ | |||||
[k1]: keyboard/hhkb | |||||
[k2]: keyboard/macway | |||||
[k3]: keyboard/hbkb | |||||
[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_news]: 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_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483 | |||||
Files & Directories | |||||
------------------- | |||||
### Top | |||||
* [common/](common/) - common codes | |||||
* [protocol/](protocol/) - keyboard protocol support | |||||
* [keyboard/](keyboard/) - keyboard projects | |||||
* [converter/](converter/) - protocol converter projects | |||||
* [doc/](doc/) - documents | |||||
### Keyboard Protocols | |||||
* [pjrc/](protocol/pjrc/) - PJRC USB stack | |||||
* [vusb/](protocol/vusb/) - Objective Development V-USB | |||||
* [iwrap/](protocol/iwrap) - Bluetooth HID for Bluegiga iWRAP | |||||
* [ps2.c](protocol/ps2.c) - PS/2 protocol | |||||
* [adb.c](protocol/adb.c) - Apple Desktop Bus protocol | |||||
* [m0110.c](protocol/m0110.c) - Macintosh 128K/512K/Plus keyboard protocol | |||||
* [news.c](protocol/news.c) - Sony NEWS keyboard protocol | |||||
* [x68k.c](protocol/x68k.c) - Sharp X68000 keyboard protocol | |||||
Build & Program | |||||
--------------- | |||||
### Build firmware | |||||
To compile you need `AVR GCC`, `AVR Libc` and `GNU make`. | |||||
You can use [WinAVR][winavr] on Windows and [CrossPack][crosspack] on Mac. | |||||
$ cd <project> | |||||
$ make | |||||
The firmware will be compiled as a file `tmk_<project>.hex`. | |||||
[winavr]: http://winavr.sourceforge.net/ | |||||
[crosspack]: 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 | |||||
COMMON_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 $(COMMON_DIR)/pjrc.mk | |||||
include $(COMMON_DIR)/common.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); | |||||
} | |||||
} |
endif | endif | ||||
# Search Path | # Search Path | ||||
VPATH += $(COMMON_DIR) | |||||
include $(COMMON_DIR)/rules.mk | |||||
VPATH += $(TOP_DIR)/common |
# Target file name (without extension). | |||||
TARGET = hbk | |||||
# Directory common source filess exist | |||||
COMMON_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 $(COMMON_DIR)/pjrc.mk | |||||
include $(COMMON_DIR)/common.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 | |||||
COMMON_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 $(COMMON_DIR)/iwrap.mk | |||||
# To be swatchable btween Bluetooth and USB. Comment out if you don't need USB. | |||||
include $(COMMON_DIR)/vusb.mk | |||||
include $(COMMON_DIR)/common.mk |
# | |||||
# Makefile for PJRC Teensy | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = hhkb_pjrc | |||||
# Directory common source filess exist | |||||
COMMON_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 $(COMMON_DIR)/pjrc.mk | |||||
include $(COMMON_DIR)/common.mk |
# | |||||
# Makefile for V-USB | |||||
# | |||||
# Target file name (without extension). | |||||
TARGET = hhkb_vusb | |||||
# Directory common source filess exist | |||||
COMMON_DIR = .. | |||||
# Directory keyboard dependent files exist | |||||
TARGET_DIR = . | |||||
# keyboard dependent files | |||||
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 $(COMMON_DIR)/vusb.mk | |||||
include $(COMMON_DIR)/common.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 | |||||
COMMON_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 $(COMMON_DIR)/pjrc.mk | |||||
include $(COMMON_DIR)/common.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 | |||||
COMMON_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 $(COMMON_DIR)/pjrc.mk | |||||
include $(COMMON_DIR)/common.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) | |||||
{ | |||||
} |