/* * 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 #include #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; }