1. local/github integration module 2. makefile redundancy eliminated

This commit is contained in:
Chow Castro, Marcos 2024-08-22 15:11:25 +02:00
parent 95d732af57
commit 46510619a2
53 changed files with 162 additions and 341 deletions

View file

@ -0,0 +1,54 @@
if SHIELD_CORNE_LEFT || SHIELD_CORNE_DONGLE_XIAO || SHIELD_CORNE_DONGLE_PRO_MICRO
config ZMK_KEYBOARD_NAME
default "Corne"
config ZMK_SPLIT_ROLE_CENTRAL
default y
config ZMK_USB
default y
endif
if SHIELD_CORNE_LEFT || SHIELD_CORNE_RIGHT || SHIELD_CORNE_DONGLE_XIAO || SHIELD_CORNE_LEFT_PERIPHERAL || SHIELD_CORNE_DONGLE_PRO_MICRO
config ZMK_SPLIT
default y
if ZMK_DISPLAY
config I2C
default y
config SSD1306
default y
if SHIELD_CORNE_DONGLE_XIAO || SHIELD_CORNE_DONGLE_PRO_MICRO
choice ZMK_DISPLAY_WORK_QUEUE
default ZMK_DISPLAY_WORK_QUEUE_DEDICATED
endchoice
endif
endif # ZMK_DISPLAY
if LVGL
config LV_Z_VDB_SIZE
default 64
config LV_DPI_DEF
default 148
config LV_Z_BITS_PER_PIXEL
default 1
choice LV_COLOR_DEPTH
default LV_COLOR_DEPTH_1
endchoice
endif # LVGL
endif

View file

@ -0,0 +1,17 @@
# Copyright (c) 2020 Pete Johanson
# SPDX-License-Identifier: MIT
config SHIELD_CORNE_LEFT
def_bool $(shields_list_contains,corne_left)
config SHIELD_CORNE_RIGHT
def_bool $(shields_list_contains,corne_right)
config SHIELD_CORNE_DONGLE_XIAO
def_bool $(shields_list_contains,corne_dongle_xiao)
config SHIELD_CORNE_LEFT_PERIPHERAL
def_bool $(shields_list_contains,corne_left_peripheral)
config SHIELD_CORNE_DONGLE_PRO_MICRO
def_bool $(shields_list_contains,corne_dongle_pro_micro)

View file

@ -0,0 +1,46 @@
#include <dt-bindings/led/led.h>
&pinctrl {
spi3_default: spi3_default {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 6)>;
};
};
spi3_sleep: spi3_sleep {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 6)>;
low-power-enable;
};
};
};
&spi3 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi3_default>;
pinctrl-1 = <&spi3_sleep>;
pinctrl-names = "default", "sleep";
led_strip: ws2812@0 {
compatible = "worldsemi,ws2812-spi";
/* SPI */
reg = <0>; /* ignored, but necessary for SPI bindings */
spi-max-frequency = <4000000>;
/* WS2812 */
chain-length = <10>; /* arbitrary; change at will */
spi-one-frame = <0x70>;
spi-zero-frame = <0x40>;
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
};
};
/ {
chosen {
zmk,underglow = &led_strip;
};
};

View file

@ -0,0 +1,46 @@
#include <dt-bindings/led/led.h>
&pinctrl {
spi3_default: spi3_default {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 6)>;
};
};
spi3_sleep: spi3_sleep {
group1 {
psels = <NRF_PSEL(SPIM_MOSI, 0, 6)>;
low-power-enable;
};
};
};
&spi3 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi3_default>;
pinctrl-1 = <&spi3_sleep>;
pinctrl-names = "default", "sleep";
led_strip: ws2812@0 {
compatible = "worldsemi,ws2812-spi";
/* SPI */
reg = <0>; /* ignored, but necessary for SPI bindings */
spi-max-frequency = <4000000>;
/* WS2812 */
chain-length = <10>; /* arbitrary; change at will */
spi-one-frame = <0x70>;
spi-zero-frame = <0x40>;
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
};
};
/ {
chosen {
zmk,underglow = &led_strip;
};
};

View file

@ -0,0 +1,6 @@
# Uncomment the following lines to enable the Corne RGB Underglow
# CONFIG_ZMK_RGB_UNDERGLOW=y
# CONFIG_WS2812_STRIP=y
# Uncomment the following line to enable the Corne OLED Display
# CONFIG_ZMK_DISPLAY=y

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2020 Pete Johanson
*
* SPDX-License-Identifier: MIT
*/
#include <dt-bindings/zmk/matrix_transform.h>
/ {
chosen {
zephyr,display = &oled;
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
};
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <12>;
rows = <4>;
// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 |
// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11)
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
>;
};
five_column_transform: keymap_transform_1 {
compatible = "zmk,matrix-transform";
columns = <10>;
rows = <4>;
// | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 |
// | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 |
// | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 |
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
map = <
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10)
RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10)
RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10)
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
>;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
wakeup-source;
diode-direction = "col2row";
row-gpios
= <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
;
};
// TODO: per-key RGB node(s)?
};
&pro_micro_i2c {
status = "okay";
oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <32>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <31>;
segment-remap;
com-invdir;
com-sequential;
inversion-on;
prechargep = <0x22>;
};
};

Binary file not shown.

View file

@ -0,0 +1,17 @@
file_format: "1"
id: corne
name: Corne
type: shield
url: https://github.com/foostan/crkbd/
requires: [pro_micro]
exposes: [i2c_oled]
features:
- keys
- display
- underglow
siblings:
- corne_left
- corne_right
- corne_left_peripheral
- corne_dongle_xiao
- corne_dongle_pro_micro

View file

@ -0,0 +1,49 @@
# MC:
# compatible with all versions of nrf52840 (pro micro):
# - nice_nano (not tested)
# - nice_nano_v2 (tested)
# - nice_nano_v2 (super mini -> nice_nano_v2 clon) (tested)
# - nrfmicro_11 (not tested)
# - nrfmicro_11_flipped (not tested)
# - nrfmicro_13 (not tested)
# - puchi_ble_v1 (tested)
# 3 profiles (n+2)
CONFIG_BT_MAX_CONN=5
CONFIG_BT_MAX_PAIRED=5
# dongle mode
CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS=2
# display
CONFIG_ZMK_DISPLAY=y
CONFIG_BT_BAS=n
CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING=y
# enable logging and configure zmk logging to debug output
# CONFIG_ZMK_USB_LOGGING=y
# CONFIG_LOG_PROCESS_THREAD_STARTUP_DELAY_MS=8000
### POWER OPTIONS
CONFIG_ZMK_EXT_POWER=y
# the battery power report interval unit is seconds
CONFIG_ZMK_BATTERY_REPORT_INTERVAL=60
# MC: changed so that he always stays awake
CONFIG_ZMK_SLEEP=n
# 1800000 milliseconds = 30 minutes * 60 seconds * 1000
# CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=3600000
# number of milliseconds of inactivity before entering idle state
CONFIG_ZMK_IDLE_TIMEOUT=60000
# add keyboard bounce
# CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS=5
# CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=5
# Increase the transmission power of the keyboard ble radio to solve the
# problem of left and right delay and poor communication.
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES=y
# change default keyboard display name
# CONFIG_ZMK_KEYBOARD_NAME="Nice_Dongle_Oled"
CONFIG_ZMK_MOUSE=y
### Improves compatibility with iPad
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y

View file

@ -0,0 +1,153 @@
#include <dt-bindings/zmk/matrix_transform.h>
/ {
chosen {
zmk,kscan = &mock_kscan;
zmk,matrix-transform = &default_transform;
zephyr,display = &oled;
};
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <12>;
rows = <4>;
// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 |
// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11)
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
>;
};
five_column_transform: keymap_transform_1 {
compatible = "zmk,matrix-transform";
columns = <10>;
rows = <4>;
// | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 |
// | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 |
// | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 |
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
map = <
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10)
RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10)
RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10)
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
>;
};
mock_kscan: kscan_0 {
compatible = "zmk,kscan-mock";
// wakeup-source;
columns = <0>;
rows = <0>;
events = <0>;
};
// TODO: per-key RGB node(s)?
};
&pro_micro_i2c {
status = "okay";
oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <64>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <63>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
/*
// 128x64 OLED
&pro_micro_i2c {
status = "okay";
oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <64>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <63>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
// 128x32 OLED
&pro_micro_i2c {
status = "okay";
oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <32>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <31>;
segment-remap;
com-invdir;
com-sequential;
inversion-on;
prechargep = <0x22>;
};
};
// 128x64 OLED model sh1106
&pro_micro_i2c {
status = "okay";
oled: sh1106@3c {
compatible = "sinowealth,sh1106";
reg = <0x3c>;
width = <129>;
height = <64>;
segment-offset = <1>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <63>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
// 128x128 OLED model sh1107
&pro_micro_i2c {
status = "okay";
oled: sh1106@3c {
compatible = "sinowealth,sh1106";
reg = <0x3c>;
width = <120>;
height = <128>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <119>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
*/
// vim: filetype=dts fdm=marker:

View file

@ -0,0 +1,43 @@
# MC:
# compatible with all versions of nrf52840 (xiao):
# - seeeduino_xiao_ble (tested)
# 3 profiles (n+2)
CONFIG_BT_MAX_CONN=5
CONFIG_BT_MAX_PAIRED=5
# dongle mode
CONFIG_ZMK_SPLIT_BLE_CENTRAL_PERIPHERALS=2
# display
CONFIG_ZMK_DISPLAY=y
CONFIG_BT_BAS=n
CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING=y
# enable logging and configure zmk logging to debug output
# CONFIG_ZMK_USB_LOGGING=y
# CONFIG_LOG_PROCESS_THREAD_STARTUP_DELAY_MS=8000
### POWER OPTIONS
CONFIG_ZMK_EXT_POWER=y
# the battery power report interval unit is seconds
CONFIG_ZMK_BATTERY_REPORT_INTERVAL=60
# MC: changed so that he always stays awake
CONFIG_ZMK_SLEEP=n
# 1800000 milliseconds = 30 minutes * 60 seconds * 1000
# CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=3600000
# number of milliseconds of inactivity before entering idle state
CONFIG_ZMK_IDLE_TIMEOUT=60000
# add keyboard bounce
# CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS=5
# CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=5
# Increase the transmission power of the keyboard ble radio to solve the
# problem of left and right delay and poor communication.
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES=y
# change default keyboard display name
# CONFIG_ZMK_KEYBOARD_NAME="Nice_Dongle_Oled"
CONFIG_ZMK_MOUSE=y
### Improves compatibility with iPad
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y

View file

@ -0,0 +1,184 @@
/*
* Copyright (c) 2020 Pete Johanson
*
* SPDX-License-Identifier: MIT
*/
#include <dt-bindings/zmk/matrix_transform.h>
/ {
chosen {
zmk,kscan = &mock_kscan;
zmk,matrix-transform = &default_transform;
zephyr,display = &oled;
};
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <12>;
rows = <4>;
// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 |
// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11)
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
>;
};
five_column_transform: keymap_transform_1 {
compatible = "zmk,matrix-transform";
columns = <10>;
rows = <4>;
// | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 |
// | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 |
// | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 |
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
map = <
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10)
RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10)
RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10)
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
>;
};
mock_kscan: kscan_0 {
compatible = "zmk,kscan-mock";
// wakeup-source;
columns = <0>;
rows = <0>;
events = <0>;
};
// TODO: per-key RGB node(s)?
};
&xiao_i2c {
status = "okay";
oled: sh1106@3c {
compatible = "sinowealth,sh1106";
reg = <0x3c>;
width = <120>;
height = <128>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <119>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
/*
// 128x64 OLED
&xiao_i2c {
status = "okay";
oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <64>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <63>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
// 128x32 OLED
&xiao_i2c {
status = "okay";
oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
width = <128>;
height = <32>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <31>;
segment-remap;
com-invdir;
com-sequential;
inversion-on;
prechargep = <0x22>;
};
};
// 128x64 OLED model sh1106
&xiao_i2c {
status = "okay";
oled: sh1106@3c {
compatible = "sinowealth,sh1106";
reg = <0x3c>;
width = <129>;
height = <64>;
segment-offset = <1>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <63>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
// 128x128 OLED model sh1107
&xiao_i2c {
status = "okay";
oled: sh1106@3c {
compatible = "sinowealth,sh1106";
reg = <0x3c>;
width = <120>;
height = <128>;
segment-offset = <0>;
page-offset = <0>;
display-offset = <0>;
multiplex-ratio = <119>;
segment-remap;
com-invdir;
inversion-on;
prechargep = <0x22>;
};
};
// TODO: niceview
&pinctrl {
spi0_default: spi0_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 5)>,
<NRF_PSEL(SPIM_MOSI, 0, 4)>,
<NRF_PSEL(SPIM_MISO, 0, 8)>;
};
};
spi0_sleep: spi0_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 5)>, // D5
<NRF_PSEL(SPIM_MOSI, 0, 4)>, // D4
<NRF_PSEL(SPIM_MISO, 0, 8)>;
low-power-enable;
};
};
};
nice_view_spi: &spi0 {
compatible = "nordic,nrf-spim";
pinctrl-0 = <&spi0_default>;
pinctrl-1 = <&spi0_sleep>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; // D6
};
*/
// vim: filetype=dts fdm=marker:

View file

@ -0,0 +1,43 @@
### OLED Display
# CONFIG_ZMK_DISPLAY=y
# esto creo que ya no es necesario
# CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED=y
# CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN=y
# Enable and adjust nice!view
CONFIG_ZMK_WIDGET_BATTERY_STATUS_SHOW_PERCENTAGE=y
# CONFIG_ZMK_WIDGET_WPM_STATUS=n
CONFIG_ZMK_WIDGET_LAYER_STATUS=y
CONFIG_ZMK_WIDGET_BATTERY_STATUS=y
CONFIG_ZMK_WIDGET_OUTPUT_STATUS=y
# Disable in-built nice!view widget
CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN=y
# Enable custom nice!view widget
CONFIG_ZMK_LV_FONT_DEFAULT_SMALL_MONTSERRAT_26=y
CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26=y
# Increase the bluetooth transmission power
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES=y
### POWER OPTIONS
# CONFIG_ZMK_EXT_POWER=y
# CONFIG_ZMK_SLEEP=n
# 1800000 milisegundos = 30 minutos * 60 segundos * 1000
# CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=3600000
# Número de milisegundos de inactividad antes de entrar en estado inactivo
# CONFIG_ZMK_IDLE_TIMEOUT=60000
### MOUSE
CONFIG_ZMK_MOUSE=y
### Improves compatibility with iPad
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
### HID para nice!view ePaperDisplay
# Enable eager debouncing
# "Eager Debouncing"
# Trying to lower the input lag.
CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS=1
CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=5

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2020 Pete Johanson
*
* SPDX-License-Identifier: MIT
*/
#include "corne.dtsi"
&kscan0 {
col-gpios
= <&pro_micro 21 GPIO_ACTIVE_HIGH>
, <&pro_micro 20 GPIO_ACTIVE_HIGH>
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
, <&pro_micro 15 GPIO_ACTIVE_HIGH>
, <&pro_micro 14 GPIO_ACTIVE_HIGH>
;
};

View file

@ -0,0 +1,38 @@
# Increase the bluetooth transmission power
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES=y
### MOUSE
CONFIG_ZMK_MOUSE=y
### POWER OPTIONS
# CONFIG_ZMK_EXT_POWER=y
# CONFIG_ZMK_SLEEP=n
# 1800000 milisegundos = 30 minutos * 60 segundos * 1000
# CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=3600000
# Número de milisegundos de inactividad antes de entrar en estado inactivo
# CONFIG_ZMK_IDLE_TIMEOUT=60000
# Enable and adjust nice!view
CONFIG_ZMK_WIDGET_BATTERY_STATUS_SHOW_PERCENTAGE=y
CONFIG_ZMK_WIDGET_BATTERY_STATUS=y
# Disable other widgets, because don't work with pheripherals
CONFIG_ZMK_WIDGET_WPM_STATUS=n
CONFIG_ZMK_WIDGET_LAYER_STATUS=n
CONFIG_ZMK_WIDGET_OUTPUT_STATUS=n
# Disable in-built nice!view widget
CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN=y
# Enable custom nice!view widget
CONFIG_ZMK_LV_FONT_DEFAULT_SMALL_MONTSERRAT_26=y
CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26=y
### Improves compatibility with iPad
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
### HID para nice!view ePaperDisplay
# Enable eager debouncing
# "Eager Debouncing"
# Trying to lower the input lag.
CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS=1
CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=5

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2020 Pete Johanson
*
* SPDX-License-Identifier: MIT
*/
#include "corne.dtsi"
&kscan0 {
col-gpios
= <&pro_micro 21 GPIO_ACTIVE_HIGH>
, <&pro_micro 20 GPIO_ACTIVE_HIGH>
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
, <&pro_micro 15 GPIO_ACTIVE_HIGH>
, <&pro_micro 14 GPIO_ACTIVE_HIGH>
;
};

View file

@ -0,0 +1,38 @@
# Increase the bluetooth transmission power
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES=y
### MOUSE
CONFIG_ZMK_MOUSE=y
### POWER OPTIONS
# CONFIG_ZMK_EXT_POWER=y
# CONFIG_ZMK_SLEEP=n
# 1800000 milisegundos = 30 minutos * 60 segundos * 1000
# CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=3600000
# Número de milisegundos de inactividad antes de entrar en estado inactivo
# CONFIG_ZMK_IDLE_TIMEOUT=60000
# Enable and adjust nice!view
CONFIG_ZMK_WIDGET_BATTERY_STATUS_SHOW_PERCENTAGE=y
CONFIG_ZMK_WIDGET_BATTERY_STATUS=y
# Disable other widgets, because don't work with pheripherals
CONFIG_ZMK_WIDGET_WPM_STATUS=n
CONFIG_ZMK_WIDGET_LAYER_STATUS=n
CONFIG_ZMK_WIDGET_OUTPUT_STATUS=n
# Disable in-built nice!view widget
CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN=y
# Enable custom nice!view widget
CONFIG_ZMK_LV_FONT_DEFAULT_SMALL_MONTSERRAT_26=y
CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26=y
### Improves compatibility with iPad
CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC=y
### HID para nice!view ePaperDisplay
# Enable eager debouncing
# "Eager Debouncing"
# Trying to lower the input lag.
CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS=1
CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=5

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2020 Pete Johanson
*
* SPDX-License-Identifier: MIT
*/
#include "corne.dtsi"
&default_transform {
col-offset = <6>;
};
&five_column_transform {
col-offset = <6>;
};
&kscan0 {
col-gpios
= <&pro_micro 14 GPIO_ACTIVE_HIGH>
, <&pro_micro 15 GPIO_ACTIVE_HIGH>
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
, <&pro_micro 20 GPIO_ACTIVE_HIGH>
, <&pro_micro 21 GPIO_ACTIVE_HIGH>
;
};

View file

@ -0,0 +1,18 @@
if(CONFIG_ZMK_DISPLAY AND CONFIG_ZMK_DISPLAY_STATUS_SCREEN_CUSTOM AND ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL))
zephyr_library()
zephyr_library_sources(${ZEPHYR_BASE}/misc/empty_file.c)
zephyr_library_include_directories(${ZEPHYR_LVGL_MODULE_DIR})
zephyr_library_include_directories(${ZEPHYR_BASE}/lib/gui/lvgl/)
zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include)
zephyr_library_sources(custom_status_screen.c)
zephyr_library_sources(widgets/battery_status.c)
zephyr_library_sources(widgets/bongo_cat.c)
zephyr_library_sources(widgets/bongo_cat_images.c)
target_sources_ifdef(CONFIG_ZMK_HID_INDICATORS app PRIVATE widgets/hid_indicators.c)
zephyr_library_sources(widgets/layer_status.c)
zephyr_library_sources(widgets/modifiers.c)
zephyr_library_sources(widgets/modifiers_sym.c)
zephyr_library_sources(widgets/output_status.c)
zephyr_library_sources(widgets/output_status_sym.c)
endif()

View file

@ -0,0 +1,41 @@
# Copyright (c) 2024 The ZMK Contributors
# SPDX-License-Identifier: MIT
if SHIELD_DONGLE_DISPLAY
choice ZMK_DISPLAY_STATUS_SCREEN
default ZMK_DISPLAY_STATUS_SCREEN_CUSTOM
endchoice
config ZMK_DISPLAY_STATUS_SCREEN_CUSTOM
select LV_USE_LABEL
select LV_USE_IMG
select LV_USE_CANVAS
select LV_USE_ANIMIMG
select LV_USE_ANIMATION
select LV_USE_LINE
select LV_FONT_UNSCII_8
select ZMK_WPM
imply ZMK_HID_INDICATORS
choice ZMK_DISPLAY_WORK_QUEUE
default ZMK_DISPLAY_WORK_QUEUE_DEDICATED
endchoice
config LV_Z_MEM_POOL_SIZE
default 8192
config LV_Z_VDB_SIZE
default 64
config LV_DPI_DEF
default 148
config LV_Z_BITS_PER_PIXEL
default 1
choice LV_COLOR_DEPTH
default LV_COLOR_DEPTH_1
endchoice
endif

View file

@ -0,0 +1,5 @@
# Copyright (c) 2024 The ZMK Contributors
# SPDX-License-Identifier: MIT
config SHIELD_DONGLE_DISPLAY
def_bool $(shields_list_contains,dongle_display)

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include "custom_status_screen.h"
#include "widgets/battery_status.h"
#include "widgets/modifiers.h"
#include "widgets/bongo_cat.h"
#include "widgets/layer_status.h"
#include "widgets/output_status.h"
#include "widgets/hid_indicators.h"
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static struct zmk_widget_output_status output_status_widget;
static struct zmk_widget_layer_status layer_status_widget;
static struct zmk_widget_peripheral_battery_status peripheral_battery_status_widget;
static struct zmk_widget_modifiers modifiers_widget;
static struct zmk_widget_bongo_cat bongo_cat_widget;
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
static struct zmk_widget_hid_indicators hid_indicators_widget;
#endif
lv_style_t global_style;
lv_obj_t *zmk_display_status_screen() {
lv_obj_t *screen;
screen = lv_obj_create(NULL);
lv_style_init(&global_style);
lv_style_set_text_font(&global_style, &lv_font_unscii_8);
lv_style_set_text_letter_space(&global_style, 1);
lv_style_set_text_line_space(&global_style, 1);
lv_obj_add_style(screen, &global_style, LV_PART_MAIN);
zmk_widget_output_status_init(&output_status_widget, screen);
lv_obj_align(zmk_widget_output_status_obj(&output_status_widget), LV_ALIGN_TOP_LEFT, 0, 0);
zmk_widget_bongo_cat_init(&bongo_cat_widget, screen);
lv_obj_align(zmk_widget_bongo_cat_obj(&bongo_cat_widget), LV_ALIGN_BOTTOM_RIGHT, 0, -7);
zmk_widget_modifiers_init(&modifiers_widget, screen);
lv_obj_align(zmk_widget_modifiers_obj(&modifiers_widget), LV_ALIGN_BOTTOM_LEFT, 0, 0);
#if IS_ENABLED(CONFIG_ZMK_HID_INDICATORS)
zmk_widget_hid_indicators_init(&hid_indicators_widget, screen);
lv_obj_align_to(zmk_widget_hid_indicators_obj(&hid_indicators_widget), zmk_widget_modifiers_obj(&modifiers_widget), LV_ALIGN_OUT_TOP_LEFT, 0, -2);
#endif
zmk_widget_layer_status_init(&layer_status_widget, screen);
// lv_obj_align(zmk_widget_layer_status_obj(&layer_status_widget), LV_ALIGN_BOTTOM_LEFT, 2, -18);
lv_obj_align_to(zmk_widget_layer_status_obj(&layer_status_widget), zmk_widget_bongo_cat_obj(&bongo_cat_widget), LV_ALIGN_BOTTOM_LEFT, 0, 5);
zmk_widget_peripheral_battery_status_init(&peripheral_battery_status_widget, screen);
lv_obj_align(zmk_widget_peripheral_battery_status_obj(&peripheral_battery_status_widget), LV_ALIGN_TOP_RIGHT, 0, 0);
return screen;
}

View file

@ -0,0 +1,12 @@
/*
*
* Copyright (c) 2024 The ZMK Contributors
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <lvgl.h>
lv_obj_t *zmk_display_status_screen();

View file

@ -0,0 +1,17 @@
CONFIG_ZMK_DISPLAY=y
CONFIG_BT_BAS=n
CONFIG_ZMK_SPLIT_BLE_CENTRAL_BATTERY_LEVEL_FETCHING=y
# The battery power report interval unit is seconds
CONFIG_ZMK_BATTERY_REPORT_INTERVAL=60
CONFIG_ZMK_SLEEP=n
# 1800000 milliseconds = 30 minutes * 60 seconds * 1000
# CONFIG_ZMK_IDLE_SLEEP_TIMEOUT=3600000
# number of milliseconds of inactivity before entering idle state
CONFIG_ZMK_IDLE_TIMEOUT=60000
# add keyboard bounce
# CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS=5
# CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=5
# Increase the transmission power of the keyboard ble radio to solve
# the problem of left and right delay and poor communication.
CONFIG_BT_CTLR_TX_PWR_PLUS_8=y
CONFIG_ZMK_MOUSE=y

View file

@ -0,0 +1,5 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

View file

@ -0,0 +1,7 @@
file_format: "1"
id: dongle_display
name: dongle_display
type: shield
url: https://github.com/englmaxi/zmk-config
requires:
- i2c_oled

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/display.h>
#include <zmk/display/widgets/battery_status.h>
#include <zmk/usb.h>
#include <zmk/ble.h>
#include <zmk/events/usb_conn_state_changed.h>
#include <zmk/event_manager.h>
#include <zmk/events/battery_state_changed.h>
#include "battery_status.h"
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
struct peripheral_battery_state {
uint8_t source;
uint8_t level;
};
static lv_color_t battery_image_buffer[ZMK_SPLIT_BLE_PERIPHERAL_COUNT][5 * 8];
static void draw_battery(lv_obj_t *canvas, uint8_t level) {
lv_canvas_fill_bg(canvas, lv_color_black(), LV_OPA_COVER);
lv_draw_rect_dsc_t rect_fill_dsc;
lv_draw_rect_dsc_init(&rect_fill_dsc);
rect_fill_dsc.bg_color = lv_color_white();
lv_canvas_set_px(canvas, 0, 0, lv_color_white());
lv_canvas_set_px(canvas, 4, 0, lv_color_white());
if (level > 90) {
// full
} else if (level > 70) {
lv_canvas_draw_rect(canvas, 1, 2, 3, 1, &rect_fill_dsc);
} else if (level > 50) {
lv_canvas_draw_rect(canvas, 1, 2, 3, 2, &rect_fill_dsc);
} else if (level > 30) {
lv_canvas_draw_rect(canvas, 1, 2, 3, 3, &rect_fill_dsc);
} else if (level > 10) {
lv_canvas_draw_rect(canvas, 1, 2, 3, 4, &rect_fill_dsc);
} else {
lv_canvas_draw_rect(canvas, 1, 2, 3, 5, &rect_fill_dsc);
}
}
static void set_battery_symbol(lv_obj_t *widget, struct peripheral_battery_state state) {
lv_obj_t *symbol = lv_obj_get_child(widget, state.source * 2);
lv_obj_t *label = lv_obj_get_child(widget, state.source * 2 + 1);
draw_battery(symbol, state.level);
lv_label_set_text_fmt(label, "%3u%%", state.level);
if (state.level > 0) {
lv_obj_clear_flag(symbol, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(label, LV_OBJ_FLAG_HIDDEN);
} else {
lv_obj_add_flag(symbol, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(label, LV_OBJ_FLAG_HIDDEN);
}
}
void battery_status_update_cb(struct peripheral_battery_state state) {
struct zmk_widget_battery_status *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_battery_symbol(widget->obj, state); }
}
static struct peripheral_battery_state battery_status_get_state(const zmk_event_t *eh) {
const struct zmk_peripheral_battery_state_changed *ev = as_zmk_peripheral_battery_state_changed(eh);
return (struct peripheral_battery_state){
.source = ev->source,
.level = ev->state_of_charge,
};
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_battery_status, struct peripheral_battery_state,
battery_status_update_cb, battery_status_get_state)
ZMK_SUBSCRIPTION(widget_battery_status, zmk_peripheral_battery_state_changed);
int zmk_widget_peripheral_battery_status_init(struct zmk_widget_peripheral_battery_status *widget, lv_obj_t *parent) {
widget->obj = lv_obj_create(parent);
lv_obj_set_size(widget->obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
for (int i = 0; i < ZMK_SPLIT_BLE_PERIPHERAL_COUNT; i++) {
lv_obj_t *image_canvas = lv_canvas_create(widget->obj);
lv_obj_t *battery_label = lv_label_create(widget->obj);
lv_canvas_set_buffer(image_canvas, battery_image_buffer[i], 5, 8, LV_IMG_CF_TRUE_COLOR);
lv_obj_align(image_canvas, LV_ALIGN_TOP_RIGHT, 0, i * 10);
lv_obj_align(battery_label, LV_ALIGN_TOP_RIGHT, -7, i * 10);
}
sys_slist_append(&widgets, &widget->node);
widget_battery_status_init();
return 0;
}
lv_obj_t *zmk_widget_peripheral_battery_status_obj(struct zmk_widget_peripheral_battery_status *widget) {
return widget->obj;
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <lvgl.h>
#include <zephyr/kernel.h>
struct zmk_widget_peripheral_battery_status {
sys_snode_t node;
lv_obj_t *obj;
};
int zmk_widget_peripheral_battery_status_init(struct zmk_widget_peripheral_battery_status *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_peripheral_battery_status_obj(struct zmk_widget_peripheral_battery_status *widget);

View file

@ -0,0 +1,148 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/display.h>
#include <zmk/event_manager.h>
#include <zmk/events/wpm_state_changed.h>
#include <zmk/wpm.h>
#include "bongo_cat.h"
#define SRC(array) (const void **)array, sizeof(array) / sizeof(lv_img_dsc_t *)
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
LV_IMG_DECLARE(bongo_cat_none);
LV_IMG_DECLARE(bongo_cat_left1);
LV_IMG_DECLARE(bongo_cat_left2);
LV_IMG_DECLARE(bongo_cat_right1);
LV_IMG_DECLARE(bongo_cat_right2);
LV_IMG_DECLARE(bongo_cat_both1);
LV_IMG_DECLARE(bongo_cat_both1_open);
LV_IMG_DECLARE(bongo_cat_both2);
#define ANIMATION_SPEED_IDLE 10000
const lv_img_dsc_t *idle_imgs[] = {
&bongo_cat_both1_open,
&bongo_cat_both1_open,
&bongo_cat_both1_open,
&bongo_cat_both1,
};
#define ANIMATION_SPEED_SLOW 2000
const lv_img_dsc_t *slow_imgs[] = {
&bongo_cat_left1,
&bongo_cat_both1,
&bongo_cat_both1,
&bongo_cat_right1,
&bongo_cat_both1,
&bongo_cat_both1,
&bongo_cat_left1,
&bongo_cat_both1,
&bongo_cat_both1,
};
#define ANIMATION_SPEED_MID 500
const lv_img_dsc_t *mid_imgs[] = {
&bongo_cat_left2,
&bongo_cat_left1,
&bongo_cat_none,
&bongo_cat_right2,
&bongo_cat_right1,
&bongo_cat_none,
};
#define ANIMATION_SPEED_FAST 200
const lv_img_dsc_t *fast_imgs[] = {
&bongo_cat_both2,
&bongo_cat_both1,
&bongo_cat_none,
&bongo_cat_none,
};
struct bongo_cat_wpm_status_state {
uint8_t wpm;
};
enum anim_state {
anim_state_none,
anim_state_idle,
anim_state_slow,
anim_state_mid,
anim_state_fast
} current_anim_state;
static void set_animation(lv_obj_t *animing, struct bongo_cat_wpm_status_state state) {
if (state.wpm < 5) {
if (current_anim_state != anim_state_idle) {
lv_animimg_set_src(animing, SRC(idle_imgs));
lv_animimg_set_duration(animing, ANIMATION_SPEED_IDLE);
lv_animimg_set_repeat_count(animing, LV_ANIM_REPEAT_INFINITE);
lv_animimg_start(animing);
current_anim_state = anim_state_idle;
}
} else if (state.wpm < 30) {
if (current_anim_state != anim_state_slow) {
lv_animimg_set_src(animing, SRC(slow_imgs));
lv_animimg_set_duration(animing, ANIMATION_SPEED_SLOW);
lv_animimg_set_repeat_count(animing, LV_ANIM_REPEAT_INFINITE);
lv_animimg_start(animing);
current_anim_state = anim_state_slow;
}
} else if (state.wpm < 70) {
if (current_anim_state != anim_state_mid) {
lv_animimg_set_src(animing, SRC(mid_imgs));
lv_animimg_set_duration(animing, ANIMATION_SPEED_MID);
lv_animimg_set_repeat_count(animing, LV_ANIM_REPEAT_INFINITE);
lv_animimg_start(animing);
current_anim_state = anim_state_mid;
}
} else {
if (current_anim_state != anim_state_fast) {
lv_animimg_set_src(animing, SRC(fast_imgs));
lv_animimg_set_duration(animing, ANIMATION_SPEED_FAST);
lv_animimg_set_repeat_count(animing, LV_ANIM_REPEAT_INFINITE);
lv_animimg_start(animing);
current_anim_state = anim_state_fast;
}
}
}
struct bongo_cat_wpm_status_state bongo_cat_wpm_status_get_state(const zmk_event_t *eh) {
struct zmk_wpm_state_changed *ev = as_zmk_wpm_state_changed(eh);
return (struct bongo_cat_wpm_status_state) { .wpm = ev->state };
};
void bongo_cat_wpm_status_update_cb(struct bongo_cat_wpm_status_state state) {
struct zmk_widget_bongo_cat *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_animation(widget->obj, state); }
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_bongo_cat, struct bongo_cat_wpm_status_state,
bongo_cat_wpm_status_update_cb, bongo_cat_wpm_status_get_state)
ZMK_SUBSCRIPTION(widget_bongo_cat, zmk_wpm_state_changed);
int zmk_widget_bongo_cat_init(struct zmk_widget_bongo_cat *widget, lv_obj_t *parent) {
widget->obj = lv_animimg_create(parent);
lv_obj_center(widget->obj);
sys_slist_append(&widgets, &widget->node);
widget_bongo_cat_init();
return 0;
}
lv_obj_t *zmk_widget_bongo_cat_obj(struct zmk_widget_bongo_cat *widget) {
return widget->obj;
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <lvgl.h>
#include <zephyr/kernel.h>
#include <dt-bindings/zmk/modifiers.h>
struct zmk_widget_bongo_cat {
sys_snode_t node;
lv_obj_t *obj;
};
int zmk_widget_bongo_cat_init(struct zmk_widget_bongo_cat *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_bongo_cat_obj(struct zmk_widget_bongo_cat *widget);

View file

@ -0,0 +1,383 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <lvgl.h>
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_NONE
#define LV_ATTRIBUTE_IMG_BONGO_CAT_NONE
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_NONE uint8_t bongo_cat_none_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x18, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x24, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x43, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x40, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x40, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x20, 0x00, 0x29, 0x82, 0x00, 0x00,
0x1f, 0x10, 0x01, 0x02, 0x41, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x84, 0x21, 0x80, 0x00,
0x00, 0x03, 0xe0, 0x04, 0x10, 0x80, 0x00,
0x00, 0x00, 0x1f, 0x84, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x03, 0xf0, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_none = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_none_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_LEFT1
#define LV_ATTRIBUTE_IMG_BONGO_CAT_LEFT1
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_LEFT1 uint8_t bongo_cat_left1_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x04, 0x00, 0x29, 0x82, 0x00, 0x00,
0x1f, 0x08, 0x01, 0x02, 0x41, 0x00, 0x00,
0x00, 0xf0, 0x03, 0x84, 0x21, 0x80, 0x00,
0x00, 0x10, 0x20, 0x04, 0x10, 0x80, 0x00,
0x00, 0x10, 0x7f, 0x84, 0x00, 0x80, 0x00,
0x00, 0x09, 0x80, 0x7e, 0x00, 0xc0, 0x00,
0x00, 0x06, 0x00, 0x03, 0xf0, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_left1 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_left1_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_LEFT2
#define LV_ATTRIBUTE_IMG_BONGO_CAT_LEFT2
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_LEFT2 uint8_t bongo_cat_left2_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x04, 0x00, 0x29, 0x82, 0x00, 0x00,
0x1f, 0x08, 0x01, 0x02, 0x41, 0x00, 0x00,
0x00, 0xf0, 0x03, 0x84, 0x21, 0x80, 0x00,
0x00, 0x10, 0x20, 0x04, 0x10, 0x80, 0x00,
0x00, 0x10, 0x7f, 0x84, 0x00, 0x80, 0x00,
0x00, 0x09, 0x80, 0x7e, 0x00, 0xc0, 0x00,
0x00, 0x66, 0x00, 0x03, 0xf0, 0x40, 0x00,
0x00, 0x40, 0x80, 0x00, 0x0f, 0xe0, 0x00,
0x00, 0x04, 0x80, 0x00, 0x00, 0x3e, 0x00,
0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_left2 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_left2_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_RIGHT1
#define LV_ATTRIBUTE_IMG_BONGO_CAT_RIGHT1
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_RIGHT1 uint8_t bongo_cat_right1_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x18, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x24, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x43, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x40, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x40, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x20, 0x00, 0x28, 0x02, 0x00, 0x00,
0x1f, 0x10, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x80, 0x01, 0x80, 0x00,
0x00, 0x03, 0xe0, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x1f, 0x82, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00,
0x00, 0x00, 0x00, 0x08, 0x2f, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x04, 0x40, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_right1 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_right1_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_RIGHT2
#define LV_ATTRIBUTE_IMG_BONGO_CAT_RIGHT2
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_RIGHT2 uint8_t bongo_cat_right2_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x18, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x24, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x43, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x40, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x40, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x20, 0x00, 0x28, 0x02, 0x00, 0x00,
0x1f, 0x10, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x80, 0x01, 0x80, 0x00,
0x00, 0x03, 0xe0, 0x00, 0x00, 0x80, 0x00,
0x00, 0x00, 0x1f, 0x82, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x00, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x08, 0x10, 0x40, 0x00,
0x00, 0x00, 0x00, 0x08, 0x2f, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x04, 0x40, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x33, 0x80, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_right2 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_right2_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH1
#define LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH1
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH1 uint8_t bongo_cat_both1_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x04, 0x00, 0x28, 0x02, 0x00, 0x00,
0x1f, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0xf0, 0x03, 0x80, 0x01, 0x80, 0x00,
0x00, 0x10, 0x20, 0x00, 0x00, 0x80, 0x00,
0x00, 0x10, 0x7f, 0x82, 0x00, 0x80, 0x00,
0x00, 0x09, 0x80, 0x7c, 0x00, 0xc0, 0x00,
0x00, 0x06, 0x00, 0x08, 0x10, 0x40, 0x00,
0x00, 0x00, 0x00, 0x08, 0x2f, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x04, 0x40, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_both1 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_both1_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH1_OPEN
#define LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH1_OPEN
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH1_OPEN uint8_t bongo_cat_both1_open_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x08, 0x00, 0x02, 0x00, 0x00,
0xe0, 0x04, 0x00, 0x10, 0x02, 0x00, 0x00,
0x1f, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0xf0, 0x03, 0x80, 0x01, 0x80, 0x00,
0x00, 0x10, 0x20, 0x00, 0x00, 0x80, 0x00,
0x00, 0x10, 0x7f, 0x82, 0x00, 0x80, 0x00,
0x00, 0x09, 0x80, 0x7c, 0x00, 0xc0, 0x00,
0x00, 0x06, 0x00, 0x08, 0x10, 0x40, 0x00,
0x00, 0x00, 0x00, 0x08, 0x2f, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x04, 0x40, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_both1_open = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_both1_open_map,
};
#ifndef LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH2
#define LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH2
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BONGO_CAT_BOTH2 uint8_t bongo_cat_both2_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x7c, 0x02, 0x00, 0x00,
0x00, 0x00, 0x20, 0x07, 0xc5, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x79, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x11, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x08, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x14, 0x10, 0x02, 0x00, 0x00,
0xe0, 0x04, 0x00, 0x28, 0x02, 0x00, 0x00,
0x1f, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0xf0, 0x03, 0x80, 0x01, 0x80, 0x00,
0x00, 0x10, 0x20, 0x00, 0x00, 0x80, 0x00,
0x00, 0x10, 0x7f, 0x82, 0x00, 0x80, 0x00,
0x00, 0x09, 0x80, 0x7c, 0x00, 0xc0, 0x00,
0x00, 0x66, 0x00, 0x08, 0x10, 0x40, 0x00,
0x00, 0x40, 0x80, 0x08, 0x2f, 0xe0, 0x00,
0x00, 0x04, 0x80, 0x04, 0x40, 0x3e, 0x00,
0x00, 0x0c, 0x00, 0x33, 0x80, 0x01, 0xc0,
0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const lv_img_dsc_t bongo_cat_both2 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 50,
.header.h = 26,
.data_size = 190,
.data = bongo_cat_both2_map,
};

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/display.h>
#include <zmk/event_manager.h>
#include <zmk/events/hid_indicators_changed.h>
#include "hid_indicators.h"
#define LED_NLCK 0x01
#define LED_CLCK 0x02
#define LED_SLCK 0x04
struct hid_indicators_state {
uint8_t hid_indicators;
};
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
static void set_hid_indicators(lv_obj_t *label, struct hid_indicators_state state) {
char text[7] = {};
bool lock = false;
if (state.hid_indicators & LED_CLCK) {
strncat(text, "C", 1);
lock = true;
}
if (state.hid_indicators & LED_NLCK) {
strncat(text, "N", 1);
lock = true;
}
if (state.hid_indicators & LED_SLCK) {
strncat(text, "S", 1);
lock = true;
}
if (lock) {
strncat(text, "LCK", 3);
}
lv_label_set_text(label, text);
}
void hid_indicators_update_cb(struct hid_indicators_state state) {
struct zmk_widget_hid_indicators *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_hid_indicators(widget->obj, state); }
}
static struct hid_indicators_state hid_indicators_get_state(const zmk_event_t *eh) {
struct zmk_hid_indicators_changed *ev = as_zmk_hid_indicators_changed(eh);
return (struct hid_indicators_state) {
.hid_indicators = ev->indicators,
};
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_hid_indicators, struct hid_indicators_state,
hid_indicators_update_cb, hid_indicators_get_state)
ZMK_SUBSCRIPTION(widget_hid_indicators, zmk_hid_indicators_changed);
int zmk_widget_hid_indicators_init(struct zmk_widget_hid_indicators *widget, lv_obj_t *parent) {
widget->obj = lv_label_create(parent);
sys_slist_append(&widgets, &widget->node);
widget_hid_indicators_init();
return 0;
}
lv_obj_t *zmk_widget_hid_indicators_obj(struct zmk_widget_hid_indicators *widget) {
return widget->obj;
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <lvgl.h>
#include <zephyr/kernel.h>
struct zmk_widget_hid_indicators {
sys_snode_t node;
lv_obj_t *obj;
};
int zmk_widget_hid_indicators_init(struct zmk_widget_hid_indicators *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_hid_indicators_obj(struct zmk_widget_hid_indicators *widget);

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/display.h>
#include <zmk/display/widgets/layer_status.h>
#include <zmk/events/layer_state_changed.h>
#include <zmk/event_manager.h>
#include <zmk/endpoints.h>
#include <zmk/keymap.h>
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
struct layer_status_state {
uint8_t index;
const char *label;
};
static void set_layer_symbol(lv_obj_t *label, struct layer_status_state state) {
if (state.label == NULL) {
char text[7] = {};
sprintf(text, "%i", state.index);
lv_label_set_text(label, text);
} else {
char text[13] = {};
snprintf(text, sizeof(text), "%s", state.label);
lv_label_set_text(label, text);
}
}
static void layer_status_update_cb(struct layer_status_state state) {
struct zmk_widget_layer_status *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_layer_symbol(widget->obj, state); }
}
static struct layer_status_state layer_status_get_state(const zmk_event_t *eh) {
uint8_t index = zmk_keymap_highest_layer_active();
return (struct layer_status_state) {
.index = index,
.label = zmk_keymap_layer_name(index)
};
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_layer_status, struct layer_status_state, layer_status_update_cb,
layer_status_get_state)
ZMK_SUBSCRIPTION(widget_layer_status, zmk_layer_state_changed);
int zmk_widget_layer_status_init(struct zmk_widget_layer_status *widget, lv_obj_t *parent) {
widget->obj = lv_label_create(parent);
sys_slist_append(&widgets, &widget->node);
widget_layer_status_init();
return 0;
}
lv_obj_t *zmk_widget_layer_status_obj(struct zmk_widget_layer_status *widget) {
return widget->obj;
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <lvgl.h>
#include <zephyr/kernel.h>
struct zmk_widget_layer_status {
sys_snode_t node;
lv_obj_t *obj;
};
int zmk_widget_layer_status_init(struct zmk_widget_layer_status *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_layer_status_obj(struct zmk_widget_layer_status *widget);

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/display.h>
#include <zmk/event_manager.h>
#include <zmk/events/keycode_state_changed.h>
#include <zmk/hid.h>
#include <dt-bindings/zmk/modifiers.h>
#include "modifiers.h"
struct modifiers_state {
uint8_t modifiers;
};
struct modifier_symbol {
uint8_t modifier;
const lv_img_dsc_t *symbol_dsc;
lv_obj_t *symbol;
lv_obj_t *selection_line;
bool is_active;
};
LV_IMG_DECLARE(control_icon);
struct modifier_symbol ms_control = {
.modifier = MOD_LCTL | MOD_RCTL,
.symbol_dsc = &control_icon,
};
LV_IMG_DECLARE(shift_icon);
struct modifier_symbol ms_shift = {
.modifier = MOD_LSFT | MOD_RSFT,
.symbol_dsc = &shift_icon,
};
LV_IMG_DECLARE(alt_icon);
struct modifier_symbol ms_alt = {
.modifier = MOD_LALT | MOD_RALT,
.symbol_dsc = &alt_icon,
};
LV_IMG_DECLARE(win_icon);
struct modifier_symbol ms_gui = {
.modifier = MOD_LGUI | MOD_RGUI,
.symbol_dsc = &win_icon,
};
LV_IMG_DECLARE(opt_icon);
struct modifier_symbol ms_opt = {
.modifier = MOD_LALT | MOD_RALT,
.symbol_dsc = &opt_icon,
};
LV_IMG_DECLARE(cmd_icon);
struct modifier_symbol ms_cmd = {
.modifier = MOD_LGUI | MOD_RGUI,
.symbol_dsc = &cmd_icon,
};
struct modifier_symbol *modifier_symbols[] = {
// this order determines the order of the symbols
&ms_cmd,
&ms_opt,
&ms_control,
&ms_shift
};
#define NUM_SYMBOLS (sizeof(modifier_symbols) / sizeof(struct modifier_symbol *))
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
static void anim_y_cb(void *var, int32_t v) {
lv_obj_set_y(var, v);
}
static void move_object_y(void *obj, int32_t from, int32_t to) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
lv_anim_set_time(&a, 200); // will be replaced with lv_anim_set_duration
lv_anim_set_exec_cb(&a, anim_y_cb);
lv_anim_set_path_cb(&a, lv_anim_path_overshoot);
lv_anim_set_values(&a, from, to);
lv_anim_start(&a);
}
static void set_modifiers(lv_obj_t *widget, struct modifiers_state state) {
for (int i = 0; i < NUM_SYMBOLS; i++) {
bool mod_is_active = (state.modifiers & modifier_symbols[i]->modifier) > 0;
if (mod_is_active && !modifier_symbols[i]->is_active) {
move_object_y(modifier_symbols[i]->symbol, 1, 0);
move_object_y(modifier_symbols[i]->selection_line, SIZE_SYMBOLS + 4, SIZE_SYMBOLS + 2);
modifier_symbols[i]->is_active = true;
} else if (!mod_is_active && modifier_symbols[i]->is_active) {
move_object_y(modifier_symbols[i]->symbol, 0, 1);
move_object_y(modifier_symbols[i]->selection_line, SIZE_SYMBOLS + 2, SIZE_SYMBOLS + 4);
modifier_symbols[i]->is_active = false;
}
}
}
void modifiers_update_cb(struct modifiers_state state) {
struct zmk_widget_modifiers *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_modifiers(widget->obj, state); }
}
static struct modifiers_state modifiers_get_state(const zmk_event_t *eh) {
return (struct modifiers_state) {
.modifiers = zmk_hid_get_explicit_mods()
};
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_modifiers, struct modifiers_state,
modifiers_update_cb, modifiers_get_state)
ZMK_SUBSCRIPTION(widget_modifiers, zmk_keycode_state_changed);
int zmk_widget_modifiers_init(struct zmk_widget_modifiers *widget, lv_obj_t *parent) {
widget->obj = lv_obj_create(parent);
lv_obj_set_size(widget->obj, NUM_SYMBOLS * (SIZE_SYMBOLS + 1) + 1, SIZE_SYMBOLS + 3);
static lv_style_t style_line;
lv_style_init(&style_line);
lv_style_set_line_width(&style_line, 2);
static const lv_point_t selection_line_points[] = { {0, 0}, {SIZE_SYMBOLS, 0} };
for (int i = 0; i < NUM_SYMBOLS; i++) {
modifier_symbols[i]->symbol = lv_img_create(widget->obj);
lv_obj_align(modifier_symbols[i]->symbol, LV_ALIGN_TOP_LEFT, 1 + (SIZE_SYMBOLS + 1) * i, 1);
lv_img_set_src(modifier_symbols[i]->symbol, modifier_symbols[i]->symbol_dsc);
modifier_symbols[i]->selection_line = lv_line_create(widget->obj);
lv_line_set_points(modifier_symbols[i]->selection_line, selection_line_points, 2);
lv_obj_add_style(modifier_symbols[i]->selection_line, &style_line, 0);
lv_obj_align_to(modifier_symbols[i]->selection_line, modifier_symbols[i]->symbol, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 3);
}
sys_slist_append(&widgets, &widget->node);
widget_modifiers_init();
return 0;
}
lv_obj_t *zmk_widget_modifiers_obj(struct zmk_widget_modifiers *widget) {
return widget->obj;
}

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <lvgl.h>
#include <zephyr/kernel.h>
#include <dt-bindings/zmk/modifiers.h>
#define SIZE_SYMBOLS 14 // 14 x 14 pixel
struct zmk_widget_modifiers {
sys_snode_t node;
lv_obj_t *obj;
};
int zmk_widget_modifiers_init(struct zmk_widget_modifiers *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_modifiers_obj(struct zmk_widget_modifiers *widget);

View file

@ -0,0 +1,215 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <lvgl.h>
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_CONTROL
#define LV_ATTRIBUTE_IMG_CONTROL
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_CONTROL uint8_t control_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00,
0x00, 0x00,
0x03, 0x00,
0x07, 0x80,
0x0c, 0xc0,
0x18, 0x60,
0x30, 0x30,
0x20, 0x10,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
};
const lv_img_dsc_t control_icon = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 14,
.header.h = 14,
.data_size = 36,
.data = control_map,
};
#ifndef LV_ATTRIBUTE_IMG_SHIFT
#define LV_ATTRIBUTE_IMG_SHIFT
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SHIFT uint8_t shift_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00,
0x00, 0x00,
0x03, 0x00,
0x07, 0x80,
0x0c, 0xc0,
0x18, 0x60,
0x30, 0x30,
0x78, 0x78,
0x08, 0x40,
0x08, 0x40,
0x08, 0x40,
0x0f, 0xc0,
0x00, 0x00,
0x00, 0x00,
};
const lv_img_dsc_t shift_icon = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 14,
.header.h = 14,
.data_size = 36,
.data = shift_map,
};
#ifndef LV_ATTRIBUTE_IMG_ALT
#define LV_ATTRIBUTE_IMG_ALT
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ALT uint8_t alt_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x32, 0xf8,
0x4a, 0x20,
0x4a, 0x20,
0x7a, 0x20,
0x4a, 0x20,
0x4b, 0xa0,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
};
const lv_img_dsc_t alt_icon = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 14,
.header.h = 14,
.data_size = 36,
.data = alt_map,
};
#ifndef LV_ATTRIBUTE_IMG_GUI
#define LV_ATTRIBUTE_IMG_GUI
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_GUI uint8_t win_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00,
0x00, 0x00,
0x00, 0xf0,
0x0b, 0xf0,
0x3b, 0xf0,
0x3b, 0xf0,
0x3b, 0xf0,
0x00, 0x00,
0x3b, 0xf0,
0x3b, 0xf0,
0x3b, 0xf0,
0x03, 0xf0,
0x00, 0x30,
0x00, 0x00,
};
const lv_img_dsc_t win_icon = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 14,
.header.h = 14,
.data_size = 36,
.data = win_map,
};
#ifndef LV_ATTRIBUTE_IMG_CMD
#define LV_ATTRIBUTE_IMG_CMD
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_CMD uint8_t cmd_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00,
0x00, 0x00,
0x18, 0x60,
0x24, 0x90,
0x24, 0x90,
0x1f, 0xe0,
0x04, 0x80,
0x04, 0x80,
0x1f, 0xe0,
0x24, 0x90,
0x24, 0x90,
0x18, 0x60,
0x00, 0x00,
0x00, 0x00,
};
const lv_img_dsc_t cmd_icon = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 14,
.header.h = 14,
.data_size = 36,
.data = cmd_map,
};
#ifndef LV_ATTRIBUTE_IMG_OPT
#define LV_ATTRIBUTE_IMG_OPT
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_OPT uint8_t opt_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x00, 0x00,
0x00, 0x00,
0x3c, 0xe0,
0x3c, 0xe0,
0x06, 0x00,
0x06, 0x00,
0x06, 0x00,
0x03, 0x00,
0x03, 0x00,
0x03, 0x00,
0x01, 0xe0,
0x01, 0xe0,
0x00, 0x00,
0x00, 0x00,
};
const lv_img_dsc_t opt_icon = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 14,
.header.h = 14,
.data_size = 36,
.data = opt_map,
};

View file

@ -0,0 +1,207 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/display.h>
#include <zmk/event_manager.h>
#include <zmk/events/ble_active_profile_changed.h>
#include <zmk/events/endpoint_changed.h>
#include <zmk/events/usb_conn_state_changed.h>
#include <zmk/usb.h>
#include <zmk/ble.h>
#include <zmk/endpoints.h>
#include "output_status.h"
static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);
LV_IMG_DECLARE(sym_usb);
LV_IMG_DECLARE(sym_bt);
LV_IMG_DECLARE(sym_ok);
LV_IMG_DECLARE(sym_nok);
LV_IMG_DECLARE(sym_open);
LV_IMG_DECLARE(sym_1);
LV_IMG_DECLARE(sym_2);
LV_IMG_DECLARE(sym_3);
LV_IMG_DECLARE(sym_4);
LV_IMG_DECLARE(sym_5);
const lv_img_dsc_t *sym_num[] = {
&sym_1,
&sym_2,
&sym_3,
&sym_4,
&sym_5,
};
enum output_symbol {
output_symbol_usb,
output_symbol_usb_hid_status,
output_symbol_bt,
output_symbol_bt_number,
output_symbol_bt_status,
output_symbol_selection_line
};
enum selection_line_state {
selection_line_state_usb,
selection_line_state_bt
} current_selection_line_state;
lv_point_t selection_line_points[] = { {-1, 0}, {12, 0} }; // will be replaced with lv_point_precise_t
struct output_status_state {
struct zmk_endpoint_instance selected_endpoint;
int active_profile_index;
bool active_profile_connected;
bool active_profile_bonded;
bool usb_is_hid_ready;
};
static struct output_status_state get_state(const zmk_event_t *_eh) {
return (struct output_status_state){
.selected_endpoint = zmk_endpoints_selected(),
.active_profile_index = zmk_ble_active_profile_index(),
.active_profile_connected = zmk_ble_active_profile_is_connected(),
.active_profile_bonded = !zmk_ble_active_profile_is_open(),
.usb_is_hid_ready = zmk_usb_is_hid_ready()
};
}
static void anim_x_cb(void * var, int32_t v) {
lv_obj_set_x(var, v);
}
static void anim_size_cb(void * var, int32_t v) {
selection_line_points[1].x = v;
}
static void move_object_x(void *obj, int32_t from, int32_t to) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
lv_anim_set_time(&a, 200); // will be replaced with lv_anim_set_duration
lv_anim_set_exec_cb(&a, anim_x_cb);
lv_anim_set_path_cb(&a, lv_anim_path_overshoot);
lv_anim_set_values(&a, from, to);
lv_anim_start(&a);
}
static void change_size_object(void *obj, int32_t from, int32_t to) {
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
lv_anim_set_time(&a, 200); // will be replaced with lv_anim_set_duration
lv_anim_set_exec_cb(&a, anim_size_cb);
lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);
lv_anim_set_values(&a, from, to);
lv_anim_start(&a);
}
static void set_status_symbol(lv_obj_t *widget, struct output_status_state state) {
lv_obj_t *usb = lv_obj_get_child(widget, output_symbol_usb);
lv_obj_t *usb_hid_status = lv_obj_get_child(widget, output_symbol_usb_hid_status);
lv_obj_t *bt = lv_obj_get_child(widget, output_symbol_bt);
lv_obj_t *bt_number = lv_obj_get_child(widget, output_symbol_bt_number);
lv_obj_t *bt_status = lv_obj_get_child(widget, output_symbol_bt_status);
lv_obj_t *selection_line = lv_obj_get_child(widget, output_symbol_selection_line);
switch (state.selected_endpoint.transport) {
case ZMK_TRANSPORT_USB:
if (current_selection_line_state != selection_line_state_usb) {
move_object_x(selection_line, lv_obj_get_x(bt) - 1, lv_obj_get_x(usb) - 1);
change_size_object(selection_line, 18, 11);
current_selection_line_state = selection_line_state_usb;
}
break;
case ZMK_TRANSPORT_BLE:
if (current_selection_line_state != selection_line_state_bt) {
move_object_x(selection_line, lv_obj_get_x(usb) - 1, lv_obj_get_x(bt) - 1);
change_size_object(selection_line, 11, 18);
current_selection_line_state = selection_line_state_bt;
}
break;
}
if (state.usb_is_hid_ready) {
lv_img_set_src(usb_hid_status, &sym_ok);
} else {
lv_img_set_src(usb_hid_status, &sym_nok);
}
if (state.active_profile_index < (sizeof(sym_num) / sizeof(lv_img_dsc_t *))) {
lv_img_set_src(bt_number, sym_num[state.active_profile_index]);
} else {
lv_img_set_src(bt_number, &sym_nok);
}
if (state.active_profile_bonded) {
if (state.active_profile_connected) {
lv_img_set_src(bt_status, &sym_ok);
} else {
lv_img_set_src(bt_status, &sym_nok);
}
} else {
lv_img_set_src(bt_status, &sym_open);
}
}
static void output_status_update_cb(struct output_status_state state) {
struct zmk_widget_output_status *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_status_symbol(widget->obj, state); }
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_output_status, struct output_status_state,
output_status_update_cb, get_state)
ZMK_SUBSCRIPTION(widget_output_status, zmk_endpoint_changed);
ZMK_SUBSCRIPTION(widget_output_status, zmk_ble_active_profile_changed);
ZMK_SUBSCRIPTION(widget_output_status, zmk_usb_conn_state_changed);
int zmk_widget_output_status_init(struct zmk_widget_output_status *widget, lv_obj_t *parent) {
widget->obj = lv_obj_create(parent);
lv_obj_set_size(widget->obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_t *usb = lv_img_create(widget->obj);
lv_obj_align(usb, LV_ALIGN_TOP_LEFT, 1, 4);
lv_img_set_src(usb, &sym_usb);
lv_obj_t *usb_hid_status = lv_img_create(widget->obj);
lv_obj_align_to(usb_hid_status, usb, LV_ALIGN_BOTTOM_LEFT, 2, -7);
lv_obj_t *bt = lv_img_create(widget->obj);
lv_obj_align_to(bt, usb, LV_ALIGN_OUT_RIGHT_TOP, 6, 0);
lv_img_set_src(bt, &sym_bt);
lv_obj_t *bt_number = lv_img_create(widget->obj);
lv_obj_align_to(bt_number, bt, LV_ALIGN_OUT_RIGHT_TOP, 2, 7);
lv_obj_t *bt_status = lv_img_create(widget->obj);
lv_obj_align_to(bt_status, bt, LV_ALIGN_OUT_RIGHT_TOP, 2, 1);
static lv_style_t style_line;
lv_style_init(&style_line);
lv_style_set_line_width(&style_line, 2);
lv_obj_t *selection_line;
selection_line = lv_line_create(widget->obj);
lv_line_set_points(selection_line, selection_line_points, 2);
lv_obj_add_style(selection_line, &style_line, 0);
lv_obj_align_to(selection_line, usb, LV_ALIGN_OUT_TOP_LEFT, 3, -1);
sys_slist_append(&widgets, &widget->node);
widget_output_status_init();
return 0;
}
lv_obj_t *zmk_widget_output_status_obj(struct zmk_widget_output_status *widget) {
return widget->obj;
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <lvgl.h>
#include <zephyr/kernel.h>
struct zmk_widget_output_status {
sys_snode_t node;
lv_obj_t *obj;
};
int zmk_widget_output_status_init(struct zmk_widget_output_status *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_output_status_obj(struct zmk_widget_output_status *widget);

View file

@ -0,0 +1,231 @@
/*
* Copyright (c) 2024 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <lvgl.h>
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_SYM_1
#define LV_ATTRIBUTE_IMG_SYM_1
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_1 uint8_t sym_1_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x30, 0x70, 0x70, 0x30, 0x30, 0x30,
};
const lv_img_dsc_t sym_1 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 6,
.data_size = 14,
.data = sym_1_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_2
#define LV_ATTRIBUTE_IMG_SYM_2
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_2 uint8_t sym_2_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x70, 0xd8, 0x18, 0x30, 0x60, 0xf8,
};
const lv_img_dsc_t sym_2 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 6,
.data_size = 14,
.data = sym_2_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_3
#define LV_ATTRIBUTE_IMG_SYM_3
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_3 uint8_t sym_3_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x70, 0x98, 0x30, 0x18, 0xd8, 0x70,
};
const lv_img_dsc_t sym_3 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 6,
.data_size = 14,
.data = sym_3_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_4
#define LV_ATTRIBUTE_IMG_SYM_4
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_4 uint8_t sym_4_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x10, 0x30, 0x70, 0xd0, 0xf8, 0x10,
};
const lv_img_dsc_t sym_4 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 6,
.data_size = 14,
.data = sym_4_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_5
#define LV_ATTRIBUTE_IMG_SYM_5
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_5 uint8_t sym_5_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x78, 0x40, 0x70, 0x18, 0xd8, 0x70,
};
const lv_img_dsc_t sym_5 = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 6,
.data_size = 14,
.data = sym_5_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_OK
#define LV_ATTRIBUTE_IMG_SYM_OK
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_OK uint8_t sym_ok_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x08, 0x18, 0xb0, 0xe0, 0x40,
};
const lv_img_dsc_t sym_ok = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 5,
.data_size = 13,
.data = sym_ok_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_NOK
#define LV_ATTRIBUTE_IMG_SYM_NOK
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_NOK uint8_t sym_nok_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x88, 0xd8, 0x70, 0xd8, 0x88,
};
const lv_img_dsc_t sym_nok = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 5,
.data_size = 13,
.data = sym_nok_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_OPEN
#define LV_ATTRIBUTE_IMG_SYM_OPEN
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_OPEN uint8_t sym_open_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x20, 0x70, 0xd8, 0x70, 0x20,
};
const lv_img_dsc_t sym_open = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 5,
.header.h = 5,
.data_size = 13,
.data = sym_open_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_BT
#define LV_ATTRIBUTE_IMG_SYM_BT
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_BT uint8_t sym_bt_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x3e, 0x00, 0x67, 0x00, 0xe3, 0x80, 0xe9,
0x80, 0x8c, 0x80, 0xc9, 0x80, 0xe3, 0x80,
0xe3, 0x80, 0xc9, 0x80, 0x8c, 0x80, 0xe9,
0x80, 0xe3, 0x80, 0x67, 0x00, 0x3e, 0x00,
};
const lv_img_dsc_t sym_bt = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 9,
.header.h = 14,
.data_size = 36,
.data = sym_bt_map,
};
#ifndef LV_ATTRIBUTE_IMG_SYM_USB
#define LV_ATTRIBUTE_IMG_SYM_USB
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_SYM_USB uint8_t sym_usb_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/
0x7f, 0x00, 0x41, 0x00, 0x55, 0x00, 0x41,
0x00, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80,
};
const lv_img_dsc_t sym_usb = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 9,
.header.h = 14,
.data_size = 36,
.data = sym_usb_map,
};