[Keyboard] Handwired Maltron DQz11N1G contoured keyboard (#17237)

* Basic support for Maltron DQz11N1G controller replacement.

* Update keyboards/handwired/dqz11n1g/rules.mk

* Rehost images to cubeupload.com.

(They were previously hosted via github wiki)

* Apply suggestions from noroadsleft code review

* Update keyboards/handwired/dqz11n1g/dqz11n1g.h
This commit is contained in:
David Kühling 2022-07-17 18:49:36 +02:00 committed by GitHub
parent 747b33cb81
commit 931c7539d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 574 additions and 0 deletions

View file

@ -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 */

View file

@ -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:
*/

View file

@ -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] }
]
}
}
}

View file

@ -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:
*/

View file

@ -0,0 +1,17 @@
![DQz11N1G-DE Layout Image](https://u.cubeupload.com/ddklg/OPBN5q.jpg)
# 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.

View file

@ -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:
*/

View file

@ -0,0 +1,80 @@
# DQz11N1G
![DQz11N1G](https://u.cubeupload.com/ddklg/OPBN5q.jpg)
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
![DQz11N1G-DE keyboard matrix](https://u.cubeupload.com/ddklg/OJFue6.jpg)
![DQz11N1G-DE keyboard matrix connector](https://u.cubeupload.com/ddklg/fjFXeL.png)
### 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.
![Sketch of Keyboard Controller Board](https://u.cubeupload.com/ddklg/GBZgSf.png)
This is how the assembled controller board looks like, on the right side you
see the original PIC-based controller the keyboard ships with.
![The assembled controller next to the original controller the keyboard ships with](https://u.cubeupload.com/ddklg/KLYF2V.jpg)
Inside of the keyboard after installing the new controller board:
![Installed controller](https://u.cubeupload.com/ddklg/Br0aiF.jpg)
(Not visible in the photo: I drilled hole into the keyboard above the USB
connector for a reset switch to simplify flashing controller firmware)

View file

@ -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