mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-28 03:51:15 +00:00
Refactor work timer structure for improved state management and simplify color definitions. Remove unused warning color definitions and clarify break warning time comment.
This commit is contained in:
parent
cc50f2cd92
commit
7f49c0408f
@ -19,237 +19,159 @@
|
|||||||
#include "rgb_effects/rgb_effects.h"
|
#include "rgb_effects/rgb_effects.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
// Bitpacked flags to save memory
|
// Simple work timer structure
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t active: 1;
|
// Basic state
|
||||||
uint8_t paused: 1;
|
bool active; // Is the timer running?
|
||||||
uint8_t lunch_break: 1;
|
bool paused; // Is the timer paused?
|
||||||
uint8_t mid_break: 1;
|
work_timer_type_t type; // Timer type (30min, 1hr, etc.)
|
||||||
uint8_t lunch_warning_shown: 1;
|
|
||||||
uint8_t mid_break_warning_shown: 1;
|
// Time tracking
|
||||||
uint8_t end_warning_shown: 1;
|
uint32_t start_time; // When this timer started
|
||||||
uint8_t pulse_active: 1; // Flag to track if any pulse is currently active
|
uint32_t end_time; // When this timer should end
|
||||||
} work_timer_flags_t;
|
uint32_t pause_time; // When timer was paused (if paused)
|
||||||
|
uint32_t break_time; // Break duration for this timer
|
||||||
// Simplified work timer state structure
|
|
||||||
typedef struct {
|
// Midpoint break tracking
|
||||||
work_timer_flags_t flags;
|
uint32_t mid_point; // Time value at midpoint (when break starts)
|
||||||
work_timer_type_t timer_type;
|
uint32_t mid_point_end; // Time value when break ends
|
||||||
uint32_t start_time; // When timer was started
|
|
||||||
uint32_t end_time; // When timer should end (calculated)
|
|
||||||
uint32_t pause_time; // When pause started (if paused)
|
|
||||||
uint32_t break_start_time; // When current break started
|
|
||||||
uint32_t mid_break_time; // When mid-break should occur
|
|
||||||
uint32_t mid_break_duration; // How long the mid-break should last
|
|
||||||
bool has_lunch_break; // Whether this timer has a lunch break
|
|
||||||
} work_timer_t;
|
} work_timer_t;
|
||||||
|
|
||||||
// Global work timer state with simplified initialization
|
// Global timer state
|
||||||
static work_timer_t work_timer = {
|
static work_timer_t timer = {0};
|
||||||
.flags = {0},
|
|
||||||
.timer_type = TIMER_TYPE_8HR,
|
|
||||||
.start_time = 0,
|
|
||||||
.end_time = 0,
|
|
||||||
.pause_time = 0,
|
|
||||||
.break_start_time = 0,
|
|
||||||
.mid_break_time = 0,
|
|
||||||
.mid_break_duration = LUNCH_BREAK_DURATION,
|
|
||||||
.has_lunch_break = true
|
|
||||||
};
|
|
||||||
|
|
||||||
// Predefined RGB colors for timer states
|
// Timer colors
|
||||||
static const rgb_color_t WORK_TIMER_START_COLOR = {WORK_TIMER_START_R, WORK_TIMER_START_G, WORK_TIMER_START_B};
|
static const rgb_color_t TIMER_START_COLOR = {WORK_TIMER_START_R, WORK_TIMER_START_G, WORK_TIMER_START_B};
|
||||||
static const rgb_color_t WORK_TIMER_MID_COLOR = {WORK_TIMER_MID_R, WORK_TIMER_MID_G, WORK_TIMER_MID_B};
|
static const rgb_color_t TIMER_MID_COLOR = {WORK_TIMER_MID_R, WORK_TIMER_MID_G, WORK_TIMER_MID_B};
|
||||||
static const rgb_color_t WORK_TIMER_END_COLOR = {WORK_TIMER_END_R, WORK_TIMER_END_G, WORK_TIMER_END_B};
|
static const rgb_color_t TIMER_END_COLOR = {WORK_TIMER_END_R, WORK_TIMER_END_G, WORK_TIMER_END_B};
|
||||||
static const rgb_color_t WORK_TIMER_LUNCH_COLOR = {WORK_TIMER_LUNCH_R, WORK_TIMER_LUNCH_G, WORK_TIMER_LUNCH_B};
|
static const rgb_color_t TIMER_BREAK_COLOR = {WORK_TIMER_LUNCH_R, WORK_TIMER_LUNCH_G, WORK_TIMER_LUNCH_B};
|
||||||
static const rgb_color_t WORK_TIMER_WARNING_COLOR = {WORK_TIMER_WARNING_R, WORK_TIMER_WARNING_G, WORK_TIMER_WARNING_B};
|
|
||||||
|
|
||||||
// Function prototypes for internal functions
|
// Function declarations
|
||||||
static void configure_timer_for_type(work_timer_type_t timer_type);
|
static void save_timer_state(void);
|
||||||
static void display_progress_bar(uint8_t num_leds, float overall_progress, float brightness_factor);
|
static void load_timer_state(void);
|
||||||
static void save_work_timer_state(void);
|
static void display_progress_bar(uint8_t num_leds, float progress, float brightness);
|
||||||
static void load_work_timer_state(void);
|
|
||||||
static void update_pulse_active_state(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure timer parameters based on timer type
|
* Configure a timer with the specified type
|
||||||
*/
|
*/
|
||||||
static void configure_timer_for_type(work_timer_type_t timer_type) {
|
static void configure_timer(work_timer_type_t type) {
|
||||||
work_timer.timer_type = timer_type;
|
timer.type = type;
|
||||||
|
|
||||||
switch (timer_type) {
|
// Set break duration based on timer type
|
||||||
|
switch (type) {
|
||||||
case TIMER_TYPE_30MIN:
|
case TIMER_TYPE_30MIN:
|
||||||
work_timer.mid_break_time = TIMER_30MIN_DURATION / 2;
|
timer.break_time = MID_BREAK_30MIN_DURATION;
|
||||||
work_timer.mid_break_duration = MID_BREAK_30MIN_DURATION;
|
|
||||||
work_timer.has_lunch_break = false;
|
|
||||||
work_timer.end_time = work_timer.start_time + TIMER_30MIN_DURATION;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_TYPE_1HR:
|
case TIMER_TYPE_1HR:
|
||||||
work_timer.mid_break_time = TIMER_1HR_DURATION / 2;
|
timer.break_time = MID_BREAK_1HR_DURATION;
|
||||||
work_timer.mid_break_duration = MID_BREAK_1HR_DURATION;
|
|
||||||
work_timer.has_lunch_break = false;
|
|
||||||
work_timer.end_time = work_timer.start_time + TIMER_1HR_DURATION;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_TYPE_4HR:
|
case TIMER_TYPE_4HR:
|
||||||
work_timer.mid_break_time = TIMER_4HR_DURATION / 2;
|
timer.break_time = MID_BREAK_4HR_DURATION;
|
||||||
work_timer.mid_break_duration = MID_BREAK_4HR_DURATION;
|
|
||||||
work_timer.has_lunch_break = false;
|
|
||||||
work_timer.end_time = work_timer.start_time + TIMER_4HR_DURATION;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_TYPE_8HR:
|
case TIMER_TYPE_8HR:
|
||||||
work_timer.mid_break_time = TIMER_8HR_DURATION / 2;
|
timer.break_time = LUNCH_BREAK_DURATION;
|
||||||
work_timer.mid_break_duration = LUNCH_BREAK_DURATION;
|
|
||||||
work_timer.has_lunch_break = true;
|
|
||||||
work_timer.end_time = work_timer.start_time + TIMER_8HR_DURATION;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_TYPE_10HR:
|
case TIMER_TYPE_10HR:
|
||||||
work_timer.mid_break_time = TIMER_10HR_DURATION / 2;
|
timer.break_time = LUNCH_BREAK_DURATION;
|
||||||
work_timer.mid_break_duration = LUNCH_BREAK_DURATION;
|
|
||||||
work_timer.has_lunch_break = true;
|
|
||||||
work_timer.end_time = work_timer.start_time + TIMER_10HR_DURATION;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Default to 8HR if something goes wrong
|
timer.break_time = LUNCH_BREAK_DURATION;
|
||||||
work_timer.mid_break_time = TIMER_8HR_DURATION / 2;
|
|
||||||
work_timer.mid_break_duration = LUNCH_BREAK_DURATION;
|
|
||||||
work_timer.has_lunch_break = true;
|
|
||||||
work_timer.end_time = work_timer.start_time + TIMER_8HR_DURATION;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate timer duration (excluding break)
|
||||||
|
uint32_t work_duration = 0;
|
||||||
|
switch (type) {
|
||||||
|
case TIMER_TYPE_30MIN: work_duration = TIMER_30MIN_DURATION; break;
|
||||||
|
case TIMER_TYPE_1HR: work_duration = TIMER_1HR_DURATION; break;
|
||||||
|
case TIMER_TYPE_4HR: work_duration = TIMER_4HR_DURATION; break;
|
||||||
|
case TIMER_TYPE_8HR: work_duration = TIMER_8HR_DURATION; break;
|
||||||
|
case TIMER_TYPE_10HR: work_duration = TIMER_10HR_DURATION; break;
|
||||||
|
default: work_duration = TIMER_8HR_DURATION; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate end time and midpoint
|
||||||
|
timer.end_time = timer.start_time + work_duration;
|
||||||
|
timer.mid_point = timer.start_time + (work_duration / 2);
|
||||||
|
timer.mid_point_end = timer.mid_point + timer.break_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the work timer state to EEPROM
|
* Save timer state to EEPROM
|
||||||
*/
|
*/
|
||||||
static void save_work_timer_state(void) {
|
static void save_timer_state(void) {
|
||||||
// Create a buffer to store all our data
|
uint8_t buffer[24] = {0};
|
||||||
uint8_t buffer[24] = {0}; // Increased from 21 to 24 bytes to have enough space
|
|
||||||
|
|
||||||
// Set the active flag
|
// Basic state
|
||||||
buffer[0] = work_timer.flags.active;
|
buffer[0] = timer.active ? 1 : 0;
|
||||||
|
buffer[1] = timer.paused ? 1 : 0;
|
||||||
|
buffer[2] = (uint8_t)timer.type;
|
||||||
|
|
||||||
// Only save time info if timer is active
|
// Time values
|
||||||
if (work_timer.flags.active) {
|
memcpy(&buffer[3], &timer.start_time, sizeof(uint32_t));
|
||||||
// Save start time (4 bytes)
|
memcpy(&buffer[7], &timer.end_time, sizeof(uint32_t));
|
||||||
memcpy(&buffer[1], &work_timer.start_time, sizeof(uint32_t));
|
memcpy(&buffer[11], &timer.pause_time, sizeof(uint32_t));
|
||||||
|
memcpy(&buffer[15], &timer.break_time, sizeof(uint32_t));
|
||||||
// Save end time (4 bytes)
|
memcpy(&buffer[19], &timer.mid_point, sizeof(uint32_t));
|
||||||
memcpy(&buffer[5], &work_timer.end_time, sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Save timer type (1 byte)
|
|
||||||
buffer[9] = (uint8_t)work_timer.timer_type;
|
|
||||||
|
|
||||||
// Save pause state and time (5 bytes)
|
|
||||||
buffer[10] = work_timer.flags.paused;
|
|
||||||
memcpy(&buffer[11], &work_timer.pause_time, sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Save break state (1 byte)
|
|
||||||
buffer[15] = (work_timer.flags.lunch_break ? 1 : 0) |
|
|
||||||
(work_timer.flags.mid_break ? 2 : 0);
|
|
||||||
|
|
||||||
// Save break start time (4 bytes)
|
|
||||||
memcpy(&buffer[16], &work_timer.break_start_time, sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Save mid-break time (4 bytes) - fixed buffer position
|
|
||||||
memcpy(&buffer[20], &work_timer.mid_break_time, sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write all data at once to EEPROM
|
// Write to EEPROM
|
||||||
eeprom_update_block(buffer, (void *)EEPROM_WORK_TIMER_ACTIVE, sizeof(buffer));
|
eeprom_update_block(buffer, (void *)EEPROM_WORK_TIMER_ACTIVE, sizeof(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the work timer state from EEPROM
|
* Load timer state from EEPROM
|
||||||
*/
|
*/
|
||||||
static void load_work_timer_state(void) {
|
static void load_timer_state(void) {
|
||||||
// Create a buffer to read all our data
|
uint8_t buffer[24] = {0};
|
||||||
uint8_t buffer[24] = {0}; // Increased from 21 to 24 bytes to match save function
|
|
||||||
|
|
||||||
// Read all data at once from EEPROM
|
// Read from EEPROM
|
||||||
eeprom_read_block(buffer, (const void *)EEPROM_WORK_TIMER_ACTIVE, sizeof(buffer));
|
eeprom_read_block(buffer, (const void *)EEPROM_WORK_TIMER_ACTIVE, sizeof(buffer));
|
||||||
|
|
||||||
// Get the active flag
|
// Basic state
|
||||||
work_timer.flags.active = buffer[0];
|
timer.active = buffer[0] ? true : false;
|
||||||
|
timer.paused = buffer[1] ? true : false;
|
||||||
|
timer.type = (work_timer_type_t)buffer[2];
|
||||||
|
|
||||||
// Only process the rest if timer was active
|
// Time values
|
||||||
if (work_timer.flags.active) {
|
memcpy(&timer.start_time, &buffer[3], sizeof(uint32_t));
|
||||||
// Load timer type
|
memcpy(&timer.end_time, &buffer[7], sizeof(uint32_t));
|
||||||
work_timer_type_t saved_type = (work_timer_type_t)buffer[9];
|
memcpy(&timer.pause_time, &buffer[11], sizeof(uint32_t));
|
||||||
|
memcpy(&timer.break_time, &buffer[15], sizeof(uint32_t));
|
||||||
|
memcpy(&timer.mid_point, &buffer[19], sizeof(uint32_t));
|
||||||
|
|
||||||
|
// Calculate mid_point_end from loaded values
|
||||||
|
if (timer.active) {
|
||||||
|
timer.mid_point_end = timer.mid_point + timer.break_time;
|
||||||
|
|
||||||
// Get start time (4 bytes)
|
// Verify timer is still valid
|
||||||
memcpy(&work_timer.start_time, &buffer[1], sizeof(uint32_t));
|
if (!timer.paused) {
|
||||||
|
|
||||||
// Get end time (4 bytes)
|
|
||||||
memcpy(&work_timer.end_time, &buffer[5], sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Get pause state and time (5 bytes)
|
|
||||||
work_timer.flags.paused = buffer[10];
|
|
||||||
memcpy(&work_timer.pause_time, &buffer[11], sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Get break state (1 byte)
|
|
||||||
uint8_t break_state = buffer[15];
|
|
||||||
work_timer.flags.lunch_break = (break_state & 1) > 0;
|
|
||||||
work_timer.flags.mid_break = (break_state & 2) > 0;
|
|
||||||
|
|
||||||
// Get break start time (4 bytes)
|
|
||||||
memcpy(&work_timer.break_start_time, &buffer[16], sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Get mid-break time (4 bytes) - fixed buffer position
|
|
||||||
memcpy(&work_timer.mid_break_time, &buffer[20], sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Apply configuration for this timer type (durations, etc.)
|
|
||||||
configure_timer_for_type(saved_type);
|
|
||||||
|
|
||||||
// If currently in a break, we need to adjust for time passed since poweroff
|
|
||||||
if (work_timer.flags.lunch_break || work_timer.flags.mid_break) {
|
|
||||||
uint32_t current_time = timer_read32();
|
uint32_t current_time = timer_read32();
|
||||||
uint32_t time_off = current_time - work_timer.break_start_time;
|
if (current_time > timer.end_time) {
|
||||||
|
timer.active = false;
|
||||||
// If we've been powered off longer than the break duration, end the break
|
save_timer_state();
|
||||||
if (time_off > work_timer.mid_break_duration) {
|
|
||||||
work_timer.flags.lunch_break = 0;
|
|
||||||
work_timer.flags.mid_break = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate timer values
|
|
||||||
uint32_t current_time = timer_read32();
|
|
||||||
|
|
||||||
// If end time is in the past, timer is done
|
|
||||||
if (work_timer.end_time <= current_time && !work_timer.flags.paused) {
|
|
||||||
work_timer.flags.active = 0;
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for end warning state (within 5 minutes of end)
|
|
||||||
if (!work_timer.flags.paused &&
|
|
||||||
current_time >= (work_timer.end_time - BREAK_WARNING_TIME)) {
|
|
||||||
work_timer.flags.end_warning_shown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update pulse active state
|
|
||||||
update_pulse_active_state();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display progress bar with gradient colors
|
* Display progress bar with gradient colors
|
||||||
*/
|
*/
|
||||||
static void display_progress_bar(uint8_t num_leds, float overall_progress, float brightness_factor) {
|
static void display_progress_bar(uint8_t num_leds, float progress, float brightness) {
|
||||||
// Calculate hour segments and LED positions
|
// Progress is a value from 0.0 to 1.0
|
||||||
float hours_per_led = 1.0f / (float)num_leds;
|
float hours_per_led = 1.0f / (float)num_leds;
|
||||||
|
|
||||||
// Determine how many LEDs should be fully lit
|
// Determine how many LEDs should be lit
|
||||||
uint8_t leds_lit = (uint8_t)(overall_progress / hours_per_led);
|
uint8_t leds_lit = (uint8_t)(progress / hours_per_led);
|
||||||
if (leds_lit > num_leds) leds_lit = num_leds;
|
if (leds_lit > num_leds) leds_lit = num_leds;
|
||||||
|
|
||||||
// Calculate progress within the current LED
|
// Calculate progress for the partially-lit LED
|
||||||
float current_led_progress = (overall_progress - (leds_lit * hours_per_led)) / hours_per_led;
|
float current_led_progress = (progress - (leds_lit * hours_per_led)) / hours_per_led;
|
||||||
|
|
||||||
// Set colors for each LED in the progress bar
|
// Set colors for each LED in the progress bar
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
for (uint8_t i = 0; i < num_leds; i++) {
|
||||||
@ -257,46 +179,41 @@ static void display_progress_bar(uint8_t num_leds, float overall_progress, float
|
|||||||
|
|
||||||
if (i < leds_lit) {
|
if (i < leds_lit) {
|
||||||
// Fully lit LED - calculate gradient color based on position
|
// Fully lit LED - calculate gradient color based on position
|
||||||
float led_position = (float)i / (float)(num_leds - 1);
|
float position = (float)i / (float)(num_leds - 1);
|
||||||
|
|
||||||
// Adjust transition points - more green-to-orange (first 80% of bar),
|
// Use green to orange gradient for most of bar, orange to red at end
|
||||||
// and less orange-to-red (last 20% of bar)
|
if (position < 0.7f) {
|
||||||
if (led_position < 0.3f) {
|
// First 70% is green to orange
|
||||||
// Scale to 0.0 - 1.0 for green-to-orange part (now 80% of the bar)
|
float adj_progress = position / 0.7f;
|
||||||
float adjusted_progress = led_position / 0.3f;
|
color = calculate_gradient_color(TIMER_START_COLOR, TIMER_MID_COLOR, adj_progress);
|
||||||
color = calculate_gradient_color(WORK_TIMER_START_COLOR, WORK_TIMER_MID_COLOR, adjusted_progress);
|
} else {
|
||||||
}
|
// Last 30% is orange to red
|
||||||
else {
|
float adj_progress = (position - 0.7f) / 0.3f;
|
||||||
float adjusted_progress = (led_position - 0.3f) / 0.7f; // Scale to 0.0 - 1.0 for last 20%
|
color = calculate_gradient_color(TIMER_MID_COLOR, TIMER_END_COLOR, adj_progress);
|
||||||
color = calculate_gradient_color(WORK_TIMER_MID_COLOR, WORK_TIMER_END_COLOR, adjusted_progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply overall RGB brightness factor
|
// Apply brightness
|
||||||
color.r = (uint8_t)((float)color.r * brightness_factor);
|
color.r = (uint8_t)((float)color.r * brightness);
|
||||||
color.g = (uint8_t)((float)color.g * brightness_factor);
|
color.g = (uint8_t)((float)color.g * brightness);
|
||||||
color.b = (uint8_t)((float)color.b * brightness_factor);
|
color.b = (uint8_t)((float)color.b * brightness);
|
||||||
}
|
}
|
||||||
else if (i == leds_lit && current_led_progress > 0.0f) {
|
else if (i == leds_lit && current_led_progress > 0.0f) {
|
||||||
// Current LED - partially lit based on progress
|
// Partially lit LED
|
||||||
float led_position = (float)i / (float)(num_leds - 1);
|
float position = (float)i / (float)(num_leds - 1);
|
||||||
|
|
||||||
rgb_color_t full_color;
|
rgb_color_t full_color;
|
||||||
// Adjust transition points - more green-to-orange, less orange-to-red
|
|
||||||
if (led_position < 0.3f) {
|
if (position < 0.7f) {
|
||||||
// Scale to 0.0 - 1.0 for green-to-orange part
|
float adj_progress = position / 0.7f;
|
||||||
float adjusted_progress = led_position / 0.3f;
|
full_color = calculate_gradient_color(TIMER_START_COLOR, TIMER_MID_COLOR, adj_progress);
|
||||||
full_color = calculate_gradient_color(WORK_TIMER_START_COLOR, WORK_TIMER_MID_COLOR, adjusted_progress);
|
} else {
|
||||||
}
|
float adj_progress = (position - 0.7f) / 0.3f;
|
||||||
// Last 30% is orange-to-red gradient
|
full_color = calculate_gradient_color(TIMER_MID_COLOR, TIMER_END_COLOR, adj_progress);
|
||||||
else {
|
|
||||||
float adjusted_progress = (led_position - 0.3f) / 0.7f; // Scale to 0.0 - 1.0 for last 20%
|
|
||||||
full_color = calculate_gradient_color(WORK_TIMER_MID_COLOR, WORK_TIMER_END_COLOR, adjusted_progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dim the color based on progress within this LED and overall brightness
|
// Dim by progress and brightness
|
||||||
color.r = (uint8_t)((float)full_color.r * current_led_progress * brightness_factor);
|
color.r = (uint8_t)((float)full_color.r * current_led_progress * brightness);
|
||||||
color.g = (uint8_t)((float)full_color.g * current_led_progress * brightness_factor);
|
color.g = (uint8_t)((float)full_color.g * current_led_progress * brightness);
|
||||||
color.b = (uint8_t)((float)full_color.b * current_led_progress * brightness_factor);
|
color.b = (uint8_t)((float)full_color.b * current_led_progress * brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the LED color
|
// Set the LED color
|
||||||
@ -305,326 +222,114 @@ static void display_progress_bar(uint8_t num_leds, float overall_progress, float
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the pulse active state
|
* Initialize the work timer
|
||||||
* This determines if any pulse effect is currently active
|
|
||||||
*/
|
*/
|
||||||
static void update_pulse_active_state(void) {
|
void work_timer_init(void) {
|
||||||
if (!work_timer.flags.active || work_timer.flags.paused) {
|
load_timer_state();
|
||||||
work_timer.flags.pulse_active = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t current_time = timer_read32();
|
|
||||||
|
|
||||||
// Check if any pulse condition is active
|
|
||||||
bool lunch_warning = false;
|
|
||||||
bool lunch_end_warning = false;
|
|
||||||
bool mid_point_warning = false;
|
|
||||||
bool end_warning = false;
|
|
||||||
|
|
||||||
// Mid-break (lunch) timing logic
|
|
||||||
if (work_timer.has_lunch_break) {
|
|
||||||
// Time until mid-break (lunch)
|
|
||||||
uint32_t time_to_mid_break = 0;
|
|
||||||
if (current_time < work_timer.mid_break_time) {
|
|
||||||
time_to_mid_break = work_timer.mid_break_time - current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lunch break warning (before lunch)
|
|
||||||
lunch_warning = !work_timer.flags.lunch_break &&
|
|
||||||
(time_to_mid_break > 0 && time_to_mid_break < BREAK_WARNING_TIME);
|
|
||||||
|
|
||||||
// Lunch end warning (before end of lunch)
|
|
||||||
lunch_end_warning = work_timer.flags.lunch_break &&
|
|
||||||
(timer_elapsed32(work_timer.break_start_time) >=
|
|
||||||
(work_timer.mid_break_duration - BREAK_WARNING_TIME));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Simple mid-break logic
|
|
||||||
uint32_t time_to_mid_break = 0;
|
|
||||||
if (current_time < work_timer.mid_break_time) {
|
|
||||||
time_to_mid_break = work_timer.mid_break_time - current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mid-point break warning for shorter timers
|
|
||||||
mid_point_warning = !work_timer.flags.mid_break &&
|
|
||||||
(time_to_mid_break > 0 && time_to_mid_break < BREAK_WARNING_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
// End timer warning (5 minutes before end)
|
|
||||||
end_warning = (current_time >= (work_timer.end_time - BREAK_WARNING_TIME) &&
|
|
||||||
current_time < work_timer.end_time);
|
|
||||||
|
|
||||||
// Set pulse active if any of these conditions are true
|
|
||||||
work_timer.flags.pulse_active = (
|
|
||||||
work_timer.flags.mid_break || // Mid-point break pulse
|
|
||||||
work_timer.flags.lunch_break || // Lunch break
|
|
||||||
work_timer.flags.end_warning_shown || // End warning
|
|
||||||
lunch_warning || // Pre-lunch warning
|
|
||||||
lunch_end_warning || // End of lunch warning
|
|
||||||
mid_point_warning || // Mid-point warning for shorter timers
|
|
||||||
end_warning // End warning for all timers
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the work timer on/off
|
* Toggle the work timer on/off
|
||||||
*/
|
*/
|
||||||
void toggle_work_timer(void) {
|
void toggle_work_timer(void) {
|
||||||
if (work_timer.flags.active) {
|
if (timer.active) {
|
||||||
// If timer is active, stop it and reset all state flags
|
// Turn off timer
|
||||||
work_timer.flags.active = 0;
|
timer.active = false;
|
||||||
work_timer.flags.paused = 0;
|
timer.paused = false;
|
||||||
work_timer.flags.lunch_break = 0;
|
|
||||||
work_timer.flags.mid_break = 0;
|
|
||||||
work_timer.flags.lunch_warning_shown = 0;
|
|
||||||
work_timer.flags.mid_break_warning_shown = 0;
|
|
||||||
work_timer.flags.end_warning_shown = 0;
|
|
||||||
work_timer.flags.pulse_active = 0;
|
|
||||||
|
|
||||||
// Save clean state to EEPROM
|
save_timer_state();
|
||||||
save_work_timer_state();
|
|
||||||
|
|
||||||
// Force immediate RGB refresh
|
// Force RGB refresh
|
||||||
rgb_matrix_mode_noeeprom(rgb_matrix_get_mode());
|
rgb_matrix_mode_noeeprom(rgb_matrix_get_mode());
|
||||||
} else {
|
} else {
|
||||||
// If timer is inactive, start a new timer
|
// Start a new timer
|
||||||
work_timer.flags.active = 1;
|
timer.active = true;
|
||||||
work_timer.flags.paused = 0;
|
timer.paused = false;
|
||||||
work_timer.flags.lunch_break = 0;
|
timer.start_time = timer_read32();
|
||||||
work_timer.flags.mid_break = 0;
|
timer.pause_time = 0;
|
||||||
work_timer.flags.lunch_warning_shown = 0;
|
|
||||||
work_timer.flags.mid_break_warning_shown = 0;
|
|
||||||
work_timer.flags.end_warning_shown = 0;
|
|
||||||
work_timer.flags.pulse_active = 0;
|
|
||||||
|
|
||||||
// Set timer start and calculate end time
|
// Configure for current timer type
|
||||||
work_timer.start_time = timer_read32();
|
configure_timer(timer.type);
|
||||||
work_timer.break_start_time = 0;
|
save_timer_state();
|
||||||
|
|
||||||
// Set up mid-break time based on current time
|
|
||||||
uint32_t duration = 0;
|
|
||||||
switch (work_timer.timer_type) {
|
|
||||||
case TIMER_TYPE_30MIN: duration = TIMER_30MIN_DURATION; break;
|
|
||||||
case TIMER_TYPE_1HR: duration = TIMER_1HR_DURATION; break;
|
|
||||||
case TIMER_TYPE_4HR: duration = TIMER_4HR_DURATION; break;
|
|
||||||
case TIMER_TYPE_8HR: duration = TIMER_8HR_DURATION; break;
|
|
||||||
case TIMER_TYPE_10HR: duration = TIMER_10HR_DURATION; break;
|
|
||||||
default: duration = TIMER_8HR_DURATION; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set mid-break time (halfway through timer)
|
|
||||||
work_timer.mid_break_time = work_timer.start_time + (duration / 2);
|
|
||||||
|
|
||||||
// Set end time
|
|
||||||
work_timer.end_time = work_timer.start_time + duration;
|
|
||||||
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_pulse_active_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the work timer - load state from EEPROM
|
|
||||||
*/
|
|
||||||
void work_timer_init(void) {
|
|
||||||
load_work_timer_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a specific timer type
|
* Start a specific timer type
|
||||||
*/
|
*/
|
||||||
void start_timer(work_timer_type_t timer_type) {
|
void start_timer(work_timer_type_t type) {
|
||||||
// Reset timer state
|
// Start fresh
|
||||||
work_timer.flags.active = 1;
|
timer.active = true;
|
||||||
work_timer.flags.paused = 0;
|
timer.paused = false;
|
||||||
work_timer.flags.lunch_break = 0;
|
timer.start_time = timer_read32();
|
||||||
work_timer.flags.mid_break = 0;
|
timer.pause_time = 0;
|
||||||
work_timer.flags.lunch_warning_shown = 0;
|
|
||||||
work_timer.flags.mid_break_warning_shown = 0;
|
|
||||||
work_timer.flags.end_warning_shown = 0;
|
|
||||||
work_timer.flags.pulse_active = 0;
|
|
||||||
|
|
||||||
work_timer.start_time = timer_read32();
|
// Configure based on type
|
||||||
work_timer.break_start_time = 0;
|
configure_timer(type);
|
||||||
|
save_timer_state();
|
||||||
// Configure timer parameters based on type
|
|
||||||
work_timer.timer_type = timer_type;
|
|
||||||
configure_timer_for_type(timer_type);
|
|
||||||
|
|
||||||
save_work_timer_state();
|
|
||||||
|
|
||||||
// Update pulse state immediately after starting timer
|
|
||||||
update_pulse_active_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause or resume the work timer
|
* Pause or resume the timer
|
||||||
*/
|
*/
|
||||||
void toggle_pause_work_timer(void) {
|
void toggle_pause_work_timer(void) {
|
||||||
if (!work_timer.flags.active) return;
|
if (!timer.active) return;
|
||||||
|
|
||||||
if (!work_timer.flags.paused) {
|
if (timer.paused) {
|
||||||
// Pause the timer
|
// Resume - calculate time paused and adjust timers
|
||||||
work_timer.flags.paused = 1;
|
|
||||||
work_timer.pause_time = timer_read32();
|
|
||||||
save_work_timer_state();
|
|
||||||
} else {
|
|
||||||
// Resume the timer - extend all time values by pause duration
|
|
||||||
uint32_t current_time = timer_read32();
|
uint32_t current_time = timer_read32();
|
||||||
uint32_t pause_duration = current_time - work_timer.pause_time;
|
uint32_t pause_duration = current_time - timer.pause_time;
|
||||||
|
|
||||||
// Extend end time by pause duration
|
// Extend all time points by pause duration
|
||||||
work_timer.end_time += pause_duration;
|
timer.end_time += pause_duration;
|
||||||
|
timer.mid_point += pause_duration;
|
||||||
|
timer.mid_point_end += pause_duration;
|
||||||
|
|
||||||
// If mid-break hasn't happened yet, extend that too
|
timer.paused = false;
|
||||||
if (current_time < work_timer.mid_break_time) {
|
} else {
|
||||||
work_timer.mid_break_time += pause_duration;
|
// Pause
|
||||||
}
|
timer.pause_time = timer_read32();
|
||||||
|
timer.paused = true;
|
||||||
// If in a break, adjust break start time too
|
|
||||||
if (work_timer.flags.lunch_break || work_timer.flags.mid_break) {
|
|
||||||
work_timer.break_start_time += pause_duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
work_timer.flags.paused = 0;
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_pulse_active_state();
|
save_timer_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the work timer state
|
* Check if the blue pulse effect should be active
|
||||||
*/
|
*/
|
||||||
void update_work_timer(void) {
|
bool is_timer_pulse_active(void) {
|
||||||
if (!work_timer.flags.active || work_timer.flags.paused) return;
|
if (!timer.active || timer.paused) return false;
|
||||||
|
|
||||||
uint32_t current_time = timer_read32();
|
uint32_t current_time = timer_read32();
|
||||||
|
|
||||||
// Process different timer states based on timer type
|
// Only return true when we're in the mid-point break window
|
||||||
if (work_timer.has_lunch_break) {
|
return (current_time >= timer.mid_point && current_time < timer.mid_point_end);
|
||||||
// Handle lunch break state transitions
|
|
||||||
if (!work_timer.flags.lunch_break) {
|
|
||||||
// Check if it's time to start lunch
|
|
||||||
if (!work_timer.flags.lunch_warning_shown &&
|
|
||||||
current_time >= (work_timer.mid_break_time - BREAK_WARNING_TIME) &&
|
|
||||||
current_time < work_timer.mid_break_time) {
|
|
||||||
// Pre-lunch warning
|
|
||||||
work_timer.flags.lunch_warning_shown = 1;
|
|
||||||
}
|
|
||||||
else if (current_time >= work_timer.mid_break_time) {
|
|
||||||
// Start lunch break
|
|
||||||
work_timer.flags.lunch_break = 1;
|
|
||||||
work_timer.break_start_time = current_time;
|
|
||||||
work_timer.flags.lunch_warning_shown = 0; // Reset for lunch end warning
|
|
||||||
|
|
||||||
// Don't need to extend end time yet - will do that when break ends
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Currently in lunch break
|
|
||||||
uint32_t break_elapsed = timer_elapsed32(work_timer.break_start_time);
|
|
||||||
|
|
||||||
// Check for lunch end warning
|
|
||||||
if (!work_timer.flags.lunch_warning_shown &&
|
|
||||||
break_elapsed >= (work_timer.mid_break_duration - BREAK_WARNING_TIME)) {
|
|
||||||
// Pre-end warning
|
|
||||||
work_timer.flags.lunch_warning_shown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// End lunch break after duration (plus grace period)
|
|
||||||
if (break_elapsed >= (work_timer.mid_break_duration + 5000)) {
|
|
||||||
// End lunch break
|
|
||||||
work_timer.flags.lunch_break = 0;
|
|
||||||
work_timer.flags.lunch_warning_shown = 0;
|
|
||||||
|
|
||||||
// Extend end time by break duration
|
|
||||||
work_timer.end_time += break_elapsed;
|
|
||||||
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Handle mid-break state transitions for shorter timers
|
|
||||||
if (!work_timer.flags.mid_break) {
|
|
||||||
// Check if it's time to start mid-break
|
|
||||||
if (!work_timer.flags.mid_break_warning_shown &&
|
|
||||||
current_time >= (work_timer.mid_break_time - BREAK_WARNING_TIME) &&
|
|
||||||
current_time < work_timer.mid_break_time) {
|
|
||||||
// Mid-break warning
|
|
||||||
work_timer.flags.mid_break_warning_shown = 1;
|
|
||||||
}
|
|
||||||
else if (current_time >= work_timer.mid_break_time) {
|
|
||||||
// Start mid-break
|
|
||||||
work_timer.flags.mid_break = 1;
|
|
||||||
work_timer.break_start_time = current_time;
|
|
||||||
work_timer.flags.mid_break_warning_shown = 0;
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Currently in mid-break
|
|
||||||
uint32_t break_elapsed = timer_elapsed32(work_timer.break_start_time);
|
|
||||||
|
|
||||||
// End mid-break after duration (plus grace period)
|
|
||||||
if (break_elapsed >= (work_timer.mid_break_duration + 5000)) {
|
|
||||||
// End mid-break
|
|
||||||
work_timer.flags.mid_break = 0;
|
|
||||||
work_timer.flags.mid_break_warning_shown = 0;
|
|
||||||
|
|
||||||
// Extend end time by break duration
|
|
||||||
work_timer.end_time += break_elapsed;
|
|
||||||
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for end of day warning
|
|
||||||
if (!work_timer.flags.end_warning_shown &&
|
|
||||||
current_time >= (work_timer.end_time - BREAK_WARNING_TIME)) {
|
|
||||||
work_timer.flags.end_warning_shown = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto-stop after timer ends
|
|
||||||
if (current_time >= work_timer.end_time) {
|
|
||||||
work_timer.flags.active = 0;
|
|
||||||
work_timer.flags.lunch_break = 0;
|
|
||||||
work_timer.flags.mid_break = 0;
|
|
||||||
save_work_timer_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
update_pulse_active_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if any timer pulse is currently active
|
* Update timer state
|
||||||
* Used for easier state checking
|
|
||||||
*
|
|
||||||
* @return true if any timer pulse effect is active, false otherwise
|
|
||||||
*/
|
*/
|
||||||
bool is_timer_pulse_active(void) {
|
void update_work_timer(void) {
|
||||||
// If timer is not active or is paused, no pulse is active
|
if (!timer.active || timer.paused) return;
|
||||||
if (!work_timer.flags.active || work_timer.flags.paused) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the pulse_active flag directly from the work timer state
|
uint32_t current_time = timer_read32();
|
||||||
return work_timer.flags.pulse_active;
|
|
||||||
|
// Check if timer has ended
|
||||||
|
if (current_time >= timer.end_time) {
|
||||||
|
timer.active = false;
|
||||||
|
save_timer_state();
|
||||||
|
rgb_matrix_mode_noeeprom(rgb_matrix_get_mode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the work timer visualization on LEDs
|
* Handle work timer visualization
|
||||||
*/
|
*/
|
||||||
void handle_work_timer(void) {
|
void handle_work_timer(void) {
|
||||||
static bool was_active = false;
|
static bool was_active = false;
|
||||||
|
|
||||||
if (!work_timer.flags.active) {
|
if (!timer.active) {
|
||||||
// If the timer was just deactivated, force RGB refresh
|
|
||||||
if (was_active) {
|
if (was_active) {
|
||||||
rgb_matrix_mode_noeeprom(rgb_matrix_get_mode());
|
rgb_matrix_mode_noeeprom(rgb_matrix_get_mode());
|
||||||
was_active = false;
|
was_active = false;
|
||||||
@ -634,165 +339,55 @@ void handle_work_timer(void) {
|
|||||||
|
|
||||||
was_active = true;
|
was_active = true;
|
||||||
|
|
||||||
// Get current RGB matrix brightness
|
// Get current time and brightness
|
||||||
|
uint32_t current_time = timer_read32();
|
||||||
uint8_t rgb_brightness = rgb_matrix_get_val();
|
uint8_t rgb_brightness = rgb_matrix_get_val();
|
||||||
float brightness_factor = (float)rgb_brightness / 255.0f;
|
float brightness_factor = (float)rgb_brightness / 255.0f;
|
||||||
|
|
||||||
// Number of LEDs in the progress bar
|
// Number of LEDs in the progress bar
|
||||||
const uint8_t num_leds = WORK_TIMER_LED_END - WORK_TIMER_LED_START + 1;
|
const uint8_t num_leds = WORK_TIMER_LED_END - WORK_TIMER_LED_START + 1;
|
||||||
|
|
||||||
// Calculate overall progress (0.0 - 1.0)
|
// Calculate progress based on active timer duration
|
||||||
uint32_t current_time = timer_read32();
|
float progress;
|
||||||
float overall_progress;
|
if (timer.paused) {
|
||||||
|
// When paused, use pause time for progress calculation
|
||||||
// Simple progress calculation based on total time range
|
progress = (float)(timer.pause_time - timer.start_time) /
|
||||||
if (work_timer.flags.paused) {
|
(float)(timer.end_time - timer.start_time);
|
||||||
// When paused, use the pause time for calculation
|
|
||||||
overall_progress = (float)(work_timer.pause_time - work_timer.start_time) /
|
|
||||||
(float)(work_timer.end_time - work_timer.start_time);
|
|
||||||
} else {
|
} else {
|
||||||
// Normal operation - current progress through timer
|
// When active, use current time for progress calculation
|
||||||
overall_progress = (float)(current_time - work_timer.start_time) /
|
progress = (float)(current_time - timer.start_time) /
|
||||||
(float)(work_timer.end_time - work_timer.start_time);
|
(float)(timer.end_time - timer.start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overall_progress > 1.0f) overall_progress = 1.0f;
|
// Clamp progress to valid range
|
||||||
|
if (progress > 1.0f) progress = 1.0f;
|
||||||
|
if (progress < 0.0f) progress = 0.0f;
|
||||||
|
|
||||||
// Create pulsing effect
|
// Check if we're in the break window (midpoint of the timer)
|
||||||
uint8_t pulse_brightness = abs((timer_read() / 4) % 510 - 255);
|
if (!timer.paused && current_time >= timer.mid_point && current_time < timer.mid_point_end) {
|
||||||
float pulse_ratio = (float)pulse_brightness / 255.0f;
|
// In break time - show blue pulse
|
||||||
|
rgb_color_t color = TIMER_BREAK_COLOR;
|
||||||
// Check for various timer states
|
|
||||||
bool lunch_warning = false;
|
|
||||||
bool lunch_end_warning = false;
|
|
||||||
bool mid_break_warning = false;
|
|
||||||
bool end_warning = false;
|
|
||||||
|
|
||||||
// For timers with lunch breaks
|
|
||||||
if (work_timer.has_lunch_break) {
|
|
||||||
// Pre-lunch warning (red pulse)
|
|
||||||
lunch_warning = !work_timer.flags.lunch_break &&
|
|
||||||
(current_time >= (work_timer.mid_break_time - BREAK_WARNING_TIME) &&
|
|
||||||
current_time < work_timer.mid_break_time);
|
|
||||||
|
|
||||||
// Lunch-end warning (red pulse)
|
// Slow pulse for break time
|
||||||
lunch_end_warning = work_timer.flags.lunch_break &&
|
uint8_t break_pulse = timer_read() / 10;
|
||||||
work_timer.break_start_time != 0 &&
|
float break_intensity = (float)(abs(break_pulse % 510 - 255)) / 255.0f;
|
||||||
(timer_elapsed32(work_timer.break_start_time) >=
|
|
||||||
(work_timer.mid_break_duration - BREAK_WARNING_TIME));
|
|
||||||
|
|
||||||
// End warning
|
// Apply blue pulse to all LEDs in progress bar
|
||||||
end_warning = current_time >= (work_timer.end_time - BREAK_WARNING_TIME) &&
|
for (uint8_t i = 0; i < num_leds; i++) {
|
||||||
current_time < work_timer.end_time;
|
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
||||||
|
(uint8_t)((float)color.r * break_intensity * brightness_factor),
|
||||||
// Choose appropriate display based on current state
|
(uint8_t)((float)color.g * break_intensity * brightness_factor),
|
||||||
if (lunch_warning || lunch_end_warning) {
|
(uint8_t)((float)color.b * break_intensity * brightness_factor));
|
||||||
// Pre/Post lunch red warning pulse
|
|
||||||
rgb_color_t pulse_color = WORK_TIMER_WARNING_COLOR;
|
|
||||||
|
|
||||||
// Apply pulsing effect to all progress bar LEDs
|
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
|
||||||
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
|
||||||
(uint8_t)((float)pulse_color.r * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.g * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.b * pulse_ratio * brightness_factor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (work_timer.flags.lunch_break && work_timer.break_start_time != 0) {
|
|
||||||
// During lunch break - blue pulse
|
|
||||||
rgb_color_t pulse_color = WORK_TIMER_LUNCH_COLOR;
|
|
||||||
|
|
||||||
// Use a slower pulse for regular lunch break
|
|
||||||
uint8_t lunch_pulse = abs((timer_read() / 10) % 510 - 255);
|
|
||||||
float lunch_pulse_ratio = (float)lunch_pulse / 255.0f;
|
|
||||||
|
|
||||||
// Apply lunch break color to all progress bar LEDs
|
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
|
||||||
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
|
||||||
(uint8_t)((float)pulse_color.r * lunch_pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.g * lunch_pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.b * lunch_pulse_ratio * brightness_factor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (work_timer.flags.end_warning_shown || end_warning) {
|
|
||||||
// End of day warning - red pulse
|
|
||||||
rgb_color_t pulse_color = WORK_TIMER_WARNING_COLOR;
|
|
||||||
|
|
||||||
// Apply pulsing effect to all progress bar LEDs
|
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
|
||||||
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
|
||||||
(uint8_t)((float)pulse_color.r * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.g * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.b * pulse_ratio * brightness_factor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Normal progress bar display
|
|
||||||
display_progress_bar(num_leds, overall_progress, brightness_factor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// For timers without lunch breaks (30MIN, 1HR, 4HR)
|
|
||||||
else {
|
|
||||||
mid_break_warning = !work_timer.flags.mid_break &&
|
|
||||||
(current_time >= (work_timer.mid_break_time - BREAK_WARNING_TIME) &&
|
|
||||||
current_time < work_timer.mid_break_time);
|
|
||||||
|
|
||||||
end_warning = current_time >= (work_timer.end_time - BREAK_WARNING_TIME) &&
|
|
||||||
current_time < work_timer.end_time;
|
|
||||||
|
|
||||||
// Choose appropriate display based on current state
|
|
||||||
if (mid_break_warning) {
|
|
||||||
// Mid-break warning - red pulse
|
|
||||||
rgb_color_t pulse_color = WORK_TIMER_WARNING_COLOR;
|
|
||||||
|
|
||||||
// Apply pulsing effect to all progress bar LEDs
|
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
|
||||||
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
|
||||||
(uint8_t)((float)pulse_color.r * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.g * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.b * pulse_ratio * brightness_factor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Mid-break active
|
|
||||||
else if (work_timer.flags.mid_break && work_timer.break_start_time != 0) {
|
|
||||||
// Mid-break active - blue pulse
|
|
||||||
rgb_color_t pulse_color = WORK_TIMER_LUNCH_COLOR;
|
|
||||||
|
|
||||||
// Use a faster pulse for mid-break reminder
|
|
||||||
uint8_t mid_pulse = abs((timer_read() / 3) % 510 - 255);
|
|
||||||
float mid_pulse_ratio = (float)mid_pulse / 255.0f;
|
|
||||||
|
|
||||||
// Apply pulsing effect to all progress bar LEDs
|
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
|
||||||
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
|
||||||
(uint8_t)((float)pulse_color.r * mid_pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.g * mid_pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.b * mid_pulse_ratio * brightness_factor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (work_timer.flags.end_warning_shown || end_warning) {
|
|
||||||
// End of timer warning - red pulse
|
|
||||||
rgb_color_t pulse_color = WORK_TIMER_WARNING_COLOR;
|
|
||||||
|
|
||||||
// Apply pulsing effect to all progress bar LEDs
|
|
||||||
for (uint8_t i = 0; i < num_leds; i++) {
|
|
||||||
rgb_matrix_set_color(WORK_TIMER_LED_START + i,
|
|
||||||
(uint8_t)((float)pulse_color.r * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.g * pulse_ratio * brightness_factor),
|
|
||||||
(uint8_t)((float)pulse_color.b * pulse_ratio * brightness_factor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Normal progress bar display
|
|
||||||
display_progress_bar(num_leds, overall_progress, brightness_factor);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Normal progress display
|
||||||
|
display_progress_bar(num_leds, progress, brightness_factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Work timer task - can be called periodically
|
* Periodic timer task
|
||||||
*/
|
*/
|
||||||
void work_timer_task(void) {
|
void work_timer_task(void) {
|
||||||
// Update work timer state
|
|
||||||
update_work_timer();
|
update_work_timer();
|
||||||
}
|
}
|
@ -58,11 +58,6 @@ typedef enum {
|
|||||||
#define WORK_TIMER_LUNCH_G 0
|
#define WORK_TIMER_LUNCH_G 0
|
||||||
#define WORK_TIMER_LUNCH_B 255
|
#define WORK_TIMER_LUNCH_B 255
|
||||||
|
|
||||||
// Warning color (red)
|
|
||||||
#define WORK_TIMER_WARNING_R 255
|
|
||||||
#define WORK_TIMER_WARNING_G 0
|
|
||||||
#define WORK_TIMER_WARNING_B 0
|
|
||||||
|
|
||||||
// Standard timer durations (in milliseconds)
|
// Standard timer durations (in milliseconds)
|
||||||
// IMPORTANT: These represent actual working time (excluding breaks)
|
// IMPORTANT: These represent actual working time (excluding breaks)
|
||||||
#define TIMER_30MIN_DURATION 1800000 // 30 minutes
|
#define TIMER_30MIN_DURATION 1800000 // 30 minutes
|
||||||
@ -72,7 +67,7 @@ typedef enum {
|
|||||||
#define TIMER_10HR_DURATION 36000000 // 10 hours (real world 11 hours with lunch)
|
#define TIMER_10HR_DURATION 36000000 // 10 hours (real world 11 hours with lunch)
|
||||||
|
|
||||||
// Break durations
|
// Break durations
|
||||||
#define BREAK_WARNING_TIME 60000 // 60 seconds
|
#define BREAK_WARNING_TIME 60000 // 60 seconds (kept for calculations but not used for warnings)
|
||||||
#define MID_BREAK_30MIN_DURATION 30000 // 30 seconds
|
#define MID_BREAK_30MIN_DURATION 30000 // 30 seconds
|
||||||
#define MID_BREAK_1HR_DURATION 45000 // 45 seconds
|
#define MID_BREAK_1HR_DURATION 45000 // 45 seconds
|
||||||
#define MID_BREAK_4HR_DURATION 60000 // 60 seconds
|
#define MID_BREAK_4HR_DURATION 60000 // 60 seconds
|
||||||
|
Loading…
Reference in New Issue
Block a user