[Keyboard] Kinesis + Pro Micro (#9944)
* [Keyboard] Kinesis + Pro Micro init - docs for DIY - custom matrix = lite - a near-factory dvorak mapping - optimized debouncing for lower latency * chore: reformatting * chore: update doc * chore: cleanups according to PR feedback * chore: PR feedback * fix: compile error * chore: add include * fix: LEDs hanging after USB disconnect * chore: enable QMK goodies by default * chore: use semantic write pinpre-develop-merge-nov20
parent
e071206c58
commit
194dc0984e
@ -0,0 +1,30 @@ |
||||
#include QMK_KEYBOARD_H |
||||
|
||||
#define DVORAK_MAC_MODE 0 // Base Dvorak in Kinesis's Mac Mode with (Cmd, Option, Ctrl, Cmd) thumbkeys
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { |
||||
[DVORAK_MAC_MODE] = LAYOUT( |
||||
// left hand
|
||||
KC_CAPS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, |
||||
KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, |
||||
KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, |
||||
KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, |
||||
KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, |
||||
KC_GRV, KC_INS, KC_LEFT, KC_RIGHT, |
||||
// left thumb
|
||||
KC_LGUI, KC_LALT, |
||||
KC_HOME, |
||||
KC_BSPC, KC_DEL, KC_END, |
||||
// right hand
|
||||
KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, KC_NLCK, KC_POWER, |
||||
KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, |
||||
KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH, |
||||
KC_D, KC_H, KC_T, KC_N, KC_S, KC_BSLS, |
||||
KC_B, KC_M, KC_W, KC_V, KC_Z, KC_RSFT, |
||||
KC_UP, KC_DOWN, KC_LBRC, KC_RBRC, |
||||
// right thumb
|
||||
KC_RCTL, KC_RGUI, |
||||
KC_PGUP, |
||||
KC_PGDN, KC_ENT, KC_SPC |
||||
) |
||||
}; |
@ -0,0 +1,109 @@ |
||||
# Viet's Kinesis + Pro Micro |
||||
|
||||
July 2020 |
||||
|
||||
This work is inspired by `alvicstep`'s solution. Instead of hooking up the Kinesis to a Teensy 2, this one hooks it up to a Pro Micro. |
||||
|
||||
## Kinesis Board Layout |
||||
The following is a reinterpretation of [@chrisandreae](https://github.com/chrisandreae/keyboard-firmware/blob/public/hardware/kinesis.h)'s work. |
||||
|
||||
### Used Pins |
||||
* 8 columns mapped to output pins 21 - 28 |
||||
* 16 rows mapped to 4 input pins: pin 39 - 36. Rows are traversed by iterating and setting 16 values from 0000 to 1111. |
||||
* 4 leds (e.g. capslock) mapped to input pin 1 - 4 |
||||
* keypad key mapped to pin 5 |
||||
* program key mapped to pin 6 |
||||
* `VCC` mapped to pin 40 |
||||
|
||||
### Matrix Configuration |
||||
The matrix configuration of the columns and rows on my Advantage is as follows: |
||||
|
||||
| | row 0 | row 1 | row 2 | row 3 | row 4 | row 5 | row 6 | row 7 | row 8 | row 9 | row A | row B | row C | row D | row E | row F | |
||||
| ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | |
||||
| col0 | F6 | F8 | F7 | 5% | 4$ | 3# | 2@ | 1! | =+ | | | | | | | | |
||||
| col1 | F3 | F5 | F4 | T | R | E | W | Q | Tab | | | | | | | | |
||||
| col2 | Esc | F2 | F1 | G | F | D | S | A | CapsLk | | | | | | | | |
||||
| col3 | F9 | F11 | F10 | B | V | C | X | Z | LShift | Up | | Down | | [{ | ]} | | |
||||
| col4 | F12 | ScrLk | PrtSc | Right | | Left | Insert | ~ | | 6^ | 7& | 8* | | 9( | 0) | -_ | |
||||
| col5 | Pause | | | LAlt | | Home | | End | | Y | U | I | | O | P | `\|` | |
||||
| col6 | | | | LCtrl | Delete | Bksp | RCtrl | Enter | Space | H | J | K | | L | ;: | '" | |
||||
| col7 | | | | | RGUI | | PageUp | | PageDn | N | M | ,< | | .> | /? | RShift | |
||||
|
||||
(this is a modified copy from [@alvicstep](https://github.com/qmk/qmk_firmware/blob/master/keyboards/kinesis/alvicstep/alvicstep.h)) |
||||
|
||||
In the code, keypad and program keys are mapped respectively to col0 and col1 of row C, the 12th row. |
||||
|
||||
### Omitted Pins |
||||
There are pins that we currently omit: |
||||
* serial eeprom clock line mapped to pin 7 |
||||
* serial eeprom data line mapped to pin 8 |
||||
* EEPROM write protect mapped to pin 10. |
||||
* foot switch 1 mapped to pin 11 |
||||
* PS/2 clock mapped to pin 12 |
||||
* PS/2 data mapped to pin 13 |
||||
* foot switch 2 mapped to pin 17 |
||||
* foot switch 3 mapped to pin 15 |
||||
* audio mapped to pin 32 |
||||
|
||||
### DIP Socket |
||||
Here's an ASCII drawing of the 40 pin DIP socket. |
||||
``` |
||||
DL2 1 40 VCC |
||||
DR1 2 39 A |
||||
DR2 3 38 B |
||||
DL1 4 37 C |
||||
KPD 5 36 G |
||||
PGM 6 35 |
||||
SCL 7 34 |
||||
SDA 8 33 |
||||
RST 9 32 BUZZ |
||||
WP 10 31 EA |
||||
FS1 11 30 ALE |
||||
CLOCK 12 29 PSEN |
||||
DATA 13 28 r8 |
||||
14 27 r7 |
||||
FS3 15 26 r6 |
||||
16 25 r5 |
||||
FS2 17 24 r4 |
||||
XTAL1 18 23 r3 |
||||
XTAL2 19 22 r2 |
||||
GND 20 21 r1 |
||||
``` |
||||
(this is copied from [@wjanssens](https://raw.githubusercontent.com/wjanssens/tmk_keyboard/master/keyboard/kinesis/doc/readme.txt)) |
||||
|
||||
## Pin Mapping to Pro Micro |
||||
|
||||
The following table is ordered by physical Arduino pin order. |
||||
|
||||
| Arduino | Kinesis | Meaning | |
||||
| ------- | ------- | ------- | |
||||
| D3 | 36 | G | |
||||
| D2 | 37 | C | |
||||
| GND | | | |
||||
| GND | | | |
||||
| D1 | 38 | B | |
||||
| D0 | 39 | A | |
||||
| D4 | 1 | DL2 | |
||||
| C6 | 2 | DR1 | |
||||
| D7 | 3 | DR2 | |
||||
| E6 | 4 | DL1 | |
||||
| B4 | 5 | KPD | |
||||
| B5 | 6 | PGM | |
||||
| B6 | 21 | r1 | |
||||
| B2 | 22 | r2 | |
||||
| B3 | 23 | r3 | |
||||
| B1 | 24 | r4 | |
||||
| F7 | 25 | r5 | |
||||
| F6 | 26 | r6 | |
||||
| F5 | 27 | r7 | |
||||
| F4 | 28 | r8 | |
||||
| VCC | 40 | | |
||||
| RESET | | | |
||||
| GND | 20 | | |
||||
| RAW | | | |
||||
|
||||
## Notes |
||||
|
||||
* The rows are multiplexed. Instead of reading them out, one sets the row value and corresponding column values are returned through r1-r8. |
||||
* On my keyboard, the keypad and program key have dedicated pins. Since row 12 had no mapping in the physical matrix, there's a code override injects the keypad and program pins to the first two bits in the matrix. |
||||
* I've experimented with debouncing approaches. The current setting delivers a snappier feeling than Kinesis's factory default for me. |
@ -0,0 +1,27 @@ |
||||
#pragma once |
||||
|
||||
/* USB Device descriptor parameter */ |
||||
#define PRODUCT_ID 0x6060 |
||||
#define DEVICE_VER 0x0003 |
||||
|
||||
/* key matrix size */ |
||||
#define MATRIX_ROWS 16 |
||||
#define MATRIX_COLS 8 |
||||
|
||||
/*
|
||||
* Keyboard Matrix Assignments |
||||
* |
||||
* Change this to how you wired your keyboard |
||||
* COLS: AVR pins used for columns, left to right |
||||
* ROWS: AVR pins used for rows, top to bottom |
||||
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) |
||||
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) |
||||
* |
||||
*/ |
||||
// Passed through the port multipler, so 4 pins =16
|
||||
#define MATRIX_ROW_PINS { D0, D1, D2, D3 } |
||||
#define MATRIX_COL_PINS { B6, B2, B3, B1, F7, F6, F5, F4 } |
||||
#define UNUSED_PINS |
||||
|
||||
/* COL2ROW or ROW2COL */ |
||||
#define DIODE_DIRECTION COL2ROW |
@ -0,0 +1,64 @@ |
||||
#include "matrix.h" |
||||
|
||||
#include "quantum.h" |
||||
|
||||
static matrix_row_t read_row(uint8_t row) { |
||||
matrix_io_delay(); // without this wait read unstable value.
|
||||
|
||||
// keypad and program buttons
|
||||
if (row == 12) { |
||||
return ~(readPin(B4) | (readPin(B5) << 1) | 0b11111100); |
||||
} |
||||
|
||||
return ~(readPin(B6) | readPin(B2) << 1 | readPin(B3) << 2 | readPin(B1) << 3 | readPin(F7) << 4 | readPin(F6) << 5 | readPin(F5) << 6 | readPin(F4) << 7); |
||||
} |
||||
|
||||
static void unselect_rows(void) { |
||||
// set A,B,C,G to 0
|
||||
PORTD &= 0xF0; |
||||
} |
||||
|
||||
static void select_rows(uint8_t row) { |
||||
// set A,B,C,G to row value
|
||||
PORTD |= (0x0F & row); |
||||
} |
||||
|
||||
void matrix_init_custom(void) { |
||||
// output low (multiplexers)
|
||||
setPinOutput(D0); |
||||
setPinOutput(D1); |
||||
setPinOutput(D2); |
||||
setPinOutput(D3); |
||||
|
||||
// input with pullup (matrix)
|
||||
setPinInputHigh(B6); |
||||
setPinInputHigh(B2); |
||||
setPinInputHigh(B3); |
||||
setPinInputHigh(B1); |
||||
setPinInputHigh(F7); |
||||
setPinInputHigh(F6); |
||||
setPinInputHigh(F5); |
||||
setPinInputHigh(F4); |
||||
|
||||
// input with pullup (program and keypad buttons)
|
||||
setPinInputHigh(B4); |
||||
setPinInputHigh(B5); |
||||
|
||||
// initialize row and col
|
||||
unselect_rows(); |
||||
} |
||||
|
||||
bool matrix_scan_custom(matrix_row_t current_matrix[]) { |
||||
bool matrix_has_changed = false; |
||||
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { |
||||
select_rows(i); |
||||
matrix_row_t row = read_row(i); |
||||
unselect_rows(); |
||||
bool row_has_changed = current_matrix[i] != row; |
||||
matrix_has_changed |= row_has_changed; |
||||
current_matrix[i] = row; |
||||
} |
||||
|
||||
return matrix_has_changed; |
||||
} |
@ -0,0 +1,31 @@ |
||||
#include "nguyenvietyen.h" |
||||
|
||||
void matrix_init_kb(void) { |
||||
led_init_ports(); |
||||
matrix_init_user(); |
||||
} |
||||
|
||||
void led_init_ports() { |
||||
// * Set our LED pins as output
|
||||
setPinOutput(D7); // Keypad LED
|
||||
setPinOutput(C6); // ScrLock LED
|
||||
setPinOutput(D4); // NumLock LED
|
||||
setPinOutput(E6); // CapsLock LED
|
||||
|
||||
// turn all LEDs off by default
|
||||
writePinHigh(D7); |
||||
writePinHigh(C6); |
||||
writePinHigh(D4); |
||||
writePinHigh(E6); |
||||
} |
||||
|
||||
bool led_update_kb(led_t led_state) { |
||||
bool res = led_update_user(led_state); |
||||
if (res) { |
||||
writePin(D7, !led_state.compose); |
||||
writePin(C6, !led_state.scroll_lock); |
||||
writePin(D4, !led_state.num_lock); |
||||
writePin(E6, !led_state.caps_lock); |
||||
} |
||||
return res; |
||||
} |
@ -0,0 +1,74 @@ |
||||
#pragma once |
||||
|
||||
#include "quantum.h" |
||||
|
||||
#define ___ KC_NO |
||||
|
||||
#define LAYOUT( \ |
||||
k02, k22, k12, k01, k21, k11, k00, k20, k10, \
|
||||
k80, k70, k60, k50, k40, k30, \
|
||||
k81, k71, k61, k51, k41, k31, \
|
||||
k82, k72, k62, k52, k42, k32, \
|
||||
k83, k73, k63, k53, k43, k33, \
|
||||
k74, k64, k54, k34, \
|
||||
k36, k35, \
|
||||
k55, \
|
||||
k56, k46, k75, \
|
||||
\
|
||||
k03, k23, k13, k04, k24, k14, k05, kC0, kC1, \
|
||||
k94, kA4, kB4, kD4, kE4, kF4, \
|
||||
k95, kA5, kB5, kD5, kE5, kF5, \
|
||||
k96, kA6, kB6, kD6, kE6, kF6, \
|
||||
k97, kA7, kB7, kD7, kE7, kF7, \
|
||||
k93, kB3, kD3, kE3, \
|
||||
k47, k66, \
|
||||
k67, \
|
||||
k87, k76, k86 \
|
||||
) { \
|
||||
{ k00, k01, k02, k03, k04, k05, ___, ___ }, \
|
||||
{ k10, k11, k12, k13, k14, ___, ___, ___ }, \
|
||||
{ k20, k21, k22, k23, k24, ___, ___, ___ }, \
|
||||
{ k30, k31, k32, k33, k34, k35, k36, ___ }, \
|
||||
{ k40, k41, k42, k43, ___, ___, k46, k47 }, \
|
||||
{ k50, k51, k52, k53, k54, k55, k56, ___ }, \
|
||||
{ k60, k61, k62, k63, k64, ___, k66, k67 }, \
|
||||
{ k70, k71, k72, k73, k74, k75, k76, ___ }, \
|
||||
{ k80, k81, k82, k83, ___, ___, k86, k87 }, \
|
||||
{ ___, ___, ___, k93, k94, k95, k96, k97 }, \
|
||||
{ ___, ___, ___, ___, kA4, kA5, kA6, kA7 }, \
|
||||
{ ___, ___, ___, kB3, kB4, kB5, kB6, kB7 }, \
|
||||
{ kC0, kC1, ___, ___, ___, ___, ___, ___ }, \
|
||||
{ ___, ___, ___, kD3, kD4, kD5, kD6, kD7 }, \
|
||||
{ ___, ___, ___, kE3, kE4, kE5, kE6, kE7 }, \
|
||||
{ ___, ___, ___, ___, kF4, kF5, kF6, kF7 } \
|
||||
} |
||||
|
||||
/* ---------------- LEFT HAND ----------------- ---------------- RIGHT HAND ---------------- */ |
||||
#define LAYOUT_pretty( \ |
||||
k02, k22, k12, k01, k21, k11, k00, k20, k10, k03, k23, k13, k04, k24, k14, k05, kC0, kC1, \
|
||||
k80, k70, k60, k50, k40, k30, k94, kA4, kB4, kD4, kE4, kF4, \
|
||||
k81, k71, k61, k51, k41, k31, k95, kA5, kB5, kD5, kE5, kF5, \
|
||||
k82, k72, k62, k52, k42, k32, k96, kA6, kB6, kD6, kE6, kF6, \
|
||||
k83, k73, k63, k53, k43, k33, k97, kA7, kB7, kD7, kE7, kF7, \
|
||||
k74, k64, k54, k34, k93, kB3, kD3, kE3, \
|
||||
k36, k35, k47, k66, \
|
||||
k55, k67, \
|
||||
k56, k46, k75, k87, k76, k86 \
|
||||
) { \
|
||||
{ k00, k01, k02, k03, k04, k05, ___, ___ }, \
|
||||
{ k10, k11, k12, k13, k14, ___, ___, ___ }, \
|
||||
{ k20, k21, k22, k23, k24, ___, ___, ___ }, \
|
||||
{ k30, k31, k32, k33, k34, k35, k36, ___ }, \
|
||||
{ k40, k41, k42, k43, ___, ___, k46, k47 }, \
|
||||
{ k50, k51, k52, k53, k54, k55, k56, ___ }, \
|
||||
{ k60, k61, k62, k63, k64, ___, k66, k67 }, \
|
||||
{ k70, k71, k72, k73, k74, k75, k76, ___ }, \
|
||||
{ k80, k81, k82, k83, ___, ___, k86, k87 }, \
|
||||
{ ___, ___, ___, k93, k94, k95, k96, k97 }, \
|
||||
{ ___, ___, ___, ___, kA4, kA5, kA6, kA7 }, \
|
||||
{ ___, ___, ___, kB3, kB4, kB5, kB6, kB7 }, \
|
||||
{ kC0, kC1, ___, ___, ___, ___, ___, ___ }, \
|
||||
{ ___, ___, ___, kD3, kD4, kD5, kD6, kD7 }, \
|
||||
{ ___, ___, ___, kE3, kE4, kE5, kE6, kE7 }, \
|
||||
{ ___, ___, ___, ___, kF4, kF5, kF6, kF7 } \
|
||||
} |
@ -0,0 +1,20 @@ |
||||
# MCU name
|
||||
MCU = atmega32u4
|
||||
|
||||
# Bootloader selection
|
||||
BOOTLOADER = caterina
|
||||
|
||||
# Build Options
|
||||
# change yes to no to disable
|
||||
#
|
||||
BOOTMAGIC_ENABLE = yes
|
||||
MOUSEKEY_ENABLE = yes
|
||||
EXTRAKEY_ENABLE = yes
|
||||
COMMAND_ENABLE = yes
|
||||
NKRO_ENABLE = yes
|
||||
SLEEP_LED_ENABLE = yes
|
||||
CUSTOM_MATRIX = lite
|
||||
SRC += matrix.c
|
||||
|
||||
# experimentally determined to be sufficient :)
|
||||
DEBOUNCE=1
|
Loading…
Reference in new issue