Skip to content

The ultimate configuration in the ultimate keyboard .

Notifications You must be signed in to change notification settings

pascualmg/hhkb-ultimate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 

Repository files navigation

HHKB Ultimate QMK Setup Guide

The Ultimate HHKB Experience

This guide documents the installation of a custom HHKB keymap that combines three legendary elements:

  • The timeless HHKB layout by Eiiti Wada
  • Hasu’s revolutionary mouse control layer
  • The efficiency of SpaceFN

The result is a zero-compromise configuration that enhances the HHKB while preserving its philosophical purity.

Pre-requisites

Hardware Required

  • HHKB Professional (any version)
  • USB cable
  • Hasu Controller

Software Required

Choose your preferred environment:

Nix Environment (Recommended)

The cleanest and most reliable setup:

# Enter a shell with QMK tools
nix-shell -p qmk

Traditional Setup

If you prefer the traditional approach:

# Clone QMK Firmware repository
git clone https://github.com/qmk/qmk_firmware.git
cd qmk_firmware

# Install dependencies
util/qmk_install.sh  # For Linux/macOS users

Installation Steps

pro-tip

This file is an .org!! if you use emacs you can tangle the code and use it directly in your qmk_firmware folder and use literate programming to document your keymap.

1. Prepare Your Directory

Create a dedicated space for your custom keymap:

# Create the keymap directory
mkdir -p keyboards/hhkb/ansi/32u4/keymaps/ultimate
cd keyboards/hhkb/ansi/32u4/keymaps/ultimate

2. Create Required Files

rules.mk

This enables the necessary QMK features:

MOUSEKEY_ENABLE = yes    # Mouse keys
EXTRAKEY_ENABLE = yes    # Audio control and System control
COMMAND_ENABLE = yes     # Commands for debug and configuration
NKRO_ENABLE = yes       # USB Nkey Rollover

keymap.c

The heart of the configuration. Copy our complete keymap here. The file includes:

  • Base HHKB layer
  • Function layer with media controls
  • Mouse control layer (activated by holding ;)
  • VI-style navigation (activated by holding /)
  • SpaceFN layer for quick access to function keys

3. Building the Firmware

Compile your custom firmware:

# Compile the keymap
qmk compile -kb hhkb/ansi/32u4 -km ultimate

4. Flashing Instructions

  1. Remove the HHKB’s back cover
  2. Locate the reset button (small button near the USB port)
  3. Connect your HHKB to your computer
  4. Press the reset button
  5. Flash the firmware:
qmk flash -kb hhkb/ansi/32u4 -km ultimate

Layout Guide

Available Layers

LayerActivationPrimary Use
BaseDefaultStandard HHKB typing
FnFn keyMedia & function keys
MouseHold ;Complete mouse control
VIHold /Efficient navigation
SpaceFNHold SpaceQuick access to function keys

Special Features

  • Full mouse control without leaving the home row
  • VI-style navigation for efficient text editing
  • One-handed F-key access via SpaceFN
  • All HHKB standard functions preserved

Customization

The keymap is designed to be built upon. Common customizations include:

  • Adjusting mouse movement speed
  • Changing layer activation keys
  • Adding new layers
  • Creating custom macros

Credits & References

Keymap

Your keymap.c content goes here for org-babel-tangle.

/*
  ██╗  ██╗██╗  ██╗██╗  ██╗██████╗     ██╗   ██╗██╗  ████████╗██╗███╗   ███╗ █████╗ ████████╗███████╗
  ██║  ██║██║  ██║██║ ██╔╝██╔══██╗    ██║   ██║██║  ╚══██╔══╝██║████╗ ████║██╔══██╗╚══██╔══╝██╔════╝
  ███████║███████║█████╔╝ ██████╔╝    ██║   ██║██║     ██║   ██║██╔████╔██║███████║   ██║   █████╗
  ██╔══██║██╔══██║██╔═██╗ ██╔══██╗    ██║   ██║██║     ██║   ██║██║╚██╔╝██║██╔══██║   ██║   ██╔══╝
  ██║  ██║██║  ██║██║  ██╗██████╔╝    ╚██████╔╝███████╗██║   ██║██║ ╚═╝ ██║██║  ██║   ██║   ███████╗
  ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚═════╝      ╚═════╝ ╚══════╝╚═╝   ╚═╝╚═╝     ╚═╝╚═╝  ╚═╝   ╚═╝   ╚══════╝
 *
 * [Previous documentation remains exactly the same...]
 */

#include QMK_KEYBOARD_H

enum layers { BASE = 0, FN = 1, MOUSE = 2, VI = 3, SPACE_FN = 4 };

enum custom_keycodes { SPACEFN_TOGGLE = SAFE_RANGE, BT_TOGGLE_KEY, BT_PAIR_KEY };

static bool spacefn_enabled = true;

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* Base Layer
     * ,-----------------------------------------------------------.
     * |Esc|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|  \|  `|
     * |-----------------------------------------------------------|
     * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|Backs|
     * |-----------------------------------------------------------|
     * |Contro|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;*|  '|Enter |
     * |-----------------------------------------------------------|
     * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|Shift |Fn|
     * `-----------------------------------------------------------'
     *       |Alt|Gui  |         Space         |SFTog|Alt|
     *       `-------------------------------------------'
     * * ; = Tap for ; or Hold for Mouse Layer
     * * / = Tap for / or Hold for VI Layer
     * * Space = Tap for Space or Hold for SpaceFN (when enabled)
     */
    [BASE] = LAYOUT(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, LT(MOUSE, 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, LT(VI, KC_SLSH), KC_RSFT, MO(FN), KC_LALT, KC_LGUI, LT(SPACE_FN, KC_SPC), SPACEFN_TOGGLE, KC_RALT),

    /* Fn Layer
     * ,-----------------------------------------------------------.
     * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |Caps |   |   |   |   |   |   |   |PSc|SLk|Pus|Up |   |     |
     * |-----------------------------------------------------------|
     * |      |VoD|VoU|Mut|   |   |  *|  /|Hom|PgU|Lef|Rig|Enter   |
     * |-----------------------------------------------------------|
     * |        |BTP|   |   |   |   |  +|  -|End|PgD|Dow|      |   |
     * `-----------------------------------------------------------'
     *       |BTS|     |         Space         |     |   |
     *       `-------------------------------------------'
     * BTS = Bluetooth Toggle Switch
     * BTP = Bluetooth Toggle Pair
     */
    [FN] = LAYOUT(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_SCRL, KC_PAUS, KC_UP, KC_TRNS, KC_TRNS, 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, BT_PAIR_KEY, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, BT_TOGGLE_KEY, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),

    /* Mouse Layer (Hold ;)
     * ,-----------------------------------------------------------.
     * |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
     * |-----------------------------------------------------------|
     * |     |   |   |   |   |   |WhL|WhD|MsU|WhU|WhR|   |   |     |
     * |-----------------------------------------------------------|
     * |      |Ac0|Ac1|Ac2|   |   |   |MsL|MsD|MsR|   |   |        |
     * |-----------------------------------------------------------|
     * |        |   |   |   |   |   |Mb3|Mb2|Mb1|Mb4|Mb5|      |   |
     * `-----------------------------------------------------------'
     *       |   |     |          Mb1          |     |   |
     *       `-------------------------------------------'
     * Mb = Mouse Button | Ms = Mouse Movement
     * Wh = Mouse Wheel  | Ac = Mouse Acceleration
     */
    [MOUSE] = LAYOUT(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_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_MS_U, KC_WH_U, KC_WH_R, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_ACL0, KC_ACL1, KC_ACL2, KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN3, KC_BTN2, KC_BTN1, KC_BTN4, KC_BTN5, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_TRNS, KC_TRNS),

    /* Vi Layer (Hold /)
     * ,-----------------------------------------------------------.
     * |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
     * |-----------------------------------------------------------|
     * |     |   |   |   |   |   |   |Hom|Up |End|   |   |   |     |
     * |-----------------------------------------------------------|
     * |      |   |   |   |   |   |PgU|Lef|Dow|Rig|   |   |        |
     * |-----------------------------------------------------------|
     * |        |   |   |   |   |   |PgD|   |   |   |   |      |   |
     * `-----------------------------------------------------------'
     *       |   |     |         Space         |     |   |
     *       `-------------------------------------------'
     */
    [VI] = LAYOUT(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_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_UP, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),

    /* SpaceFN Layer (Hold Space)
     * ,-----------------------------------------------------------.
     * |`  | F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
     * |-----------------------------------------------------------|
     * |     |   |   |Esc|   |   |   |Hom|Up |End|PSc|SLk|Pau|     |
     * |-----------------------------------------------------------|
     * |      |   |   |   |   |   |PgU|Lef|Dow|Rig|   |   |        |
     * |-----------------------------------------------------------|
     * |        |   |   |   |   |Spc|PgD|   |   |   |   |      |   |
     * `-----------------------------------------------------------'
     *       |   |     |         Space         |     |   |
     *       `-------------------------------------------'
     */
    [SPACE_FN] = LAYOUT(KC_GRV, 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_TRNS, KC_TRNS, KC_TRNS, KC_ESC, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_UP, KC_END, KC_PSCR, KC_SCRL, KC_PAUS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_SPC, KC_PGDN, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)};

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
        case SPACEFN_TOGGLE:
            if (record->event.pressed) {
                spacefn_enabled = !spacefn_enabled;
                if (!spacefn_enabled) {
                    layer_off(SPACE_FN);
                }
            }
            return false;
        case BT_TOGGLE_KEY:
            if (record->event.pressed) {
                SEND_STRING("$" SS_DELAY(100) "sw");
            }
            return false;
        case BT_PAIR_KEY:
            if (record->event.pressed) {
                SEND_STRING("$" SS_DELAY(100) "pair");
            }
            return false;
        case LT(SPACE_FN, KC_SPC):
            if (spacefn_enabled) {
                return true;
            } else {
                if (record->event.pressed) {
                    register_code(KC_SPC);
                } else {
                    unregister_code(KC_SPC);
                }
                return false;
            }
        default:
            return true;
    }
}
/*
 * 🔧 Usage Guide 🔧
 * ================
 *
 * This keymap combines multiple powerful features:
 *
 * 1. Classic HHKB Layer (Always active)
 *    - Your familiar HHKB layout, untouched in its perfection
 *    - SpaceFN can be toggled on/off using the dedicated key
 *
 * 2. Mouse Control (Hold Semicolon)
 *    - Mouse movement: IJKL
 *    - Mouse buttons: M, <, >
 *    - Wheel: YUIO
 *    - Adjustable speed: ASD
 *
 * 3. VI Navigation (Hold Slash)
 *    - Cursor: HJKL (VI style)
 *    - Page Up/Down, Home/End easily accessible
 *    - Perfect for text editing and coding
 *
 * 4. SpaceFN Features (Hold Space)
 *    - F1-F12 keys in number row
 *    - Navigation cluster around IJKL
 *    - System keys (Print Screen, Scroll Lock, Pause)
 *    - Can be disabled with SpaceFN Toggle key
 *
 * 5. Traditional Fn Layer (Fn Key)
 *    - Standard HHKB function layer
 *    - Media controls
 *    - Arrow keys
 *    - Bluetooth controls:
 *      + Fn + Left Alt: Toggle Bluetooth
 *      + Fn + Z: Pair Bluetooth
 *
 * 💫 Pro Tips:
 * - Use Mouse layer for precise pointer control
 * - VI layer is perfect for code navigation
 * - SpaceFN gives you lightning-fast access to F-keys
 * - Toggle SpaceFN off temporarily when needed
 * - Use Bluetooth controls for quick device switching
 * - Combine layers creatively for maximum efficiency
 *
 * Remember Wada-san's wisdom: mastery takes time, but the results are worth it.
 *
 * Happy Hacking! ⌨
 *
 * Special thanks to Hasu for the original alternate controller
 * and his invaluable help in the geekhack forums.
 *
 * Version: 1.1
 * Author: Pascual Muñoz Galián
 * Source: https://github.com/pascualmg/hhkb-ultimate
 *
 * This keymap is shared with the community in the spirit of
 * open source and the HHKB philosophy. Feel free to modify
 * and improve upon it!
 */

About

The ultimate configuration in the ultimate keyboard .

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published