sc8-gat-stand/gat_stand_fw/user/periph/rgbled.c

152 lines
3.4 KiB
C

/*
* rgbled.c
*
* using TIM2 CH1-CH3
*
* * errata:
* - board design makes overcurrent on GAT port practically impossible.
* overcurrent condition may either trip low voltage condition due to
* decoupling or voltage output limit on LDO. as such, displaying
* any overcurrent state is meaningless.
*/
#include <ch32v20x.h>
#include <stdint.h>
#include "periph/btn.h"
#include "periph/port_pwr.h"
#include "periph/rtc.h"
#define RED 0
#define GRN 1
#define BLU 2
#define BRT_RED 40
#define BRT_GRN 32
#define BRT_BLU 36
#define BRT_OFF 0
#define RGBLED_TIM TIM2
static uint8_t flash_timeout[3];
static uint8_t flash[3] = {0};
static uint8_t state[3] = {0};
void rgbled_set()
{
int8_t i;
uint16_t out[3];
// flash counters
for (i = 0; i < 3; i++) {
if (!flash[i]) {
flash[i] = flash_timeout[i];
} else flash[i]--;
switch (flash_timeout[i]) {
// always on
case 0x00: {
state[i] = 1;
break;
}
// always off
case 0xff: {
state[i] = 0;
break;
}
// standard
default: {
if (flash[i] == flash_timeout[i]) {
state[i] ^= 1;
}
}
}
}
out[BLU] = BRT_BLU;
out[GRN] = BRT_GRN;
out[RED] = BRT_RED;
for (i = 0; i < 3; i++) {
// jumper 1 will reduce brightness
if (btn[DIP1]._mask & BTN_PUSH) {
out[i] >>= 2;
}
// jumper 2 will turn off LEDs entirely
if (btn[DIP2]._mask & BTN_PUSH) {
out[i] = BRT_OFF;
}
}
RGBLED_TIM->CH1CVR = state[BLU] ? out[BLU] : BRT_OFF;
RGBLED_TIM->CH2CVR = state[GRN] ? out[GRN] : BRT_OFF;
RGBLED_TIM->CH3CVR = state[RED] ? out[RED] : BRT_OFF;
}
void rgbled_update()
{
// VCR flash if clock isn't set
/*
switch (rtc_state) {
case RTC_STATE_CLOCK_NOT_SET: {
flash_timeout[BLU] = 48;
break;
}
default: {
flash_timeout[BLU] = 0;
break;
}
}
*/
// see errata on why we aren't showing overcurrent status anymore
// flash_timeout[RED] = gat_oc_state() ? 16 : 0xff;
// power output state
flash_timeout[GRN] = gat_pwr_state() ? 0 : 0xff;
flash_timeout[RED] = usb2_pwr_state() ? 0 : 0xff;
rgbled_set();
}
void rgbled_init()
{
TIM_TimeBaseInitTypeDef timer ={0};
TIM_OCInitTypeDef pwm = {0};
timer.TIM_Period = (1 << 10) - 1; // 10-bit
timer.TIM_Prescaler = 0;
timer.TIM_ClockDivision = TIM_CKD_DIV1;
timer.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(RGBLED_TIM, &timer);
pwm.TIM_OCMode = TIM_OCMode_PWM1;
pwm.TIM_OutputState = TIM_OutputState_Enable;
pwm.TIM_Pulse = BRT_OFF;
pwm.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1PreloadConfig(RGBLED_TIM, TIM_OCPreload_Disable);
TIM_OC2PreloadConfig(RGBLED_TIM, TIM_OCPreload_Disable);
TIM_OC3PreloadConfig(RGBLED_TIM, TIM_OCPreload_Disable);
TIM_ARRPreloadConfig(RGBLED_TIM, ENABLE);
TIM_OC1Init(RGBLED_TIM, &pwm);
TIM_OC2Init(RGBLED_TIM, &pwm);
TIM_OC3Init(RGBLED_TIM, &pwm);
TIM_CtrlPWMOutputs(RGBLED_TIM, ENABLE);
RGBLED_TIM->CNT = 0;
TIM_Cmd(RGBLED_TIM, ENABLE);
flash_timeout[BLU] = flash_timeout[GRN] = flash_timeout[RED] = 0xff;
}