LibreVNA/Software/VNA_embedded/Application/Led.cpp
2022-10-01 23:27:03 +02:00

143 lines
2.4 KiB
C++

#include "Led.hpp"
#include "stm.hpp"
#include "FreeRTOS.h"
#include "task.h"
#if HW_REVISION == 'B'
#define LED_STATUS_TASK_STACK_SIZE_WORDS 128
extern TIM_HandleTypeDef htim2;
enum class Mode {
Off,
On,
Blink,
Pulsating,
Error,
};
static Mode mode;
static uint8_t led_statecnt;
static int8_t led_ncnt;
static StackType_t LedStatusStack[LED_STATUS_TASK_STACK_SIZE_WORDS];
static StaticTask_t LedStatusCB;
static xTaskHandle LedStatusHandle = NULL;
static uint8_t err_cnt;
static void led_set_percentage(uint8_t val) {
uint16_t compare = val * val / 100;
TIM2->CCR1 = compare;
}
static void LedStatus(void * const argument) {
UNUSED(argument);
while (1) {
if (led_statecnt < 199) {
led_statecnt++;
} else {
led_statecnt = 0;
}
switch (mode) {
case Mode::Off:
led_set_percentage(0);
vTaskSuspend(NULL);
break;
case Mode::On:
led_set_percentage(100);
vTaskSuspend(NULL);
break;
case Mode::Error:
if (led_statecnt == 0) {
err_cnt++;
if (err_cnt > led_ncnt) {
// reached number of blinks + 1
err_cnt = 0;
}
}
if (err_cnt >= led_ncnt) {
break;
}
// fall through
/* no break */
case Mode::Blink:
if(led_statecnt < 100) {
led_set_percentage(100);
} else {
led_set_percentage(0);
}
break;
case Mode::Pulsating:
if (led_statecnt < 100) {
led_set_percentage(led_statecnt);
} else {
led_set_percentage(200 - led_statecnt);
}
break;
}
vTaskDelay(5);
}
}
#endif
void LED::Init() {
#if HW_REVISION == 'B'
led_ncnt = 0;
mode = Mode::Off;
HAL_TIM_Base_Start(&htim2);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
LedStatusHandle = xTaskCreateStatic(LedStatus, "LedStatusTask", LED_STATUS_TASK_STACK_SIZE_WORDS,
NULL, 6, LedStatusStack, &LedStatusCB);
vTaskSuspend(LedStatusHandle);
#endif
}
void LED::Pulsating() {
#if HW_REVISION == 'B'
if(led_ncnt) {
return;
}
vTaskSuspend(LedStatusHandle);
mode = Mode::Pulsating;
vTaskResume(LedStatusHandle);
#endif
}
void LED::Off() {
#if HW_REVISION == 'B'
if(led_ncnt) {
return;
}
vTaskSuspend(LedStatusHandle);
mode = Mode::Off;
vTaskResume(LedStatusHandle);
#endif
}
void LED::Error(uint8_t code) {
#if HW_REVISION == 'B'
if(led_ncnt) {
return;
}
vTaskSuspend(LedStatusHandle);
mode = Mode::Error;
led_statecnt = 0;
err_cnt = 0;
led_ncnt = code;
vTaskResume(LedStatusHandle);
#endif
}
void LED::On() {
GPIOA->BSRR = GPIO_PIN_15;
}
void LED::Toggle() {
GPIOA->ODR ^= GPIO_PIN_15;
}