add fixed auto brightness control option, led brightness options

jumper 1 will set LEDs to a dimmer level.
jumper 2 will disable LEDs entirely.
jumper 3 will turn the addon and USB ports on and off depending on ambient light level. the levels decided are arbitrary and may be updated with further testing.
This commit is contained in:
true 2024-10-23 04:19:13 -07:00
parent 5829bc190d
commit 6ee4233c2f
7 changed files with 121 additions and 74 deletions

View File

@ -23,13 +23,21 @@
void btn_top_push_cb(uint8_t idx)
{
// jumper 3, if set, will manage power by brightness automatically
// only respect the button if this switch isn't set
if (!(btn[DIP3]._mask & BTN_PUSH)) {
gat_toggle();
}
}
void btn_bot_push_cb(uint8_t idx)
{
// jumper 3, if set, will manage power by brightness automatically
// only respect the button if this switch isn't set
if (!(btn[DIP3]._mask & BTN_PUSH)) {
usb2_toggle();
}
}
static inline void systick_init(void)
{
@ -76,6 +84,16 @@ static void gpio_init()
gpio.GPIO_Pin = GAT_EN_PIN;
GPIO_Init(GAT_EN_PORT, &gpio);
// lightsense anode (PA5)
LSENS_A_PORT->BCR = LSENS_A_PIN;
gpio.GPIO_Pin = LSENS_A_PIN;
GPIO_Init(LSENS_A_PORT, &gpio);
// lightsense cathode (PB0)
LSENS_K_PORT->BCR = LSENS_K_PIN;
gpio.GPIO_Pin = LSENS_K_PIN;
GPIO_Init(LSENS_K_PORT, &gpio);
// USB2 power enable (PB4)
USB2_EN_PORT->BCR = USB2_EN_PIN;
gpio.GPIO_Pin = USB2_EN_PIN;
@ -86,6 +104,7 @@ static void gpio_init()
gpio.GPIO_Pin = GAT_OC_PIN;
GPIO_Init(GAT_EN_PORT, &gpio);
// buttons (PB10, PB11) and DIP switches (PB12, PB13, PB14)
gpio.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_Init(GPIOB, &gpio);
@ -167,7 +186,24 @@ __attribute__((interrupt("WCH-Interrupt-fast")))
void SysTick_Handler(void)
{
st_tick++;
if (!st_tick) uptime++;
if (!st_tick) {
uptime++;
// jumper 3, if set, will manage power by brightness automatically
if (btn[DIP3]._mask & BTN_PUSH) {
if (adc_get_lsens_coarse() > LSENS_DARK) {
gat_off();
usb2_off();
}
if (adc_get_lsens_coarse() <= LSENS_BRIGHT) {
gat_on();
usb2_on();
}
}
}
// light sensor updating at ~4ms
adc_process_lsens();
// update buttons
btn_poll();

View File

@ -13,25 +13,9 @@
static const uint8_t led_brightness_map[] = {
47, 44, 42, 41,
40, 38, 36, 34,
32, 31, 30, 29,
27, 25, 21, 19,
17, 16, 15, 15, // indoors normal brightness
14, 14, 13, 13,
12, 12, 12, 11,
11, 11, 10, 10,
10, 9, 9, 9,
8, 8, 8, 8,
7, 7, 7, 7,
7, 6, 6, 6
};
static GPIO_InitTypeDef lsens_gpio = {
.GPIO_Mode = GPIO_Mode_Out_PP,
.GPIO_Pin = LSENS_A_PIN | LSENS_K_PIN,
.GPIO_Pin = LSENS_A_PIN,
.GPIO_Speed = GPIO_Speed_2MHz
};
@ -42,6 +26,8 @@ static uint8_t lsens_mode = LSENS_READING_IDLE;
uint8_t lsens_wait;
uint8_t lsens_coarse = 1;
uint16_t lsens_timeout;
void adc_init()
@ -82,9 +68,11 @@ void adc_set_mode_lsens(uint8_t mode)
lsens_mode = mode;
if (mode == LSENS_OUTPUT) {
lsens_gpio.GPIO_Pin = LSENS_A_PIN | LSENS_K_PIN;
lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LSENS_PORT, &lsens_gpio);
lsens_gpio.GPIO_Pin = LSENS_A_PIN;
GPIO_Init(LSENS_A_PORT, &lsens_gpio);
lsens_gpio.GPIO_Pin = LSENS_K_PIN;
GPIO_Init(LSENS_K_PORT, &lsens_gpio);
}
}
@ -96,29 +84,32 @@ uint8_t adc_get_mode_lsens()
static void lsens_start()
{
// set anode and cathode low
LSENS_PORT->BCR = LSENS_A_PIN | LSENS_K_PIN;
LSENS_A_PORT->BCR = LSENS_A_PIN;
LSENS_K_PORT->BCR = LSENS_K_PIN;
adc_set_mode_lsens(LSENS_READING_START);
// set cathode high, let it charge
LSENS_PORT->BSHR = LSENS_K_PIN;
LSENS_K_PORT->BSHR = LSENS_K_PIN;
// set anode low
lsens_gpio.GPIO_Pin = LSENS_A_PIN;
lsens_gpio.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(LSENS_PORT, &lsens_gpio);
GPIO_Init(LSENS_A_PORT, &lsens_gpio);
// set cathode as analog input
lsens_gpio.GPIO_Pin = LSENS_K_PIN;
lsens_gpio.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(LSENS_PORT, &lsens_gpio);
GPIO_Init(LSENS_K_PORT, &lsens_gpio);
}
static void lsens_stop()
{
lsens_gpio.GPIO_Pin = LSENS_A_PIN | LSENS_K_PIN;
lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LSENS_PORT, &lsens_gpio);
lsens_gpio.GPIO_Pin = LSENS_A_PIN;
GPIO_Init(LSENS_A_PORT, &lsens_gpio);
lsens_gpio.GPIO_Pin = LSENS_K_PIN;
GPIO_Init(LSENS_K_PORT, &lsens_gpio);
lsens_mode = LSENS_READING_IDLE;
}
@ -190,22 +181,3 @@ uint8_t adc_get_lsens_coarse()
{
return lsens_coarse;
}
uint8_t adc_get_brightness(uint8_t level)
{
if (!level) {
// are you outside? why? it's too fucking hot
// we'll shut down when in the presence of big nuclear fire
if (adc_get_lsens() < 400) {
// yup, outside or in a spotlight at 3ft away or something
return 0;
}
}
if (level >= sizeof(led_brightness_map)) {
return led_brightness_map[sizeof(led_brightness_map) - 1];
}
return led_brightness_map[level];
}

View File

@ -12,13 +12,17 @@
#define LSENS_DARK_THRESHOLD 0x7ff // baseline minimum value reading achieved in darkness
#define LSENS_PORT GPIOA
#define LSENS_A_PIN GPIO_Pin_2
#define LSENS_K_PIN GPIO_Pin_3
#define LSENS_ADC_CH ADC_Channel_3
#define LSENS_A_PORT GPIOA
#define LSENS_A_PIN GPIO_Pin_5
#define LSENS_K_PORT GPIOB
#define LSENS_K_PIN GPIO_Pin_0
#define LSENS_ADC_CH ADC_Channel_8
#define LSENS_COARSE_UP 0x690 // counts higher than this increase lsens_coarse, maximum 64
#define LSENS_COARSE_DOWN 0x5a0 // counts lower than this decrease lsens_coarse, minimum 1
#define LSENS_COARSE_UP 0x990 // counts higher than this increase lsens_coarse, maximum 64
#define LSENS_COARSE_DOWN 0x890 // counts lower than this decrease lsens_coarse, minimum 1
#define LSENS_DARK 48
#define LSENS_BRIGHT 32
enum lsens_mode {
LSENS_READING_IDLE = 0,
@ -43,8 +47,6 @@ void adc_process_lsens();
uint16_t adc_get_lsens();
uint8_t adc_get_lsens_coarse();
uint8_t adc_get_brightness(uint8_t level);
#endif /* USER_SRC_ADC_H_ */

View File

@ -23,12 +23,12 @@ void btn_init()
// this function assumes GPIO has been configured already
// initialize default setup
btn[0]._pintype = BTN1_PIN;
btn[1]._pintype = BTN2_PIN;
btn[BTN1]._pintype = BTN1_PIN;
btn[BTN2]._pintype = BTN2_PIN;
btn[2]._pintype = DIP1_PIN;
btn[3]._pintype = DIP2_PIN;
btn[4]._pintype = DIP3_PIN;
btn[DIP1]._pintype = DIP1_PIN;
btn[DIP2]._pintype = DIP2_PIN;
btn[DIP3]._pintype = DIP3_PIN;
for (i = 0; i < BTN_COUNT; i++) {
btn[i]._mask = BTN_RELEASE;

View File

@ -16,11 +16,16 @@
#define BTN_PORT GPIOB
#define BTN1 0
#define BTN1_PIN 10
#define BTN2 1
#define BTN2_PIN 11
#define DIP1 2
#define DIP1_PIN 12
#define DIP2 3
#define DIP2_PIN 13
#define DIP3 4
#define DIP3_PIN 14
#define BTN_PIN_MASK 0xf

View File

@ -26,7 +26,7 @@ static uint8_t gat_oc_state_latch = 0;
void port_pwr_commit_bkp()
void port_pwr_state_commit_bkp()
{
BKP_WriteBackupRegister(PORT_PWR_STATE_DR, port_pwr_state);
RTC_WaitForLastTask();
@ -39,7 +39,7 @@ void gat_on()
GAT_EN_PORT->BSHR = GAT_EN_PIN;
port_pwr_state |= GAT_ON_FLAG;
port_pwr_commit_bkp();
port_pwr_state_commit_bkp();
}
void gat_off()
@ -47,7 +47,7 @@ void gat_off()
GAT_EN_PORT->BCR = GAT_EN_PIN;
port_pwr_state &= ~GAT_ON_FLAG;
port_pwr_commit_bkp();
port_pwr_state_commit_bkp();
}
uint8_t gat_pwr_state()
@ -77,7 +77,7 @@ void usb2_on()
USB2_EN_PORT->BSHR = USB2_EN_PIN;
port_pwr_state |= USB2_ON_FLAG;
port_pwr_commit_bkp();
port_pwr_state_commit_bkp();
}
void usb2_off()
@ -85,7 +85,7 @@ void usb2_off()
USB2_EN_PORT->BCR = USB2_EN_PIN;
port_pwr_state &= ~USB2_ON_FLAG;
port_pwr_commit_bkp();
port_pwr_state_commit_bkp();
}
uint8_t usb2_pwr_state()
@ -111,7 +111,7 @@ void port_pwr_init()
port_pwr_state = INIT_FLAG | USB2_ON_FLAG | GAT_ON_FLAG;
// and commit state flags
port_pwr_commit_bkp();
port_pwr_state_commit_bkp();
}
if (port_pwr_state & GAT_ON_FLAG) gat_on();

View File

@ -2,14 +2,21 @@
* 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 "btn.h"
#include "port_pwr.h"
#include "rtc.h"
#include "port_pwr.h"
@ -17,7 +24,7 @@
#define GRN 1
#define BLU 2
#define BRT_RED 80
#define BRT_RED 40
#define BRT_GRN 32
#define BRT_BLU 36
#define BRT_OFF 0
@ -34,7 +41,8 @@ static uint8_t state[3] = {0};
void rgbled_set()
{
uint8_t i;
int8_t i;
uint16_t out[3];
// flash counters
for (i = 0; i < 3; i++) {
@ -64,14 +72,31 @@ void rgbled_set()
}
}
RGBLED_TIM->CH1CVR = state[BLU] ? BRT_BLU : BRT_OFF;
RGBLED_TIM->CH2CVR = state[GRN] ? BRT_GRN : BRT_OFF;
RGBLED_TIM->CH3CVR = state[RED] ? BRT_RED : BRT_OFF;
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;
@ -82,9 +107,14 @@ void rgbled_update()
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] = gat_oc_state() ? 16 : 0xff;
flash_timeout[RED] = usb2_pwr_state() ? 0 : 0xff;
rgbled_set();
}
@ -117,4 +147,6 @@ void rgbled_init()
RGBLED_TIM->CNT = 0;
TIM_Cmd(RGBLED_TIM, ENABLE);
flash_timeout[BLU] = flash_timeout[GRN] = flash_timeout[RED] = 0xff;
}