Adding Bad Wings Support (#20153)
parent
0bb9eada83
commit
b1e6b3798a
@ -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 |
@ -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> |
@ -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 } |
||||
] |
||||
} |
||||
} |
||||
} |
@ -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 |
@ -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 |
||||
) |
||||
}; |
@ -0,0 +1,2 @@ |
||||
MOUSEKEY_ENABLE = yes
|
||||
EXTRAKEY_ENABLE = yes
|
@ -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; |
||||
} |
@ -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 |
@ -0,0 +1,27 @@ |
||||
# Bad Wings |
||||
|
||||
 |
||||
|
||||
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 |
@ -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
|
Loading…
Reference in new issue