mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-27 03:21:15 +00:00
Merge 165a41515b
into 36c3f4deba
This commit is contained in:
commit
b416c676a7
6
keyboards/model_f_labs/f62/info.json
Normal file
6
keyboards/model_f_labs/f62/info.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"manufacturer": "Model F Labs",
|
||||||
|
"keyboard_name": "Reproduction IBM F62 Keyboard",
|
||||||
|
"maintainer": "Purdea Andrei",
|
||||||
|
"url": "https://www.modelfkeyboards.com/"
|
||||||
|
}
|
87
keyboards/model_f_labs/f62/keymaps/default/keymap.c
Normal file
87
keyboards/model_f_labs/f62/keymaps/default/keymap.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* Copyright 2022 Matthew J Wolf
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
* -----
|
||||||
|
* Based on F62_-_HHKB_-_Split_Backspace.json from Joe of Model F Labs
|
||||||
|
*/
|
||||||
|
/* all
|
||||||
|
* - Base
|
||||||
|
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||||
|
* │Esc│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + │ \ │ ` │
|
||||||
|
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤
|
||||||
|
* │Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │Bspc │
|
||||||
|
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬────│
|
||||||
|
* │Lctl │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ # │Ent │
|
||||||
|
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴┬───┤
|
||||||
|
* │Lsft│ \ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ Rsft │Fn1│
|
||||||
|
* ├────┴┬──┴┬──┴──┬┴───┴───┴───┴───┴───┴─┬─┴──┬┴───┴┬───┬─┴───┤
|
||||||
|
* │Caps │GUI│Lalt │ Space │ │Ratl │Nlk│Rctl │
|
||||||
|
* └─────┴───┴─────┴──────────────────────┴────┴─────┴───┴─────┘
|
||||||
|
* - FN1
|
||||||
|
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||||
|
* │ ` │F1 │F2 │F3 │F4 │F5 │F6 │F7 │F8 │F9 │F10│F11│F12│Ins│Del│
|
||||||
|
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤
|
||||||
|
* │ │ │ │ │ │ │ │ │Psc│Skl│Pau│Up │ │Del │
|
||||||
|
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬────│
|
||||||
|
* │ │Vo-│Vo+│Mut│Ejc│ │Kp*│Kp/│Hom│PGu│Lef│Rgh│ │ │
|
||||||
|
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴┬───┤
|
||||||
|
* │ │ │ │ │ │ │ │Kp+│Kp-│End│PGd│Dow│ │ │
|
||||||
|
* ├────┴┬──┴┬──┴──┬┴───┴───┴───┴───┴───┴─┬─┴──┬┴───┴┬───┬─┴───┤
|
||||||
|
* │ │ │ │ Fn2 │ │ │ │ │
|
||||||
|
* └─────┴───┴─────┴──────────────────────┴────┴─────┴───┴─────┘
|
||||||
|
* - FN2
|
||||||
|
* ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
|
||||||
|
* │ │ │ │ │ │ │ │ │ │ │ │Dl-│Dl+│ │ │
|
||||||
|
* ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤
|
||||||
|
* │ │ │ │Epr│Res│HPt│ │ │ │ │ │ │ │ │
|
||||||
|
* ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬────│
|
||||||
|
* │ │ │ │Deb│ │ │ │ │ │ │ │ │ │ │
|
||||||
|
* ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴┬───┤
|
||||||
|
* │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
|
||||||
|
* ├────┴┬──┴┬──┴──┬┴───┴───┴───┴───┴───┴─┬─┴──┬┴───┴┬───┬─┴───┤
|
||||||
|
* │ │ │ │ │ │ │ │ │
|
||||||
|
* └─────┴───┴─────┴──────────────────────┴────┴─────┴───┴─────┘
|
||||||
|
*/
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
enum layer_names {
|
||||||
|
_BASE,
|
||||||
|
_FN1,
|
||||||
|
_FN2
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[_BASE] = LAYOUT_all(
|
||||||
|
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_NUHS, KC_ENT,
|
||||||
|
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(_FN1),
|
||||||
|
KC_CAPS, KC_LGUI, KC_LALT, KC_SPC, _______, KC_RALT, KC_NUM, KC_RCTL
|
||||||
|
),
|
||||||
|
[_FN1] = LAYOUT_all(
|
||||||
|
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_PSCR, KC_SCRL, KC_PAUS, KC_UP, _______, KC_DEL,
|
||||||
|
_______, KC_VOLD, KC_VOLU, KC_MUTE, KC_EJCT, _______, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, _______, _______,
|
||||||
|
_______, _______, _______, MO(_FN2), _______, _______, _______, _______
|
||||||
|
),
|
||||||
|
[_FN2] = LAYOUT_all(
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, HF_DWLD,HF_DWLU, _______, _______,
|
||||||
|
_______, _______, _______, EE_CLR, QK_BOOT, HF_TOGG, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, DB_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______
|
||||||
|
)
|
||||||
|
};
|
3
keyboards/model_f_labs/f62/keymaps/default/readme.md
Normal file
3
keyboards/model_f_labs/f62/keymaps/default/readme.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# A keymap for model_f_labs/f62/$(CONTROLLER)
|
||||||
|
|
||||||
|
Keymap for the HHKB Split Shift and Split Backspace.
|
36
keyboards/model_f_labs/f62/readme.md
Normal file
36
keyboards/model_f_labs/f62/readme.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# model_f_labs/f62
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Model F Labs recreation of the IBM F62 keyboard. The keyboard uses the IBM
|
||||||
|
"type F" bucking spring key switch.
|
||||||
|
|
||||||
|
* Keyboard Maintainer: [Purdea Andrei](https://github.com/purdeaandrei)
|
||||||
|
* Build Maintainer: Matthew J Wolf
|
||||||
|
* Hardware Supported: Supports the brand new Model F reproductions from https://www.modelfkeyboards.com/, using the smaller xwhatsit controller developed by wcass.
|
||||||
|
* Hardware Availability: https://www.modelfkeyboards.com/
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make model_f_labs/f62/wcass:default
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm//getting_started_build_tools) and the [make instructions](https://docs.qmk.fm//getting_started_make_guide) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
## How do you enter the boot loader?
|
||||||
|
|
||||||
|
There are three ways to enter the boot loader.
|
||||||
|
* **Command**: At the same time hold down both shift key and the B key.
|
||||||
|
Left Shift + Right Shift + B
|
||||||
|
* **Keycode in Layout**: Press the key mapped to `QK_BOOT`.
|
||||||
|
The default location is the R key on the second layer.
|
||||||
|
FN + Spacebar + R
|
||||||
|
* **Physical Reset PCB Pad**: Short pads of the PCB.
|
||||||
|
The description and image below are from the
|
||||||
|
Model F Labs manual web page.
|
||||||
|
|
||||||
|
At the very worst you have to open up the keyboard to short PROG on the actual xwhatsit controller (unscrew the 2 controller screws to see the components side of the board, make a connection with a conductive metal object like an uncoated metal paper clip, then connect the USB cable to the controller and within a split second remove the paper clip). Per pandrew: “You might think that a screwdriver is gonna be enough, but due to surface oxidation it is likely not gonna be good enough. I like to use sharp metal tweezers, because they can dig into the pad a little bit, breaking up the surface oxidation, and I can actually be sure it’s shorting. Apply constant strong pressure on the pads while plugging in the keyboard to make sure they’re perfectly shorted. If you hear the windows USB plug-in sound (assuming the sound effect is enabled), then you know you have succeeded. I’ve even seen people tell me they tried everything to short the pads with, and then I asked them to solder the pads together and it suddenly works. There’s something about the size of those pads, or about the fact that they need to be shorted in the perfect moment when the chip leaves reset, that make people think they are perfectly shorted and yet they aren’t. This affects me too, sometimes it takes me up to 3 tries to get it into bootloader mode. Another thing to double check that you are indeed shorting the PROG pad and not the reset pad. I believe in some versions of the wcass controller there is a reset pad on the opposite side of the board. So don’t be like ‘I see some pads, those must be it’, make sure to be shorting the correct ones.” [1]
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. “Brand New Model F and Beam Spring keyboards manual,” Brand New Model F Keyboards, https://www.modelfkeyboards.com/manual/ (accessed Mar. 16, 2024).
|
117
keyboards/model_f_labs/f62/wcass/config.h
Normal file
117
keyboards/model_f_labs/f62/wcass/config.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Purdea Andrei
|
||||||
|
Copyright 2021-2023 Matthew J Wolf
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
/* key matrix size */
|
||||||
|
#define MATRIX_ROWS 8
|
||||||
|
#define MATRIX_COLS 9
|
||||||
|
// Note: physical column are 16, but only 11 are ever used. Column 0..9 match the physical column. Column 10 is physical column 15.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feature disable options
|
||||||
|
* These options are also useful to firmware size reduction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HOLD_ON_OTHER_KEY_PRESS
|
||||||
|
|
||||||
|
/* XWHATSIT CONTROLLER TYPE */
|
||||||
|
#define CONTROLLER_IS_XWHATSIT_MODEL_F_OR_WCASS_MODEL_F
|
||||||
|
|
||||||
|
#define CAPSENSE_KEYBOARD_SETTLE_TIME_US 8
|
||||||
|
#define CAPSENSE_DAC_SETTLE_TIME_US 8
|
||||||
|
#define CAPSENSE_HARDCODED_SAMPLE_TIME 4
|
||||||
|
|
||||||
|
#define CAPSENSE_CAL_ENABLED 1
|
||||||
|
#define CAPSENSE_CAL_DEBUG 0
|
||||||
|
#define CAPSENSE_CAL_INIT_REPS 16
|
||||||
|
#define CAPSENSE_CAL_EACHKEY_REPS 16
|
||||||
|
#define CAPSENSE_CAL_BINS 5
|
||||||
|
#define CAPSENSE_CAL_THRESHOLD_OFFSET 24
|
||||||
|
|
||||||
|
#if !CAPSENSE_CAL_ENABLED
|
||||||
|
#define CAPSENSE_HARDCODED_THRESHOLD 142
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col) (((col) == 8)?15:(col))
|
||||||
|
|
||||||
|
// By default we set up for support of xwhatsit's solenoid driver board.
|
||||||
|
// Comment out HAPTIC_ENABLE_PIN if you don't have an enable pin:
|
||||||
|
#define HAPTIC_ENABLE_PIN B7
|
||||||
|
// We disable haptic feedbeck during USB low power conditions:
|
||||||
|
#define HAPTIC_OFF_IN_LOW_POWER 1
|
||||||
|
// Change this if you are using a different pin for the solenoid:
|
||||||
|
#define SOLENOID_PIN B6
|
||||||
|
// If you are not using a solenoid then comment out the above, and also in rules.mk, remove "HAPTIC_ENABLE += SOLENOID"
|
||||||
|
// You can also tune the following for your solenoid:
|
||||||
|
#define SOLENOID_DEFAULT_DWELL 4
|
||||||
|
#define SOLENOID_MIN_DWELL 4
|
||||||
|
#define NO_HAPTIC_MOD
|
||||||
|
|
||||||
|
// ----- xwhatsit hardware configuration (type_f) -----
|
||||||
|
|
||||||
|
#define CAPSENSE_DAC_SCLK B1
|
||||||
|
#define CAPSENSE_DAC_DIN B2
|
||||||
|
#define CAPSENSE_DAC_SYNC_N B0
|
||||||
|
#define CAPSENSE_DAC_MAX 1023
|
||||||
|
|
||||||
|
#define CAPSENSE_SHIFT_DIN D4
|
||||||
|
#define CAPSENSE_SHIFT_OE D5
|
||||||
|
#define CAPSENSE_SHIFT_SHCP D7
|
||||||
|
#define CAPSENSE_SHIFT_STCP D6
|
||||||
|
#define CAPSENSE_SHIFT_STCP_IO _SFR_IO_ADDR(PORTD)
|
||||||
|
#define CAPSENSE_SHIFT_STCP_BIT 6
|
||||||
|
|
||||||
|
#define SETUP_ROW_GPIOS() \
|
||||||
|
do { \
|
||||||
|
PORTC |= 0xF0; \
|
||||||
|
PORTD |= 0x0F; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SETUP_UNUSED_PINS() do {} while (0)
|
||||||
|
|
||||||
|
#define CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE 2
|
||||||
|
#define CAPSENSE_READ_ROWS_PIN_1 _SFR_IO_ADDR(PINC)
|
||||||
|
#define CAPSENSE_READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND)
|
||||||
|
#define CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]"
|
||||||
|
#define CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS \
|
||||||
|
"st %a[arr]+, %[dest_row_1]" "\n\t" \
|
||||||
|
"st %a[arr]+, %[dest_row_2]"
|
||||||
|
#define CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS_FAKE \
|
||||||
|
"st %a[arr], %[dest_row_1]" "\n\t" \
|
||||||
|
"st %a[arr], %[dest_row_2]"
|
||||||
|
#define CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2)
|
||||||
|
#define CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (CAPSENSE_READ_ROWS_PIN_1), [ioreg_row_2] "I" (CAPSENSE_READ_ROWS_PIN_2)
|
||||||
|
#define CAPSENSE_READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2
|
||||||
|
#define CAPSENSE_READ_ROWS_EXTRACT_FROM_ARRAY do { dest_row_1 = array[p0++]; dest_row_2 = array[p0++]; } while (0)
|
||||||
|
|
||||||
|
#if (!defined(CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS)) && (!defined(CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS))
|
||||||
|
#define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
|
||||||
|
#endif
|
||||||
|
#define CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row) (7-(row))
|
||||||
|
#define CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row) (7-(row))
|
||||||
|
#define CAPSENSE_READ_ROWS_VALUE ((dest_row_1 >> 4) | (dest_row_2 << 4))
|
629
keyboards/model_f_labs/f62/wcass/keyboard.json
Normal file
629
keyboards/model_f_labs/f62/wcass/keyboard.json
Normal file
@ -0,0 +1,629 @@
|
|||||||
|
{
|
||||||
|
"bootloader": "atmel-dfu",
|
||||||
|
"build": {
|
||||||
|
"lto": true
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"backlight": false,
|
||||||
|
"bootmagic": false,
|
||||||
|
"command": true,
|
||||||
|
"console": false,
|
||||||
|
"extrakey": true,
|
||||||
|
"haptic": true,
|
||||||
|
"mousekey": true,
|
||||||
|
"nkro": true,
|
||||||
|
"raw": true,
|
||||||
|
"rgblight": false
|
||||||
|
},
|
||||||
|
"indicators": {
|
||||||
|
"caps_lock": "B5",
|
||||||
|
"num_lock": "B4"
|
||||||
|
},
|
||||||
|
"processor": "atmega32u2",
|
||||||
|
"usb": {
|
||||||
|
"device_version": "0.0.1",
|
||||||
|
"pid": "0x6262",
|
||||||
|
"vid": "0x1209"
|
||||||
|
},
|
||||||
|
"community_layouts": [
|
||||||
|
"60_ansi_tsangan",
|
||||||
|
"60_ansi_tsangan_split_bs_rshift",
|
||||||
|
"60_iso_tsangan",
|
||||||
|
"60_iso_tsangan_split_bs_rshift"
|
||||||
|
],
|
||||||
|
"layouts": {
|
||||||
|
"LAYOUT_all": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "|`", "matrix": [4, 7], "x": 13, "y": 0},
|
||||||
|
{"label": "~", "matrix": [6, 7], "x": 14, "y": 0},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "Backspace", "matrix": [7, 7], "x": 13.5, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Ctrl", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "#", "matrix": [7, 6], "x": 12.75, "y": 2},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 13.75, "y": 2, "w": 1.25},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 1.25},
|
||||||
|
{"label": "\\", "matrix": [0, 0], "x": 1.25, "y": 3},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [0, 7], "x": 12.25, "y": 3, "w": 1.75},
|
||||||
|
{"label": "Fn", "matrix": [1, 7], "x": 14, "y": 3},
|
||||||
|
{"label": "Caps Lock", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 6},
|
||||||
|
{"label": "K44", "matrix": [3, 6], "x": 10, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_ansi_tsangan": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "Backspace", "matrix": [6, 7], "x": 13, "y": 0, "w": 2},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "\\|", "matrix": [7, 7], "x": 13.5, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Caps Lock", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 12.75, "y": 2, "w": 2.25},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 2.25},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [1, 7], "x": 12.25, "y": 3, "w": 2.75},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Fn", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_ansi_tsangan_split_bs": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "`~", "matrix": [4, 7], "x": 13, "y": 0},
|
||||||
|
{"label": "Backspace", "matrix": [6, 7], "x": 14, "y": 0},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "\\|", "matrix": [7, 7], "x": 13.5, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Caps Lock", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 12.75, "y": 2, "w": 2.25},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 2.25},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [1, 7], "x": 12.25, "y": 3, "w": 2.75},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Fn", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_ansi_tsangan_split_rshift": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "Backspace", "matrix": [6, 7], "x": 13, "y": 0, "w": 2},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "\\|", "matrix": [7, 7], "x": 13.5, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Ctrl", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 12.75, "y": 2, "w": 2.25},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 2.25},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [0, 7], "x": 12.25, "y": 3, "w": 1.75},
|
||||||
|
{"label": "Fn", "matrix": [1, 7], "x": 14, "y": 3},
|
||||||
|
{"label": "Caps Lock", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_ansi_tsangan_split_bs_rshift": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "|`", "matrix": [4, 7], "x": 13, "y": 0},
|
||||||
|
{"label": "~", "matrix": [6, 7], "x": 14, "y": 0},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "Backspace", "matrix": [7, 7], "x": 13.5, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Ctrl", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 12.75, "y": 2, "w": 2.25},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 2.25},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [0, 7], "x": 12.25, "y": 3, "w": 1.75},
|
||||||
|
{"label": "Fn", "matrix": [1, 7], "x": 14, "y": 3},
|
||||||
|
{"label": "Caps Lock", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_iso_tsangan": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "Backspace", "matrix": [6, 7], "x": 13, "y": 0, "w": 2},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
|
||||||
|
{"label": "Caps Lock", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "nuhs", "matrix": [7, 6], "x": 12.75, "y": 2},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 1.25},
|
||||||
|
{"label": "nubs", "matrix": [0, 0], "x": 1.25, "y": 3},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [1, 7], "x": 12.25, "y": 3, "w": 2.75},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Fn", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_iso_tsangan_split_bs": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "`~", "matrix": [4, 7], "x": 13, "y": 0},
|
||||||
|
{"label": "Backspace", "matrix": [6, 7], "x": 14, "y": 0},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
|
||||||
|
{"label": "Caps Lock", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "nuhs", "matrix": [7, 6], "x": 12.75, "y": 2},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 1.25},
|
||||||
|
{"label": "nubs", "matrix": [0, 0], "x": 1.25, "y": 3},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [1, 7], "x": 12.25, "y": 3, "w": 2.75},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Fn", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_iso_tsangan_split_rshift": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "Backspace", "matrix": [6, 7], "x": 13, "y": 0, "w": 2},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
|
||||||
|
{"label": "Ctrl", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "nuhs", "matrix": [7, 6], "x": 12.75, "y": 2},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 1.25},
|
||||||
|
{"label": "nubs", "matrix": [0, 0], "x": 1.25, "y": 3},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [0, 7], "x": 12.25, "y": 3, "w": 1.75},
|
||||||
|
{"label": "Fn", "matrix": [1, 7], "x": 14, "y": 3},
|
||||||
|
{"label": "Caps Lock", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LAYOUT_60_iso_tsangan_split_bs_rshift": {
|
||||||
|
"layout": [
|
||||||
|
{"label": "Esc", "matrix": [4, 0], "x": 0, "y": 0},
|
||||||
|
{"label": "!", "matrix": [6, 0], "x": 1, "y": 0},
|
||||||
|
{"label": "@", "matrix": [6, 1], "x": 2, "y": 0},
|
||||||
|
{"label": "#", "matrix": [4, 2], "x": 3, "y": 0},
|
||||||
|
{"label": "$", "matrix": [6, 2], "x": 4, "y": 0},
|
||||||
|
{"label": "%", "matrix": [4, 3], "x": 5, "y": 0},
|
||||||
|
{"label": "^", "matrix": [6, 3], "x": 6, "y": 0},
|
||||||
|
{"label": "&", "matrix": [4, 4], "x": 7, "y": 0},
|
||||||
|
{"label": "*", "matrix": [6, 4], "x": 8, "y": 0},
|
||||||
|
{"label": "(", "matrix": [4, 5], "x": 9, "y": 0},
|
||||||
|
{"label": ")", "matrix": [6, 5], "x": 10, "y": 0},
|
||||||
|
{"label": "_", "matrix": [4, 6], "x": 11, "y": 0},
|
||||||
|
{"label": "+", "matrix": [6, 6], "x": 12, "y": 0},
|
||||||
|
{"label": "|`", "matrix": [4, 7], "x": 13, "y": 0},
|
||||||
|
{"label": "~", "matrix": [6, 7], "x": 14, "y": 0},
|
||||||
|
{"label": "Tab", "matrix": [5, 0], "x": 0, "y": 1, "w": 1.5},
|
||||||
|
{"label": "Q", "matrix": [4, 1], "x": 1.5, "y": 1},
|
||||||
|
{"label": "W", "matrix": [5, 1], "x": 2.5, "y": 1},
|
||||||
|
{"label": "E", "matrix": [7, 2], "x": 3.5, "y": 1},
|
||||||
|
{"label": "R", "matrix": [5, 2], "x": 4.5, "y": 1},
|
||||||
|
{"label": "T", "matrix": [7, 3], "x": 5.5, "y": 1},
|
||||||
|
{"label": "Y", "matrix": [5, 3], "x": 6.5, "y": 1},
|
||||||
|
{"label": "U", "matrix": [7, 4], "x": 7.5, "y": 1},
|
||||||
|
{"label": "I", "matrix": [5, 4], "x": 8.5, "y": 1},
|
||||||
|
{"label": "O", "matrix": [7, 5], "x": 9.5, "y": 1},
|
||||||
|
{"label": "P", "matrix": [5, 5], "x": 10.5, "y": 1},
|
||||||
|
{"label": "{", "matrix": [5, 6], "x": 11.5, "y": 1},
|
||||||
|
{"label": "}", "matrix": [5, 7], "x": 12.5, "y": 1},
|
||||||
|
{"label": "Enter", "matrix": [2, 7], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
|
||||||
|
{"label": "Ctrl", "matrix": [7, 0], "x": 0, "y": 2, "w": 1.75},
|
||||||
|
{"label": "A", "matrix": [7, 1], "x": 1.75, "y": 2},
|
||||||
|
{"label": "S", "matrix": [2, 1], "x": 2.75, "y": 2},
|
||||||
|
{"label": "D", "matrix": [0, 2], "x": 3.75, "y": 2},
|
||||||
|
{"label": "F", "matrix": [2, 2], "x": 4.75, "y": 2},
|
||||||
|
{"label": "G", "matrix": [0, 3], "x": 5.75, "y": 2},
|
||||||
|
{"label": "H", "matrix": [2, 3], "x": 6.75, "y": 2},
|
||||||
|
{"label": "J", "matrix": [2, 4], "x": 7.75, "y": 2},
|
||||||
|
{"label": "K", "matrix": [0, 4], "x": 8.75, "y": 2},
|
||||||
|
{"label": "L", "matrix": [0, 5], "x": 9.75, "y": 2},
|
||||||
|
{"label": ":", "matrix": [2, 5], "x": 10.75, "y": 2},
|
||||||
|
{"label": "\"", "matrix": [2, 6], "x": 11.75, "y": 2},
|
||||||
|
{"label": "nuhs", "matrix": [7, 6], "x": 12.75, "y": 2},
|
||||||
|
{"label": "Shift", "matrix": [2, 0], "x": 0, "y": 3, "w": 1.25},
|
||||||
|
{"label": "nubs", "matrix": [0, 0], "x": 1.25, "y": 3},
|
||||||
|
{"label": "Z", "matrix": [1, 1], "x": 2.25, "y": 3},
|
||||||
|
{"label": "X", "matrix": [0, 1], "x": 3.25, "y": 3},
|
||||||
|
{"label": "C", "matrix": [1, 2], "x": 4.25, "y": 3},
|
||||||
|
{"label": "V", "matrix": [3, 2], "x": 5.25, "y": 3},
|
||||||
|
{"label": "B", "matrix": [1, 3], "x": 6.25, "y": 3},
|
||||||
|
{"label": "N", "matrix": [1, 4], "x": 7.25, "y": 3},
|
||||||
|
{"label": "M", "matrix": [3, 4], "x": 8.25, "y": 3},
|
||||||
|
{"label": "<", "matrix": [3, 5], "x": 9.25, "y": 3},
|
||||||
|
{"label": ">", "matrix": [1, 5], "x": 10.25, "y": 3},
|
||||||
|
{"label": "?", "matrix": [0, 6], "x": 11.25, "y": 3},
|
||||||
|
{"label": "Shift", "matrix": [0, 7], "x": 12.25, "y": 3, "w": 1.75},
|
||||||
|
{"label": "Fn", "matrix": [1, 7], "x": 14, "y": 3},
|
||||||
|
{"label": "Caps Lock", "matrix": [3, 0], "x": 0, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K41", "matrix": [1, 0], "x": 1.5, "y": 4},
|
||||||
|
{"label": "Alt", "matrix": [3, 1], "x": 2.5, "y": 4, "w": 1.5},
|
||||||
|
{"label": "K43", "matrix": [3, 3], "x": 4, "y": 4, "w": 7},
|
||||||
|
{"label": "Alt", "matrix": [1, 6], "x": 11, "y": 4, "w": 1.5},
|
||||||
|
{"label": "Num Lock", "matrix": [3, 7], "x": 12.5, "y": 4},
|
||||||
|
{"label": "Ctrl", "matrix": [3, 8], "x": 13.5, "y": 4, "w": 1.5}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
keyboards/model_f_labs/f62/wcass/readme.md
Normal file
38
keyboards/model_f_labs/f62/wcass/readme.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# model_f_labs/f62/wcass
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Model F Labs recreation of the IBM F62 keyboard. The keyboard uses the IBM
|
||||||
|
"type F" bucking spring key switch.
|
||||||
|
|
||||||
|
The keyboard is using the community developed wcass controller.
|
||||||
|
|
||||||
|
* Keyboard Maintainer: [Purdea Andrei](https://github.com/purdeaandrei)
|
||||||
|
* Hardware Supported: Supports the brand new Model F reproductions from https://www.modelfkeyboards.com/, using the smaller xwhatsit controller developed by wcass.
|
||||||
|
* Hardware Availability: https://www.modelfkeyboards.com/
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make model_f_labs/f62/wcass:default
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/getting_started_make_guide) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
## How do you enter the boot loader?
|
||||||
|
|
||||||
|
There are three ways to enter the boot loader.
|
||||||
|
* **Command**: At the same time hold down both shift key and the B key.
|
||||||
|
Left Shift + Right Shift + B
|
||||||
|
* **Keycode in Layout**: Press the key mapped to `QK_BOOT`.
|
||||||
|
The default location is the R key on the second layer.
|
||||||
|
FN + Spacebar + R
|
||||||
|
* **Physical Reset PCB Pad**: Short pads of the PCB.
|
||||||
|
The description and image below are from the
|
||||||
|
Model F Labs manual web page.
|
||||||
|
|
||||||
|
At the very worst you have to open up the keyboard to short PROG on the actual xwhatsit controller (unscrew the 2 controller screws to see the components side of the board, make a connection with a conductive metal object like an uncoated metal paper clip, then connect the USB cable to the controller and within a split second remove the paper clip). Per pandrew: “You might think that a screwdriver is gonna be enough, but due to surface oxidation it is likely not gonna be good enough. I like to use sharp metal tweezers, because they can dig into the pad a little bit, breaking up the surface oxidation, and I can actually be sure it’s shorting. Apply constant strong pressure on the pads while plugging in the keyboard to make sure they’re perfectly shorted. If you hear the windows USB plug-in sound (assuming the sound effect is enabled), then you know you have succeeded. I’ve even seen people tell me they tried everything to short the pads with, and then I asked them to solder the pads together and it suddenly works. There’s something about the size of those pads, or about the fact that they need to be shorted in the perfect moment when the chip leaves reset, that make people think they are perfectly shorted and yet they aren’t. This affects me too, sometimes it takes me up to 3 tries to get it into bootloader mode. Another thing to double check that you are indeed shorting the PROG pad and not the reset pad. I believe in some versions of the wcass controller there is a reset pad on the opposite side of the board. So don’t be like ‘I see some pads, those must be it’, make sure to be shorting the correct ones.” [1]
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. “Brand New Model F and Beam Spring keyboards manual,” Brand New Model F Keyboards, https://www.modelfkeyboards.com/manual/ (accessed Mar. 16, 2024).
|
||||||
|
|
7
keyboards/model_f_labs/f62/wcass/rules.mk
Normal file
7
keyboards/model_f_labs/f62/wcass/rules.mk
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Build Options
|
||||||
|
# change yes to no to disable
|
||||||
|
#
|
||||||
|
#HAPTIC_ENABLE = yes
|
||||||
|
HAPTIC_DRIVER = solenoid
|
||||||
|
CUSTOM_MATRIX=lite
|
||||||
|
SRC += xwhatsit_capsense_matrix.c xwhatsit_util_comm.c
|
18
keyboards/model_f_labs/f62/wcass/wcass.c
Normal file
18
keyboards/model_f_labs/f62/wcass/wcass.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright 2020 Purdea Andrei
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *KEYBOARD_FILENAME = __FILE__; // used by util_comm
|
||||||
|
|
63
keyboards/model_f_labs/post_config.h
Normal file
63
keyboards/model_f_labs/post_config.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright 2020 Purdea Andrei
|
||||||
|
* Copyright 2021 Matthew J Wolf
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file should be included at the end of each keyboard-specific config.h
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef MATRIX_CAPSENSE_ROWS
|
||||||
|
# ifdef MATRIX_EXTRA_DIRECT_ROWS
|
||||||
|
# define MATRIX_CAPSENSE_ROWS (MATRIX_ROWS - MATRIX_EXTRA_DIRECT_ROWS)
|
||||||
|
# ifndef MATRIX_EXTRA_DIRECT_COLS
|
||||||
|
# define MATRIX_EXTRA_DIRECT_COLS MATRIX_COLS
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# define MATRIX_CAPSENSE_ROWS MATRIX_ROWS
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CAPSENSE_CAL_INIT_REPS
|
||||||
|
# define CAPSENSE_CAL_INIT_REPS 16
|
||||||
|
#endif
|
||||||
|
#ifndef CAPSENSE_CAL_EACHKEY_REPS
|
||||||
|
# define CAPSENSE_CAL_EACHKEY_REPS 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Testing Options
|
||||||
|
|
||||||
|
#ifndef CAPSENSE_KEYBOARD_SETTLE_TIME_US
|
||||||
|
# error "Please define CAPSENSE_KEYBOARD_SETTLE_TIME_US in config.h"
|
||||||
|
#endif
|
||||||
|
#ifndef CAPSENSE_DAC_SETTLE_TIME_US
|
||||||
|
# error "Please define CAPSENSE_DAC_SETTLE_TIME_US in config.h"
|
||||||
|
#endif
|
||||||
|
#ifndef CAPSENSE_HARDCODED_SAMPLE_TIME
|
||||||
|
# error "Please define CAPSENSE_HARDCODED_SAMPLE_TIME in config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CAPSENSE_CAL_ENABLED
|
||||||
|
# error "Please define CAPSENSE_CAL_ENABLED as 1/0 in config.h"
|
||||||
|
#endif
|
||||||
|
#ifndef CAPSENSE_CAL_DEBUG
|
||||||
|
# error "Please define CAPSENSE_CAL_DEBUG as 1/0 in config.h"
|
||||||
|
#endif
|
||||||
|
#ifndef CAPSENSE_CAL_BINS
|
||||||
|
# error "Please define CAPSENSE_CAL_BINS in config.h"
|
||||||
|
#endif
|
||||||
|
#ifndef CAPSENSE_CAL_THRESHOLD_OFFSET
|
||||||
|
# error "Please define CAPSENSE_CAL_THRESHOLD_OFFSET in config.h"
|
||||||
|
#endif
|
827
keyboards/model_f_labs/xwhatsit_capsense_matrix.c
Normal file
827
keyboards/model_f_labs/xwhatsit_capsense_matrix.c
Normal file
@ -0,0 +1,827 @@
|
|||||||
|
/* Copyright 2020 Purdea Andrei
|
||||||
|
* Copyright 2021-2022 Matthew J Wolf
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include "keymap_introspection.h"
|
||||||
|
#include "xwhatsit_capsense_matrix.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Notes on Expansion Header:
|
||||||
|
|
||||||
|
Pinout:
|
||||||
|
--1--O O--2--
|
||||||
|
--3--O O--4--
|
||||||
|
--5--O O--6--
|
||||||
|
|
||||||
|
Pin 1 is always VCC
|
||||||
|
Pin 6 in always GND
|
||||||
|
|
||||||
|
When using xwhatsit's solenoid controller board,
|
||||||
|
pin 2 is connected to the ENABLE input of the current
|
||||||
|
limiter, and pin 4 drives the solenoid.
|
||||||
|
|
||||||
|
On original xwhatsit controllers:
|
||||||
|
pin 2 = PB7
|
||||||
|
pin 3 = PB4
|
||||||
|
pin 4 = PB6
|
||||||
|
pin 5 = PB5
|
||||||
|
|
||||||
|
On the TH xwhatsit controller:
|
||||||
|
pin 2 = HEADER3 = TXO = PD3
|
||||||
|
pin 3 = HEADER1 = D(igital)6 = PD7
|
||||||
|
pin 4 = HEADER4 = RXI = PD2
|
||||||
|
pin 5 = HEADER2 = D(igital)7 = PE6
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline uint8_t read_rows(void) {
|
||||||
|
CAPSENSE_READ_ROWS_LOCAL_VARS;
|
||||||
|
asm volatile(CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS:CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS : CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS);
|
||||||
|
return CAPSENSE_READ_ROWS_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CAPSENSE_DAC_MCP4921)
|
||||||
|
|
||||||
|
void dac_init(void) {
|
||||||
|
writePin(CAPSENSE_DAC_NCS, 1);
|
||||||
|
setPinOutput(CAPSENSE_DAC_NCS);
|
||||||
|
setPinOutput(CAPSENSE_DAC_SCK);
|
||||||
|
setPinOutput(CAPSENSE_DAC_SDI);
|
||||||
|
writePin(CAPSENSE_DAC_NCS, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCK, 0);
|
||||||
|
writePin(CAPSENSE_DAC_SDI, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dac_write_threshold(uint16_t value) {
|
||||||
|
const uint16_t buffered = 0;
|
||||||
|
value |= 1 << nSHDN_BIT; // nSHDN = 0 -- make sure output is not floating.
|
||||||
|
value |= MCP_DAC_GAIN_1X << nGA_BIT;
|
||||||
|
value |= buffered << BUF_BIT;
|
||||||
|
|
||||||
|
writePin(CAPSENSE_DAC_NCS, 0);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
writePin(CAPSENSE_DAC_SDI, (value >> 15) & 1);
|
||||||
|
value <<= 1;
|
||||||
|
writePin(CAPSENSE_DAC_SCK, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCK, 0);
|
||||||
|
}
|
||||||
|
writePin(CAPSENSE_DAC_NCS, 1);
|
||||||
|
wait_us(CAPSENSE_DAC_SETTLE_TIME_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void dac_init(void) {
|
||||||
|
setPinOutput(CAPSENSE_DAC_SCLK);
|
||||||
|
setPinOutput(CAPSENSE_DAC_DIN);
|
||||||
|
setPinOutput(CAPSENSE_DAC_SYNC_N);
|
||||||
|
writePin(CAPSENSE_DAC_SYNC_N, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 0);
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dac_write_threshold(uint16_t value) {
|
||||||
|
value <<= 2; // The two LSB bits of this DAC are don't care.
|
||||||
|
writePin(CAPSENSE_DAC_SYNC_N, 0);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
writePin(CAPSENSE_DAC_DIN, (value >> 15) & 1);
|
||||||
|
value <<= 1;
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 0);
|
||||||
|
}
|
||||||
|
writePin(CAPSENSE_DAC_SYNC_N, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 1);
|
||||||
|
writePin(CAPSENSE_DAC_SCLK, 0);
|
||||||
|
wait_us(CAPSENSE_DAC_SETTLE_TIME_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define SHIFT_BITS (((CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(MATRIX_COLS - 1) >= 16) || \
|
||||||
|
(CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(0) >= 16)) ? 24 : 16)
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline int shift_bits(void) {
|
||||||
|
return (((CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(MATRIX_COLS - 1) >= 16) || (CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(0) >= 16)) ? 24 : 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shift_select_nothing(void) {
|
||||||
|
writePin(CAPSENSE_SHIFT_DIN, 0);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < shift_bits(); i++)
|
||||||
|
// for (i=0;i<SHIFT_BITS;i++)
|
||||||
|
{
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 1);
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 0);
|
||||||
|
}
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 1);
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shift_data(uint32_t data, int data_idle, int shcp_idle, int stcp_idle) {
|
||||||
|
int i;
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 0);
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 0);
|
||||||
|
for (i = shift_bits() - 1; i >= 0; i--)
|
||||||
|
// for (i=SHIFT_BITS-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
writePin(CAPSENSE_SHIFT_DIN, (data >> (shift_bits() - 1)) & 1);
|
||||||
|
// writePin(CAPSENSE_SHIFT_DIN, (data >> (SHIFT_BITS - 1)) & 1);
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 1);
|
||||||
|
if (!((i == 0) && (shcp_idle))) {
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 0);
|
||||||
|
}
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 1);
|
||||||
|
if (!stcp_idle) {
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 0);
|
||||||
|
}
|
||||||
|
writePin(CAPSENSE_SHIFT_DIN, !!data_idle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shift_select_col_no_strobe(uint8_t col) {
|
||||||
|
int i;
|
||||||
|
for (i = shift_bits() - 1; i >= 0; i--)
|
||||||
|
// for (i=SHIFT_BITS-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
writePin(CAPSENSE_SHIFT_DIN, !!(col == i));
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 1);
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void shift_select_col(uint8_t col) {
|
||||||
|
shift_select_col_no_strobe(col);
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 1);
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shift_init(void) {
|
||||||
|
setPinOutput(CAPSENSE_SHIFT_DIN);
|
||||||
|
setPinOutput(CAPSENSE_SHIFT_OE);
|
||||||
|
setPinOutput(CAPSENSE_SHIFT_STCP);
|
||||||
|
setPinOutput(CAPSENSE_SHIFT_SHCP);
|
||||||
|
writePin(CAPSENSE_SHIFT_OE, 0);
|
||||||
|
writePin(CAPSENSE_SHIFT_STCP, 0);
|
||||||
|
writePin(CAPSENSE_SHIFT_SHCP, 0);
|
||||||
|
shift_select_nothing();
|
||||||
|
wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timing:
|
||||||
|
// IN instructions (1 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE)
|
||||||
|
// Store to array instructions (2 * number of bytes)
|
||||||
|
// adiw: 1 cycle
|
||||||
|
// cp: 1 cycle
|
||||||
|
// cpc: 1 cycle
|
||||||
|
// brlo: 2 cycles (when jumping)
|
||||||
|
// --- Total loop length:
|
||||||
|
// 3 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 5 cycles
|
||||||
|
// first sample elements will be taken after [1..CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE-1] cycles
|
||||||
|
// second sample elements will be taken after
|
||||||
|
// [3 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 5 + 1..
|
||||||
|
// 3 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 5 + CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE-1] cycles
|
||||||
|
|
||||||
|
// the following function requires storage for CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE * (time + 1) bytes
|
||||||
|
// but returns valid data only in the first (time + 1) bytes
|
||||||
|
void test_multiple(uint8_t col, uint16_t time, uint8_t *array) {
|
||||||
|
shift_select_col_no_strobe(col);
|
||||||
|
uint16_t index;
|
||||||
|
CAPSENSE_READ_ROWS_LOCAL_VARS;
|
||||||
|
uint8_t *arrayp = array;
|
||||||
|
asm volatile("ldi %A[index], 0"
|
||||||
|
"\n\t"
|
||||||
|
"ldi %B[index], 0"
|
||||||
|
"\n\t"
|
||||||
|
"cli"
|
||||||
|
"\n\t"
|
||||||
|
"sbi %[stcp_regaddr], %[stcp_bit]"
|
||||||
|
"\n\t"
|
||||||
|
"1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "\n\t" CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS "\n\t"
|
||||||
|
"adiw %A[index], 0x01"
|
||||||
|
"\n\t"
|
||||||
|
"cp %A[index], %A[time]"
|
||||||
|
"\n\t"
|
||||||
|
"cpc %B[index], %B[time]"
|
||||||
|
"\n\t"
|
||||||
|
"brlo 1b"
|
||||||
|
"\n\t"
|
||||||
|
"sei"
|
||||||
|
"\n\t"
|
||||||
|
"cbi %[stcp_regaddr], %[stcp_bit]"
|
||||||
|
"\n\t"
|
||||||
|
: [arr] "=e"(arrayp), [index] "=&w"(index), CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS
|
||||||
|
: [time] "r"(time + 1), [stcp_regaddr] "I"(CAPSENSE_SHIFT_STCP_IO), [stcp_bit] "I"(CAPSENSE_SHIFT_STCP_BIT), CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS, "0"(arrayp)
|
||||||
|
: "memory");
|
||||||
|
uint16_t i, p0, p1;
|
||||||
|
p0 = p1 = 0;
|
||||||
|
for (i = 0; i <= time; i++) {
|
||||||
|
CAPSENSE_READ_ROWS_EXTRACT_FROM_ARRAY;
|
||||||
|
array[p1++] = CAPSENSE_READ_ROWS_VALUE;
|
||||||
|
}
|
||||||
|
shift_select_nothing();
|
||||||
|
wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t test_single(uint8_t col, uint16_t time, uint8_t *interference_ptr) {
|
||||||
|
shift_select_col_no_strobe(col);
|
||||||
|
uint16_t index;
|
||||||
|
CAPSENSE_READ_ROWS_LOCAL_VARS;
|
||||||
|
uint8_t array[CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 1]; // one sample before triggering, and one dummy byte
|
||||||
|
uint8_t *arrayp = array;
|
||||||
|
asm volatile("ldi %A[index], 0"
|
||||||
|
"\n\t"
|
||||||
|
"ldi %B[index], 0"
|
||||||
|
"\n\t"
|
||||||
|
"cli"
|
||||||
|
"\n\t" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "\n\t" CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS "\n\t"
|
||||||
|
"sbi %[stcp_regaddr], %[stcp_bit]"
|
||||||
|
"\n\t"
|
||||||
|
"1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "\n\t" CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS_FAKE "\n\t"
|
||||||
|
"adiw %A[index], 0x01"
|
||||||
|
"\n\t"
|
||||||
|
"cp %A[index], %A[time]"
|
||||||
|
"\n\t"
|
||||||
|
"cpc %B[index], %B[time]"
|
||||||
|
"\n\t"
|
||||||
|
"brlo 1b"
|
||||||
|
"\n\t"
|
||||||
|
"sei"
|
||||||
|
"\n\t"
|
||||||
|
"cbi %[stcp_regaddr], %[stcp_bit]"
|
||||||
|
"\n\t"
|
||||||
|
: [arr] "=e"(arrayp), [index] "=&w"(index), CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS
|
||||||
|
: [time] "r"(time + 1), [stcp_regaddr] "I"(CAPSENSE_SHIFT_STCP_IO), [stcp_bit] "I"(CAPSENSE_SHIFT_STCP_BIT), CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS, "0"(arrayp)
|
||||||
|
: "memory");
|
||||||
|
shift_select_nothing();
|
||||||
|
wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US);
|
||||||
|
uint8_t value_at_time = CAPSENSE_READ_ROWS_VALUE;
|
||||||
|
if (interference_ptr) {
|
||||||
|
uint16_t p0 = 0;
|
||||||
|
CAPSENSE_READ_ROWS_EXTRACT_FROM_ARRAY;
|
||||||
|
uint8_t interference = CAPSENSE_READ_ROWS_VALUE;
|
||||||
|
*interference_ptr = interference;
|
||||||
|
}
|
||||||
|
return value_at_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
void test_col_print_data_v2(uint8_t col) {
|
||||||
|
uprintf("%d: ", col);
|
||||||
|
static uint8_t data[NRTIMES * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE];
|
||||||
|
static uint8_t sums[(TESTATONCE + 1) * MATRIX_CAPSENSE_ROWS];
|
||||||
|
uint8_t to_time = NRTIMES - 1;
|
||||||
|
uint8_t from_time = 0;
|
||||||
|
while (from_time < NRTIMES - 1) {
|
||||||
|
if (to_time - from_time + 1 > TESTATONCE) {
|
||||||
|
to_time = from_time + TESTATONCE - 1;
|
||||||
|
}
|
||||||
|
uint8_t curr_TESTATONCE = to_time - from_time + 1;
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < (sizeof(sums) / sizeof(sums[0])); i++) {
|
||||||
|
sums[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < REPS_V2; i++) {
|
||||||
|
uint8_t st = read_rows();
|
||||||
|
test_multiple(col, to_time, data);
|
||||||
|
uint8_t j;
|
||||||
|
uint8_t ii = 0;
|
||||||
|
uint8_t k;
|
||||||
|
for (j = 0; j < curr_TESTATONCE; j++) {
|
||||||
|
uint8_t dataj = data[j + from_time];
|
||||||
|
for (k = 0; k < MATRIX_CAPSENSE_ROWS; k++) {
|
||||||
|
sums[ii] += (dataj & 1);
|
||||||
|
dataj >>= 1;
|
||||||
|
ii += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (from_time == 0) {
|
||||||
|
ii = TESTATONCE * MATRIX_CAPSENSE_ROWS;
|
||||||
|
for (k = 0; k < MATRIX_CAPSENSE_ROWS; k++) {
|
||||||
|
sums[ii] += (st & 1);
|
||||||
|
st >>= 1;
|
||||||
|
ii += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (from_time == 0) {
|
||||||
|
for (i = TESTATONCE * MATRIX_CAPSENSE_ROWS; i < (TESTATONCE + 1) * MATRIX_CAPSENSE_ROWS; i++) {
|
||||||
|
if (sums[i] > 0xf) {
|
||||||
|
print("?");
|
||||||
|
} else {
|
||||||
|
uprintf("%X", sums[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print(":");
|
||||||
|
}
|
||||||
|
for (i = 0; i < curr_TESTATONCE * MATRIX_CAPSENSE_ROWS; i++) {
|
||||||
|
if (sums[i] > 0xf) {
|
||||||
|
print("?");
|
||||||
|
} else {
|
||||||
|
uprintf("%X", sums[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from_time = to_time + 1;
|
||||||
|
to_time = NRTIMES - 1;
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
void test_v2(void) {
|
||||||
|
int i;
|
||||||
|
for (i = 7; i > 0; i--) {
|
||||||
|
uprintf("Starting test in %d\n", i);
|
||||||
|
wait_ms(1000);
|
||||||
|
}
|
||||||
|
uprintf("shift_init()");
|
||||||
|
shift_init();
|
||||||
|
uprintf(" DONE\n");
|
||||||
|
uprintf("dac_init()");
|
||||||
|
dac_init();
|
||||||
|
uprintf(" DONE\n");
|
||||||
|
int d;
|
||||||
|
for (d = 90; d <= 260; d++) {
|
||||||
|
uprintf("Testing threshold: %d\n", d);
|
||||||
|
dac_write_threshold(d);
|
||||||
|
// WHY ?
|
||||||
|
# if 1
|
||||||
|
int c;
|
||||||
|
for (c = 0; c < MATRIX_COLS; c++) {
|
||||||
|
test_col_print_data_v2(CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(c));
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
test_col_print_data_v2(0);
|
||||||
|
test_col_print_data_v2(2);
|
||||||
|
test_col_print_data_v2(6);
|
||||||
|
test_col_print_data_v2(7);
|
||||||
|
test_col_print_data_v2(15);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
uprintf("TEST DONE\n");
|
||||||
|
while (1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t measure_middle(uint8_t col, uint8_t row, uint8_t time, uint8_t reps) {
|
||||||
|
uint8_t reps_div2 = reps / 2;
|
||||||
|
uint16_t min = 0, max = CAPSENSE_DAC_MAX;
|
||||||
|
while (min < max) {
|
||||||
|
uint16_t mid = (min + max) / 2;
|
||||||
|
dac_write_threshold(mid);
|
||||||
|
uint8_t sum = 0;
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < reps; i++) {
|
||||||
|
sum += (test_single(col, time, NULL) >> row) & 1;
|
||||||
|
}
|
||||||
|
if (sum < reps_div2) {
|
||||||
|
max = mid - 1;
|
||||||
|
} else if (sum > reps_div2) {
|
||||||
|
min = mid + 1;
|
||||||
|
} else
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t measure_middle_keymap_coords(uint8_t col, uint8_t row, uint8_t time, uint8_t reps) {
|
||||||
|
return measure_middle(CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col), CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row), time, reps);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t measure_middle_settled(uint8_t col, uint8_t row, uint8_t reps) {
|
||||||
|
uint8_t reps_div2 = reps / 2;
|
||||||
|
uint16_t min = 0, max = CAPSENSE_DAC_MAX;
|
||||||
|
while (min < max) {
|
||||||
|
uint16_t mid = (min + max) / 2;
|
||||||
|
dac_write_threshold(mid);
|
||||||
|
uint8_t sum = 0;
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < reps; i++) {
|
||||||
|
sum += (read_rows() >> row) & 1;
|
||||||
|
}
|
||||||
|
if (sum < reps_div2) {
|
||||||
|
max = mid - 1;
|
||||||
|
} else if (sum > reps_div2) {
|
||||||
|
min = mid + 1;
|
||||||
|
} else
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
void tracking_test(void) {
|
||||||
|
int i;
|
||||||
|
for (i = 7; i > 0; i--) {
|
||||||
|
uprintf("Starting test in %d\n", i);
|
||||||
|
wait_ms(1000);
|
||||||
|
}
|
||||||
|
uprintf("shift_init()");
|
||||||
|
shift_init();
|
||||||
|
uprintf(" DONE\n");
|
||||||
|
uprintf("dac_init()");
|
||||||
|
dac_init();
|
||||||
|
uprintf(" DONE\n");
|
||||||
|
while (1) {
|
||||||
|
uint32_t tt = timer_read32();
|
||||||
|
uint16_t key1 = measure_middle(TRACKING_KEY_1_COL, TRACKING_KEY_1_ROW, TRACKING_TEST_TIME, TRACKING_REPS);
|
||||||
|
uint16_t key2 = measure_middle(TRACKING_KEY_2_COL, TRACKING_KEY_2_ROW, TRACKING_TEST_TIME, TRACKING_REPS);
|
||||||
|
uint16_t key3 = measure_middle(TRACKING_KEY_3_COL, TRACKING_KEY_3_ROW, TRACKING_TEST_TIME, TRACKING_REPS);
|
||||||
|
uint16_t key4 = measure_middle(TRACKING_KEY_4_COL, TRACKING_KEY_4_ROW, TRACKING_TEST_TIME, TRACKING_REPS);
|
||||||
|
uint16_t key5 = measure_middle(TRACKING_KEY_5_COL, TRACKING_KEY_5_ROW, TRACKING_TEST_TIME, TRACKING_REPS);
|
||||||
|
uint16_t sett = measure_middle_settled(TRACKING_KEY_2_COL, TRACKING_KEY_2_ROW, TRACKING_REPS);
|
||||||
|
uint16_t key1l = measure_middle(TRACKING_KEY_1_COL, TRACKING_KEY_1_ROW, TRACKING_TEST_TIME * 2, TRACKING_REPS);
|
||||||
|
uint16_t key2l = measure_middle(TRACKING_KEY_2_COL, TRACKING_KEY_2_ROW, TRACKING_TEST_TIME * 2, TRACKING_REPS);
|
||||||
|
uprintf("%5lu.%03u, %u, %u, %u, %u, %u, %u, %u, %u\n", tt / 1000, (uint16_t)(tt % 1000), key1, key2, key3, key4, key5, sett, key1l, key2l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t calibration_measure_all_valid_keys(uint8_t time, uint8_t reps, bool looking_for_all_zero) {
|
||||||
|
uint16_t min = 0, max = CAPSENSE_DAC_MAX;
|
||||||
|
while (min < max) {
|
||||||
|
uint16_t mid = (min + max) / 2;
|
||||||
|
if (!looking_for_all_zero) {
|
||||||
|
mid = (min + max + 1) / 2;
|
||||||
|
}
|
||||||
|
dac_write_threshold(mid);
|
||||||
|
uint8_t col;
|
||||||
|
for (col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
uint8_t valid_physical_rows = 0;
|
||||||
|
uint8_t row;
|
||||||
|
for (row = 0; row < MATRIX_CAPSENSE_ROWS; row++) {
|
||||||
|
// if (pgm_read_word(&keymaps[0][row][col]) != KC_NO)
|
||||||
|
if (keycode_at_keymap_location(0, row, col) != KC_NO) {
|
||||||
|
valid_physical_rows |= (((matrix_row_t)1) << CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row)); // convert keymap row to physical row
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t physical_col = CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col);
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < reps; i++) {
|
||||||
|
if (looking_for_all_zero) {
|
||||||
|
uint8_t all_zero = (test_single(physical_col, time, NULL) & valid_physical_rows) == 0;
|
||||||
|
if (!all_zero) {
|
||||||
|
min = mid + 1;
|
||||||
|
goto next_binary_search;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint8_t all_ones = (test_single(physical_col, time, NULL) & valid_physical_rows) == valid_physical_rows;
|
||||||
|
if (!all_ones) {
|
||||||
|
max = mid - 1;
|
||||||
|
goto next_binary_search;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (looking_for_all_zero) {
|
||||||
|
max = mid;
|
||||||
|
} else {
|
||||||
|
min = mid;
|
||||||
|
}
|
||||||
|
next_binary_search:;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calibration is not supported in conjunction with BOOTMAGIC, because calibration requires that no keys are
|
||||||
|
// pressed while the keyboard is plugged in
|
||||||
|
void bootmagic_lite(void) {}
|
||||||
|
|
||||||
|
uint16_t cal_thresholds[CAPSENSE_CAL_BINS];
|
||||||
|
matrix_row_t assigned_to_threshold[CAPSENSE_CAL_BINS][MATRIX_CAPSENSE_ROWS];
|
||||||
|
uint16_t cal_tr_allzero;
|
||||||
|
uint16_t cal_tr_allone;
|
||||||
|
void calibration(void) {
|
||||||
|
uint16_t cal_thresholds_max[CAPSENSE_CAL_BINS];
|
||||||
|
uint16_t cal_thresholds_min[CAPSENSE_CAL_BINS];
|
||||||
|
memset(cal_thresholds_max, 0xff, sizeof(cal_thresholds_max));
|
||||||
|
memset(cal_thresholds_min, 0xff, sizeof(cal_thresholds_min));
|
||||||
|
cal_tr_allzero = calibration_measure_all_valid_keys(CAPSENSE_HARDCODED_SAMPLE_TIME, CAPSENSE_CAL_INIT_REPS, true);
|
||||||
|
cal_tr_allone = calibration_measure_all_valid_keys(CAPSENSE_HARDCODED_SAMPLE_TIME, CAPSENSE_CAL_INIT_REPS, false);
|
||||||
|
uint16_t max = (cal_tr_allzero == 0) ? 0 : (cal_tr_allzero - 1);
|
||||||
|
uint16_t min = cal_tr_allone + 1;
|
||||||
|
if (max < min) max = min;
|
||||||
|
uint16_t d = max - min;
|
||||||
|
uint8_t i;
|
||||||
|
for (i = 0; i < CAPSENSE_CAL_BINS; i++) {
|
||||||
|
cal_thresholds[i] = min + (d * (2 * i + 1)) / 2 / CAPSENSE_CAL_BINS;
|
||||||
|
}
|
||||||
|
uint8_t col;
|
||||||
|
for (col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
uint8_t physical_col = CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col);
|
||||||
|
uint8_t row;
|
||||||
|
for (row = 0; row < MATRIX_CAPSENSE_ROWS; row++) {
|
||||||
|
// if (pgm_read_word(&keymaps[0][row][col]) != KC_NO) {
|
||||||
|
if (keycode_at_keymap_location(0, row, col) != KC_NO) {
|
||||||
|
uint16_t threshold = measure_middle(physical_col, CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row), CAPSENSE_HARDCODED_SAMPLE_TIME, CAPSENSE_CAL_EACHKEY_REPS);
|
||||||
|
uint8_t besti = 0;
|
||||||
|
uint16_t best_diff = (uint16_t)abs(threshold - cal_thresholds[besti]);
|
||||||
|
for (i = 1; i < CAPSENSE_CAL_BINS; i++) {
|
||||||
|
uint16_t this_diff = (uint16_t)abs(threshold - cal_thresholds[i]);
|
||||||
|
if (this_diff < best_diff) {
|
||||||
|
best_diff = this_diff;
|
||||||
|
besti = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assigned_to_threshold[besti][row] |= (((matrix_row_t)1) << col);
|
||||||
|
if ((cal_thresholds_max[besti] == 0xFFFFU) || (cal_thresholds_max[besti] < threshold)) cal_thresholds_max[besti] = threshold;
|
||||||
|
if ((cal_thresholds_min[besti] == 0xFFFFU) || (cal_thresholds_min[besti] > threshold)) cal_thresholds_min[besti] = threshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < CAPSENSE_CAL_BINS; i++) {
|
||||||
|
uint16_t bin_signal_level;
|
||||||
|
if ((cal_thresholds_max[i] == 0xFFFFU) || (cal_thresholds_min[i] == 0xFFFFU)) {
|
||||||
|
bin_signal_level = cal_thresholds[i];
|
||||||
|
} else {
|
||||||
|
bin_signal_level = (cal_thresholds_max[i] + cal_thresholds_min[i]) / 2;
|
||||||
|
}
|
||||||
|
#ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
|
||||||
|
if ((bin_signal_level + CAPSENSE_CAL_THRESHOLD_OFFSET) > CAPSENSE_DAC_MAX) {
|
||||||
|
cal_thresholds[i] = CAPSENSE_DAC_MAX;
|
||||||
|
} else {
|
||||||
|
cal_thresholds[i] = bin_signal_level + CAPSENSE_CAL_THRESHOLD_OFFSET;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (bin_signal_level < CAPSENSE_CAL_THRESHOLD_OFFSET) {
|
||||||
|
cal_thresholds[i] = 0;
|
||||||
|
} else {
|
||||||
|
cal_thresholds[i] = bin_signal_level - CAPSENSE_CAL_THRESHOLD_OFFSET;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_leds(int num_lock, int caps_lock, int scroll_lock) {
|
||||||
|
#if defined(LED_NUM_LOCK_PIN)
|
||||||
|
# if defined(LED_NUM_LOCK_ACTIVE_LOW)
|
||||||
|
writePin(LED_NUM_LOCK_PIN, !num_lock);
|
||||||
|
# else
|
||||||
|
writePin(LED_NUM_LOCK_PIN, num_lock);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(LED_CAPS_LOCK_PIN)
|
||||||
|
# if defined(LED_CAPS_LOCK_ACTIVE_LOW)
|
||||||
|
writePin(LED_CAPS_LOCK_PIN, !caps_lock);
|
||||||
|
# else
|
||||||
|
writePin(LED_CAPS_LOCK_PIN, caps_lock);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#if defined(LED_SCROLL_LOCK_PIN)
|
||||||
|
# if defined(LED_SCROLL_LOCK_ACTIVE_LOW)
|
||||||
|
writePin(LED_SCROLL_LOCK_PIN, !scroll_lock);
|
||||||
|
# else
|
||||||
|
writePin(LED_SCROLL_LOCK_PIN, scroll_lock);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LED_NON_BASE_LAYER_PIN)
|
||||||
|
void set_led_non_base_layer(uint8_t value) {
|
||||||
|
# if defined(LED_NON_BASE_LAYER_ACTIVE_LOW)
|
||||||
|
writePin(LED_NON_BASE_LAYER_PIN, !value);
|
||||||
|
# else
|
||||||
|
writePin(LED_NON_BASE_LAYER_PIN, !!value);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
layer_state_t layer_state_set_kb(layer_state_t state) {
|
||||||
|
switch (get_highest_layer(state)) {
|
||||||
|
case 0:
|
||||||
|
set_led_non_base_layer(0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
set_led_non_base_layer(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return layer_state_set_user(state);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MATRIX_EXTRA_DIRECT_ROWS
|
||||||
|
static pin_t extra_direct_pins[MATRIX_EXTRA_DIRECT_ROWS][MATRIX_COLS] = MATRIX_EXTRA_DIRECT_PINS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CAPSENSE_CAL_ENABLED && CAPSENSE_CAL_DEBUG
|
||||||
|
uint16_t cal_time;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void real_keyboard_init_basic(void) {
|
||||||
|
SETUP_UNUSED_PINS();
|
||||||
|
|
||||||
|
#if defined(LED_NUM_LOCK_PIN)
|
||||||
|
setPinOutput(LED_NUM_LOCK_PIN);
|
||||||
|
#endif
|
||||||
|
#if defined(LED_CAPS_LOCK_PIN)
|
||||||
|
setPinOutput(LED_CAPS_LOCK_PIN);
|
||||||
|
#endif
|
||||||
|
#if defined(LED_SCROLL_LOCK_PIN)
|
||||||
|
setPinOutput(LED_SCROLL_LOCK_PIN);
|
||||||
|
#endif
|
||||||
|
#if defined(LED_NON_BASE_LAYER_PIN)
|
||||||
|
setPinOutput(LED_NON_BASE_LAYER_PIN);
|
||||||
|
set_led_non_base_layer(0);
|
||||||
|
#endif
|
||||||
|
set_leds(0, 0, 0);
|
||||||
|
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
uprintf("shift_init()");
|
||||||
|
#endif
|
||||||
|
shift_init();
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
uprintf(" DONE\n");
|
||||||
|
uprintf("dac_init()");
|
||||||
|
#endif
|
||||||
|
dac_init();
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
uprintf(" DONE\n");
|
||||||
|
#endif
|
||||||
|
SETUP_ROW_GPIOS();
|
||||||
|
#if CAPSENSE_CAL_ENABLED
|
||||||
|
# if CAPSENSE_CAL_DEBUG
|
||||||
|
cal_time = timer_read();
|
||||||
|
# endif
|
||||||
|
calibration();
|
||||||
|
# if CAPSENSE_CAL_DEBUG
|
||||||
|
cal_time = timer_read() - cal_time;
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
dac_write_threshold(CAPSENSE_HARDCODED_THRESHOLD);
|
||||||
|
dac_write_threshold(CAPSENSE_HARDCODED_THRESHOLD);
|
||||||
|
dac_write_threshold(CAPSENSE_HARDCODED_THRESHOLD);
|
||||||
|
#endif
|
||||||
|
#if defined(CONTROLLER_IS_THROUGH_HOLE_BEAMSPRING) || defined(CONTROLLER_IS_THROUGH_HOLE_MODEL_F)
|
||||||
|
// Disable on-board leds.
|
||||||
|
setPinOutput(D5);
|
||||||
|
writePin(D5, 1);
|
||||||
|
setPinOutput(B0);
|
||||||
|
writePin(B0, 1);
|
||||||
|
#endif
|
||||||
|
#if MATRIX_EXTRA_DIRECT_ROWS
|
||||||
|
for (int row = 0; row < MATRIX_EXTRA_DIRECT_ROWS; row++) {
|
||||||
|
for (int col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
pin_t pin = extra_direct_pins[row][col];
|
||||||
|
if (pin != NO_PIN) {
|
||||||
|
# if MATRIX_EXTRA_DIRECT_PINS_NEED_INTERNAL_PULLUP
|
||||||
|
setPinInputHigh(pin);
|
||||||
|
# else
|
||||||
|
setPinInput(pin);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool led_update_kb(led_t led_state) {
|
||||||
|
bool res = led_update_user(led_state);
|
||||||
|
if (res) {
|
||||||
|
set_leds(led_state.num_lock, led_state.caps_lock, led_state.scroll_lock);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_init_custom(void) {
|
||||||
|
// test_v2();
|
||||||
|
// tracking_test();
|
||||||
|
real_keyboard_init_basic();
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix_row_t previous_matrix[MATRIX_ROWS];
|
||||||
|
|
||||||
|
bool matrix_has_it_changed(const matrix_row_t current_matrix[]) {
|
||||||
|
uint8_t row;
|
||||||
|
bool changed = false;
|
||||||
|
for (row = 0; row < MATRIX_ROWS; row++) {
|
||||||
|
if (previous_matrix[row] != current_matrix[row]) changed = true;
|
||||||
|
previous_matrix[row] = current_matrix[row];
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CAPSENSE_CAL_ENABLED && CAPSENSE_CAL_DEBUG
|
||||||
|
bool cal_stats_printed = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool keyboard_scan_enabled = 1;
|
||||||
|
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
void matrix_print_stats(void) {
|
||||||
|
uint8_t row, cal;
|
||||||
|
# if CAPSENSE_CAL_ENABLED && CAPSENSE_CAL_DEBUG
|
||||||
|
if (!cal_stats_printed) {
|
||||||
|
uint32_t time = timer_read32();
|
||||||
|
if (time >= 10 * 1000UL) { // after 10 seconds
|
||||||
|
uprintf("Calibration took: %u ms\n", cal_time);
|
||||||
|
uprintf("Cal All Zero = %u, Cal All Ones = %u\n", cal_tr_allzero, cal_tr_allone);
|
||||||
|
for (cal = 0; cal < CAPSENSE_CAL_BINS; cal++) {
|
||||||
|
uprintf("Cal bin %u, Threshold=%u Assignments:\n", cal, cal_thresholds[cal]);
|
||||||
|
for (row = 0; row < MATRIX_CAPSENSE_ROWS; row++) {
|
||||||
|
# if MATRIX_COLS > 16
|
||||||
|
uprintf("0x%06X\n", assigned_to_threshold[cal][row]);
|
||||||
|
# elif MATRIX_COLS > 12
|
||||||
|
uprintf("0x%04X\n", assigned_to_threshold[cal][row]);
|
||||||
|
# else
|
||||||
|
uprintf("0x%03X\n", assigned_to_threshold[cal][row]);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cal_stats_printed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void matrix_scan_raw(matrix_row_t current_matrix[]) {
|
||||||
|
uint8_t col, row;
|
||||||
|
memset(current_matrix, 0, sizeof(matrix_row_t) * MATRIX_ROWS);
|
||||||
|
#if CAPSENSE_CAL_ENABLED
|
||||||
|
uint8_t cal;
|
||||||
|
for (cal = 0; cal < CAPSENSE_CAL_BINS; cal++) {
|
||||||
|
dac_write_threshold(cal_thresholds[cal]);
|
||||||
|
for (col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
uint8_t real_col = CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col);
|
||||||
|
uint8_t d, interference;
|
||||||
|
uint8_t d_tested = 0;
|
||||||
|
for (row = 0; row < MATRIX_CAPSENSE_ROWS; row++) {
|
||||||
|
if (assigned_to_threshold[cal][row] & (((matrix_row_t)1) << col)) {
|
||||||
|
if (!d_tested) {
|
||||||
|
d = test_single(real_col, CAPSENSE_HARDCODED_SAMPLE_TIME, &interference);
|
||||||
|
# ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
|
||||||
|
d = ~d;
|
||||||
|
# endif
|
||||||
|
d_tested = 1;
|
||||||
|
}
|
||||||
|
uint8_t physical_row = CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row);
|
||||||
|
if (!((interference >> physical_row) & 1)) {
|
||||||
|
current_matrix[row] |= ((matrix_row_t)((d >> physical_row) & 1)) << col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
uint8_t real_col = CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col);
|
||||||
|
uint8_t interference;
|
||||||
|
uint8_t d = test_single(real_col, CAPSENSE_HARDCODED_SAMPLE_TIME, &interference);
|
||||||
|
# ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
|
||||||
|
d = ~d;
|
||||||
|
# endif
|
||||||
|
for (row = 0; row < MATRIX_CAPSENSE_ROWS; row++) {
|
||||||
|
current_matrix[CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row)] |= (((matrix_row_t)(d & 1)) << col);
|
||||||
|
d >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MATRIX_EXTRA_DIRECT_ROWS
|
||||||
|
for (int row = 0; row < MATRIX_EXTRA_DIRECT_ROWS; row++) {
|
||||||
|
for (int col = 0; col < MATRIX_EXTRA_DIRECT_COLS; col++) {
|
||||||
|
pin_t pin = extra_direct_pins[row][col];
|
||||||
|
if (pin != NO_PIN) {
|
||||||
|
uint8_t value = !!readPin(pin);
|
||||||
|
# if MATRIX_EXTRA_DIRECT_PINS_ACTIVE_LOW
|
||||||
|
value = !value;
|
||||||
|
# endif
|
||||||
|
if (value) {
|
||||||
|
current_matrix[MATRIX_CAPSENSE_ROWS + row] |= ((matrix_row_t)1) << col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
matrix_print_stats();
|
||||||
|
#endif
|
||||||
|
if (keyboard_scan_enabled) {
|
||||||
|
matrix_scan_raw(current_matrix);
|
||||||
|
} else {
|
||||||
|
memset(current_matrix, 0, sizeof(matrix_row_t) * MATRIX_ROWS);
|
||||||
|
}
|
||||||
|
return matrix_has_it_changed(current_matrix);
|
||||||
|
}
|
69
keyboards/model_f_labs/xwhatsit_capsense_matrix.h
Normal file
69
keyboards/model_f_labs/xwhatsit_capsense_matrix.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* Copyright 2020 Purdea Andrei
|
||||||
|
* Copyright 2021 Matthew J Wolf
|
||||||
|
*
|
||||||
|
* 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 nSHDN_BIT 12
|
||||||
|
#define MCP_DAC_GAIN_2X 0
|
||||||
|
#define MCP_DAC_GAIN_1X 1
|
||||||
|
#define nGA_BIT 13
|
||||||
|
#define BUF_BIT 14
|
||||||
|
|
||||||
|
#define TRACKING_TEST_TIME 4
|
||||||
|
// Key 1 is the always non-pressed key under the space bar to the right.
|
||||||
|
#define TRACKING_KEY_1_COL 6
|
||||||
|
#define TRACKING_KEY_1_ROW 4
|
||||||
|
// Key 2 is the always-pressed calibration pad to the far right-bottom of the keyboard. (both on F62 and F77)
|
||||||
|
#define TRACKING_KEY_2_COL 15
|
||||||
|
#define TRACKING_KEY_2_ROW 6
|
||||||
|
// Key 3 is the F key
|
||||||
|
#define TRACKING_KEY_3_COL 2
|
||||||
|
#define TRACKING_KEY_3_ROW 5
|
||||||
|
// Key 4 is the half of the split backspace that is unused if the user has a normal backspace.
|
||||||
|
#define TRACKING_KEY_4_COL 7
|
||||||
|
#define TRACKING_KEY_4_ROW 3
|
||||||
|
// Key 5 is hidden key next to the left shift, which is only used in ISO layouts.
|
||||||
|
#define TRACKING_KEY_5_COL 0
|
||||||
|
#define TRACKING_KEY_5_ROW 7
|
||||||
|
|
||||||
|
#define TRACKING_REPS 16
|
||||||
|
|
||||||
|
#ifndef NO_PRINT
|
||||||
|
# define NRTIMES 64
|
||||||
|
# define TESTATONCE 8
|
||||||
|
# define REPS_V2 15
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MATRIX_MANIPULATE_H
|
||||||
|
# define MATRIX_MANIPULATE_H
|
||||||
|
|
||||||
|
# include "quantum.h"
|
||||||
|
|
||||||
|
// Contains stuff used to manipulate the matrix using the util.
|
||||||
|
// These are defined in capsense_matrix.c. This file is not called matrix.h to avoid conflict with qmk-native matrix.h
|
||||||
|
|
||||||
|
extern bool keyboard_scan_enabled;
|
||||||
|
void matrix_scan_raw(matrix_row_t current_matrix[]);
|
||||||
|
extern uint16_t cal_thresholds[CAPSENSE_CAL_BINS];
|
||||||
|
extern matrix_row_t assigned_to_threshold[CAPSENSE_CAL_BINS][MATRIX_CAPSENSE_ROWS];
|
||||||
|
uint16_t measure_middle_keymap_coords(uint8_t col, uint8_t row, uint8_t time, uint8_t reps);
|
||||||
|
void shift_data(uint32_t data, int data_idle, int shcp_idle, int stcp_idle);
|
||||||
|
void dac_write_threshold(uint16_t value);
|
||||||
|
uint8_t test_single(uint8_t col, uint16_t time, uint8_t *interference_ptr);
|
||||||
|
void shift_select_col_no_strobe(uint8_t col);
|
||||||
|
void shift_select_nothing(void);
|
||||||
|
|
||||||
|
#endif
|
210
keyboards/model_f_labs/xwhatsit_util_comm.c
Normal file
210
keyboards/model_f_labs/xwhatsit_util_comm.c
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/* Copyright 2020 Purdea Andrei
|
||||||
|
* Copyright 2021-2022 Matthew J Wolf
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
#include "raw_hid.h"
|
||||||
|
#include "xwhatsit_util_comm.h"
|
||||||
|
#include "xwhatsit_capsense_matrix.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <platforms/eeprom.h>
|
||||||
|
|
||||||
|
extern const char *KEYBOARD_FILENAME; // This must be defined in keyboard_name.c to equal the filename. This is sent back to the PC-side software for it to determine which keyboard we are using.
|
||||||
|
|
||||||
|
static const uint8_t magic[] = UTIL_COMM_MAGIC;
|
||||||
|
|
||||||
|
// Has well know issues.
|
||||||
|
//#define min(x, y) (((x) < (y))?(x):(y))
|
||||||
|
|
||||||
|
inline int min(int x, int y) {
|
||||||
|
if (x > y) {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void raw_hid_receive(uint8_t *data, uint8_t length) {
|
||||||
|
if (0 != memcmp(data, magic, sizeof(magic))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t response[RAW_EPSIZE];
|
||||||
|
memcpy(response, magic, sizeof(magic));
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_ERROR;
|
||||||
|
switch (data[2]) {
|
||||||
|
case UTIL_COMM_GET_VERSION:
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
response[3] = UTIL_COMM_VERSION_MAJOR;
|
||||||
|
response[4] = UTIL_COMM_VERSION_MID;
|
||||||
|
response[5] = (UTIL_COMM_VERSION_MINOR >> 8) & 0xff;
|
||||||
|
response[6] = (UTIL_COMM_VERSION_MINOR >> 0) & 0xff;
|
||||||
|
break;
|
||||||
|
case UTIL_COMM_DISABLE_KEYBOARD:
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
response[3] = (uint8_t)keyboard_scan_enabled;
|
||||||
|
keyboard_scan_enabled = 0;
|
||||||
|
break;
|
||||||
|
case UTIL_COMM_ENABLE_KEYBOARD:
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
response[3] = (uint8_t)keyboard_scan_enabled;
|
||||||
|
keyboard_scan_enabled = 1;
|
||||||
|
break;
|
||||||
|
case UTIL_COMM_ENTER_BOOTLOADER:
|
||||||
|
keyboard_scan_enabled = 0;
|
||||||
|
wait_ms(10);
|
||||||
|
bootloader_jump();
|
||||||
|
// we should not be reaching the following:
|
||||||
|
wait_ms(10);
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
break;
|
||||||
|
case UTIL_COMM_GET_KEYSTATE:
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
{
|
||||||
|
matrix_row_t current_matrix[MATRIX_ROWS];
|
||||||
|
matrix_scan_raw(current_matrix);
|
||||||
|
char *current_matrix_ptr = (char *)current_matrix;
|
||||||
|
int offset = 0;
|
||||||
|
if (sizeof(current_matrix) > 32 - 3) {
|
||||||
|
offset = data[3];
|
||||||
|
current_matrix_ptr += offset;
|
||||||
|
}
|
||||||
|
memcpy(&response[3], current_matrix_ptr, min(32 - 3, sizeof(current_matrix) - offset));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UTIL_COMM_GET_THRESHOLDS:
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
#if CAPSENSE_CAL_ENABLED
|
||||||
|
response[3] = CAPSENSE_CAL_BINS;
|
||||||
|
{
|
||||||
|
const uint8_t cal_bin = data[3];
|
||||||
|
response[4] = cal_thresholds[cal_bin] & 0xff;
|
||||||
|
response[5] = (cal_thresholds[cal_bin] >> 8) & 0xff;
|
||||||
|
char *assigned_to_threshold_ptr = (char *)assigned_to_threshold[cal_bin];
|
||||||
|
int offset = 0;
|
||||||
|
if (sizeof(assigned_to_threshold[cal_bin]) > 32 - 6) {
|
||||||
|
offset = data[4];
|
||||||
|
assigned_to_threshold_ptr += offset;
|
||||||
|
}
|
||||||
|
memcpy(&response[6], assigned_to_threshold_ptr, min(32 - 6, sizeof(assigned_to_threshold[cal_bin]) - offset));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
response[3] = 0;
|
||||||
|
response[4] = (CAPSENSE_HARDCODED_THRESHOLD)&0xff;
|
||||||
|
response[5] = ((CAPSENSE_HARDCODED_THRESHOLD) >> 8) & 0xff;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case UTIL_COMM_GET_KEYBOARD_FILENAME: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
if (data[3] >= strlen(KEYBOARD_FILENAME) + 1) {
|
||||||
|
response[3] = 0;
|
||||||
|
} else {
|
||||||
|
const char *substring = KEYBOARD_FILENAME + data[3];
|
||||||
|
size_t substring_length = strlen(substring) + 1;
|
||||||
|
if (substring_length > RAW_EPSIZE - 3) substring_length = RAW_EPSIZE - 3;
|
||||||
|
memcpy(&response[3], substring, substring_length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UTIL_COMM_ERASE_EEPROM: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
uint16_t addr;
|
||||||
|
for (addr = 0; addr < E2END; addr += 1) {
|
||||||
|
eeprom_update_byte((uint8_t *)addr, 0xff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UTIL_COMM_GET_SIGNAL_VALUE: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
uint8_t col = data[3];
|
||||||
|
uint8_t row = data[4];
|
||||||
|
uint8_t count = data[5];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
uint16_t value = measure_middle_keymap_coords(col, row, CAPSENSE_HARDCODED_SAMPLE_TIME, 8);
|
||||||
|
response[3 + i * 2] = value & 0xff;
|
||||||
|
response[3 + i * 2 + 1] = (value >> 8) & 0xff;
|
||||||
|
col += 1;
|
||||||
|
if (col >= MATRIX_COLS) {
|
||||||
|
col -= MATRIX_COLS;
|
||||||
|
row += 1;
|
||||||
|
}
|
||||||
|
if (row >= MATRIX_CAPSENSE_ROWS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UTIL_COMM_GET_KEYBOARD_DETAILS: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
response[3] = MATRIX_COLS;
|
||||||
|
response[4] = MATRIX_ROWS;
|
||||||
|
response[5] = GET_KEYBOARD_DETAILS_5;
|
||||||
|
#if defined(CONTROLLER_IS_XWHATSIT_BEAMSPRING_REV_4)
|
||||||
|
response[5] = 1;
|
||||||
|
#elif defined(CONTROLLER_IS_XWHATSIT_MODEL_F_OR_WCASS_MODEL_F)
|
||||||
|
response[5] = 2;
|
||||||
|
#elif defined(CONTROLLER_IS_THROUGH_HOLE_BEAMSPRING)
|
||||||
|
response[5] = 3;
|
||||||
|
#elif defined(CONTROLLER_IS_THROUGH_HOLE_MODEL_F)
|
||||||
|
response[5] = 4;
|
||||||
|
#else
|
||||||
|
response[5] = 0;
|
||||||
|
#endif
|
||||||
|
response[6] = CAPSENSE_KEYBOARD_SETTLE_TIME_US;
|
||||||
|
response[7] = CAPSENSE_DAC_SETTLE_TIME_US;
|
||||||
|
response[8] = CAPSENSE_HARDCODED_SAMPLE_TIME;
|
||||||
|
response[9] = CAPSENSE_CAL_ENABLED;
|
||||||
|
response[10] = CAPSENSE_DAC_MAX & 0xFF;
|
||||||
|
response[11] = (CAPSENSE_DAC_MAX >> 8) & 0xFF;
|
||||||
|
response[12] = MATRIX_CAPSENSE_ROWS;
|
||||||
|
response[13] = 0; // reserved for future
|
||||||
|
response[14] = 0; // reserved for future
|
||||||
|
response[15] = 0; // reserved for future
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UTIL_COMM_SHIFT_DATA:
|
||||||
|
case UTIL_COMM_SHIFT_DATA_EXT: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
uint32_t shdata = (((uint32_t)(data[3])) << 0) | (((uint32_t)(data[4])) << 8) | (((uint32_t)(data[5])) << 16) | (((uint32_t)(data[6])) << 24);
|
||||||
|
int data_idle = 0;
|
||||||
|
int shcp_idle = 0;
|
||||||
|
int stcp_idle = 0;
|
||||||
|
if (data[2] == UTIL_COMM_SHIFT_DATA_EXT) {
|
||||||
|
data_idle = data[7];
|
||||||
|
shcp_idle = data[8];
|
||||||
|
stcp_idle = data[9];
|
||||||
|
}
|
||||||
|
shift_data(shdata, data_idle, shcp_idle, stcp_idle);
|
||||||
|
response[3] = readPin(CAPSENSE_SHIFT_DIN);
|
||||||
|
response[4] = readPin(CAPSENSE_SHIFT_SHCP);
|
||||||
|
response[5] = readPin(CAPSENSE_SHIFT_STCP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UTIL_COMM_SET_DAC_VALUE: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
uint16_t value = data[3] | (((uint16_t)data[4]) << 8);
|
||||||
|
dac_write_threshold(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UTIL_COMM_GET_ROW_STATE: {
|
||||||
|
response[2] = UTIL_COMM_RESPONSE_OK;
|
||||||
|
response[3] = test_single(255, 0, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
raw_hid_send(response, sizeof(response));
|
||||||
|
}
|
59
keyboards/model_f_labs/xwhatsit_util_comm.h
Normal file
59
keyboards/model_f_labs/xwhatsit_util_comm.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* Copyright 2020 Purdea Andrei
|
||||||
|
* Copyright 2021 Matthew J Wolf
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#ifndef RAW_EPSIZE
|
||||||
|
# define RAW_EPSIZE 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define UTIL_COMM_VERSION_MAJOR 2
|
||||||
|
# define UTIL_COMM_VERSION_MID 0
|
||||||
|
# define UTIL_COMM_VERSION_MINOR 5
|
||||||
|
|
||||||
|
# define UTIL_COMM_MAGIC \
|
||||||
|
{ 0x55, 0xAA }
|
||||||
|
|
||||||
|
enum command {
|
||||||
|
UTIL_COMM_GET_VERSION = 0x11,
|
||||||
|
UTIL_COMM_ENTER_BOOTLOADER,
|
||||||
|
UTIL_COMM_DISABLE_KEYBOARD,
|
||||||
|
UTIL_COMM_ENABLE_KEYBOARD,
|
||||||
|
UTIL_COMM_GET_KEYSTATE,
|
||||||
|
UTIL_COMM_GET_THRESHOLDS,
|
||||||
|
UTIL_COMM_GET_KEYBOARD_FILENAME,
|
||||||
|
UTIL_COMM_ERASE_EEPROM,
|
||||||
|
UTIL_COMM_GET_SIGNAL_VALUE,
|
||||||
|
UTIL_COMM_GET_KEYBOARD_DETAILS,
|
||||||
|
UTIL_COMM_SHIFT_DATA,
|
||||||
|
UTIL_COMM_SET_DAC_VALUE,
|
||||||
|
UTIL_COMM_GET_ROW_STATE,
|
||||||
|
UTIL_COMM_SHIFT_DATA_EXT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum response { UTIL_COMM_RESPONSE_OK = 0x22, UTIL_COMM_RESPONSE_ERROR };
|
||||||
|
|
||||||
|
#if defined(CONTROLLER_IS_XWHATSIT_BEAMSPRING_REV_4)
|
||||||
|
# define GET_KEYBOARD_DETAILS_5 1
|
||||||
|
#elif defined(CONTROLLER_IS_XWHATSIT_MODEL_F_OR_WCASS_MODEL_F)
|
||||||
|
# define GET_KEYBOARD_DETAILS_5 2
|
||||||
|
#elif defined(CONTROLLER_IS_THROUGH_HOLE_BEAMSPRING)
|
||||||
|
# define GET_KEYBOARD_DETAILS_5 3
|
||||||
|
#elif defined(CONTROLLER_IS_THROUGH_HOLE_MODEL_F)
|
||||||
|
# define GET_KEYBOARD_DETAILS_5 4
|
||||||
|
#else
|
||||||
|
# define GET_KEYBOARD_DETAILS_5 0
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user