diff options
| -rw-r--r-- | keyboards/hhkb/yang/config.h | 130 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/info.json | 71 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/keymaps/default/keymap.c | 73 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/keymaps/kanru/config.h | 21 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/keymaps/kanru/keymap.c | 126 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/matrix.c | 173 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/memo.md | 135 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/readme.md | 118 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/rules.mk | 27 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/yang.c | 118 | ||||
| -rw-r--r-- | keyboards/hhkb/yang/yang.h | 36 | 
11 files changed, 1028 insertions, 0 deletions
diff --git a/keyboards/hhkb/yang/config.h b/keyboards/hhkb/yang/config.h new file mode 100644 index 0000000000..693b2501bb --- /dev/null +++ b/keyboards/hhkb/yang/config.h @@ -0,0 +1,130 @@ +/* +Copyright 2020 Kan-Ru Chen <kanru@kanru.info> +Copyright 2012 Jun Wako <wakojun@gmail.com> + +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/>. +*/ + +#pragma once + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0x4848   // HH = happy hacking +#define PRODUCT_ID 0x0001  // ANSI HHKB +#define DEVICE_VER 0x0104 +#define MANUFACTURER YANG +#define PRODUCT HHKB BLE Keyboard + +/* key matrix size */ +#define MATRIX_ROWS 8 +#define MATRIX_COLS 8 + +/* matrix power saving */ +#define MATRIX_POWER_SAVE_TIMEOUT_MS 10000 +#define MATRIX_POWER_SAVE_TIMEOUT_L2_MS 1800000 +#define MATRIX_POWER_SAVE_TIMEOUT_L3_MS 7200000 + +#define LED_CAPS_LOCK_PIN F4 + +#ifdef BLUETOOTH_ENABLE +#    define OUTPUT_DEFAULT OUTPUT_AUTO + +#    undef SERIAL_UART_BAUD +#    undef SERIAL_UART_DATA +#    undef SERIAL_UART_UBRR +#    undef SERIAL_UART_RXD_VECT +#    undef SERIAL_UART_TXD_READY +#    undef SERIAL_UART_INIT + +#    define SERIAL_UART_BAUD 76800 +#    define SERIAL_UART_DATA UDR1 +#    define SERIAL_UART_UBRR (F_CPU / (8UL * SERIAL_UART_BAUD) - 1) +#    define SERIAL_UART_RXD_VECT USART1_RX_vect +#    define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1)) +#    define SERIAL_UART_INIT()                        \ +        do {                                          \ +            cli();                                    \ +            /* baud rate */                           \ +            UBRR1L = SERIAL_UART_UBRR;                \ +            /* baud rate */                           \ +            UBRR1H = SERIAL_UART_UBRR >> 8;           \ +            /* enable TX */                           \ +            UCSR1B |= (0 << TXCIE1) | (1 << TXEN1);   \ +            /* enable RX */                           \ +            UCSR1B |= (1 << RXCIE1) | (1 << RXEN1);   \ +            /* parity: none(00), even(01), odd(11) */ \ +            UCSR1C |= (0 << UPM11) | (0 << UPM10);    \ +            /* 2x speed (error = 0.2%) */             \ +            UCSR1A |= (1 << U2X1);                    \ +            sei();                                    \ +        } while (0) +#endif + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +//#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +//#define LOCKING_RESYNC_ENABLE + +/* If defined, GRAVE_ESC will always act as ESC when CTRL is held. + * This is useful for the Windows task manager shortcut (ctrl+shift+esc). + */ +//#define GRAVE_ESC_CTRL_OVERRIDE + +/* + * Force NKRO + * + * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved + * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the + * makefile for this to work.) + * + * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) + * until the next keyboard reset. + * + * NKRO may prevent your keystrokes from being detected in the BIOS, but it is + * fully operational during normal computer usage. + * + * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) + * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by + * bootmagic, NKRO mode will always be enabled until it is toggled again during a + * power-up. + * + */ +//#define FORCE_NKRO + +/* + * Feature disable options + *  These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT + + +/* Bootmagic Lite key configuration */ +//#define BOOTMAGIC_LITE_ROW 0 +//#define BOOTMAGIC_LITE_COLUMN 0 + +//#define DEBUG_MATRIX_SCAN_RATE + +// Disable debounce +#define DEBOUNCE 0 diff --git a/keyboards/hhkb/yang/info.json b/keyboards/hhkb/yang/info.json new file mode 100644 index 0000000000..b38b8a6881 --- /dev/null +++ b/keyboards/hhkb/yang/info.json @@ -0,0 +1,71 @@ +{ +  "keyboard_name": "YANG HHKB BLE", +  "url": "", +  "maintainer": "qmk", +  "layouts": { +    "LAYOUT_60_hhkb": { +      "layout": [ +        { "label": "Esc", "x": 0, "y": 0 }, +        { "label": "!", "x": 1, "y": 0 }, +        { "label": "@", "x": 2, "y": 0 }, +        { "label": "#", "x": 3, "y": 0 }, +        { "label": "$", "x": 4, "y": 0 }, +        { "label": "%", "x": 5, "y": 0 }, +        { "label": "^", "x": 6, "y": 0 }, +        { "label": "&", "x": 7, "y": 0 }, +        { "label": "*", "x": 8, "y": 0 }, +        { "label": "(", "x": 9, "y": 0 }, +        { "label": ")", "x": 10, "y": 0 }, +        { "label": "_", "x": 11, "y": 0 }, +        { "label": "+", "x": 12, "y": 0 }, +        { "label": "|", "x": 13, "y": 0 }, +        { "label": "~", "x": 14, "y": 0 }, +        { "label": "Tab", "x": 0, "y": 1, "w": 1.5 }, +        { "label": "Q", "x": 1.5, "y": 1 }, +        { "label": "W", "x": 2.5, "y": 1 }, +        { "label": "E", "x": 3.5, "y": 1 }, +        { "label": "R", "x": 4.5, "y": 1 }, +        { "label": "T", "x": 5.5, "y": 1 }, +        { "label": "Y", "x": 6.5, "y": 1 }, +        { "label": "U", "x": 7.5, "y": 1 }, +        { "label": "I", "x": 8.5, "y": 1 }, +        { "label": "O", "x": 9.5, "y": 1 }, +        { "label": "P", "x": 10.5, "y": 1 }, +        { "label": "{", "x": 11.5, "y": 1 }, +        { "label": "}", "x": 12.5, "y": 1 }, +        { "label": "Delete", "x": 13.5, "y": 1, "w": 1.5 }, +        { "label": "Control", "x": 0, "y": 2, "w": 1.75 }, +        { "label": "A", "x": 1.75, "y": 2 }, +        { "label": "S", "x": 2.75, "y": 2 }, +        { "label": "D", "x": 3.75, "y": 2 }, +        { "label": "F", "x": 4.75, "y": 2 }, +        { "label": "G", "x": 5.75, "y": 2 }, +        { "label": "H", "x": 6.75, "y": 2 }, +        { "label": "J", "x": 7.75, "y": 2 }, +        { "label": "K", "x": 8.75, "y": 2 }, +        { "label": "L", "x": 9.75, "y": 2 }, +        { "label": ":", "x": 10.75, "y": 2 }, +        { "label": "\"", "x": 11.75, "y": 2 }, +        { "label": "Return", "x": 12.75, "y": 2, "w": 2.25 }, +        { "label": "Shift", "x": 0, "y": 3, "w": 2.25 }, +        { "label": "Z", "x": 2.25, "y": 3 }, +        { "label": "X", "x": 3.25, "y": 3 }, +        { "label": "C", "x": 4.25, "y": 3 }, +        { "label": "V", "x": 5.25, "y": 3 }, +        { "label": "B", "x": 6.25, "y": 3 }, +        { "label": "N", "x": 7.25, "y": 3 }, +        { "label": "M", "x": 8.25, "y": 3 }, +        { "label": "<", "x": 9.25, "y": 3 }, +        { "label": ">", "x": 10.25, "y": 3 }, +        { "label": "?", "x": 11.25, "y": 3 }, +        { "label": "Shift", "x": 12.25, "y": 3, "w": 1.75 }, +        { "label": "Fn", "x": 14, "y": 3 }, +        { "label": "", "x": 1.5, "y": 4 }, +        { "label": "", "x": 2.5, "y": 4, "w": 1.5 }, +        { "x": 4, "y": 4, "w": 6 }, +        { "label": "", "x": 10, "y": 4, "w": 1.5 }, +        { "label": "", "x": 11.5, "y": 4 } +      ] +    } +  } +} diff --git a/keyboards/hhkb/yang/keymaps/default/keymap.c b/keyboards/hhkb/yang/keymaps/default/keymap.c new file mode 100644 index 0000000000..f91e1fc243 --- /dev/null +++ b/keyboards/hhkb/yang/keymaps/default/keymap.c @@ -0,0 +1,73 @@ +/*  -*-  eval: (turn-on-orgtbl); -*- + * default HHKB Layout + * + * Copyright 2021 Kan-Ru Chen <kanru@kanru.info> + * + * 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 QMK_KEYBOARD_H + +enum custom_layers { +    BASE, +    HHKB, +}; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + +    /* BASE Level: 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 |   | +     |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---| +     | Cont  | A | S | D | F | G | H | J | K | L | ; | '     | Ent |       |   | +     |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---| +     | Shift | Z | X | C | V | B | N | M | , | . | / | Shift | Fn0 |       |   | +     |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---| + +            |------+------+-----------------------+------+------| +            | LAlt | LGUI | ******* Space ******* | RGUI | RAlt | +            |------+------+-----------------------+------+------| +    */ + +    [BASE] = LAYOUT_60_hhkb( //  default layer +        KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, +        KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, +        KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, +        KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(HHKB), +        KC_LALT, KC_LGUI, /*        */ KC_SPC, KC_RGUI, KC_RALT), + +    /* Layer HHKB: HHKB mode (HHKB Fn) +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      | Pwr  | F1  | F2  | F3  | F4 | F5 | F6 | F7 | F8  | F9  | F10 | F11 | F12   | Ins   | Del | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      | Caps |     |     |     |    |    |    |    | Psc | Slk | Pus | Up  |       | Backs |     | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      |      | VoD | VoU | Mut |    |    | *  | /  | Hom | PgU | Lef | Rig | Enter |       |     | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      |      |     |     |     |    |    | +  | -  | End | PgD | Dow |     |       |       |     | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| + +                 |------+------+----------------------+------+------+ +                 | **** | **** | ******************** | **** | **** | +                 |------+------+----------------------+------+------+ + +     */ + +    [HHKB] = LAYOUT_60_hhkb( +        KC_PWR, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL, +        KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, +        KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, +        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, +        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)}; diff --git a/keyboards/hhkb/yang/keymaps/kanru/config.h b/keyboards/hhkb/yang/keymaps/kanru/config.h new file mode 100644 index 0000000000..81fef2ea5e --- /dev/null +++ b/keyboards/hhkb/yang/keymaps/kanru/config.h @@ -0,0 +1,21 @@ +/* Copyright 2021 Kan-Ru Chen <kanru@kanru.info> + * + * 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/>. + */ +#pragma once + +#define MOUSEKEY_DELAY 90 +#define MOUSEKEY_INTERVAL 16 +#define MOUSEKEY_MAX_SPEED 4 +#define MOUSEKEY_WHEEL_INTERVAL 50 diff --git a/keyboards/hhkb/yang/keymaps/kanru/keymap.c b/keyboards/hhkb/yang/keymaps/kanru/keymap.c new file mode 100644 index 0000000000..c5d57c4cb3 --- /dev/null +++ b/keyboards/hhkb/yang/keymaps/kanru/keymap.c @@ -0,0 +1,126 @@ +/*  -*-  eval: (turn-on-orgtbl); -*- + * kanru's HHKB Layout + * + * Copyright 2021 Kan-Ru Chen <kanru@kanru.info> + * + * 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 QMK_KEYBOARD_H +#include <stdio.h> + +enum custom_layers { +    BASE, +    HHKB, +    MOUSE, +}; + +#define BATTERY_FULL 550 +#define BATTERY_EMPTY 326 + +enum my_keycodes { KC_VBAT = SAFE_RANGE }; + +uint32_t adafruit_ble_read_battery_voltage(void); + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { +    switch (keycode) { +#ifdef BLUETOOTH_ENABLE +        case KC_VBAT: +            if (record->event.pressed) { +                char    vbat[8]; +                uint8_t level = (adafruit_ble_read_battery_voltage() - BATTERY_EMPTY) / (float)(BATTERY_FULL - BATTERY_EMPTY) * 100; +                snprintf(vbat, sizeof(vbat), "%d", level); +                send_string(vbat); +            } +            return false; +#endif +        default: +            return true; +    } +} + +// clang-format off +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + +    /* BASE Level: 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 |   | +     |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---| +     | Cont  | A | S | D | F | G | H | J | K | L | ; | '     | Ent |       |   | +     |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---| +     | Shift | Z | X | C | V | B | N | M | , | . | / | Shift | Fn0 |       |   | +     |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---| + +            |------+------+-----------------------+------+------| +            | LAlt | LGUI | ******* Space ******* | RGUI | RAlt | +            |------+------+-----------------------+------+------| +    */ + +    [BASE] = LAYOUT_60_hhkb( //  default layer +        LT(MOUSE, KC_ESC), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, +        KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, +        KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, +        KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(HHKB), +        KC_LALT, KC_LGUI, /*        */ KC_SPC, KC_RGUI, KC_RALT), + +    /* Layer HHKB: HHKB mode (HHKB Fn) +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      | Pwr  | F1  | F2  | F3  | F4 | F5 | F6 | F7 | F8  | F9  | F10 | F11 | F12   | Ins   | Del | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      | Caps |     |     | BAT |    |    |    |    | Psc | Slk | Pus | Up  |       | Backs |     | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      |      | VoD | VoU | Mut |    |    | *  | /  | Hom | PgU | Lef | Rig | Enter |       |     | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| +      |      |     |     |     |    |    | +  | -  | End | PgD | Dow |     |       |       |     | +      |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----| + +                 |------+------+----------------------+------+------+ +                 | **** | **** | ******************** | **** | **** | +                 |------+------+----------------------+------+------+ + +     */ + +    [HHKB] = LAYOUT_60_hhkb( +        KC_PWR, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL, +        KC_CAPS, KC_TRNS, KC_TRNS, KC_VBAT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, +        KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, +        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, +        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), + +    /* Layer MOUSE: Mouse Key mode (ESC) +      |------+------+------+-----+----+----+----+----+----+----+-----+-----+-------+-------+----- | +      |      |      |      |     |    |    |    |    |    |    |     |     |       |       |     | +      |------+------+------+-----+----+----+----+----+----+----+-----+-----+-------+-------+-----| +      |      | BTN1 | WH_U |     |    |    |    |    |    |    |     |     |       |       |     | +      |------+------+------+-----+----+----+----+----+----+----+-----+-----+-------+-------+-----| +      |      | BTN2 | WH_D |     |    |    |MS_L|MS_D|MS_U|MS_R|     |     |       |       |     | +      |------+------+------+-----+----+----+----+----+----+----+-----+-----+-------+-------+-----| +      |      | BTN3 |      |     |    |    |    |    |    |    |     |     |       |       |     | +      |------+------+------+-----+----+----+----+----+----+----+-----+-----+-------+-------+-----| + +                 |------+------+----------------------+------+------+ +                 | **** | **** | ******************** | **** | **** | +                 |------+------+----------------------+------+------+ + +     */ + +    [MOUSE] = LAYOUT_60_hhkb( +        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, +        KC_TRNS, KC_BTN1, KC_WH_U, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, +        KC_TRNS, KC_BTN2, KC_WH_D, KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, KC_TRNS, KC_TRNS, KC_TRNS, +        KC_TRNS, KC_BTN3, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, +        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS) +}; +// clang-format on diff --git a/keyboards/hhkb/yang/matrix.c b/keyboards/hhkb/yang/matrix.c new file mode 100644 index 0000000000..f0eccc899d --- /dev/null +++ b/keyboards/hhkb/yang/matrix.c @@ -0,0 +1,173 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> +Copyright 2020 Kan-Ru Chen <kanru@kanru.info> + +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 "quantum.h" + +#ifdef BLUETOOTH_ENABLE +#    include "adafruit_ble.h" +#endif + +#define RELAX_TIME_US 5 +#define ADC_READ_TIME_US 5 + +uint8_t power_save_level; + +static uint32_t matrix_last_modified = 0; + +static inline void key_strobe_high(void) { writePinLow(B6); } +static inline void key_strobe_low(void) { writePinHigh(B6); } +static inline bool key_state(void) { return readPin(D7); } +static inline void key_prev_on(void) { writePinHigh(B7); } +static inline void key_prev_off(void) { writePinLow(B7); } +static inline bool key_power_state(void) { return !readPin(D6); } + +static inline void suspend_power_down_longer(void) { +    uint8_t times = 60; +    while (--times) suspend_power_down(); +} + +void matrix_power_up(void) { +    dprint("[matrix_on]\n"); +    // change pins output +    DDRB  = 0xFF; +    PORTB = 0x40; +    // switch MOS FET on +    setPinOutput(D6); +    writePinLow(D6); +} + +void matrix_power_down(void) { +    dprint("[matrix_off]\n"); +    // input with pull-up consumes less than without it when pin is open +    DDRB  = 0x00; +    PORTB = 0xFF; +    // switch MOS FET off +    setPinOutput(D6); +    writePinHigh(D6); +} + +static inline void key_select_row(uint8_t row) { PORTB = (PORTB & 0b11111000) | ((row)&0b111); } +static inline void key_select_col(uint8_t col) { PORTB = (PORTB & 0b11000111) | (((col)&0b111) << 3); } +static inline bool key_prev_was_on(matrix_row_t matrix[], uint8_t row, uint8_t col) { return matrix[row] & (1 << col); } + +void matrix_init_custom(void) { power_save_level = 0; } + +bool matrix_scan_custom(matrix_row_t current_matrix[]) { +    bool matrix_has_changed = false; + +    // power on +    if (!key_power_state()) { +        matrix_power_up(); +    } +    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { +        matrix_row_t last_row_value = current_matrix[row]; + +        key_select_row(row); +        wait_us(RELAX_TIME_US); + +        for (uint8_t col = 0; col < MATRIX_COLS; col++) { +            // Hysteresis control: assert(1) when previous key state is on +            if (key_prev_was_on(current_matrix, row, col)) { +                key_prev_on(); +            } else { +                key_prev_off(); +            } + +            // Disable interrupts to encure the ADC timing is correct +            cli(); + +            // strobe +            key_select_col(col); +            key_strobe_high(); + +            // Wait for ADC to outputs its value. +            // 1us was ok on one HHKB, but not worked on another. +            // no   wait doesn't work on Teensy++ with pro(1us works) +            // no   wait does    work on tmk PCB(8MHz) with pro2 +            // 1us  wait does    work on both of above +            // 1us  wait doesn't work on tmk(16MHz) +            // 5us  wait does    work on tmk(16MHz) +            // 5us  wait does    work on tmk(16MHz/2) +            // 5us  wait does    work on tmk(8MHz) +            // 10us wait does    work on Teensy++ with pro +            // 10us wait does    work on 328p+iwrap with pro +            // 10us wait doesn't work on tmk PCB(8MHz) with pro2(very lagged scan) +            wait_us(ADC_READ_TIME_US); + +            if (key_state()) { +                current_matrix[row] &= ~(1 << col); +            } else { +                current_matrix[row] |= (1 << col); +            } + +            key_strobe_low(); +            sei(); + +            // Make sure enough time has elapsed since the last call +            // This is to ensure the matrix voltages have relaxed +            wait_us(RELAX_TIME_US); +        } +        if (current_matrix[row] ^ last_row_value) { +            matrix_has_changed   = true; +            matrix_last_modified = timer_read32(); +        } +    } + +    // Power saving +    uint32_t time_diff = timer_elapsed32(matrix_last_modified); +    if (time_diff > MATRIX_POWER_SAVE_TIMEOUT_L3_MS) { +        power_save_level = 3; +        suspend_power_down_longer(); +    } else if (time_diff > MATRIX_POWER_SAVE_TIMEOUT_L2_MS) { +        power_save_level = 2; +#ifdef BLUETOOTH_ENABLE +        if (!adafruit_ble_is_connected()) { +            power_save_level = 3; +        } +#endif +        suspend_power_down_longer(); +    } else if (time_diff > MATRIX_POWER_SAVE_TIMEOUT_MS) { +        power_save_level = 1; +        suspend_power_down(); +    } else { +        if (power_save_level != 0) { +            power_save_level = 0; +            suspend_wakeup_init(); +        } +    } + +    return matrix_has_changed; +} + +bool adafruit_ble_delbonds(void); +bool adafruit_ble_reconnect(void); + +bool command_extra(uint8_t code) { +    switch (code) { +#ifdef BLUETOOTH_ENABLE +        case KC_R: +            adafruit_ble_delbonds(); +            return true; +        case KC_S: +            adafruit_ble_reconnect(); +            return true; +#endif +        default: +            return false; +    } +} diff --git a/keyboards/hhkb/yang/memo.md b/keyboards/hhkb/yang/memo.md new file mode 100644 index 0000000000..5c710482b3 --- /dev/null +++ b/keyboards/hhkb/yang/memo.md @@ -0,0 +1,135 @@ +## Hardware Information + +The YANG HHKB BLE controller design is similiar to hasu's +controller. Most pins are compatiable. + +**MCU**: ATmega32U4   +**Bluetooth**:  MDBT40 (nRF51822-based), with Adafruit Bluefruit LE UART Friend firmware.   +**Power**: 3.3V   +**CPU Frequency**: 8MHz   +**Bootloader**: Lufa MassStorage   + +## Pin usage + +| Description                          | HASU pin usage         | YANG mod changed           | +|:------------------------------------ | ---------------------- | -------------------------- | +| ~KEY: Lo(0) when key is pressed      | PD7 input(with pullup) |                            | +| Hysteresis: Hi(1) if key was pressed | PB7 output             |                            | +| Row selector bit0                    | PB0 output             |                            | +| Row selector bit1                    | PB1 output             |                            | +| Row selector bit2                    | PB2 output             |                            | +| Col selector bit0                    | PB3 output             |                            | +| Col selector bit1                    | PB4 output             |                            | +| Col selector bit2                    | PB5 output             |                            | +| Key unable                           | PB6 output             |                            | +| Switch power                         | PD4 output             | PD6 output (PMOS FET)      | +| Bluetooth UART Rx                    | PC4 input              | PD2                        | +| Bluetooth UART Tx                    | PC5 output             | PD3                        | +| Bluetooth power                      |                        | PD5 output (low: power on) | +| LED 0                                |                        | PF4                        | +| LED 2                                |                        | PF1                        | +| LED 4                                |                        | PF0                        | +| Unused for PRO2                      | PC6                    |                            | +| Unused for PRO2                      | PC7                    |                            | +| Inner USB power                      |                        | PF7                        | + +## How to flash LUFA MassStorage bootloader on Linux + +The FAT filesystem on Linux very often cannot flush the write cache, +leading to broken firmware in the flash. + +We can use `dd` to write to the virtual block storage directly to +bypass the vfs layer. + +``` +dd if=FLASH.bin of=<path of virtual block device> seek=4 +``` + +Skip 4 sectors because the default sector size of the virtual device +and dd is 512 bytes and the emulated flash file starts at 5th sector. + +## How to find the path of the virtual block device + +After the keyboard boots into flash mode, on Linux system you should +be able to find the block device in `dmesg` logs. + +For exmaple if you type + +``` +sudo dmesg +``` + +You should find something like + +``` +[357885.143593] usb 1-1.4: USB disconnect, device number 24 +[357885.627740] usb 1-1.4: new full-speed USB device number 25 using xhci_hcd +[357885.729486] usb 1-1.4: New USB device found, idVendor=03eb, idProduct=1962, bcdDevice= 0.01 +[357885.729492] usb 1-1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0 +[357885.745620] SCSI subsystem initialized +[357885.746712] usb-storage 1-1.4:1.0: USB Mass Storage device detected +[357885.746818] scsi host0: usb-storage 1-1.4:1.0 +[357885.746919] usbcore: registered new interface driver usb-storage +[357885.747689] usbcore: registered new interface driver uas +[357886.766755] scsi 0:0:0:0: Direct-Access     LUFA     Bootloader       0.00 PQ: 0 ANSI: 0 +[357886.773216] scsi 0:0:0:0: Attached scsi generic sg0 type 0 +[357886.777474] sd 0:0:0:0: [sdx] 134 512-byte logical blocks: (68.6 kB/67.0 KiB) +[357886.780300] sd 0:0:0:0: [sdx] Write Protect is off +[357886.780302] sd 0:0:0:0: [sdx] Mode Sense: 00 00 00 00 +[357886.783113] sd 0:0:0:0: [sdx] Asking for cache data failed +[357886.783114] sd 0:0:0:0: [sdx] Assuming drive cache: write through +[357886.842676]  sdx: +[357886.859528] sd 0:0:0:0: [sdx] Attached SCSI removable disk +``` + +The `sdx` is the block device name and the full path is at `/dev/sdx` +The above flash command will become + +``` +dd if=FLASH.bin of=/dev/sdx seek=4 +``` + +## Adafruit Bluefruit LE UART configuraton + +The default baud rate used by the firmware is 76800 although adafruit +do not recommend using higher baudrates than 9600 because the nRF51 +UART can drop characters. + +Double speed mode to get more accurate async reading because the F_CPU +speed is 8MHz. + +## Power saving mode design + +Power saving is only enabled when USB is detached and using battery +power. Here we define several levels of power saving mode, each saves +more power but takes longer to resume operation. + +1. Level 1: idle mode is activated after a short configurable time +   (MATRIX_POWER_SAVE_TIMEOUT_MS) MCU is put into sleep mode and only +   scan the matrix per 15ms. PORTB pins are set to input with pull-up +   to save power. Sensing PCB is powered down between scans. + +2. Level 2: after idling for longer (MATRIX_POWER_SAVE_TIMEOUT_L2_MS) +   we entry this state. Matrix scan is skipped until the time lapses +   900ms. + +2. Level 3: sleep mode is activated after a longer timeout +   (MATRIX_POWER_SAVE_TIMEOUT_L3_MS) Bluetooth module is powered down. + +## Battery reading + +VBAT is connected to AIN6 pin on the MDBT40 module and the AREF pin is +the reference voltage. Doing a ADC with AT+HWDAC=6 will return the +difference between VBAT and VREF. + +It seems when fully charged the ADC read is 550. Likely VREF is 3311mV +and the fully charged VBAT is thus 3861mV. + +Enable battery service with AT+BLEBATTEN=1 first then we can update the +battery level by using AT+BLEBATTVAL=%d + +## References + +* https://github.com/joric/qmk/wiki/hhkb_ble +* https://github.com/tomsmalley/custom-topre-guide +* https://github.com/abcminiuser/lufa/blob/master/Bootloaders/MassStorage/Lib/VirtualFAT.h diff --git a/keyboards/hhkb/yang/readme.md b/keyboards/hhkb/yang/readme.md new file mode 100644 index 0000000000..6f85c0f198 --- /dev/null +++ b/keyboards/hhkb/yang/readme.md @@ -0,0 +1,118 @@ +# HHKB Alternate Controller (YANG HHKB BLE Mod) + + + +An alternative controler for the HHKB designed by YANG (yangdigi) +based on the hasu controller. + +* Keyboard Maintainer: [Kan-Ru Chen](https://github.com/kanru)   +* Hardware Supported: YANG HHKB BLE Controller   +* Hardware Availability: https://kbdfans.com/products/hhkb-ble-mod-upgrade-module + +Make example for this keyboard (after setting up your build environment): + +    make hhkb/yang:default + +To flash, first boot your keyboard into bootloader (hold ESC and attach usb cable) +then a virtual USB storage should appear. You can copy the `hhkb_yang_default.bin` +file to the virtual USB storage and override the `HHKB_BLE.BIN` file in there. + +Make sure to unmount and eject the virtual USB storage. + +## Features: + +- [x] QMK (via USB) +- [x] Bluetooth (BLE) +- [x] Power saving mode +  - [x] Idle mode +  - [x] Deep sleep mode +- [x] LEDs +- [x] Battery service +- [x] Special commands +  - [x] Switch BT peer + +## Entering flash mode + +Different ways to enter flash mode: + +* Press and hold the ESC key. Insert the USB cable to enter the flash +  mode. When the OS shows the drive disk, you can release the key. + +* Use the magic command LSHIFT+RSHIFT+B to reboot to bootloader then +  quickly hold the ESC key. + +If you reflash the wrong firmware or did not reflash successfully, you +can no longer enter the flash mode, especially the wireless keyboard +with battery. You need to turn off the keyboard's power switch, and +re-enter the flash mode, reflash the correct firmware. + +After entering the bootloader(flash mode), three indicators on the top +right of the HHKB BLE controller will flash. LED3(green) will flash +quickly when writing firmware to the controller. + +If these three leds are not soldered or your hhkb case is black, you +can't know their status, but you can still see LED3 under the right +USB port. + +## How to reliably flash LUFA MassStorage bootloader on Linux + +The FAT filesystem on Linux very often cannot flush the write cache, +leading to broken firmware in the flash. + +We can use `dd` to write to the virtual block storage directly to +bypass the vfs layer. + +``` +dd if=FLASH.bin of=<path of virtual block device> seek=4 +``` + +Skip 4 sectors because the default sector size of the virtual device +and dd is 512 bytes and the emulated flash file starts at 5th sector. + +## How to find the path of the virtual block device + +After the keyboard boots into flash mode, on Linux system you should +be able to find the block device in `dmesg` logs. + +For exmaple if you type + +``` +sudo dmesg +``` + +You should find something like + +``` +[357885.143593] usb 1-1.4: USB disconnect, device number 24 +[357885.627740] usb 1-1.4: new full-speed USB device number 25 using xhci_hcd +[357885.729486] usb 1-1.4: New USB device found, idVendor=03eb, idProduct=1962, bcdDevice= 0.01 +[357885.729492] usb 1-1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0 +[357885.745620] SCSI subsystem initialized +[357885.746712] usb-storage 1-1.4:1.0: USB Mass Storage device detected +[357885.746818] scsi host0: usb-storage 1-1.4:1.0 +[357885.746919] usbcore: registered new interface driver usb-storage +[357885.747689] usbcore: registered new interface driver uas +[357886.766755] scsi 0:0:0:0: Direct-Access     LUFA     Bootloader       0.00 PQ: 0 ANSI: 0 +[357886.773216] scsi 0:0:0:0: Attached scsi generic sg0 type 0 +[357886.777474] sd 0:0:0:0: [sdx] 134 512-byte logical blocks: (68.6 kB/67.0 KiB) +[357886.780300] sd 0:0:0:0: [sdx] Write Protect is off +[357886.780302] sd 0:0:0:0: [sdx] Mode Sense: 00 00 00 00 +[357886.783113] sd 0:0:0:0: [sdx] Asking for cache data failed +[357886.783114] sd 0:0:0:0: [sdx] Assuming drive cache: write through +[357886.842676]  sdx: +[357886.859528] sd 0:0:0:0: [sdx] Attached SCSI removable disk +``` + +The `sdx` is the block device name and the full path is at `/dev/sdx` +The above flash command will become + +``` +dd if=FLASH.bin of=/dev/sdx seek=4 +``` + +**Caution**: if set to incorrect device it may wipe out +your actual disk. + +## Help page of original firmware + +http://help.ydkb.io/doku.php?id=en:kb-mods:hhkb-ble diff --git a/keyboards/hhkb/yang/rules.mk b/keyboards/hhkb/yang/rules.mk new file mode 100644 index 0000000000..6027a07176 --- /dev/null +++ b/keyboards/hhkb/yang/rules.mk @@ -0,0 +1,27 @@ +# MCU name +MCU = atmega32u4 + +# MCU frequency +F_CPU = 8000000 + +# Bootloader selection +BOOTLOADER = lufa-ms + +# Build Options +#   change yes to no to disable +# +BOOTMAGIC_ENABLE = yes      # Enable Bootmagic Lite +MOUSEKEY_ENABLE = yes       # Mouse keys +EXTRAKEY_ENABLE = yes       # Audio control and System control +CONSOLE_ENABLE = no         # Console for debug +COMMAND_ENABLE = yes        # Commands for debug and configuration +NKRO_ENABLE = no            # USB Nkey Rollover + +LAYOUTS = 60_hhkb + +# Disable bluetooth until the UART code is merged +BLUETOOTH_DRIVER = BluefruitLE + +# Custom matrix file for the HHKB +CUSTOM_MATRIX = lite +SRC += matrix.c diff --git a/keyboards/hhkb/yang/yang.c b/keyboards/hhkb/yang/yang.c new file mode 100644 index 0000000000..7ae0d76390 --- /dev/null +++ b/keyboards/hhkb/yang/yang.c @@ -0,0 +1,118 @@ +/* Copyright 2021 Kan-Ru Chen <kanru@kanru.info> + * + * 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 "yang.h" + +extern uint8_t power_save_level; + +void hhkb_led_on(uint8_t led) { +    switch (led) { +        case 1: +            writePinHigh(F4); +            break; +        case 2: +            writePinHigh(F2); +            break; +        case 3: +            writePinHigh(F0); +            break; +    } +} + +void hhkb_led_off(uint8_t led) { +    switch (led) { +        case 1: +            writePinLow(F4); +            break; +        case 2: +            writePinLow(F2); +            break; +        case 3: +            writePinLow(F0); +            break; +    } +} + +void keyboard_pre_init_kb(void) { +    // BT power up +    setPinOutput(D5); +    writePinLow(D5); + +    // Row selectors +    setPinOutput(B0); +    setPinOutput(B1); +    setPinOutput(B2); + +    // Col selectors +    setPinOutput(B3); +    setPinOutput(B4); +    setPinOutput(B5); + +    // Key strobe +    setPinOutput(B6); +    writePinHigh(B6); + +    // Key: input with pull-up +    setPinInputHigh(D7); + +    // Unused pins on Pro2 ANSI +    // Input with pull up to save power +    setPinInputHigh(C6); +    setPinInputHigh(C7); + +    // LED pin configuration +    setPinOutput(F0); +    setPinOutput(F1); +    setPinOutput(F4); +    writePinLow(F0); +    writePinLow(F1); +    writePinLow(F4); + +    // Turn on switch PCB +    setPinOutput(D6); +    writePinLow(D6); + +    keyboard_pre_init_user(); +} + +void suspend_power_down_kb(void) { +    if (power_save_level > 2) { +        // Disable UART TX to avoid current leakage +        UCSR1B &= ~_BV(TXEN1); +        // Power down BLE module +        writePinHigh(D5); +    } + +    suspend_power_down_user(); +} + +void suspend_wakeup_init_kb(void) { +    // Power up BLE module +    writePinLow(D5); +    // Enable UART TX +    UCSR1B |= _BV(TXEN1); + +    suspend_wakeup_init_user(); +} + +layer_state_t layer_state_set_kb(layer_state_t state) { +    state = layer_state_set_user(state); + +    writePin(F1, IS_LAYER_ON_STATE(state, 1)); +    writePin(F0, IS_LAYER_ON_STATE(state, 2)); + +    return state; +} diff --git a/keyboards/hhkb/yang/yang.h b/keyboards/hhkb/yang/yang.h new file mode 100644 index 0000000000..4858c18554 --- /dev/null +++ b/keyboards/hhkb/yang/yang.h @@ -0,0 +1,36 @@ +/* Copyright 2021 Kan-Ru Chen <kanru@kanru.info> + * + * 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/>. + */ +#pragma once + +#include "quantum.h" + +#define LAYOUT_60_hhkb(                                                        \ +    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)                     \ +                                                                               \ +{                                                                              \ +    { K00, K01, K02, K03, K04, K05, K06, K07   },                              \ +    { K10, K11, K12, K13, K14, K15, K16, K17   },                              \ +    { K20, K21, K22, K23, K24, K25, K26, KC_NO },                              \ +    { K30, K31, K32, K33, K34, K35, K36, K37   },                              \ +    { K40, K41, K42, K43, K44, K45, K46, KC_NO },                              \ +    { K50, K51, K52, K53, K54, K55, K56, K57   },                              \ +    { K60, K61, K62, K63, K64, K65, K66, KC_NO },                              \ +    { K70, K71, K72, K73, K74, K75, K76, KC_NO }                               \ +}  | 
