98 lines
2.5 KiB
C
98 lines
2.5 KiB
C
#include "gpio.h"
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "ch32v003fun.h"
|
|
#include "systick.h"
|
|
|
|
#define LED_BLINK_SLOW 1000 // Warning blink interval (ms)
|
|
#define LED_BLINK_FAST 500 // Error blink interval (ms)
|
|
#define LED_BREATH_PERIOD 2000 // Breathing effect period (ms)
|
|
#define STATE_STABILITY 500 // Minimum time before state change (ms)
|
|
|
|
#define LED_G (1 << 4)
|
|
#define LED_B (1 << 3)
|
|
|
|
typedef struct {
|
|
uint32_t last_update;
|
|
uint32_t stable_since;
|
|
led_state_t current_state;
|
|
led_state_t target_state;
|
|
uint8_t blink_state;
|
|
uint32_t last_blink;
|
|
} led_status_t;
|
|
|
|
static led_status_t led_status = {0};
|
|
|
|
void gpio_init(void) {
|
|
// Enable clock for GPIOB
|
|
RCC->APB2PCENR |= RCC_APB2Periph_GPIOB;
|
|
|
|
// GPIOB: Pins 3 and 4 as Output, Push-Pull, 10MHz
|
|
GPIOB->CFGLR &= ~((0xF << (4 * 3)) | (0xF << (4 * 4)));
|
|
GPIOB->CFGLR |= ((GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 3)) |
|
|
((GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 4));
|
|
|
|
// GPIOB: Pin 9 as Output, Push-Pull, 10MHz
|
|
GPIOB->CFGHR &= ~(0xF << (4 * (9 - 8)));
|
|
GPIOB->CFGHR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * (9 - 8));
|
|
|
|
led_status.current_state = LED_STATE_OFF;
|
|
led_status.target_state = LED_STATE_OFF;
|
|
|
|
GPIOB->BSHR = LED_G | LED_B;
|
|
}
|
|
|
|
void led_status_set(led_state_t state) {
|
|
uint32_t now = millis();
|
|
|
|
// stability timer upd on state change
|
|
if (led_status.target_state != state) {
|
|
led_status.stable_since = now;
|
|
led_status.target_state = state;
|
|
}
|
|
}
|
|
|
|
static inline void leds(bool g, bool b) {
|
|
uint32_t val = (g ? LED_G << 16 : LED_G) | (b ? LED_B << 16 : LED_B);
|
|
GPIOB->BSHR = val;
|
|
}
|
|
|
|
void led_status_process(void) {
|
|
uint32_t now = millis();
|
|
|
|
if (now - led_status.stable_since < STATE_STABILITY) {
|
|
return;
|
|
}
|
|
|
|
switch (led_status.target_state) {
|
|
case LED_STATE_OFF:
|
|
GPIOB->BSHR = LED_G | LED_B;
|
|
break;
|
|
|
|
case LED_STATE_ON:
|
|
leds(1, 0); // green on, blue off
|
|
break;
|
|
|
|
case LED_STATE_WARNING:
|
|
if (now - led_status.last_blink >= LED_BLINK_SLOW) {
|
|
led_status.blink_state = !led_status.blink_state;
|
|
led_status.last_blink = now;
|
|
leds(led_status.blink_state, 0);
|
|
}
|
|
break;
|
|
|
|
case LED_STATE_ERROR:
|
|
if (now - led_status.last_blink >= LED_BLINK_FAST) {
|
|
led_status.blink_state = !led_status.blink_state;
|
|
led_status.last_blink = now;
|
|
leds(led_status.blink_state, !led_status.blink_state);
|
|
}
|
|
break;
|
|
|
|
case LED_STATE_BUSY:
|
|
bool blue_on = (now % LED_BREATH_PERIOD) < LED_BREATH_PERIOD / 2;
|
|
leds(0, blue_on);
|
|
break;
|
|
}
|
|
} |