SOFTWARE.
*/
-#include "visualizer.h"
#include "config.h"
+#include "visualizer.h"
#include <string.h>
#ifdef PROTOCOL_CHIBIOS
#include "ch.h"
// Define this in config.h
#ifndef VISUALIZER_THREAD_PRIORITY
-#define "Visualizer thread priority not defined"
+// The visualizer needs gfx thread priorities
+#define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2)
#endif
static visualizer_keyboard_status_t current_status = {
.layer = 0xFFFFFFFF,
.default_layer = 0xFFFFFFFF,
- .mods = 0xFF,
.leds = 0xFFFFFFFF,
+#ifdef BACKLIGHT_ENABLE
+ .backlight_level = 0,
+#endif
+ .mods = 0xFF,
.suspended = false,
#ifdef VISUALIZER_USER_DATA_SIZE
.user_data = {0}
status1->mods == status2->mods &&
status1->leds == status2->leds &&
status1->suspended == status2->suspended
+#ifdef BACKLIGHT_ENABLE
+ && status1->backlight_level == status2->backlight_level
+#endif
#ifdef VISUALIZER_USER_DATA_SIZE
&& memcmp(status1->user_data, status2->user_data, VISUALIZER_USER_DATA_SIZE) == 0
#endif
GDisplay* LCD_DISPLAY = 0;
GDisplay* LED_DISPLAY = 0;
+#ifdef LCD_DISPLAY_NUMBER
__attribute__((weak))
GDisplay* get_lcd_display(void) {
- return gdispGetDisplay(0);
+ return gdispGetDisplay(LCD_DISPLAY_NUMBER);
}
+#endif
+#ifdef LED_DISPLAY_NUMBER
__attribute__((weak))
GDisplay* get_led_display(void) {
- return gdispGetDisplay(1);
+ return gdispGetDisplay(LED_DISPLAY_NUMBER);
}
+#endif
void start_keyframe_animation(keyframe_animation_t* animation) {
animation->current_frame = -1;
}
}
+static uint8_t get_num_running_animations(void) {
+ uint8_t count = 0;
+ for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) {
+ count += animations[i] ? 1 : 0;
+ }
+ return count;
+}
+
static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systemticks_t delta, systemticks_t* sleep_time) {
// TODO: Clean up this messy code
dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame,
(*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state);
}
-bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- return false;
-}
-
-bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
-#ifdef LCD_ENABLE
- gdispSetPowerMode(powerOff);
-#endif
-#ifdef LCD_BACKLIGHT_ENABLE
- lcd_backlight_hal_color(0, 0, 0);
-#endif
- return false;
-}
-
-bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
-#ifdef LCD_ENABLE
- gdispSetPowerMode(powerOn);
-#endif
- return false;
-}
-
-bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state) {
- (void)animation;
- (void)state;
- dprint("User visualizer inited\n");
- visualizer_enabled = true;
- return false;
-}
-
// TODO: Optimize the stack size, this is probably way too big
static DECLARE_THREAD_STACK(visualizerThreadStack, 1024);
static DECLARE_THREAD_FUNCTION(visualizerThread, arg) {
.mods = 0xFF,
.leds = 0xFFFFFFFF,
.suspended = false,
-#ifdef VISUALIZER_USER_DATA_SIZE
+ #ifdef BACKLIGHT_ENABLE
+ .backlight_level = 0,
+ #endif
+ #ifdef VISUALIZER_USER_DATA_SIZE
.user_data = {0},
-#endif
+ #endif
};
visualizer_state_t state = {
systemticks_t sleep_time = TIME_INFINITE;
systemticks_t current_time = gfxSystemTicks();
+ bool force_update = true;
while(true) {
systemticks_t new_time = gfxSystemTicks();
systemticks_t delta = new_time - current_time;
current_time = new_time;
bool enabled = visualizer_enabled;
- if (!same_status(&state.status, ¤t_status)) {
+ if (force_update || !same_status(&state.status, ¤t_status)) {
+ force_update = false;
+ #if BACKLIGHT_ENABLE
+ if(current_status.backlight_level != state.status.backlight_level) {
+ if (current_status.backlight_level != 0) {
+ gdispGSetPowerMode(LED_DISPLAY, powerOn);
+ uint16_t percent = (uint16_t)current_status.backlight_level * 100 / BACKLIGHT_LEVELS;
+ gdispGSetBacklight(LED_DISPLAY, percent);
+ }
+ else {
+ gdispGSetPowerMode(LED_DISPLAY, powerOff);
+ }
+ state.status.backlight_level = current_status.backlight_level;
+ }
+ #endif
if (visualizer_enabled) {
if (current_status.suspended) {
stop_all_keyframe_animations();
update_keyframe_animation(animations[i], &state, delta, &sleep_time);
}
}
-#ifdef LED_ENABLE
+#ifdef BACKLIGHT_ENABLE
gdispGFlush(LED_DISPLAY);
#endif
+#ifdef LCD_ENABLE
+ gdispGFlush(LCD_DISPLAY);
+#endif
+
#ifdef EMULATOR
draw_emulator();
#endif
- // The animation can enable the visualizer
- // And we might need to update the state when that happens
- // so don't sleep
- if (enabled != visualizer_enabled) {
+ // Enable the visualizer when the startup or the suspend animation has finished
+ if (!visualizer_enabled && state.status.suspended == false && get_num_running_animations() == 0) {
+ visualizer_enabled = true;
+ force_update = true;
sleep_time = 0;
}
void visualizer_init(void) {
gfxInit();
-#ifdef LCD_BACKLIGHT_ENABLE
+ #ifdef LCD_BACKLIGHT_ENABLE
lcd_backlight_init();
-#endif
+ #endif
-#ifdef SERIAL_LINK_ENABLE
+ #ifdef SERIAL_LINK_ENABLE
add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) );
-#endif
+ #endif
-#ifdef LCD_ENABLE
+ #ifdef LCD_ENABLE
LCD_DISPLAY = get_lcd_display();
-#endif
-#ifdef LED_ENABLE
+ #endif
+
+ #ifdef BACKLIGHT_ENABLE
LED_DISPLAY = get_led_display();
-#endif
+ #endif
// We are using a low priority thread, the idea is to have it run only
// when the main thread is sleeping during the matrix scanning
- gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack),
- VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL);
+ gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack),
+ VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL);
}
void update_status(bool changed) {
.default_layer = default_state,
.mods = mods,
.leds = leds,
+#ifdef BACKLIGHT_ENABLE
+ .backlight_level = current_status.backlight_level,
+#endif
.suspended = current_status.suspended,
};
#ifdef VISUALIZER_USER_DATA_SIZE
current_status.suspended = false;
update_status(true);
}
+
+#ifdef BACKLIGHT_ENABLE
+void backlight_set(uint8_t level) {
+ current_status.backlight_level = level;
+ update_status(true);
+}
+#endif