-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
30dfe0f
commit 2a90780
Showing
51 changed files
with
9,287 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
on: [push, pull_request, workflow_dispatch] | ||
|
||
jobs: | ||
build: | ||
uses: zmkfirmware/zmk/.github/workflows/build-user-config.yml@main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# nice_oled | ||
|
||
![Banner](./assets/banner.JPG) | ||
|
||
nice_oled vertical widgets for oled screens in 128x32 portrait orientation with | ||
zmk software. | ||
|
||
Inspired/forked by the work of @M165437 with his [nice-view-gem](https://github.com/M165437/nice-view-gem). | ||
All credits to him for the original design and implementation. | ||
|
||
Shields supported: | ||
- nice_oled | ||
|
||
The nice_oled is a ZMK module: | ||
- **Vertical layout** | ||
- **Compact** | ||
- **Prevents your neck from hurting when looking at the keyboard** | ||
- **Easy to read in the dark** | ||
|
||
## Gallery | ||
|
||
![Animation Preview](./assets/animation.gif) | ||
![Preview #2](./assets/preview1.JPG) | ||
![Preview #3](./assets/preview2.JPG) | ||
|
||
## Installation | ||
|
||
Only small changes are needed to your keyboard configuration's build setup. Then, you'll need to rebuild and flash your keyboard firmware. | ||
|
||
1. In the `config/west.yml` file, add a new remote and its related project. | ||
|
||
```diff | ||
manifest: | ||
remotes: | ||
- name: zmkfirmware | ||
url-base: https://github.com/zmkfirmware | ||
+ - name: mctechnology17 | ||
+ url-base: https://github.com/mctechnology17 | ||
projects: | ||
- name: zmk | ||
remote: zmkfirmware | ||
revision: main | ||
import: app/west.yml | ||
+ - name: zmk-nice-oled | ||
+ remote: mctechnology17 | ||
+ revision: main | ||
self: | ||
path: config | ||
``` | ||
|
||
2. In the `build.yaml` file, add the `nice_oled` shield. | ||
|
||
```diff | ||
--- | ||
include: | ||
- board: nice_nano_v2 | ||
- shield: corne_left | ||
+ shield: corne_left nice_oled | ||
- board: nice_nano_v2 | ||
- shield: corne_right | ||
+ shield: corne_right nice_oled | ||
``` | ||
|
||
3. Build the firmware, flash it to your keyboard, and enjoy! | ||
|
||
# Configuration | ||
> [!IMPORTANT] | ||
> Make sure to enable the custom status screen in your ZMK configuration: | ||
Make sure to enable the custom status screen in your ZMK configuration: | ||
|
||
```conf | ||
CONFIG_ZMK_DISPLAY=y | ||
CONFIG_ZMK_DISPLAY_STATUS_SCREEN_CUSTOM=y | ||
``` | ||
|
||
## Configuration | ||
|
||
Modify the behavior of this shield by adjusting these options in your personal configuration files. For a more detailed explanation, refer to [Configuration in the ZMK documentation](https://zmk.dev/docs/config). | ||
|
||
| Option | Type | Description | Default | | ||
| ------------------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | ||
| `CONFIG_NICE_OLED_GEM_WPM_FIXED_RANGE` | bool | This shield uses a fixed range for the chart and gauge deflection. If you set this option to `n`, it will switch to a dynamic range, like the default nice!view shield, which dynamically adjusts based on the last 10 WPM values provided by ZMK. | y | | ||
| `CONFIG_NICE_OLED_GEM_WPM_FIXED_RANGE_MAX` | int | You can adjust the maximum value of the fixed range to align with your current goal. | 100 | | ||
| `CONFIG_NICE_OLED_GEM_ANIMATION` | bool | If you find the animation distracting (or want to save on battery usage), you can turn it off by setting this option to `n`. It will instead pick a random frame of the animation every time you restart your keyboard. | y | | ||
| `CONFIG_NICE_OLED_GEM_ANIMATION_MS` | int | Alternatively, you can slow down the animation. A high value, such as 96000, slows the animation considerably, showing the next frame every couple of seconds. The animation consists of 16 frames, and the default value of 960 milliseconds plays it at 60 fps. | 960 | | ||
|
||
## Inspiration | ||
- [nice-view-gem](https://github.com/M165437/nice-view-gem) by @M165437 | ||
- [nice-view-elemental](https://github.com/kevinpastor/nice-view-elemental) by @kevinpastor |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
if(CONFIG_ZMK_DISPLAY AND CONFIG_NICE_VIEW_WIDGET_STATUS) | ||
zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include) | ||
zephyr_library_sources(custom_status_screen.c) | ||
zephyr_library_sources(assets/images.c) | ||
zephyr_library_sources(widgets/battery.c) | ||
zephyr_library_sources(widgets/output.c) | ||
zephyr_library_sources(widgets/util.c) | ||
|
||
if(NOT CONFIG_ZMK_SPLIT OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) | ||
zephyr_library_sources(widgets/layer.c) | ||
zephyr_library_sources(widgets/profile.c) | ||
zephyr_library_sources(widgets/screen.c) | ||
zephyr_library_sources(assets/bongo_cat_images.c) | ||
zephyr_library_sources(widgets/wpm.c) | ||
else() | ||
zephyr_library_sources(assets/vim.c) | ||
zephyr_library_sources(assets/vip_marcos.c) | ||
zephyr_library_sources(assets/crystal.c) | ||
zephyr_library_sources(assets/pokemon.c) | ||
zephyr_library_sources(widgets/animation.c) | ||
zephyr_library_sources(widgets/screen_peripheral.c) | ||
endif() | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
if SHIELD_NICE_OLED | ||
|
||
config LV_Z_VDB_SIZE | ||
default 64 | ||
# default 100 | ||
|
||
config LV_DPI_DEF | ||
default 148 | ||
# default 161 | ||
|
||
config LV_Z_BITS_PER_PIXEL | ||
default 1 | ||
|
||
choice LV_COLOR_DEPTH | ||
default LV_COLOR_DEPTH_1 | ||
endchoice | ||
|
||
choice ZMK_DISPLAY_WORK_QUEUE | ||
default ZMK_DISPLAY_WORK_QUEUE_DEDICATED | ||
endchoice | ||
|
||
choice ZMK_DISPLAY_STATUS_SCREEN | ||
default ZMK_DISPLAY_STATUS_SCREEN_CUSTOM | ||
endchoice | ||
|
||
config LV_Z_MEM_POOL_SIZE | ||
default 4096 if ZMK_DISPLAY_STATUS_SCREEN_CUSTOM | ||
|
||
config ZMK_DISPLAY_STATUS_SCREEN_CUSTOM | ||
imply NICE_VIEW_WIDGET_STATUS | ||
|
||
config NICE_OLED_GEM_ANIMATION_WPM_FIXED_RANGE | ||
bool "Enable fixed range for WPM gauge/chart" | ||
default y | ||
|
||
config NICE_OLED_GEM_ANIMATION_WPM_FIXED_RANGE_MAX | ||
int "Fixed range maximum for WPM gauge/chart" | ||
default 100 | ||
|
||
config NICE_OLED_GEM_ANIMATION | ||
bool "Enable animation on peripheral" | ||
default y | ||
|
||
config NICE_OLED_GEM_ANIMATION_MS | ||
int "Animation length in milliseconds" | ||
default 960 | ||
|
||
config NICE_OLED_POKEMON_ANIMATION | ||
bool "Enable animation on peripheral" | ||
default n | ||
|
||
config NICE_OLED_POKEMON_ANIMATION_MS | ||
int "Animation length in milliseconds" | ||
default 4800 | ||
|
||
config NICE_OLED_VIM | ||
bool "Enable static vim on peripheral" | ||
default n | ||
|
||
config NICE_OLED_VIP_MARCOS | ||
bool "Enable static vim_marcos on peripheral" | ||
default n | ||
|
||
config NICE_VIEW_WIDGET_STATUS | ||
select LV_USE_LABEL | ||
select LV_USE_IMG | ||
select LV_USE_CANVAS | ||
select LV_USE_ANIMIMG | ||
select LV_USE_ANIMATION | ||
|
||
config NICE_VIEW_WIDGET_INVERTED | ||
bool "Invert display colors" | ||
|
||
if !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL | ||
|
||
config NICE_VIEW_WIDGET_STATUS | ||
select ZMK_WPM | ||
|
||
endif # !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL | ||
|
||
endif # SHIELD_NICE_OLED |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
config SHIELD_NICE_OLED | ||
def_bool $(shields_list_contains,nice_oled) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
Oops, something went wrong.