Commit 4ac704af authored by schneider's avatar schneider
Browse files

feat(personal-state): Convert personal state to use the work queue

This reduces the power consumption of the system by around .1 mA when
the personal state is not active.
parent 01dab506
Pipeline #5248 passed with stages
in 2 minutes and 5 seconds
......@@ -29,8 +29,6 @@ number of tasks that will have been keeping card10 running. These are:
+--------------------+-------------------------------+----------+-------------------------------------------+
| `vInterruptsTask`_ | ``interrupts_task`` (static) | +2 | Interrupt dispatcher worker |
+--------------------+-------------------------------+----------+-------------------------------------------+
| `vLedTask`_ | -/- | +1 | LED Animations |
+--------------------+-------------------------------+----------+-------------------------------------------+
| `vMAX30001Task`_ | ``max30001_task_id`` (static) | +1 | `MAX30001`_ ECG driver |
+--------------------+-------------------------------+----------+-------------------------------------------+
| `vBhi160Task`_ | ``bhi160_task_id`` (static) | +1 | `BHI160`_ sensor fusion driver |
......
......@@ -172,17 +172,6 @@ int main(void)
}
}
/* LEDs */
if (xTaskCreate(
vLedTask,
(const char *)"LED",
configMINIMAL_STACK_SIZE,
NULL,
tskIDLE_PRIORITY + 1,
NULL) != pdPASS) {
panic("Failed to create %s task!", "LED");
}
/* Lifecycle */
if (xTaskCreate(
vLifecycleTask,
......
......@@ -2,20 +2,36 @@
#include "leds.h"
#include "modules.h"
#include "os/work_queue.h"
#include "FreeRTOS.h"
#include "timers.h"
#include <math.h>
uint8_t _personal_state_enabled = 0;
uint8_t personal_state = STATE_NONE;
uint8_t personal_state_persistent = 0;
static uint8_t _personal_state_enabled = 0;
static uint8_t personal_state = STATE_NONE;
static uint8_t personal_state_persistent = 0;
static int led_animation_ticks = 0;
static int led_animation_state = 0;
int led_animation_ticks = 0;
int led_animation_state = 0;
static TimerHandle_t led_timer;
static StaticTimer_t led_timer_buffer;
static void worktick(void *data);
static const int led_animation_rate = 1000 / 25; /* 25Hz -> 40ms*/
int personal_state_enabled()
{
return _personal_state_enabled;
}
static void tick(TimerHandle_t xTimer)
{
workqueue_schedule(worktick, NULL);
}
int epic_personal_state_set(uint8_t state, bool persistent)
{
if (state > STATE_CAMP)
......@@ -30,7 +46,29 @@ int epic_personal_state_set(uint8_t state, bool persistent)
_personal_state_enabled = (state != STATE_NONE);
personal_state_persistent = persistent;
if (was_enabled && !_personal_state_enabled) {
if (!was_enabled && _personal_state_enabled) {
// Activate
if (!led_timer) {
led_timer = xTimerCreateStatic(
"personal state",
led_animation_rate / portTICK_PERIOD_MS,
pdTRUE,
NULL,
tick,
&led_timer_buffer
);
// since &poll_timer_buffer is not NULL, xTimerCreateStatic should allways succeed, so
// we don't need to check for poll_timer being NULL.
}
if (xTimerIsTimerActive(led_timer) == pdFALSE) {
xTimerStart(led_timer, 0);
}
} else if (was_enabled && !_personal_state_enabled) {
// Deactivate
xTimerStop(led_timer, 0);
// TODO: we might need a lock here to avoid a race condition
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
epic_leds_update();
}
......@@ -48,80 +86,68 @@ int epic_personal_state_is_persistent()
return personal_state_persistent;
}
void vLedTask(void *pvParameters)
static void worktick(void *data)
{
const int led_animation_rate = 1000 / 25; /* 25Hz -> 40ms*/
while (1) {
if (_personal_state_enabled) {
led_animation_ticks++;
if (personal_state == STATE_NO_CONTACT) {
leds_prep(PERSONAL_STATE_LED, 255, 0, 0);
} else if (personal_state == STATE_CHAOS) {
if (led_animation_state == 0) {
leds_prep(
PERSONAL_STATE_LED, 0, 0, 255
);
if (led_animation_ticks >
(200 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 1;
}
} else if (led_animation_state == 1) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
if (led_animation_ticks >
(300 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 2;
}
} else if (led_animation_state == 2) {
leds_prep(
PERSONAL_STATE_LED, 0, 0, 255
);
if (led_animation_ticks >
(1000 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 3;
}
} else if (led_animation_state == 3) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
if (led_animation_ticks >
(300 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 0;
}
if (_personal_state_enabled) {
led_animation_ticks++;
if (personal_state == STATE_NO_CONTACT) {
leds_prep(PERSONAL_STATE_LED, 255, 0, 0);
} else if (personal_state == STATE_CHAOS) {
if (led_animation_state == 0) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 255);
if (led_animation_ticks >
(200 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 1;
}
} else if (led_animation_state == 1) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
if (led_animation_ticks >
(300 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 2;
}
} else if (personal_state == STATE_COMMUNICATION) {
if (led_animation_state == 0) {
leds_prep(
PERSONAL_STATE_LED, 255, 255, 0
);
if (led_animation_ticks >
(1000 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 1;
}
} else if (led_animation_state == 1) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
if (led_animation_ticks >
(300 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 0;
}
} else if (led_animation_state == 2) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 255);
if (led_animation_ticks >
(1000 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 3;
}
} else if (led_animation_state == 3) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
if (led_animation_ticks >
(300 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 0;
}
} else if (personal_state == STATE_CAMP) {
leds_prep_hsv(
PERSONAL_STATE_LED,
120.0f,
1.0f,
fabs(sin(
led_animation_ticks /
(float)(1000 /
led_animation_rate))));
}
epic_leds_update();
} else if (personal_state == STATE_COMMUNICATION) {
if (led_animation_state == 0) {
leds_prep(PERSONAL_STATE_LED, 255, 255, 0);
if (led_animation_ticks >
(1000 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 1;
}
} else if (led_animation_state == 1) {
leds_prep(PERSONAL_STATE_LED, 0, 0, 0);
if (led_animation_ticks >
(300 / led_animation_rate)) {
led_animation_ticks = 0;
led_animation_state = 0;
}
}
} else if (personal_state == STATE_CAMP) {
leds_prep_hsv(
PERSONAL_STATE_LED,
120.0f,
1.0f,
fabs(sin(
led_animation_ticks /
(float)(1000 / led_animation_rate))));
}
vTaskDelay(led_animation_rate / portTICK_PERIOD_MS);
epic_leds_update();
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment