diff --git a/app/boards/arm/pseudacris/Kconfig b/app/boards/arm/pseudacris/Kconfig new file mode 100644 index 00000000..f31adfd8 --- /dev/null +++ b/app/boards/arm/pseudacris/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2022 Tony Grosinger +# SPDX-License-Identifier: MIT + +config BOARD_ENABLE_DCDC + bool "Enable DCDC mode" + select SOC_DCDC_NRF52X + default y + depends on BOARD_PSEUDACRIS + +config BOARD_ENABLE_CHARGER + bool "Enable battery charger" + default y + depends on (BOARD_PSEUDACRIS) diff --git a/app/boards/arm/pseudacris/Kconfig.board b/app/boards/arm/pseudacris/Kconfig.board new file mode 100644 index 00000000..4f126cfe --- /dev/null +++ b/app/boards/arm/pseudacris/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2022 Tony Grosinger +# SPDX-License-Identifier: MIT + +config BOARD_PSEUDACRIS + bool "pseudacris" + depends on SOC_NRF52840_QIAA diff --git a/app/boards/arm/pseudacris/Kconfig.defconfig b/app/boards/arm/pseudacris/Kconfig.defconfig new file mode 100644 index 00000000..9e11e4fe --- /dev/null +++ b/app/boards/arm/pseudacris/Kconfig.defconfig @@ -0,0 +1,31 @@ +# Copyright (c) 2022 Tony Grosinger +# SPDX-License-Identifier: MIT + +if BOARD_PSEUDACRIS + +config ZMK_KEYBOARD_NAME + default "pseudacris" + +if USB_DEVICE_STACK + +config USB_NRFX + default y + +endif # USB_DEVICE_STACK + +config BT_CTLR + default BT + +config ZMK_BLE + default y + +config ZMK_USB + default y + +config PINMUX + default y + +config BOARD_ENABLE_CHARGER + default y + +endif # BOARD_PSEUDACRIS diff --git a/app/boards/arm/pseudacris/README.md b/app/boards/arm/pseudacris/README.md new file mode 100644 index 00000000..80b9ae92 --- /dev/null +++ b/app/boards/arm/pseudacris/README.md @@ -0,0 +1,15 @@ +# Pseudacris + +Pseudacris is a hotswap 30% keyboard made by Tony Grosinger. + +More details, including the BOM and PCB files can be found at https://git.sr.ht/~tgrosinger/keyboards/tree/main/item/pseudacris + +## Building Pseudacris ZMK firmware + +```bash +# From in this repo +cd app +west build -p -b pseudacris + +# Built firmware output to app/build/zephyr/zmk.uf2 +``` diff --git a/app/boards/arm/pseudacris/board.cmake b/app/boards/arm/pseudacris/board.cmake new file mode 100644 index 00000000..d129e7e4 --- /dev/null +++ b/app/boards/arm/pseudacris/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2022 Tony Grosinger +# SPDX-License-Identifier: MIT + +set(OPENOCD_NRF5_SUBFAMILY nrf52) +board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset") +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake) diff --git a/app/boards/arm/pseudacris/pinmux.c b/app/boards/arm/pseudacris/pinmux.c new file mode 100644 index 00000000..962cf47a --- /dev/null +++ b/app/boards/arm/pseudacris/pinmux.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +#include + +static int pinmux_pseudacris_init(const struct device *port) { + ARG_UNUSED(port); + + const struct device *p0 = device_get_binding("GPIO_0"); + +#if CONFIG_BOARD_ENABLE_CHARGER + gpio_pin_configure(p0, 5, GPIO_OUTPUT); + gpio_pin_set(p0, 5, 0); +#else + gpio_pin_configure(p0, 5, GPIO_INPUT); +#endif + + return 0; +} + +SYS_INIT(pinmux_pseudacris_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/boards/arm/pseudacris/pseudacris.dts b/app/boards/arm/pseudacris/pseudacris.dts new file mode 100644 index 00000000..74e45bc2 --- /dev/null +++ b/app/boards/arm/pseudacris/pseudacris.dts @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2022 Tony Grosinger + * + * SPDX-License-Identifier: MIT + */ + +/dts-v1/; +#include + +#include + +/ { + model = "pseudacris"; + compatible = "pseudacris"; + + chosen { + zephyr,code-partition = &code_partition; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &cdc_acm_uart; + zmk,kscan = &kscan0; + zmk,matrix_transform = &default_transform; + }; + + default_transform: keymap_transform_0 { + compatible = "zmk,matrix-transform"; + columns = <10>; + rows = <7>; + map = < + RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) + RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) RC(4,9) + RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(5,5) RC(5,6) RC(5,7) RC(5,8) RC(5,9) + RC(6,2) RC(6,3) RC(6,4) RC(6,5) RC(6,6) RC(6,7) + >; + }; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-matrix"; + label = "KSCAN"; + + diode-direction = "row2col"; + /* + * P0.13 - Left Matrix Top + * P0.22 - Left Matrix Middle + * P1.06 - Left Matrix Bottom + * + * P0.30 - Right Matrix Top + * P0.31 - Right Matrix Middle + * P1.11 - Right Matrix Bottom + * + * P0.10 - Thumbs + */ + row-gpios + = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 22 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + + , <&gpio0 30 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio0 31 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + , <&gpio1 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + + , <&gpio0 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> + ; + + + /* + * P0.09 - Left Pinky + * P1.04 - Left Ring + * P1.02 - Left Middle + * P1.00 - Left Pointer + * P0.24 - Left Inner + + * P0.29 - Right Inner + * P0.02 - Right Pointer + * P1.13 - Right Middle + * P0.28 - Right Ring + * P0.03 - Right Pinky + */ + col-gpios + = <&gpio0 9 GPIO_ACTIVE_HIGH> + , <&gpio1 4 GPIO_ACTIVE_HIGH> + , <&gpio1 2 GPIO_ACTIVE_HIGH> + , <&gpio1 0 GPIO_ACTIVE_HIGH> + , <&gpio0 24 GPIO_ACTIVE_HIGH> + + , <&gpio0 29 GPIO_ACTIVE_HIGH> + , <&gpio0 2 GPIO_ACTIVE_HIGH> + , <&gpio1 13 GPIO_ACTIVE_HIGH> + , <&gpio0 28 GPIO_ACTIVE_HIGH> + , <&gpio0 3 GPIO_ACTIVE_HIGH> + ; + }; + + ext-power { + compatible = "zmk,ext-power-generic"; + label = "EXT_POWER"; + control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c0 { + compatible = "nordic,nrf-twi"; + sda-pin = <15>; + scl-pin = <17>; +}; + +&uart0 { + compatible = "nordic,nrf-uarte"; + tx-pin = <6>; + rx-pin = <8>; +}; + +&usbd { + status = "okay"; + cdc_acm_uart: cdc_acm_uart { + compatible = "zephyr,cdc-acm-uart"; + label = "CDC_ACM_0"; + }; +}; + +&flash0 { + /* + * For more information, see: + * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + sd_partition: partition@0 { + label = "softdevice"; + reg = <0x00000000 0x00026000>; + }; + + code_partition: partition@26000 { + label = "code_partition"; + reg = <0x00026000 0x000c6000>; + }; + + /* + * The flash starting at 0x000ec000 and ending at + * 0x000f3fff is reserved for use by the application. + */ + + /* + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + storage_partition: partition@ec000 { + label = "storage"; + reg = <0x000ec000 0x00008000>; + }; + + boot_partition: partition@f4000 { + label = "adafruit_boot"; + reg = <0x000f4000 0x0000c000>; + }; + }; +}; diff --git a/app/boards/arm/pseudacris/pseudacris.keymap b/app/boards/arm/pseudacris/pseudacris.keymap new file mode 100644 index 00000000..1e958568 --- /dev/null +++ b/app/boards/arm/pseudacris/pseudacris.keymap @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2022 Tony Grosinger + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +#define DEF_L 0 +#define NUM_L 1 +#define SYM_L 2 +#define TMUX_L 3 + +// Using layer taps on thumbs, having quick tap as well helps w/ repeating space/backspace +< { quick_tap_ms = <200>; }; + +/ { + behaviors { + hm: homerow_mods { + compatible = "zmk,behavior-hold-tap"; + label = "homerow mods"; + #binding-cells = <2>; + tapping_term_ms = <225>; + flavor = "tap-preferred"; + bindings = <&kp>, <&kp>; + }; + }; + + combos { + compatible = "zmk,combos"; + combo_backtick { + timeout-ms = <50>; + key-positions = <0 1>; + bindings = <&kp GRAVE>; + }; + combo_esc { + timeout-ms = <50>; + key-positions = <1 11>; + bindings = <&kp ESC>; + }; + combo_backspace { + timeout-ms = <50>; + key-positions = <11 12>; + bindings = <&kp BSPC>; + }; + combo_tab { + timeout-ms = <50>; + key-positions = <12 13>; + bindings = <&kp TAB>; + }; + combo_enter { + timeout-ms = <50>; + key-positions = <22 23>; + bindings = <&kp ENTER>; + }; + combo_minus { + timeout-ms = <50>; + key-positions = <7 8>; + bindings = <&kp MINUS>; + }; + combo_backslash { + timeout-ms = <50>; + key-positions = <8 9>; + bindings = <&kp BACKSLASH>; + }; + combo_less_than { + timeout-ms = <50>; + key-positions = <15 16>; + bindings = <&kp LT>; + }; + combo_greater_than { + timeout-ms = <50>; + key-positions = <17 18>; + bindings = <&kp GT>; + }; + combo_colon { + timeout-ms = <50>; + key-positions = <16 17>; + bindings = <&kp COLON>; + }; + combo_quote { + timeout-ms = <50>; + key-positions = <25 26>; + bindings = <&kp APOSTROPHE>; + }; + combo_underscore { + timeout-ms = <50>; + key-positions = <26 27>; + bindings = <&kp UNDER>; + }; + }; + + macros { + tmux_new: tmux_new { + label = "ZM_tmux_new"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp C> + ; + }; + tmux_zoom: tmux_zoom { + label = "ZM_tmux_zoom"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp Z> + ; + }; + tmux_scroll: tmux_scroll { + label = "ZM_tmux_scroll"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp LEFT_BRACKET> + ; + }; + tmux_pn_lt: tmux_pn_lt { + label = "ZM_tmux_pn_lt"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp LEFT> + ; + }; + tmux_pn_dn: tmux_pn_dn { + label = "ZM_tmux_pn_dn"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp DOWN> + ; + }; + tmux_pn_up: tmux_pn_up { + label = "ZM_tmux_pn_up"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp UP> + ; + }; + tmux_pn_rt: tmux_pn_rt { + label = "ZM_tmux_pn_rt"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp RIGHT> + ; + }; + tmux_wn_next: tmux_wn_next { + label = "ZM_tmux_wn_next"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp N> + ; + }; + tmux_wn_prev: tmux_wn_prev { + label = "ZM_tmux_wn_prev"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp P> + ; + }; + tmux_sp_v: tmux_sp_v { + label = "ZM_tmux_sp_v"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp PERCENT> + ; + }; + tmux_sp_h: tmux_sp_h { + label = "ZM_tmux_sp_h"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(B)> + , <¯o_tap &kp DOUBLE_QUOTES> + ; + }; + vi_clip_cp: vi_clip_cp { + label = "ZM_vi_clip_cp"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp DOUBLE_QUOTES> + , <¯o_tap &kp PLUS> + , <¯o_tap &kp Y> + ; + }; + vi_clip_pst: vi_clip_pst { + label = "ZM_vi_clip_pst"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp DOUBLE_QUOTES> + , <¯o_tap &kp PLUS> + , <¯o_tap &kp P> + ; + }; + vi_macro: vi_macro { + label = "ZM_vi_macro"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp AT> + , <¯o_tap &kp Q> + ; + }; + vi_save: vi_save { + label = "ZM_vi_save"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp ESC> + , <¯o_tap &kp COLON &kp W &kp ENTER> + , <¯o_tap &kp LC(T)> + ; + }; + term_full: term_full { + label = "ZM_term_full"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(TILDE)> + ; + }; + desk_left: desk_left { + label = "ZM_desk_left"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(LG(LEFT))> + ; + }; + desk_right: desk_right { + label = "ZM_desk_right"; + compatible = "zmk,behavior-macro"; + #binding-cells = <0>; + bindings + = <¯o_tap &kp LC(LG(RIGHT))> + ; + }; + }; + + keymap { + compatible = "zmk,keymap"; + + // 0 + // 10 + // 20 + + default_layer { + bindings = < + &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P + &hm LCTL A &kp S &kp D &kp F &kp G &kp H &hm LGUI J &kp K &kp L &hm RCTL SEMI + &hm LALT Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp SLASH + &mo NUM_L &kp LSHIFT &kp ESC &mo TMUX_L &kp SPACE &mo SYM_L + >; + }; + + num_layer { + label = "Num"; + bindings = < + &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 + &trans &desk_left &kp LG(E) &kp LG(R) &desk_right &trans &kp N4 &kp N5 &kp N6 &kp COLON + &kp F1 &kp F2 &kp F12 &kp F4 &kp F5 &trans &kp N1 &kp N2 &kp N3 &kp DOT + &none &none &none &none &none &kp N0 + >; + }; + + sym_layer { + label = "Sym"; + bindings = < + &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp ASTRK &kp PLUS &kp EQUAL + &kp COLON &none &kp LPAR &kp RPAR &none &kp LEFT &kp DOWN &kp UP &kp RIGHT &trans + &none &kp LBRC &kp LBKT &kp RBKT &kp RBRC &kp HOME &kp PG_DN &kp PG_UP &kp END &trans + &none &none &none &none &none &none + >; + }; + + tmux_layer { + label = "Tmux"; + bindings = < + &vi_macro &vi_save &none &none &tmux_sp_v &vi_clip_cp &none &none &none &vi_clip_pst + &none &tmux_scroll &none &term_full &none &tmux_pn_lt &tmux_pn_dn &tmux_pn_up &tmux_pn_rt &tmux_sp_h + &tmux_zoom &none &tmux_new &none &none &tmux_wn_prev &none &none &tmux_wn_next &none + &none &kp DEL &none &none &none &none + >; + }; + }; +}; diff --git a/app/boards/arm/pseudacris/pseudacris.yaml b/app/boards/arm/pseudacris/pseudacris.yaml new file mode 100644 index 00000000..82df18fd --- /dev/null +++ b/app/boards/arm/pseudacris/pseudacris.yaml @@ -0,0 +1,15 @@ +identifier: pseudacris +name: pseudacris +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - adc + - usb_device + - ble + - ieee802154 + - pwm + - watchdog diff --git a/app/boards/arm/pseudacris/pseudacris.zmk.yml b/app/boards/arm/pseudacris/pseudacris.zmk.yml new file mode 100644 index 00000000..d208f77a --- /dev/null +++ b/app/boards/arm/pseudacris/pseudacris.zmk.yml @@ -0,0 +1,11 @@ +file_format: "1" +id: pseudacris +name: pseudacris +type: board +arch: arm +features: + - keys +outputs: + - usb + - ble +url: https://git.sr.ht/~tgrosinger/keyboards/tree/main/item/pseudacris diff --git a/app/boards/arm/pseudacris/pseudacris_defconfig b/app/boards/arm/pseudacris/pseudacris_defconfig new file mode 100644 index 00000000..95be6911 --- /dev/null +++ b/app/boards/arm/pseudacris/pseudacris_defconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2022 Tony Grosinger +# SPDX-License-Identifier: MIT + +CONFIG_SOC_SERIES_NRF52X=y +CONFIG_SOC_NRF52840_QIAA=y +CONFIG_BOARD_PSEUDACRIS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# enable GPIO +CONFIG_GPIO=y + +CONFIG_USE_DT_CODE_PARTITION=y +CONFIG_BUILD_OUTPUT_UF2=y + +CONFIG_MPU_ALLOW_FLASH_WRITE=y +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y +CONFIG_CLOCK_CONTROL_NRF=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y