├── README.md └── juni.lua /README.md: -------------------------------------------------------------------------------- 1 | # Juni Keyboard 2 | 3 | The [Juni Layout](http://wiki.xxiivv.com/Juni) is a **12-keys [chorded keyboard](https://en.wikipedia.org/wiki/Chorded_keyboard)** running on Pimoroni's [Keybow](https://learn.pimoroni.com/keybow). It was designed to be used with the [Orca livecoding environment](http://github.com/hundredrabbits/Orca/), but has most common keys and controls, making it a versatile and portable single-handed keyboard. 4 | 5 | You can see the `juni.lua` in action [here](https://twitter.com/neauoire/status/1112617902270607360). 6 | 7 | 8 | 9 | ## Installation 10 | 11 | Save `juni.lua` into the `/layouts` folder, and modify `keys.lua`, by adding the following line and **comment previously active layouts**: 12 | 13 | ``` 14 | require "layouts/juni" -- 12 Keys Chorded Keyboard 15 | ``` 16 | 17 | ## Layout 18 | 19 | There are **8 input keys**(`in`), and **4 function keys**(`fn`). 20 | 21 | Typing letters & numbers is done by moving across the different layers of the keyboard. 22 | 23 | | row1 | row2 | row3 | row4 | 24 | | :-: | :-: | :-: | :-: | 25 | | in8 `B` | in7 `8` | in6 `5` | in5 `2` | 26 | | in4 `A` | in3 `7` | in2 `4` | in1 `1` | 27 | | fn4 `9` | fn3 `6` | fn2 `3` | fn1 `0` | 28 | 29 | ## Guide 30 | 31 | There are **9 layers in total**, by default, the 8 top keys will input the values of `layer 0`. Layers are navigated by holding down an input key and typing a second key. For instance, holding down `in1`, and then tapping `in8`, will input `w`. To capitalize it, just hold down the `fn4` key, before holding down `in1`, and then tapping `in8`. 32 | 33 | ### Input Layers 34 | 35 | | Layer 0 | Layer 1 | Layer 2 | Layer 3 | Layer 4 | 36 | | :-: | :-: | :-: | :-: | :-: | 37 | | `hsni` | `wmuc` | `kvbp` | `321z` | `0987` | 38 | | `oate` | `ldr*` | `yg*f` | `q*xj` | `*543` | 39 | 40 | ### Special Layers 41 | 42 | #### Layer 5 — Math Layer 43 | 44 | | row1 | row2 | row3 | row4 | 45 | | :-: | :-: | :-: | :-: | 46 | | ? | ? | ? | * | 47 | | `-` | `=` | `/` | `backtick` | 48 | 49 | #### Layer 6 — Punctuation Layer 50 | 51 | | row1 | row2 | row3 | row4 | 52 | | :-: | :-: | :-: | :-: | 53 | | ? | ? | * | ? | 54 | | `;` | `'` | `,` | `.` | 55 | 56 | #### Layer 7 — Brackets Layer 57 | 58 | | row1 | row2 | row3 | row4 | 59 | | :-: | :-: | :-: | :-: | 60 | | `pipe` | * | `<` | `>` | 61 | | `(` | `)` | `[` | `]` | 62 | 63 | #### Layer 8 — Navigation Layer 64 | 65 | | row1 | row2 | row3 | row4 | 66 | | :-: | :-: | :-: | :-: | 67 | | * | `home` | `arrow up` | `end` | 68 | | `escape` | `arrow left` | `arrow down` | `arrow right` | 69 | 70 | ### Functions Keys 71 | 72 | | **fn4** | **fn3** | **fn2** | **fn1** | 73 | | :-: | :-: | :-: | :-: | 74 | | `shift` | `backspace` | `enter` | `space` | 75 | 76 | ### Extras 77 | 78 | - To use capslock, double-tap **fn4**. 79 | - To use delete, instead of backspace, hold **fn4** and tap **fn3**. 80 | - To input a tab, hold **fn4** and tap **fn1**. 81 | - To input curlies, use the sequences **fn4 + in7 + in2**, and **fn4 + in7 + in1**. 82 | 83 | ### TODOs 84 | 85 | - Implement `Meta/Ctrl` keys. 86 | - Allow for key repeat for layered inputs. 87 | 88 | 89 | -------------------------------------------------------------------------------- /juni.lua: -------------------------------------------------------------------------------- 1 | require "keybow" 2 | 3 | local layer = 0 4 | local last_key = nil 5 | local shift_key = false 6 | 7 | function setup() 8 | keybow.auto_lights(false) 9 | keybow.clear_lights() 10 | end 11 | 12 | template = { 13 | {}, 14 | {"e", "_", "f", "j", "4", "`", ".", "]", "$ar"}, -- 01 15 | {"i", "c", "p", "z", "7", "_", "?", ">", "$je"}, -- 02 16 | {}, 17 | {"t", "r", "_", "x", "5", "/", ",", "[", "$ad"}, -- 04 18 | {"n", "u", "b", "1", "8", "?", "_", "<", "$au"}, -- 05 19 | {}, 20 | {"a", "d", "g", "_", "6", "=", "'", ")", "$al"}, -- 07 21 | {"s", "m", "v", "2", "9", "?", "?", "_", "$jh"}, -- 08 22 | {}, 23 | {"o", "l", "y", "q", "_", "-", ";", "(", "$es"}, -- 10 24 | {"h", "w", "k", "3", "0", "?", "?", "|", "_"}, -- 11 25 | {} 26 | } 27 | 28 | function input(key,mod,pressed) 29 | if pressed == true then 30 | key_down(key,mod) 31 | else 32 | key_up(key,mod) 33 | end 34 | update_lights() 35 | end 36 | 37 | function key_down(key,mod) 38 | push_layer(mod) 39 | last_key = key 40 | end 41 | 42 | function key_up(key,mod) 43 | pop_layer(mod) 44 | -- Letters 45 | if key == last_key then 46 | ch = get_char(key,layer) 47 | -- Arrows 48 | if ch == "$au" then keybow.tap_key(keybow.UP_ARROW) ; return end 49 | if ch == "$ad" then keybow.tap_key(keybow.DOWN_ARROW) ; return end 50 | if ch == "$al" then keybow.tap_key(keybow.LEFT_ARROW) ; return end 51 | if ch == "$ar" then keybow.tap_key(keybow.RIGHT_ARROW) ; return end 52 | if ch == "$jh" then keybow.tap_key(keybow.HOME) ; return end 53 | if ch == "$je" then keybow.tap_key(keybow.END) ; return end 54 | if ch == "$es" then keybow.tap_key(keybow.ESC) ; return end 55 | -- Sends 56 | send(ch) 57 | end 58 | end 59 | 60 | function get_char(key,layer) 61 | return template[key+1][layer+1] 62 | end 63 | 64 | function push_layer(id) 65 | if layer > 0 then return end 66 | if layer == id then return end 67 | layer = id 68 | 69 | end 70 | 71 | function pop_layer(id) 72 | if id ~= layer then return end 73 | layer = 0 74 | end 75 | 76 | function send(ch) 77 | keybow.tap_key(ch) 78 | end 79 | 80 | function update_lights() 81 | keybow.clear_lights() 82 | if layer > 0 then 83 | keybow.set_pixel(layer_key(layer), 255, 255, 255) 84 | end 85 | if shift_key == true then 86 | keybow.set_pixel(9, 255, 0, 0) 87 | end 88 | end 89 | 90 | function layer_key(layer) 91 | if layer == 1 then return 1 end 92 | if layer == 2 then return 4 end 93 | if layer == 3 then return 7 end 94 | if layer == 4 then return 10 end 95 | if layer == 5 then return 2 end 96 | if layer == 6 then return 5 end 97 | if layer == 7 then return 8 end 98 | if layer == 8 then return 11 end 99 | return 0 100 | end 101 | 102 | -- Map -- 103 | 104 | -- TOP 11 08 05 02 -- 105 | -- MID 10 07 04 01 -- 106 | -- LOW 09 06 03 00 -- 107 | 108 | -- Top -- 109 | 110 | function handle_key_11(pressed) 111 | input(11, 8, pressed) 112 | end 113 | 114 | function handle_key_08(pressed) 115 | input(8, 7, pressed) 116 | end 117 | 118 | function handle_key_05(pressed) 119 | input(5, 6, pressed) 120 | end 121 | 122 | function handle_key_02(pressed) 123 | input(2, 5, pressed) 124 | end 125 | 126 | -- Mid -- 127 | 128 | function handle_key_10(pressed) 129 | input(10, 4, pressed) 130 | end 131 | 132 | function handle_key_07(pressed) 133 | input(7, 3, pressed) 134 | end 135 | 136 | function handle_key_04(pressed) 137 | input(4, 2, pressed) 138 | end 139 | 140 | function handle_key_01(pressed) 141 | input(1, 1, pressed) 142 | end 143 | 144 | -- Low -- 145 | 146 | function handle_key_09(pressed) 147 | if pressed == true then 148 | keybow.set_modifier(keybow.LEFT_SHIFT, keybow.KEY_DOWN) 149 | else 150 | keybow.set_modifier(keybow.LEFT_SHIFT, keybow.KEY_UP) 151 | end 152 | shift_key = pressed 153 | update_lights() 154 | end 155 | 156 | function handle_key_06(pressed) 157 | if shift_key == true then 158 | keybow.set_key(keybow.DELETE, pressed) 159 | else 160 | keybow.set_key(keybow.BACKSPACE, pressed) 161 | end 162 | end 163 | 164 | function handle_key_03(pressed) 165 | keybow.set_key(keybow.ENTER, pressed) 166 | end 167 | 168 | function handle_key_00(pressed) 169 | if shift_key == true then 170 | keybow.set_key(keybow.TAB, pressed) 171 | else 172 | keybow.set_key(keybow.SPACE, pressed) 173 | end 174 | end --------------------------------------------------------------------------------