HHKB YDKB Yang BT Controller (#15759)

Co-authored-by: Drashna Jaelre <drashna@live.com>
master
Kan-Ru Chen 2022-07-02 20:01:03 +09:00 committed by GitHub
parent 0eab24be26
commit f439fe6055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1028 additions and 0 deletions

View File

@ -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

View File

@ -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 }
]
}
}
}

View File

@ -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)};

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -0,0 +1,118 @@
# HHKB Alternate Controller (YANG HHKB BLE Mod)
![YANG HHKB BLE Mod](https://i.imgur.com/aZP1GYc.jpeg)
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

View File

@ -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

View File

@ -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;
}

View File

@ -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 } \
}