118 lines
4.4 KiB
C
118 lines
4.4 KiB
C
/**
|
||
* @file led_indicator.h
|
||
* @brief Неблокирующая индикация состояния устройства на одном или нескольких LED.
|
||
*/
|
||
|
||
#ifndef LED_INDICATOR_H
|
||
#define LED_INDICATOR_H
|
||
|
||
#include <stddef.h>
|
||
#include <stdint.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define LED_INDICATOR_MAX_STEPS 8U
|
||
|
||
typedef enum {
|
||
LED_INDICATOR_MODE_OFF = 0,
|
||
LED_INDICATOR_MODE_ON,
|
||
LED_INDICATOR_MODE_STARTUP,
|
||
LED_INDICATOR_MODE_WORK,
|
||
LED_INDICATOR_MODE_ACTIVITY,
|
||
LED_INDICATOR_MODE_WARNING,
|
||
LED_INDICATOR_MODE_ERROR,
|
||
LED_INDICATOR_MODE_CRITICAL,
|
||
LED_INDICATOR_MODE_COUNT
|
||
} LedIndicator_Mode;
|
||
|
||
/** Один период сигнала. Бит N в levels задаёт уровень шага N. */
|
||
typedef struct {
|
||
uint32_t duration_ms[LED_INDICATOR_MAX_STEPS];
|
||
uint8_t levels;
|
||
uint8_t step_count;
|
||
uint8_t repeat;
|
||
uint8_t final_level;
|
||
} LedIndicator_Pattern;
|
||
|
||
/**
|
||
* Аппаратный порт. write получает логический уровень, поэтому active-low,
|
||
* GPIO, PWM и регистры расширителя обрабатываются за границей ядра.
|
||
*/
|
||
typedef struct {
|
||
void (*write)(void *context, uint8_t channel, uint8_t on);
|
||
uint32_t (*now_ms)(void *context);
|
||
void *context;
|
||
} LedIndicator_Port;
|
||
|
||
typedef struct {
|
||
LedIndicator_Mode mode;
|
||
uint32_t started_ms;
|
||
uint8_t output_level;
|
||
uint8_t initialized;
|
||
} LedIndicator_Channel;
|
||
|
||
typedef struct {
|
||
const LedIndicator_Pattern *patterns;
|
||
size_t pattern_count;
|
||
} LedIndicator_Config;
|
||
|
||
typedef struct {
|
||
LedIndicator_Port port;
|
||
const LedIndicator_Pattern *patterns;
|
||
LedIndicator_Channel *channels;
|
||
size_t pattern_count;
|
||
size_t channel_count;
|
||
uint8_t initialized;
|
||
} LedIndicator;
|
||
|
||
/** Заполняет конфигурацию встроенными шаблонами режимов. */
|
||
void LedIndicator_ConfigDefault(LedIndicator_Config *config);
|
||
|
||
/** Копирует встроенные шаблоны в изменяемую таблицу; возвращает число записей. */
|
||
size_t LedIndicator_CopyDefaultPatterns(LedIndicator_Pattern *patterns, size_t capacity);
|
||
|
||
/** Проверяет таблицу шаблонов. */
|
||
uint8_t LedIndicator_ValidateConfig(const LedIndicator_Config *config);
|
||
|
||
/**
|
||
* Инициализирует экземпляр и немедленно выключает все его каналы.
|
||
* Массив channels принадлежит приложению и должен жить столько же, сколько instance.
|
||
*/
|
||
uint8_t LedIndicator_Init(LedIndicator *instance,
|
||
LedIndicator_Channel *channels,
|
||
size_t channel_count,
|
||
const LedIndicator_Port *port,
|
||
const LedIndicator_Config *config);
|
||
|
||
/** Назначает режим, используя время порта. Повтор того же режима не сбрасывает фазу. */
|
||
uint8_t LedIndicator_SetMode(LedIndicator *instance, size_t channel,
|
||
LedIndicator_Mode mode);
|
||
|
||
/** Назначает режим с явно переданной меткой времени. Повтор не сбрасывает фазу. */
|
||
uint8_t LedIndicator_SetModeAt(LedIndicator *instance, size_t channel,
|
||
LedIndicator_Mode mode, uint32_t now_ms);
|
||
|
||
/** Принудительно запускает режим с первого шага, используя время порта. */
|
||
uint8_t LedIndicator_RestartMode(LedIndicator *instance, size_t channel,
|
||
LedIndicator_Mode mode);
|
||
|
||
/** Принудительно запускает режим с первого шага в указанное время. */
|
||
uint8_t LedIndicator_RestartModeAt(LedIndicator *instance, size_t channel,
|
||
LedIndicator_Mode mode, uint32_t now_ms);
|
||
|
||
/** Обновляет выходы, используя время порта. Вызывать в главном цикле. */
|
||
void LedIndicator_Process(LedIndicator *instance);
|
||
|
||
/** Обновляет выходы с явно переданной меткой времени. */
|
||
void LedIndicator_ProcessAt(LedIndicator *instance, uint32_t now_ms);
|
||
|
||
LedIndicator_Mode LedIndicator_GetMode(const LedIndicator *instance, size_t channel);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* LED_INDICATOR_H */
|