~ruther/qmk_firmware

194dc0984ee3bdaa285125c024b292794fa198d8 — Viet Yen Nguyen 5 years ago e071206
[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 pin
M keyboards/kinesis/config.h => keyboards/kinesis/config.h +0 -10
@@ 130,14 130,4 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION

#ifdef SUBPROJECT_alvicstep
    #include "alvicstep/config.h"
#endif
#ifdef SUBPROJECT_stapelberg
    #include "stapelberg/config.h"
#endif
#ifdef SUBPROJECT_kint2pp
    #include "kint2pp/config.h"
#endif

#endif

A keyboards/kinesis/keymaps/dvorak_nguyenvietyen/keymap.c => keyboards/kinesis/keymaps/dvorak_nguyenvietyen/keymap.c +30 -0
@@ 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
    )
};

M keyboards/kinesis/kinesis.h => keyboards/kinesis/kinesis.h +3 -0
@@ 10,6 10,9 @@
#ifdef KEYBOARD_kinesis_kint2pp
	#include "kint2pp.h"
#endif
#ifdef KEYBOARD_kinesis_nguyenvietyen
	#include "nguyenvietyen.h"
#endif

#include "quantum.h"


A keyboards/kinesis/nguyenvietyen/README.md => keyboards/kinesis/nguyenvietyen/README.md +109 -0
@@ 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.

A keyboards/kinesis/nguyenvietyen/config.h => keyboards/kinesis/nguyenvietyen/config.h +27 -0
@@ 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

A keyboards/kinesis/nguyenvietyen/matrix.c => keyboards/kinesis/nguyenvietyen/matrix.c +64 -0
@@ 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;
}

A keyboards/kinesis/nguyenvietyen/nguyenvietyen.c => keyboards/kinesis/nguyenvietyen/nguyenvietyen.c +31 -0
@@ 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;
}

A keyboards/kinesis/nguyenvietyen/nguyenvietyen.h => keyboards/kinesis/nguyenvietyen/nguyenvietyen.h +74 -0
@@ 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 }  \
}

A keyboards/kinesis/nguyenvietyen/rules.mk => keyboards/kinesis/nguyenvietyen/rules.mk +20 -0
@@ 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