Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Bad Wings Support #20153

Merged
merged 20 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions keyboards/hazel/bad_wings/config.h
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions keyboards/hazel/bad_wings/halconf.h
Original file line number Diff line number Diff line change
@@ -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>
69 changes: 69 additions & 0 deletions keyboards/hazel/bad_wings/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"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": {
"backlight": false,
"bootmagic": true,
"command": false,
"console": false,
"deferred_exec": true,
"nkro": false,
"rgblight": false
},
"layouts": {
"LAYOUT": {
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
"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 }
]
}
}
}
16 changes: 16 additions & 0 deletions keyboards/hazel/bad_wings/keymaps/default/config.h
Original file line number Diff line number Diff line change
@@ -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
85 changes: 85 additions & 0 deletions keyboards/hazel/bad_wings/keymaps/default/keymap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2023 Jason Hazel (@jasonhazel)
// SPDX-License-Identifier: GPL-3.0-or-later

#include QMK_KEYBOARD_H

enum layers {
_ALPHA,
_SYMBOL,
_NUMBER,
_NAVIGATION,
LAYER_LENGTH
};


enum tapdances {
TD_QESC,
TD_SBKT,
TD_CBKT,
TD_PARN,
TD_LTGT,
TD_ATAB,
TAPDANCE_LENGTH
};


layer_state_t layer_state_set_user(layer_state_t state) {
return update_tri_layer_state(state, _SYMBOL, _NUMBER, _NAVIGATION);
}

#define KC_QESC TD(TD_QESC) // Q, ESC
#define KC_SBKT TD(TD_SBKT) // [, ]
#define KC_CBKT TD(TD_CBKT) // {, }
#define KC_PARN TD(TD_PARN) // (, )
#define KC_LTGT TD(TD_LTGT) // <, >
#define KC_GUIX LGUI_T(KC_X)
#define KC_ALTC LALT_T(KC_C)
#define KC_OSFT OSM(MOD_LSFT)
#define KC_OALT OSM(MOD_LALT)
#define KC_OSYM OSL(_SYMBOL)
#define KC_ONUM LT(_NUMBER, KC_BSPC)

uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
switch(keycode) {
case KC_GUIX:
case KC_ALTC:
return TAPPING_TERM * 2;
default:
return TAPPING_TERM;
}
}

tap_dance_action_t tap_dance_actions[] = {
[TD_QESC] = ACTION_TAP_DANCE_DOUBLE(KC_Q, KC_ESC),
[TD_SBKT] = ACTION_TAP_DANCE_DOUBLE(KC_LBRC, KC_RBRC),
[TD_CBKT] = ACTION_TAP_DANCE_DOUBLE(KC_LCBR, KC_RCBR),
[TD_PARN] = ACTION_TAP_DANCE_DOUBLE(KC_LPRN, KC_RPRN),
[TD_LTGT] = ACTION_TAP_DANCE_DOUBLE(KC_LABK, KC_RABK),
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_ALPHA] = LAYOUT(
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
KC_QESC, 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, KC_GUIX, KC_ALTC, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, \
KC_LCTL, KC_OSYM, KC_OSFT, KC_SPC, KC_ONUM, KC_ENT
),
[_SYMBOL] = LAYOUT(
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_PIPE, KC_NO, \
KC_GRV, KC_TILD, KC_UNDS, KC_EQL, KC_NO, KC_SBKT, KC_CBKT, KC_PARN, KC_LTGT, KC_BACKSLASH, \
KC_NO, KC_NO, KC_PLUS, KC_MINS, KC_NO, KC_NO, KC_NO, KC_COLN, KC_DOT, KC_SCLN, \
KC_LCTL, KC_OSYM, KC_OSFT, KC_SPC, KC_ONUM, KC_ENT
),
[_NUMBER] = LAYOUT(
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, 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_LCTL, KC_OSYM, KC_OSFT, KC_SPC, KC_ONUM, KC_ENT
),
[_NAVIGATION] = LAYOUT(
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
KC_NO, KC_F2, KC_NO, KC_NO, KC_NO, KC_NO, KC_HOME, KC_UP, KC_END, KC_BSPC, \
KC_TAB, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, KC_ENT, \
KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MPRV, KC_MPLY, KC_MNXT, KC_DEL, \
KC_LCTL, KC_OSYM, KC_OSFT, KC_SPC, KC_ONUM, KC_ENT
)
};
8 changes: 8 additions & 0 deletions keyboards/hazel/bad_wings/keymaps/default/rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
GRAVE_ESC_ENABLE = no
SPACE_CADET_ENABLE = no
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
MOUSEKEY_ENABLE = yes
EXTRAKEY_ENABLE = yes
CAPS_WORD_ENABLE = yes
TAP_DANCE_ENABLE = yes
TRI_LAYER_ENABLE = yes
POINTING_DEVICE_ENABLE = yes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be at the kb level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're talking just POINTING_DEVICE_ENABLE, right? if so, that's been updated.

Copy link
Contributor

@lesshonor lesshonor Mar 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per the docs Configurator will choke on TAP_DANCE_ENABLE at keyboard level, though CAPS_WORD_ENABLE is fine and TRI_LAYER_ENABLE probably would be too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I've got a couple other things from the configurator docs that I need to address as well. I'll get started on those, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated my branch with keymap changes required for the configurator.

Copy link
Contributor

@lesshonor lesshonor Mar 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate to say this after you already went and did it, but the default keymap was fine.
Configurator creates an entirely blank keymap, it only has access to the keyboard-level information. It does not use any information from the default keymap.

I can confirm Tri-Layer and Caps Word are both OK to enable at the keyboard level after testing them. The issue is that if you enable Tap Dance without actually implementing any tap dances, compilation fails, and Configurator has no way to implement tap dances.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mind updating the default keymap - it was mostly changes I've been wanting to make for a while.<

I've moved TRI_LAYER_ENABLE and CAPS_WORD_ENABLE to the keyboard level rules.mk. Thanks so much for your feedback!

137 changes: 137 additions & 0 deletions keyboards/hazel/bad_wings/matrix.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright 2022 @sadekbaroudi (Sadek Baroudi)
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
// 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)) {
xprintf("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) {
xprintf("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) {
xprintf("column iteration: %d\n", c);
jasonhazel marked this conversation as resolved.
Show resolved Hide resolved
}
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();
}
// matrix_print();
// xprintf("matrix_has_changed: %d\n", matrix_has_changed);

// Deactivate all the columns for the next run.
clearColumns();
matrix_io_delay();

return matrix_has_changed;
}
11 changes: 11 additions & 0 deletions keyboards/hazel/bad_wings/mcuconf.c
Original file line number Diff line number Diff line change
@@ -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
Loading