diff --git a/README.md b/README.md index cc1309c..075e788 100644 --- a/README.md +++ b/README.md @@ -29,16 +29,21 @@ Be advised that right now the underglow only works on the XIAO nRF52840 board, a | Board | Chip | USB Wired | Bluetooth Wireless | RGB Underglow | Comments | | --------------------- | -------- | ------------------ | ------------------ | ------------------ | ------------------------------------------------------------ | | XIAO | SAMD21 | :white_check_mark: | :x: | :x: | Should work but untested | -| Adafruit Qt PY | SAMD21 | :white_check_mark: | :x: | :x: | Should work but untested | | XIAO BLE | nRF52840 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | | XIAO RP2040 | RP2040 | :white_check_mark: | :x: | :x: for now | Underglow [maybe someday](https://github.com/zmkfirmware/zmk/issues/1085) | -| Adafruit Qt PY RP2040 | RP2040 | :white_check_mark: | :x: | :x: for now | Should work but untested | ### QMK -I have not written QMK firmware yet, but maybe I will for the RP2040. +Copy the contents of `firmware/qmk/keyboards/re_gret` into `[your_qmk_firmware]/keyboards/re_gret`, since I have not put the Re-gret firmware into the official QMK repo. + +Only the XIAO RP2040 is supported. The Adafruit QT Py RP2040 might possibly work but I don't think the reset button will function. + +| Board | Chip | USB Wired | RGB Underglow | Comments | +| --------------------- | -------- | ------------------ | ------------------ | ------------------------------------------------------------ | +| XIAO RP2040 | RP2040 | :white_check_mark: | :white_check_mark: | | ## Related * I cribbed the Xiao footprint, pogo pin idea, and battery from the [revxlp](https://gitlab.com/lpgalaxy/revxlp) +* I based the QMK shift register matrix code on [Sadek's](https://github.com/sadekbaroudi/qmk_firmware) * My original 36 key [Egret](https://github.com/rschenk/egret) was the starting point diff --git a/firmware/qmk/keyboards/re_gret/config.h b/firmware/qmk/keyboards/re_gret/config.h new file mode 100644 index 0000000..0e291e7 --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/config.h @@ -0,0 +1,31 @@ +// Copyright 2024 Ryan Schenk (@rschenk) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define MATRIX_COLS 5 +#define MATRIX_ROWS 8 + +#define SPI_SCK_PIN GP2 +#define SPI_MOSI_PIN GP3 +#define SPI_MISO_PIN NO_PIN + +#define SHIFTREG_MATRIX_ROW_CS GP4 +#define SHIFTREG_DIVISOR 8 +#define SHIFTREG_COLS 5 +#define SHIFTREG_ROWS 8 + +#define MATRIX_COL_PINS { GP27, GP28, GP29, GP6, GP7 } +// Row Number 0 1 2 3 4 5 6 7 +// SHR Pin Q: H G F E A B C D +#define SHIFTREG_ROW_PINS { 0x80, 0x40, 0x20, 0x10, 0x01, 0x02, 0x04, 0x08 } + +#define WS2812_DI_PIN GP26 +#define RGBLIGHT_LED_COUNT 11 + +#ifdef RGBLIGHT_ENABLE + #define RGBLIGHT_EFFECT_RAINBOW_SWIRL // enable rainbow swirl + #define RGBLIGHT_SLEEP // turn off LEDs when host sleeps + #define RGBLIGHT_LAYERS // per-layer LED effects + #define RGBLIGHT_DEFAULT_MODE RGBLIGHT_MODE_RAINBOW_SWIRL +#endif \ No newline at end of file diff --git a/firmware/qmk/keyboards/re_gret/halconf.h b/firmware/qmk/keyboards/re_gret/halconf.h new file mode 100644 index 0000000..6f838b4 --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/halconf.h @@ -0,0 +1,10 @@ +// Copyright 2024 Ryan Schenk (@rschenk) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#define HAL_USE_SPI TRUE +#define SPI_USE_WAIT TRUE +#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD + +#include_next diff --git a/firmware/qmk/keyboards/re_gret/keyboard.json b/firmware/qmk/keyboards/re_gret/keyboard.json new file mode 100644 index 0000000..2e9be5d --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/keyboard.json @@ -0,0 +1,63 @@ +{ + "manufacturer": "Ryan Schenk", + "keyboard_name": "re_gret", + "maintainer": "rschenk", + "bootloader": "rp2040", + "diode_direction": "ROW2COL", + "features": { + "bootmagic": true, + "command": false, + "console": false, + "extrakey": true, + "mousekey": true, + "nkro": true + }, + "processor": "RP2040", + "url": "https://github.com/rschenk/re-gret", + "usb": { + "device_version": "1.0.0", + "pid": "0xE9E8", + "vid": "0xFEED" + }, + "community_layouts": ["split_3x5_2"], + "layouts": { + "LAYOUT_split_3x5_2": { + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0.25}, + {"matrix": [0, 1], "x": 1, "y": 0.125}, + {"matrix": [0, 2], "x": 2, "y": 0}, + {"matrix": [0, 3], "x": 3, "y": 0.125}, + {"matrix": [0, 4], "x": 4, "y": 0.25}, + {"matrix": [4, 4], "x": 7, "y": 0.25}, + {"matrix": [4, 3], "x": 8, "y": 0.125}, + {"matrix": [4, 2], "x": 9, "y": 0}, + {"matrix": [4, 1], "x": 10, "y": 0.125}, + {"matrix": [4, 0], "x": 11, "y": 0.25}, + {"matrix": [1, 0], "x": 0, "y": 1.25}, + {"matrix": [1, 1], "x": 1, "y": 1.125}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1.125}, + {"matrix": [1, 4], "x": 4, "y": 1.25}, + {"matrix": [5, 4], "x": 7, "y": 1.25}, + {"matrix": [5, 3], "x": 8, "y": 1.125}, + {"matrix": [5, 2], "x": 9, "y": 1}, + {"matrix": [5, 1], "x": 10, "y": 1.125}, + {"matrix": [5, 0], "x": 11, "y": 1.25}, + {"matrix": [2, 0], "x": 0, "y": 2.25}, + {"matrix": [2, 1], "x": 1, "y": 2.125}, + {"matrix": [2, 2], "x": 2, "y": 2}, + {"matrix": [2, 3], "x": 3, "y": 2.125}, + {"matrix": [2, 4], "x": 4, "y": 2.25}, + {"matrix": [6, 4], "x": 7, "y": 2.25}, + {"matrix": [6, 3], "x": 8, "y": 2.125}, + {"matrix": [6, 2], "x": 9, "y": 2}, + {"matrix": [6, 1], "x": 10, "y": 2.125}, + {"matrix": [6, 0], "x": 11, "y": 2.25}, + {"matrix": [3, 3], "x": 3.5, "y": 3.25}, + {"matrix": [3, 4], "x": 4.5, "y": 3.5}, + {"matrix": [7, 4], "x": 6.5, "y": 3.5}, + {"matrix": [7, 3], "x": 7.5, "y": 3.25} + ] + } + } +} diff --git a/firmware/qmk/keyboards/re_gret/keymaps/default/keymap.c b/firmware/qmk/keyboards/re_gret/keymaps/default/keymap.c new file mode 100644 index 0000000..82db680 --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/keymaps/default/keymap.c @@ -0,0 +1,26 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* + * ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + * │ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │ + * ├───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┤ + * │ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ ; │ + * ├───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┤ + * │ Z │ X │ C │ V │ B │ │ N │ M │ , │ . │ / │ + * └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + * ┌───┐ ┌───┐ + * │Bsp├───┐ ┌───┤Ent│ + * └───┤Tab│ │Spc├───┘ + * └───┘ └───┘ + */ + [0] = LAYOUT_split_3x5_2( + KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, + KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, + KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, + KC_BSPC, KC_TAB, KC_SPC, KC_ENT + ) +}; diff --git a/firmware/qmk/keyboards/re_gret/matrix.c b/firmware/qmk/keyboards/re_gret/matrix.c new file mode 100644 index 0000000..7571929 --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/matrix.c @@ -0,0 +1,153 @@ +// Copyright 2024 Ryan Schenk (@rschenk) +// Copyright 2022 @sadekbaroudi (Sadek Baroudi) +// SPDX-License-Identifier: GPL-3.0-or-later +#include "quantum.h" +#include "spi_master.h" +#include /* memset */ +#include /* close */ +#include "quantum.h" +#include "matrix.h" +#ifdef FP_SR595_MATRIX_DEBUG +#include +#include +#define FP_SR595_MATRIX_DEBUG_RATIO 10000 +#endif + +#if (!defined(SHIFTREG_MATRIX_ROW_CS)) +# error Missing shift register I/O pin definitions +#endif + +int matrixArraySize = MATRIX_ROWS * sizeof(matrix_row_t); +matrix_row_t oldMatrix[MATRIX_ROWS]; + +#define SHIFTREG_OUTPUT_BITS 8 +pin_t colPinsSR[MATRIX_COLS] = MATRIX_COL_PINS; +uint8_t rowPinCodesSR[SHIFTREG_ROWS] = SHIFTREG_ROW_PINS; + +// semaphore to make sure SPI doesn't get called multiple times +static bool shiftRegisterSPILocked = false; + +void semaphore_lock(bool value) { + shiftRegisterSPILocked = value; +} + +bool semaphore_is_locked(void) { + return shiftRegisterSPILocked; +} + +void sr_74hc595_spi_stop(void) { + spi_stop(); + semaphore_lock(false); +} + +bool sr_74hc595_spi_start(void) { + if (!spi_start(SHIFTREG_MATRIX_ROW_CS, false, 0, SHIFTREG_DIVISOR)) { + dprintf("74hc595 matrix: failed to start spi\n"); + sr_74hc595_spi_stop(); + return false; + } + + semaphore_lock(true); + wait_us(1); // not sure if I need this + return true; +} + +bool sr_74hc595_spi_send_byte(uint8_t data) { + sr_74hc595_spi_start(); + gpio_write_pin_low(SHIFTREG_MATRIX_ROW_CS); + matrix_io_delay(); + spi_write(data); + matrix_io_delay(); + gpio_write_pin_high(SHIFTREG_MATRIX_ROW_CS); + sr_74hc595_spi_stop(); + return true; +} + +/** + * Set the entire shift register to be full of inactive bits + */ +void clearRows(void) { + uint8_t value = 0b00000000; + sr_74hc595_spi_send_byte(value); +} + +void setRow(int rowNumber, bool test_run) { + uint8_t rowShiftByte = rowPinCodesSR[rowNumber]; + if(test_run) { + dprintf("byte sent: %d\n", rowShiftByte); + } + sr_74hc595_spi_send_byte(rowShiftByte); +} + +/* + * Override QMK matrix initialization + */ +void matrix_init_custom(void) { + wait_ms(300); + spi_init(); + + // Set up initial states for all the column pins + for(int c = 0; c < SHIFTREG_COLS; c++) { + // Note: This needs to use the internal pull down resistors, and atmegas + // do *not* support that + gpio_set_pin_input_low(colPinsSR[c]); + } + + // Set the CS to low by default, and specify as an output pin + gpio_write_pin_high(SHIFTREG_MATRIX_ROW_CS); // should be high when using SPI? + gpio_set_pin_output(SHIFTREG_MATRIX_ROW_CS); + + // Since it's the init, deactivate all the columns. We'll activate once we + // get to the matrix scan + clearRows(); +} + +/* + * Override QMK matrix scan + */ +bool matrix_scan_custom(matrix_row_t current_matrix[]) { + // respect the semaphore + if (semaphore_is_locked()) { + return false; + } + + bool matrix_has_changed = false; + + // reset the current matrix, as we'll be updating and comparing to the old matrix + memset(current_matrix, 0, matrixArraySize); + +#ifdef FP_SR595_MATRIX_DEBUG + bool debug_output = ((rand() % FP_SR595_MATRIX_DEBUG_RATIO) == 1); +#else + bool debug_output = false; +#endif + + // Loop through the rows, activating one at a time, and read the columns, + // and place in the new current_matrix + for (int r = 0; r < SHIFTREG_ROWS; r++) { + if (debug_output) { + dprintf("row iteration: %d\n", r); + } + setRow(r, debug_output); + matrix_io_delay(); + + for (int c = 0; c < SHIFTREG_COLS; c++) { + current_matrix[r] |= ((gpio_read_pin(colPinsSR[c]) ? 1 : 0) << c); + } + } + + matrix_has_changed = memcmp(current_matrix, oldMatrix, matrixArraySize) != 0; + memcpy(oldMatrix, current_matrix, matrixArraySize); + +#ifdef FP_SR595_MATRIX_DEBUG + if (matrix_has_changed) { + matrix_print(); + } +#endif + + // Deactivate all the columns for the next run. + clearRows(); + matrix_io_delay(); + + return matrix_has_changed; +} \ No newline at end of file diff --git a/firmware/qmk/keyboards/re_gret/mcuconf.h b/firmware/qmk/keyboards/re_gret/mcuconf.h new file mode 100644 index 0000000..e63c10f --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/mcuconf.h @@ -0,0 +1,9 @@ +// Copyright 2024 Ryan Schenk (@rschenk) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include_next + +#undef RP_SPI_USE_SPI0 +#define RP_SPI_USE_SPI0 TRUE diff --git a/firmware/qmk/keyboards/re_gret/readme.md b/firmware/qmk/keyboards/re_gret/readme.md new file mode 100644 index 0000000..9ac2185 --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/readme.md @@ -0,0 +1,27 @@ +# Re-gret + +![re_gret](https://github.com/rschenk/re-gret/blob/main/images/IMG_0812.jpeg?raw=true) + +A 34-key keyboard powered by a Seeed XIAO RP2040, with hot-swappable ChocV1 switches. + +* Keyboard Maintainer: [Ryan Schenk](https://github.com/rschenk) +* Hardware Supported: Re-gret PCB with Seeed XIAO RP2040 controller +* Hardware Availability: Gerbers are available in the [Re-gret repo](https://github.com/rschenk/re-gret) and the controller is available from [Seeed Studio](https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html) + +Make example for this keyboard (after setting up your build environment): + + make re_gret:default + +Flashing example for this keyboard: + + make re_gret:default:flash + +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. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +## Bootloader + +Enter the bootloader in 3 ways: + +* **Bootmagic reset**: Hold down the top-left key ("Q" on qwerty) and plug in the keyboard +* **Physical reset button**: Double click the reset button +* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available diff --git a/firmware/qmk/keyboards/re_gret/rules.mk b/firmware/qmk/keyboards/re_gret/rules.mk new file mode 100644 index 0000000..0ad2824 --- /dev/null +++ b/firmware/qmk/keyboards/re_gret/rules.mk @@ -0,0 +1,6 @@ +SRC += matrix.c + +SPI_DRIVER_REQUIRED = yes +CUSTOM_MATRIX = lite +RGBLIGHT_ENABLE = yes +WS2812_DRIVER = vendor \ No newline at end of file