Iris Keyboard Followup

After a couple months of using the iris keyboard, I’ve stabilized on a hardware and software configuraiton that I’m very happy with.

Keyboard Tenting

There’s many options for tenting an iris keyboard. The most common is to use a custom midlayer, often with support for ergodox-style legs. Some people also use a 3d printed base to set the keyboard on top of. I wanted to have a steeper angle than ergodox, and also to have flexibility in amount of tenting. I also like the open look of the keyboard, so didn’t want to use a mid layer.

Initially, I simply picked up some display wire stands and they worked surprisingly well. These specific ones are Gibson Holders, the 1ab model, and were a few bucks on Amazon.

Recently, I discovered a better solution. The Iris plates are joined via M2 standoffs with screws on either end. I simply bought some M2 male-female standoffs, and replaced the screws on the bottom side. Currently each of the 4 legs is using 2 x 25mm standoffs. I found that there was some very minor differences in length, causing the keyboard not to sit totally flat, but using a desk mat completely solves that, and also prevents scratching up my desk.

QMK Configuration

QMK is the software I use to configure the Iris. My goal is to keep a configuration similar to a standard keyboard, but provide easier access to common programming symbols (e.g. brackets, math symbols). The Iris has 3 thumb keys per side, and as a heavy emacs user, I want alt and ctrl available on both sides, so the 2 thumb keys in the most similar positions to those keys on a standard keyboard are assigned to alt and ctrl. This leaves 1 thumb key remaining per hand. Since I only use the left hand for space bar, I made the remaining left thumb key space, and the remaining right thumb key enter (the Iris is 6 keys wide, so no traditional enter location).

Besides simply assigning keys, QMK has 2 useful features we take advantage of. The first is the concept of layers, where keys have different behaviors depending on which “layer” the keyboard is currently in. (E.g. shift is a layer that produces upper case letters). Second, QMK allows different behaviors when a key is tapped vs. held down. I have a layer called RAISE that is reachable by holding down the enter key. In the raise layer, the left hand can type each of these symbols on or near home row position: +=-_[]{}\~`. On the right hand, I have arrow keys available, as well as LED controls. The number keys also become the F keys in this layer.

The Iris actually has a 4th thumb key available on both sides, above the other 3, though it’s more awkward to reach. On the left, I’ve replaced this key with a rotary encoder, which adjusts volume, and pushing it down mutes/unmutes. On the right, the key toggles the keyboard LEDs.

Here’s the full keymap file:

#include QMK_KEYBOARD_H

enum layers {
  QWERTY,
  RAISE
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

  [QWERTY] = LAYOUT(
  //┌────────┬────────┬────────┬────────┬────────┬────────┐                          ┌────────┬────────┬────────┬────────┬────────┬────────┐
     KC_ESC,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,                               KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_BSPC,
  //├────────┼────────┼────────┼────────┼────────┼────────┤                          ├────────┼────────┼────────┼────────┼────────┼────────┤
     KC_TAB,  KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,                               KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSLS,
  //├────────┼────────┼────────┼────────┼────────┼────────┤                          ├────────┼────────┼────────┼────────┼────────┼────────┤
     KC_BSPC, KC_A,    KC_S,    KC_D,    KC_F,    KC_G,                               KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,
  //├────────┼────────┼────────┼────────┼────────┼────────┼────────┐        ┌────────┼────────┼────────┼────────┼────────┼────────┼────────┤
     KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_MUTE,          RGB_TOG, KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_RSFT,
  //└────────┴────────┴────────┴───┬────┴───┬────┴───┬────┴───┬────┘        └───┬────┴───┬────┴───┬────┴───┬────┴────────┴────────┴────────┘
                                    KC_LCTL, KC_LALT, KC_SPC,           LT(RAISE, KC_ENT), KC_RALT, KC_RCTL
                                // └────────┴────────┴────────┘                 └────────┴────────┴────────┘
  ),

  [RAISE] = LAYOUT(
  //┌────────┬────────┬────────┬────────┬────────┬────────┐                          ┌────────┬────────┬────────┬────────┬────────┬────────┐
     KC_F12,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,                              KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,
  //├────────┼────────┼────────┼────────┼────────┼────────┤                          ├────────┼────────┼────────┼────────┼────────┼────────┤
     _______,  KC_PLUS, KC_EQL,  KC_MINS, KC_UNDS, _______,                            _______, _______, KC_UP,   _______, _______, _______,
  //├────────┼────────┼────────┼────────┼────────┼────────┤                          ├────────┼────────┼────────┼────────┼────────┼────────┤
     KC_DEL,  KC_LBRC, KC_RBRC, KC_LCBR, KC_RCBR, _______,                            _______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______,
  //├────────┼────────┼────────┼────────┼────────┼────────┼────────┐        ┌────────┼────────┼────────┼────────┼────────┼────────┼────────┤
     KC_LGUI, KC_TILD,  KC_GRV, _______, _______, _______, _______,          RGB_MOD, RGB_HUI, RGB_SAI, RGB_VAI, _______, _______, _______,
  //└────────┴────────┴────────┴───┬────┴───┬────┴───┬────┴───┬────┘        └───┬────┴───┬────┴───┬────┴───┬────┴────────┴────────┴────────┘
                                    _______, _______, _______,                   _______, _______, _______
                                // └────────┴────────┴────────┘                 └────────┴────────┴────────┘
  )
};

void encoder_update_user(uint8_t index, bool clockwise) {
    if (index == 0) {
        if (clockwise) {
            tap_code(KC_VOLU);
        } else {
            tap_code(KC_VOLD);
        }
    }
}