Adding Bad Wings Support (#20153)

This commit is contained in:
Jason Hazel 2023-03-21 16:53:06 -04:00 committed by GitHub
parent 0bb9eada83
commit b1e6b3798a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 335 additions and 0 deletions

View file

@ -0,0 +1,19 @@
// Copyright 2023 Jason Hazel (@jasonhazel)
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#define SPI_SCK_PIN GP2
#define SPI_MOSI_PIN GP3
#define SPI_MISO_PIN GP4
#define SHIFTREG_MATRIX_COL_CS GP0
#define SHIFTREG_DIVISOR 8
#define SHIFTREG_ROWS 5
#define SHIFTREG_COLS 8
#define MATRIX_ROW_PINS_SR { GP26, GP27, GP28, GP29, GP6 }
#define POINTING_DEVICE_CS_PIN GP1
#define CIRQUE_PINNACLE_DIAMETER_MM 35
#define POINTING_DEVICE_ROTATION_90

View file

@ -0,0 +1,12 @@
// Copyright 2023 Jason Hazel (@jasonhazel)
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#define HAL_USE_SPI TRUE
#define HAL_USE_I2C TRUE
#define HAL_USE_PWM TRUE
#define SPI_USE_WAIT TRUE
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
#include_next <halconf.h>

View file

@ -0,0 +1,66 @@
{
"keyboard_name": "Bad Wings",
"manufacturer": "Hazel",
"maintainer": "jasonhazel",
"url": "https://shop.hazel.cc/products/bad-wings",
"usb": {
"vid": "0x4A48",
"pid": "0x4257",
"device_version": "1.0.0"
},
"processor": "RP2040",
"bootloader": "rp2040",
"matrix_size": {
"cols": 8,
"rows": 5
},
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"deferred_exec": true,
"nkro": false
},
"community_layouts": [ "split_3x5_3" ],
"layouts": {
"LAYOUT_split_3x5_3": {
"layout": [
{ "label": "K00", "matrix": [0, 0], "w": 1, "x": 0, "y": 0.75 },
{ "label": "K10", "matrix": [1, 0], "w": 1, "x": 1, "y": 0.5 },
{ "label": "K20", "matrix": [2, 0], "w": 1, "x": 2, "y": 0 },
{ "label": "K30", "matrix": [3, 0], "w": 1, "x": 3, "y": 0.25 },
{ "label": "K40", "matrix": [4, 0], "w": 1, "x": 4, "y": 0.36 },
{ "label": "K44", "matrix": [4, 4], "w": 1, "x": 8, "y": 0.36 },
{ "label": "K34", "matrix": [3, 4], "w": 1, "x": 9, "y": 0.25 },
{ "label": "K24", "matrix": [2, 4], "w": 1, "x": 10, "y": 0 },
{ "label": "K14", "matrix": [1, 4], "w": 1, "x": 11, "y": 0.5 },
{ "label": "K04", "matrix": [0, 4], "w": 1, "x": 12, "y": 0.75 },
{ "label": "K01", "matrix": [0, 1], "w": 1, "x": 0, "y": 1.75 },
{ "label": "K11", "matrix": [1, 1], "w": 1, "x": 1, "y": 1.5 },
{ "label": "K21", "matrix": [2, 1], "w": 1, "x": 2, "y": 1 },
{ "label": "K31", "matrix": [3, 1], "w": 1, "x": 3, "y": 1.25 },
{ "label": "K41", "matrix": [4, 1], "w": 1, "x": 4, "y": 1.36 },
{ "label": "K45", "matrix": [4, 5], "w": 1, "x": 8, "y": 1.36 },
{ "label": "K35", "matrix": [3, 5], "w": 1, "x": 9, "y": 1.25 },
{ "label": "K25", "matrix": [2, 5], "w": 1, "x": 10, "y": 1 },
{ "label": "K15", "matrix": [1, 5], "w": 1, "x": 11, "y": 1.5 },
{ "label": "K05", "matrix": [0, 5], "w": 1, "x": 12, "y": 1.75 },
{ "label": "K02", "matrix": [0, 2], "w": 1, "x": 0, "y": 2.75 },
{ "label": "K12", "matrix": [1, 2], "w": 1, "x": 1, "y": 2.5 },
{ "label": "K22", "matrix": [2, 2], "w": 1, "x": 2, "y": 2 },
{ "label": "K32", "matrix": [3, 2], "w": 1, "x": 3, "y": 2.25 },
{ "label": "K42", "matrix": [4, 2], "w": 1, "x": 4, "y": 2.36 },
{ "label": "K46", "matrix": [4, 6], "w": 1, "x": 8, "y": 2.36 },
{ "label": "K36", "matrix": [3, 6], "w": 1, "x": 9, "y": 2.25 },
{ "label": "K26", "matrix": [2, 6], "w": 1, "x": 10, "y": 2 },
{ "label": "K16", "matrix": [1, 6], "w": 1, "x": 11, "y": 2.5 },
{ "label": "K06", "matrix": [0, 6], "w": 1, "x": 12, "y": 2.75 },
{ "label": "K23", "matrix": [2, 3], "w": 1, "x": 3, "y": 3.25 },
{ "label": "K33", "matrix": [3, 3], "w": 1, "x": 4, "y": 3.36 },
{ "label": "K43", "matrix": [4, 3], "w": 1, "x": 5, "y": 3.47 },
{ "label": "K47", "matrix": [4, 7], "w": 1, "x": 7, "y": 3.47 },
{ "label": "K37", "matrix": [3, 7], "w": 1, "x": 8, "y": 3.36 },
{ "label": "K27", "matrix": [2, 7], "w": 1, "x": 9, "y": 3.25 }
]
}
}
}

View file

@ -0,0 +1,16 @@
// Copyright 2023 Jason Hazel (@jasonhazel)
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#define TAPPING_TERM 200
#define PERMISSIVE_HOLD
#define IGNORE_MOD_TAP_INTERRUPT
#define TAPPING_FORCE_HOLD
#define TAPPING_TERM_PER_KEY
#define ONESHOT_TAP_TOGGLE 10
#define ONESHOT_TIMEOUT 500
#define DOUBLE_TAP_SHIFT_TURNS_ON_CAPS_WORD
#define CIRQUE_PINNACLE_TAP_ENABLE
#define CIRQUE_PINNACLE_POSITION_MODE CIRQUE_PINNACLE_ABSOLUTE_MODE
#define CIRQUE_DEVICE_GESTURES_SCROLL_ENABLE

View file

@ -0,0 +1,35 @@
// Copyright 2023 Jason Hazel (@jasonhazel)
// SPDX-License-Identifier: GPL-3.0-or-later
#include QMK_KEYBOARD_H
layer_state_t layer_state_set_user(layer_state_t state) {
return update_tri_layer_state(state, 1, 2, 3);
}
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_split_3x5_3(
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_QUOT, \
KC_Z, LGUI_T(KC_X), LALT_T(KC_C), KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, \
KC_LCTL, OSL(1), OSM(MOD_LSFT), KC_SPC, LT(2, KC_BSPC), KC_ENT
),
[1] = LAYOUT_split_3x5_3(
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_RBRC, KC_RCBR, KC_RPRN, KC_RABK, KC_NO, \
KC_GRV, KC_TILD, KC_UNDS, KC_EQL, KC_NO, KC_LBRC, KC_LCBR, KC_LPRN, KC_LABK, KC_BACKSLASH, \
KC_NO, KC_NO, KC_PLUS, KC_MINS, KC_NO, KC_NO, KC_NO, KC_COLN, KC_DOT, KC_SCLN, \
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[2] = LAYOUT_split_3x5_3(
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_PIPE, KC_NO, \
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_DOT, KC_NO, \
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
),
[3] = LAYOUT_split_3x5_3(
KC_ESC, KC_F1, KC_F4, KC_F7, KC_F10, KC_NO, KC_HOME, KC_UP, KC_END, KC_BSPC, \
KC_TAB, KC_F2, KC_F5, KC_F8, KC_F11, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_ENT, \
KC_NO, KC_F3, KC_F6, KC_F9, KC_F12, KC_NO, KC_MPRV, KC_MPLY, KC_MNXT, KC_DEL, \
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
)
};

View file

@ -0,0 +1,2 @@
MOUSEKEY_ENABLE = yes
EXTRAKEY_ENABLE = yes

View file

@ -0,0 +1,137 @@
// Copyright 2022 @sadekbaroudi (Sadek Baroudi)
// Copyright 2023 @jasonhazel (Jason Hazel)
// SPDX-License-Identifier: GPL-3.0-or-later
#include "quantum.h"
#include "spi_master.h"
#include <string.h> /* memset */
#include <unistd.h> /* close */
#include "quantum.h"
#include "matrix.h"
#if (!defined(SHIFTREG_MATRIX_COL_CS))
# error Missing shift register I/O pin definitions
#endif
int matrixArraySize = SHIFTREG_ROWS * sizeof(matrix_row_t);
matrix_row_t oldMatrix[SHIFTREG_ROWS];
#define SHIFTREG_OUTPUT_BITS 8
pin_t rowPinsSR[SHIFTREG_ROWS] = MATRIX_ROW_PINS_SR;
// 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_COL_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();
writePinLow(SHIFTREG_MATRIX_COL_CS);
matrix_io_delay();
spi_write(data);
matrix_io_delay();
writePinHigh(SHIFTREG_MATRIX_COL_CS);
sr_74hc595_spi_stop();
return true;
}
/**
* Set the entire shift register to be full of inactive bits
*/
void clearColumns(void) {
uint8_t value = 0b00000000;
sr_74hc595_spi_send_byte(value);
}
void setColumn(int columnShift, bool test_run) {
uint8_t columnShiftByte = ((uint8_t)1 << columnShift);
if(test_run) {
dprintf("byte sent: %d\n", columnShiftByte);
}
sr_74hc595_spi_send_byte(columnShiftByte);
}
/*
* override of the qmk intialization function
*/
void matrix_init_custom(void) {
wait_ms(300);
spi_init();
// Set up the initial states for all the row pins
for (int r = 0; r < SHIFTREG_ROWS; r++) {
// Note: This needs to use the internal pull down resistors, and atmegas do *not* support that
setPinInputLow(rowPinsSR[r]);
}
// Set the CS to low by default, and specify as an output pin
writePinHigh(SHIFTREG_MATRIX_COL_CS); // should be high when using SPI?
setPinOutput(SHIFTREG_MATRIX_COL_CS);
// Since it's the init, deactivate all the columns. We'll activate once we get to the matrix scan
clearColumns();
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
// respect the semaphore
if (semaphore_is_locked()) {
return false;
}
// Keep track of if something was modified
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);
bool debug_output = false;
// Loop through the columns, activating one at a time, and read the rows, and place in the new current_matrix
for (int c = 0; c < SHIFTREG_COLS; c++) {
if (debug_output) {
dprintf("column iteration: %d\n", c);
}
setColumn(c, debug_output);
matrix_io_delay();
for (int r = 0; r < SHIFTREG_ROWS; r++) {
current_matrix[r] |= ((readPin(rowPinsSR[r]) ? 1 : 0) << c);
}
}
matrix_has_changed = memcmp(current_matrix, oldMatrix, matrixArraySize) != 0;
memcpy(oldMatrix, current_matrix, matrixArraySize);
if (matrix_has_changed) {
matrix_print();
}
// Deactivate all the columns for the next run.
clearColumns();
matrix_io_delay();
return matrix_has_changed;
}

View file

@ -0,0 +1,11 @@
// Copyright 2023 Jason Hazel (@jasonhazel)
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include_next "mcuconf.h"
#undef RP_SPI_USE_SPI0
#define RP_SPI_USE_SPI0 TRUE
#undef RP_I2C_USE_I2C1
#define RP_I2C_USE_I2C1 TRUE

View file

@ -0,0 +1,27 @@
# Bad Wings
![Bad Wings](https://i.imgur.com/QpfcEj8h.png)
36 key unibody split
* Keyboard Maintainer: [Jason Hazel](https://github.com/jasonhazel)
* Hardware Supported: Bad Wings v1
* Hardware Availability: [Hazel's Garage](https://shop.hazel.cc/products/bad-wings)
Make example for this keyboard (after setting up your build environment):
make hazel/bad_wings:default
Flashing example for this keyboard:
make hazel/bad_wings: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 and plug in the keyboard
* **Physical reset button**: Hold Xiao B button, press Xiao R button, release B
* **Keycode in layout**: There is no key mapped to `QK_BOOT` in the pre-created keymaps, but you may assign this key in any keymaps you create

View file

@ -0,0 +1,10 @@
TRI_LAYER_ENABLE = yes
CAPS_WORD_ENABLE = yes
SRC += matrix.c
QUANTUM_LIB_SRC += spi_master.c
CUSTOM_MATRIX = lite
POINTING_DEVICE_DRIVER = cirque_pinnacle_spi
POINTING_DEVICE_ENABLE = yes