led: add MODE_FLASH

This commit is contained in:
Beat Küng 2017-10-05 13:14:24 +02:00 committed by Lorenz Meier
parent 263b7ea009
commit cdf17c5447
4 changed files with 73 additions and 14 deletions

View File

@ -20,6 +20,7 @@ uint8 MODE_BLINK_SLOW = 3
uint8 MODE_BLINK_NORMAL = 4
uint8 MODE_BLINK_FAST = 5
uint8 MODE_BREATHE = 6 # continuously increase & decrease brightness (solid color if driver does not support it)
uint8 MODE_FLASH = 7 # two fast blinks (on/off) with timing as in MODE_BLINK_FAST and then off for a while
uint8 MAX_PRIORITY = 2 # maxium priority (minimum is 0)
@ -27,6 +28,6 @@ uint8 MAX_PRIORITY = 2 # maxium priority (minimum is 0)
uint8 led_mask # bitmask which LED(s) to control, set to 0xff for all
uint8 color # see COLOR_*
uint8 mode # see MODE_*
uint8 num_blinks # how many times to blink (number of on-off cycles if mode is one of MODE_BLINK_*). Set to 0 for infinite
uint8 num_blinks # how many times to blink (number of on-off cycles if mode is one of MODE_BLINK_*) . Set to 0 for infinite
# in MODE_FLASH it is the number of cycles (infinite is not possible)
uint8 priority # priority: higher priority events will override current lower priority events (see MAX_PRIORITY)

View File

@ -60,7 +60,21 @@ int LedController::update(LedControlData &control_data)
// don't apply the new state just yet to avoid interrupting an ongoing blinking state
for (int i = 0; i < BOARD_MAX_LEDS; ++i) {
if (led_control.led_mask & (1 << i)) {
_states[i].next_state.set(led_control);
// if next state has already a higher priority state than
// led_control, set lower prio state directly, so that this
// information is not lost
if (_states[i].next_state.is_valid() && led_control.priority < _states[i].next_state.priority) {
_states[i].set(led_control);
} else {
// if a lower prio event is already in next state and a
// higher prio event is coming in
if (_states[i].next_state.is_valid() && led_control.priority > _states[i].next_state.priority) {
_states[i].apply_next_state();
}
_states[i].next_state.set(led_control);
}
}
}
}
@ -96,6 +110,7 @@ int LedController::update(LedControlData &control_data)
uint16_t current_blink_duration = 0;
switch (cur_data.mode) {
case led_control_s::MODE_FLASH:
case led_control_s::MODE_BLINK_FAST:
current_blink_duration = BLINK_FAST_DURATION / 100;
break;
@ -168,15 +183,7 @@ int LedController::update(LedControlData &control_data)
had_changes = true;
}
_states[i].priority[next_priority].color = _states[i].next_state.color;
_states[i].priority[next_priority].mode = _states[i].next_state.mode;
_states[i].priority[next_priority].blink_times_left = _states[i].next_state.num_blinks * 2;
if (_states[i].priority[next_priority].blink_times_left == 0) {
// handle infinite case
_states[i].priority[next_priority].blink_times_left = 254;
}
_states[i].apply_next_state();
_states[i].next_state.reset();
}
@ -204,6 +211,7 @@ void LedController::get_control_data(LedControlData &control_data)
control_data.leds[i].brightness = 255;
for (int priority = led_control_s::MAX_PRIORITY; priority >= 0; --priority) {
bool flash_output_active = true;
const PerPriorityData &cur_data = _states[i].priority[priority];
if (cur_data.mode == led_control_s::MODE_DISABLED) {
@ -225,10 +233,16 @@ void LedController::get_control_data(LedControlData &control_data)
break;
}
case led_control_s::MODE_FLASH:
if (cur_data.blink_times_left % 10 < 6) { // 2 blinks, then turn off for the rest of the cycle
flash_output_active = false;
}
/* FALLTHROUGH */
case led_control_s::MODE_BLINK_FAST:
case led_control_s::MODE_BLINK_NORMAL:
case led_control_s::MODE_BLINK_SLOW:
if (cur_data.blink_times_left % 2 == 0) {
if (cur_data.blink_times_left % 2 == 0 && flash_output_active) {
control_data.leds[i].color = cur_data.color;
}

View File

@ -141,6 +141,47 @@ private:
PerPriorityData priority[led_control_s::MAX_PRIORITY + 1];
uint16_t current_blinking_time = 0; ///< how long the Led was in current state (in 0.1 ms, wraps if > 6.5s)
NextState next_state;
void set(const led_control_s &led_control)
{
int next_priority = (int)led_control.priority;
priority[next_priority].color = led_control.color;
priority[next_priority].mode = led_control.mode;
// initialise the flash counter
if (led_control.mode == led_control_s::MODE_FLASH) {
priority[next_priority].blink_times_left = led_control.num_blinks * 10;
} else {
priority[next_priority].blink_times_left = led_control.num_blinks * 2;
}
if (priority[next_priority].blink_times_left == 0) {
// handle infinite case
priority[next_priority].blink_times_left = 254;
}
}
void apply_next_state()
{
int next_priority = (int)next_state.priority;
priority[next_priority].color = next_state.color;
priority[next_priority].mode = next_state.mode;
if (next_state.mode == led_control_s::MODE_FLASH) {
priority[next_priority].blink_times_left = next_state.num_blinks * 10;
} else {
priority[next_priority].blink_times_left = next_state.num_blinks * 2;
}
if (priority[next_priority].blink_times_left == 0) {
// handle infinite case
priority[next_priority].blink_times_left = 254;
}
}
};
PerLedData _states[BOARD_MAX_LEDS]; ///< keep current LED states
@ -150,4 +191,3 @@ private:
bool _force_update = true; ///< force an orb_copy in the beginning
bool _breathe_enabled = false; ///< true if at least one of the led's is currently in breathe mode
};

View File

@ -82,6 +82,7 @@ $ led_control blink -c blue -l 0 -n 5
PRINT_MODULE_USAGE_PARAM_INT('n', 3, 1, 20, "Number of blinks", true);
PRINT_MODULE_USAGE_PARAM_STRING('s', "normal", "fast|normal|slow", "Set blinking speed", true);
PRINT_MODULE_USAGE_COMMAND_DESCR("breathe", "Continuously fade LED in & out");
PRINT_MODULE_USAGE_COMMAND_DESCR("flash", "Two fast blinks and then off with frequency of 1Hz");
PRINT_MODULE_USAGE_PARAM_COMMENT("The following arguments apply to all of the above commands except for 'test':");
PRINT_MODULE_USAGE_PARAM_STRING('c', "white", "red|blue|green|yellow|purple|amber|cyan|white", "color", true);
@ -259,6 +260,9 @@ led_control_main(int argc, char *argv[])
} else if (!strcmp(argv[myoptind], "breathe")) {
led_control.mode = led_control_s::MODE_BREATHE;
} else if (!strcmp(argv[myoptind], "flash")) {
led_control.mode = led_control_s::MODE_FLASH;
} else {
usage();
return 1;