-
-
Notifications
You must be signed in to change notification settings - Fork 175
Expand file tree
/
Copy pathluna.c
More file actions
141 lines (117 loc) · 4.4 KB
/
Copy pathluna.c
File metadata and controls
141 lines (117 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* 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 "luna.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(dog_sit1_90);
LV_IMG_DECLARE(dog_sit2_90);
LV_IMG_DECLARE(dog_walk1_90);
LV_IMG_DECLARE(dog_walk2_90);
LV_IMG_DECLARE(dog_run1_90);
LV_IMG_DECLARE(dog_run2_90);
LV_IMG_DECLARE(dog_sneak1_90);
LV_IMG_DECLARE(dog_sneak2_90);
// Base cycle time comes from Kconfig so CPU usage is tunable (see
// docs/OPTIMIZE.md). Idle runs at 3x the base so the sitting dog stays calm.
// The Kconfig symbol only exists on central; peripheral builds with
// NICE_OLED_WIDGET_ANIMATION_PERIPHERAL_WPM fall back to the same default.
#ifdef CONFIG_NICE_OLED_WIDGET_WPM_LUNA_ANIMATION_MS
#define ANIMATION_SPEED_BASE CONFIG_NICE_OLED_WIDGET_WPM_LUNA_ANIMATION_MS
#else
#define ANIMATION_SPEED_BASE 300
#endif
#define ANIMATION_SPEED_IDLE (ANIMATION_SPEED_BASE * 3)
const lv_img_dsc_t *idle_imgs[] = {
&dog_sit1_90,
&dog_sit2_90,
};
#define ANIMATION_SPEED_SLOW ANIMATION_SPEED_BASE
const lv_img_dsc_t *slow_imgs[] = {
&dog_walk1_90,
&dog_walk2_90,
};
#define ANIMATION_SPEED_MID ANIMATION_SPEED_BASE
const lv_img_dsc_t *mid_imgs[] = {
&dog_walk1_90,
&dog_walk2_90,
};
#define ANIMATION_SPEED_FAST ANIMATION_SPEED_BASE
const lv_img_dsc_t *fast_imgs[] = {
&dog_run1_90,
&dog_run2_90,
};
struct luna_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 luna_wpm_status_state state) {
if (state.wpm < 15) { // def: 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 luna_wpm_status_state luna_wpm_status_get_state(const zmk_event_t *eh) {
struct zmk_wpm_state_changed *ev = as_zmk_wpm_state_changed(eh);
return (struct luna_wpm_status_state){.wpm = ev->state};
};
void luna_wpm_status_update_cb(struct luna_wpm_status_state state) {
struct zmk_widget_luna *widget;
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_animation(widget->obj, state); }
}
ZMK_DISPLAY_WIDGET_LISTENER(widget_luna, struct luna_wpm_status_state, luna_wpm_status_update_cb,
luna_wpm_status_get_state)
ZMK_SUBSCRIPTION(widget_luna, zmk_wpm_state_changed);
int zmk_widget_luna_init(struct zmk_widget_luna *widget, lv_obj_t *parent) {
widget->obj = lv_animimg_create(parent);
lv_obj_center(widget->obj);
sys_slist_append(&widgets, &widget->node);
widget_luna_init();
return 0;
}
lv_obj_t *zmk_widget_luna_obj(struct zmk_widget_luna *widget) { return widget->obj; }