diff options
| -rw-r--r-- | keyboards/handwired/dqz11n1g/config.h | 58 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/dqz11n1g.h | 51 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/info.json | 141 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/keymaps/default/keymap.c | 72 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/keymaps/default/readme.md | 17 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/matrix.c | 131 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/readme.md | 80 | ||||
| -rw-r--r-- | keyboards/handwired/dqz11n1g/rules.mk | 24 | 
8 files changed, 574 insertions, 0 deletions
diff --git a/keyboards/handwired/dqz11n1g/config.h b/keyboards/handwired/dqz11n1g/config.h new file mode 100644 index 0000000000..0631787f55 --- /dev/null +++ b/keyboards/handwired/dqz11n1g/config.h @@ -0,0 +1,58 @@ +/* +Copyright (c) 2022 David Kuehling <dvdkhlng TA posteo TOD de> +   +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x4451 +#define DEVICE_VER 0x0001 +#define PRODUCT    DQz11N1G Controller Replacement + +/* Matrix size */ +#define MATRIX_ROWS 7 +#define MATRIX_COLS 19 + +/* Pin-out */ +#define MATRIX_ROW_PINS { D1, D0, D4, C6, D7, E6, B4 } + +/* The pin connecting to the SN74HC165 SH/~LD in */ +#define ROW_SHIFT_PIN B6 + +/* Column read via SPI (shift register) */ +/* #define MATRIX_COL_PINS { } */ +#define UNUSED_PINS + +#define LED_CAPS_LOCK_PIN F7 /* A0 */ +#define LED_NUM_LOCK_PIN F5 /*A2 */ +#define LED_SCROLL_LOCK_PIN F4 /*A3 */ + +#define LED_FUN_LOCK_PIN F6 /* A1 (handled in layer_state_set_user()) */ + +/* audio config */ +#define AUDIO_PIN B5 +#define AUDIO_CLICKY +#define AUDIO_INIT_DELAY +#define AUDIO_CLICKY_FREQ_RANDOMNESS 0.0f +#define NO_MUSIC_MODE + +/* diodes go row->col, though this is hard-coded in matrix.c and we drive the + * matrix differently: we have pull-down on the columns and drive the selected + * row high */ +/* #define DIODE_DIRECTION ROW2COL */ diff --git a/keyboards/handwired/dqz11n1g/dqz11n1g.h b/keyboards/handwired/dqz11n1g/dqz11n1g.h new file mode 100644 index 0000000000..f5c55bd6d5 --- /dev/null +++ b/keyboards/handwired/dqz11n1g/dqz11n1g.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 David Kuehling <dvdkhlng TA posteo TOD de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "quantum.h" + +#define XXX KC_NO + +/* Fill actually existing keys into the 7x19 keyboard matrix */ +#define LAYOUT(                                                \ +    k00, k01, k02, k03, k04, k05,   k06, k07, k08, k09, k0A, k0B, k0C,   k0D, k0E, k0F, k0G, k0H, k0J, \ +    k10, k11, k12, k13, k14, k15,   k16, k17, k18, k19, k1A, k1B, k1C,   k1D, k1E, k1F, k1G, k1H, k1J, \ +    k20, k21, k22, k23, k24, k25,   k26, k27, k28, k29, k2A, k2B, k2C,   k2D, k2E, k2F, k2G, k2H, k2J, \ +    k30, k31, k32, k33, k34, k35,   k36, k37, k38, k39, k3A, k3B, k3C,   k3D, k3E, k3F, k3G, k3H, k3J, \ +    k40, k41, k42, k43, k44, k45,                                        k4D, k4E, k4F, k4G, k4H, k4J, \ +         k51, k52, k53, k54,                                                  k5E, k5F, k5G, k5H, \ +                                    k46, k47, k48,      k4A, k4B, k4C,  \ +                                    k56, k57, k58,      k5A, k5B, k5C,  \ +                                              k68,      k6A             \ +) {                                                                     \ +   /* left hand */                      /* middle/thumb block */                      /* right hand */ \ +    { k00, k01, k02, k03, k04, k05,   k06, k07, k08, k09, k0A, k0B, k0C,   k0D, k0E, k0F, k0G, k0H, k0J }, \ +    { k10, k11, k12, k13, k14, k15,   k16, k17, k18, k19, k1A, k1B, k1C,   k1D, k1E, k1F, k1G, k1H, k1J }, \ +    { k20, k21, k22, k23, k24, k25,   k26, k27, k28, k29, k2A, k2B, k2C,   k2D, k2E, k2F, k2G, k2H, k2J }, \ +    { k30, k31, k32, k33, k34, k35,   k36, k37, k38, k39, k3A, k3B, k3C,   k3D, k3E, k3F, k3G, k3H, k3J }, \ +    { k40, k41, k42, k43, k44, k45,   k46, k47, k48, XXX, k4A, k4B, k4C,   k4D, k4E, k4F, k4G, k4H, k4J }, \ +    { XXX, k51, k52, k53, k54, XXX,   k56, k57, k58, XXX, k5A, k5B, k5C,   XXX, k5E, k5F, k5G, k5H, XXX }, \ +    { XXX, XXX, XXX, XXX, XXX, XXX,   XXX, XXX, k68, XXX, k6A, XXX, XXX,   XXX, XXX, XXX, XXX, XXX, XXX }, \ +} + +/* + * Local Variables: + * c-basic-offset:4 + * fill-column: 76 + * End: + */ diff --git a/keyboards/handwired/dqz11n1g/info.json b/keyboards/handwired/dqz11n1g/info.json new file mode 100644 index 0000000000..0c56752ffd --- /dev/null +++ b/keyboards/handwired/dqz11n1g/info.json @@ -0,0 +1,141 @@ +{ +    "keyboard_name": "DQz11N1G", +    "url": "https://github.com/dvdkhlng/qmk_firmware_dqz11n1g", +    "maintainer": "dvdkhlng", +    "layouts": { +        "LAYOUT": { +            "layout": [ +                {"x": 0, "y": 0, "matrix": [0, 0] }, +                {"x": 1, "y": 0, "matrix": [0, 1] }, +                {"x": 2, "y": 0, "matrix": [0, 2] }, +                {"x": 3, "y": 0, "matrix": [0, 3] }, +                {"x": 4, "y": 0, "matrix": [0, 4] }, +                {"x": 5, "y": 0, "matrix": [0, 5] }, + +                {"x": 7, "y": 0, "matrix": [0, 6] }, +                {"x": 8, "y": 0, "matrix": [0, 7] }, +                {"x": 9, "y": 0, "matrix": [0, 8] }, +                {"x": 10, "y": 0, "matrix": [0, 9] }, +                {"x": 11, "y": 0, "matrix": [0, 10] }, +                {"x": 12, "y": 0, "matrix": [0, 11] }, +                {"x": 13, "y": 0, "matrix": [0, 12] }, + +                {"x": 15, "y": 0, "matrix": [0, 13] }, +                {"x": 16, "y": 0, "matrix": [0, 14] }, +                {"x": 17, "y": 0, "matrix": [0, 15] }, +                {"x": 18, "y": 0, "matrix": [0, 16] }, +                {"x": 19, "y": 0, "matrix": [0, 17] }, +                {"x": 20, "y": 0, "matrix": [0, 18] }, + +                {"x": 0, "y": 1, "matrix": [1, 0] }, +                {"x": 1, "y": 1, "matrix": [1, 1] }, +                {"x": 2, "y": 1, "matrix": [1, 2] }, +                {"x": 3, "y": 1, "matrix": [1, 3] }, +                {"x": 4, "y": 1, "matrix": [1, 4] }, +                {"x": 5, "y": 1, "matrix": [1, 5] }, + +                {"x": 7, "y": 1, "matrix": [1, 6] }, +                {"x": 8, "y": 1, "matrix": [1, 7] }, +                {"x": 9, "y": 1, "matrix": [1, 8] }, +                {"x": 10, "y": 1, "matrix": [1, 9] }, +                {"x": 11, "y": 1, "matrix": [1, 10] }, +                {"x": 12, "y": 1, "matrix": [1, 11] }, +                {"x": 13, "y": 1, "matrix": [1, 12] }, + +                {"x": 15, "y": 1, "matrix": [1, 13] }, +                {"x": 16, "y": 1, "matrix": [1, 14] }, +                {"x": 17, "y": 1, "matrix": [1, 15] }, +                {"x": 18, "y": 1, "matrix": [1, 16] }, +                {"x": 19, "y": 1, "matrix": [1, 17] }, +                {"x": 20, "y": 1, "matrix": [1, 18] }, + +                {"x": 0, "y": 2, "matrix": [2, 0] }, +                {"x": 1, "y": 2, "matrix": [2, 1] }, +                {"x": 2, "y": 2, "matrix": [2, 2] }, +                {"x": 3, "y": 2, "matrix": [2, 3] }, +                {"x": 4, "y": 2, "matrix": [2, 4] }, +                {"x": 5, "y": 2, "matrix": [2, 5] }, + +                {"x": 7, "y": 2, "matrix": [2, 6] }, +                {"x": 8, "y": 2, "matrix": [2, 7] }, +                {"x": 9, "y": 2, "matrix": [2, 8] }, +                {"x": 10, "y": 2, "matrix": [2, 9] }, +                {"x": 11, "y": 2, "matrix": [2, 10] }, +                {"x": 12, "y": 2, "matrix": [2, 11] }, +                {"x": 13, "y": 2, "matrix": [2, 12] }, + +                {"x": 15, "y": 2, "matrix": [2, 13] }, +                {"x": 16, "y": 2, "matrix": [2, 14] }, +                {"x": 17, "y": 2, "matrix": [2, 15] }, +                {"x": 18, "y": 2, "matrix": [2, 16] }, +                {"x": 19, "y": 2, "matrix": [2, 17] }, +                {"x": 20, "y": 2, "matrix": [2, 18] }, + +                {"x": 0, "y": 3, "matrix": [3, 0] }, +                {"x": 1, "y": 3, "matrix": [3, 1] }, +                {"x": 2, "y": 3, "matrix": [3, 2] }, +                {"x": 3, "y": 3, "matrix": [3, 3] }, +                {"x": 4, "y": 3, "matrix": [3, 4] }, +                {"x": 5, "y": 3, "matrix": [3, 5] }, + +                {"x": 7, "y": 3, "matrix": [3, 6] }, +                {"x": 8, "y": 3, "matrix": [3, 7] }, +                {"x": 9, "y": 3, "matrix": [3, 8] }, +                {"x": 10, "y": 3, "matrix": [3, 9] }, +                {"x": 11, "y": 3, "matrix": [3, 10] }, +                {"x": 12, "y": 3, "matrix": [3, 11] }, +                {"x": 13, "y": 3, "matrix": [3, 12] }, + +                {"x": 15, "y": 3, "matrix": [3, 13] }, +                {"x": 16, "y": 3, "matrix": [3, 14] }, +                {"x": 17, "y": 3, "matrix": [3, 15] }, +                {"x": 18, "y": 3, "matrix": [3, 16] }, +                {"x": 19, "y": 3, "matrix": [3, 17] }, +                {"x": 20, "y": 3, "matrix": [3, 18] }, + +                {"x": 0, "y": 4, "h": 2, "matrix": [4, 0] }, +                {"x": 1, "y": 4, "matrix": [4, 1] }, +                {"x": 2, "y": 4, "matrix": [4, 2] }, +                {"x": 3, "y": 4, "matrix": [4, 3] }, +                {"x": 4, "y": 4, "matrix": [4, 4] }, +                {"x": 5, "y": 4, "matrix": [4, 5] }, + +                {"x": 15, "y": 4, "matrix": [4, 13] }, +                {"x": 16, "y": 4, "matrix": [4, 14] }, +                {"x": 17, "y": 4, "matrix": [4, 15] }, +                {"x": 18, "y": 4, "matrix": [4, 16] }, +                {"x": 19, "y": 4, "matrix": [4, 17] }, +                {"x": 20, "y": 4, "h": 2, "matrix": [4, 18] }, + +                {"x": 1, "y": 5, "matrix": [5, 1] }, +                {"x": 2, "y": 5, "matrix": [5, 2] }, +                {"x": 3, "y": 5, "matrix": [5, 3] }, +                {"x": 4, "y": 5, "matrix": [5, 4] }, + +                {"x": 16, "y": 5, "matrix": [5, 14] }, +                {"x": 17, "y": 5, "matrix": [5, 15] }, +                {"x": 18, "y": 5, "matrix": [5, 16] }, +                {"x": 19, "y": 5, "matrix": [5, 17] }, + +                {"x": 5, "y": 7, "matrix": [4, 6] }, +                {"x": 6, "y": 7, "matrix": [4, 7] }, +                {"x": 7, "y": 7, "matrix": [4, 8] }, + +                {"x": 13, "y": 7, "matrix": [4, 10] }, +                {"x": 14, "y": 7, "matrix": [4, 11] }, +                {"x": 15, "y": 7, "matrix": [4, 12] }, + +                {"x": 5, "y": 8, "h": 2, "matrix": [5, 6] }, +                {"x": 6, "y": 8, "h": 2, "matrix": [5, 7] }, +                {"x": 7, "y": 8, "matrix": [5, 8] }, + +                {"x": 13, "y": 8, "matrix": [5, 10] }, +                {"x": 14, "y": 8, "h": 2, "matrix": [5, 11] }, +                {"x": 15, "y": 8, "h": 2, "matrix": [5, 12] }, + +                {"x": 7, "y": 9, "matrix": [6, 8] }, +                {"x": 13, "y": 9, "matrix": [6, 10] } +            ] +        } +    } +} diff --git a/keyboards/handwired/dqz11n1g/keymaps/default/keymap.c b/keyboards/handwired/dqz11n1g/keymaps/default/keymap.c new file mode 100644 index 0000000000..29d9cad7b7 --- /dev/null +++ b/keyboards/handwired/dqz11n1g/keymaps/default/keymap.c @@ -0,0 +1,72 @@ +/* Copyright (c) 2022 David Kuehling < dvdkhlng TA posteo TOD de > + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +#include QMK_KEYBOARD_H + +enum layer_names { _DEFAULT, _FUNCTION }; +#define KC_FUN TG(_FUNCTION) + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { +    [_DEFAULT] = LAYOUT( +        KC_F1,  KC_F2,  KC_F3,  KC_F4,  KC_F5,  KC_F6,  KC_FUN,  KC_NUM, KC_P7, KC_P8, KC_P9, KC_PSLS, KC_PSCR,  KC_F7,  KC_F8,  KC_F9,  KC_F10, KC_F11, KC_F12, +      +        KC_1,   KC_2,   KC_3,   KC_4,   KC_5,   KC_6,   KC_VOLU, KC_ESC, KC_P4, KC_P5, KC_P6, KC_PAST, KC_SCRL,  KC_7,   KC_8,   KC_9,   KC_0,   KC_MINS,KC_EQL,  +        KC_NUBS,KC_Q,   KC_W,   KC_E,   KC_R,   KC_T,   KC_VOLD, KC_GRV, KC_P1, KC_P2, KC_P3, KC_PMNS, KC_BRK,   KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,   KC_LBRC,  +        KC_CAPS,KC_A,   KC_S,   KC_D,   KC_F,   KC_G,   KC_MUTE, KC_WSCH,KC_P0,KC_PDOT,KC_PENT,KC_PPLS,KC_INS,   KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,KC_QUOT,  +        KC_LSFT,KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,                                                            KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,  +        /* */  KC_LCTL, KC_LGUI,KC_LALT,KC_RBRC,                                                                         KC_NUHS,KC_RALT,KC_APP, KC_RCTL, /* */ +         +        /* thumb keys: */                      KC_BSPC, KC_HOME, KC_END,                       KC_LEFT, KC_RGHT, KC_DEL, +        /* thumb keys: */                      KC_SPC,  KC_TAB,  KC_PGUP,                      KC_UP,   KC_ENT,  KC_SPC, +        /* thumb keys: */                                        KC_PGDN,                      KC_DOWN +        ), +     +    /* This is the "function key locked" layer.  It is not documented by +     * Maltron, so just putting some "Quantum" keycodes here for testing that +     * the layer exists and Fun Lock LED works. */ +    [_FUNCTION] = LAYOUT( +        KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_TRNS,KC_TRNS,KC_BTN3,KC_MS_U,KC_WH_U,KC_NO, KC_NO,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  +         +        KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  CK_UP,  AU_ON,  KC_MS_L,KC_BTN1,KC_MS_R,KC_NO, KC_TRNS,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,   +        KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  CK_DOWN,AU_OFF, KC_BTN2,KC_MS_D,KC_WH_D,KC_NO, KC_NO,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,    +        KC_TRNS,KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  CK_TOGG,KC_NO,  KC_ACL0,KC_ACL1,KC_ACL2,KC_NO, KC_NO,    KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,    +        KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,                                                           KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,  KC_NO,    +        /* */  KC_NO,   KC_NO,  KC_NO,  KC_NO,                                                                           KC_NO,  KC_NO,  KC_NO,  KC_NO,   /* */ +         +        /* thumb keys: */                      KC_NO,   KC_NO,   KC_NO,                         KC_NO,   KC_NO,   KC_NO,  +        /* thumb keys: */                      KC_NO,   KC_NO,   KC_NO,                         KC_NO,   KC_NO,   KC_NO,  +        /* thumb keys: */                                        KC_NO,                         KC_NO +        ) +}; + +/* Show "Fun Lock" layer state via the "Fun Lock" LED */ +layer_state_t layer_state_set_user(layer_state_t state) { +    +    setPinOutput(LED_FUN_LOCK_PIN); +    +    if (layer_state_cmp(state, _FUNCTION)) +        writePinHigh(LED_FUN_LOCK_PIN); +    else +        writePinLow(LED_FUN_LOCK_PIN); + +    return state; +} + +/* + * Local Variables: + * c-basic-offset:4 + * fill-column: 76 + * End: + */ diff --git a/keyboards/handwired/dqz11n1g/keymaps/default/readme.md b/keyboards/handwired/dqz11n1g/keymaps/default/readme.md new file mode 100644 index 0000000000..d61546eb37 --- /dev/null +++ b/keyboards/handwired/dqz11n1g/keymaps/default/readme.md @@ -0,0 +1,17 @@ + + +# Default Layout for DQz11N1G-DE + +This is the layout corresponding to what the Maltron keyboard DQz11N1G-DE I +own came with (using the original pre-installed controller).  Note that this +differs from German Maltron layout as published on [Maltron's +website](https://www.maltron.com/germany.html).  Use the photo above as a +reference for the layout implemented here. + +I did not find any official documentation about the the Function Lock key on +the original Maltron keyboards.  It seems that it implements some of the +features that are documented for the one-handed Maltron keyboards.  Most +keys don't send any keycodes at all when function lock is enabed. + +We instead map some of the Quantum keycodes (mouse keys and audio control) +in the middle (keypad) section of the keypad, when Function Lock is enabled.
\ No newline at end of file diff --git a/keyboards/handwired/dqz11n1g/matrix.c b/keyboards/handwired/dqz11n1g/matrix.c new file mode 100644 index 0000000000..f9f3f2b68f --- /dev/null +++ b/keyboards/handwired/dqz11n1g/matrix.c @@ -0,0 +1,131 @@ +/* +  Copyright (c) 2022 David Kuehling <dvdkhlng TA posteo TOD de> + +  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 <stdint.h> +#include <stdbool.h> +#include <string.h> + +#include <avr/io.h> + +#include "spi_master.h" +#include "quantum.h" +#include "matrix.h" + +static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; + +static void unselect_rows(void); + +void matrix_init_custom(void) { +    /* initialize row pins */ +    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { +        setPinOutput(row_pins[row]); +    } +    unselect_rows(); + +    /* columns read via shift-register on SPI lines */ + +    /* Enable SPI, Master, set clock rate fck/2.  First bit already at Qh +     * output before clock edge (CPHA=0).  SN74HC165 shift register shifts +     * on low-to-high transition (CPOL=1).  Receive the LSB first (DORD=1). +     */ +    bool lsbFirst = true; +    uint8_t mode = 2;  /* CPOL=1, CPHA=0 */ +    uint16_t divisor = 16; + +    /* According to Atmega32U4 datasheet, PB0 *must* be set to output, +     * otherwise it will interfere with SPI master operation.  On pro-micro +     * it's connected to a yellew LED. */ +    pin_t slavePin = PB0; +    spi_init(); +    spi_start(slavePin, lsbFirst, mode, divisor); + +    /* Initialize pin controlling the shift register's SH/~LD pin */ +    setPinOutput(ROW_SHIFT_PIN); +} + +static void select_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        writePinHigh(pin); +    } +} + +static void unselect_row(uint8_t row) { +    pin_t pin = row_pins[row]; +    if (pin != NO_PIN) { +        writePinLow(pin); +    } +} + +static void unselect_rows(void) { +    for (uint8_t row = 0; row < MATRIX_ROWS; row++) { +        unselect_row(row); +    } +} + +bool matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { +    /* Start with a clear matrix row */ +    matrix_row_t current_row_value = 0; + +    /* Set shift register SH/~LD pin to "load" mode */ +    writePinLow(ROW_SHIFT_PIN); +    select_row(current_row); +    matrix_output_select_delay(); + +    /* Set shift register SH/~LD pin to "shift" mode */ +    writePinHigh(ROW_SHIFT_PIN); + +    /* For each octet of columns... */ +    for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index += 8) { +        spi_status_t read_result = spi_read(); +        if (read_result >= 0) { +            /* only if SPI read successful: populate the matrix row with the +               state of the 8 consecutive column bits */ +            current_row_value |= ((matrix_row_t)read_result << col_index); +        } +    } + +    /* Unselect row & wait for all columns signals to go high. */ +    unselect_row(current_row); +    matrix_output_unselect_delay(current_row, current_row_value != 0);  + +    /* Update row in matrix. */ +    if (current_row_value != current_matrix[current_row]) { +        current_matrix[current_row] = current_row_value; +        return true; +    } + +    return false; +} + +bool matrix_scan_custom(matrix_row_t curr_matrix[]) { +    bool changed = false; + +    /* set row, read cols */ +    for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) { +        changed |= matrix_read_cols_on_row(curr_matrix, current_row); +    } + +    return changed; +} + +/* + * Local Variables: + * c-basic-offset:4 + * fill-column: 76 + * End: + */ diff --git a/keyboards/handwired/dqz11n1g/readme.md b/keyboards/handwired/dqz11n1g/readme.md new file mode 100644 index 0000000000..0e3a57873d --- /dev/null +++ b/keyboards/handwired/dqz11n1g/readme.md @@ -0,0 +1,80 @@ +# DQz11N1G + + + +Firmware for a DIY controller replacement for one of the ortholinear contoured +keyboards manufactured by [PCD Maltron Ltd](https://www.maltron.com) + +This work here in no way officially associated with PCD Maltron Ltd and comes +with NO WARRANTY.  Modifying your Maltron keyboard as described below will +certainly void your warranty and may cause damage to your keyboard.  Proceed +at your own risk! + +* maintainer: [David Kuehling](https://github.com/dvdkhlng/qmk_firmware_dqz11n1g) +* Hardware Supported: Maltron DQz11N1G with a replacement controller board +  assembled as described below.  The work here is based on a german version +  of the keyboard: DQz11N1G-DE.  I assume, but don't know for sure, that +  minor or no changes at all are required to make this work on different +  language versions of the keyboard. +* Hardware Availability: +  * [PCD Maltron Ltd](https://www.maltron.com), for the original keyboard +  * 1x [Arduino Pro Micro](https://www.sparkfun.com/products/12640) +  * 3x [SN74HC165](https://www.ti.com/product/SN74HC165) +  * 1x DIL connector 2 rows a 17 pins. +  * 19x pull-down resistors (10k Ohm), +  * 4 LED current limiting resistors (not sure about the correct resistance, +    using 470 Ohm here) + +Make example for this keyboard (after setting up your build environment): + +    make handwired/dqz11n1g:default + +## In Detail + +[PCD Maltron Ltd](https://www.maltron.com) manufacturs ergonomic keyboards +that appear to be hand-wired internally.  For the Maltron DQz11N1G-DE +keyboard that I happen to own, the keyboard matrix is wired to a 34-pin DIL +connector.  This makes it rather easy to replace the proprietary +controller-board with a self-made board based on the QMK firmware. + +I don't really like the default layout of my Maltron DQz11N1G-DE keyboard, +and modding it to work with QMK allows me to adapt it to my needs.  It +especially allows for the two space keys to assume different roles, thereby +creating an additional easily reachable thumb-key. + +### Internal Details of Keyboard Matrix and DIL Connector + + + + + +### Replacement Keyboard Controller Board + +Due to supply chain problems, I decided to base this on an +Arduino-compatible [Pro Micro](https://www.sparkfun.com/products/12640) +board which is still easy to source. + +Unfortunately pin-count of the DQz11N1G-DE's keyboard matrix is way beyond +the Pro Micro's available I/O pin count.  I'm using three 8-bit +shift-registers ([SN74HC165](https://www.ti.com/product/SN74HC165) ) to +connect the 19 colums of the keyboard matrix for readout.  Due to diode +direction in DQz11N1G-DE we also need 19 pull-down resistors one for each of +the utilized shift-register inputs. + +This is a design sketch of the replacement board this is based on.  Note how +we need a custom matrix.c source file to deal with the shift register based +keyboard readout. + + + +This is how the assembled controller board looks like, on the right side you +see the original PIC-based controller the keyboard ships with. + + + +Inside of the keyboard after installing the new controller board: + + + +(Not visible in the photo: I drilled hole into the keyboard above the USB +connector for a reset switch to simplify flashing controller firmware) diff --git a/keyboards/handwired/dqz11n1g/rules.mk b/keyboards/handwired/dqz11n1g/rules.mk new file mode 100644 index 0000000000..db8a809da9 --- /dev/null +++ b/keyboards/handwired/dqz11n1g/rules.mk @@ -0,0 +1,24 @@ +# MCU name +MCU = atmega32u4 + +# Bootloader selection +BOOTLOADER = caterina + +# Keyboard matrix uses shift-registers read via SPI +CUSTOM_MATRIX = lite +SRC += matrix.c  +QUANTUM_LIB_SRC += spi_master.c + +# Build Options +#   change yes to no to disable +# +BOOTMAGIC_ENABLE = no       # Enable Bootmagic Lite +MOUSEKEY_ENABLE = yes       # Mouse keys +EXTRAKEY_ENABLE = yes       # Audio control and System control +CONSOLE_ENABLE = no         # Console for debug +COMMAND_ENABLE = yes        # Commands for debug and configuration +NKRO_ENABLE = no            # Enable N-Key Rollover +BACKLIGHT_ENABLE = no       # Enable keyboard backlight functionality +RGBLIGHT_ENABLE = no        # Enable keyboard RGB underglow +AUDIO_ENABLE = yes          # Audio output +  | 
