232 lines
5.7 KiB
C
232 lines
5.7 KiB
C
/*
|
|
* The GAT Stand
|
|
* GAT Host Firmware
|
|
* by true
|
|
*
|
|
* version 0.0.1
|
|
*
|
|
* notes:
|
|
*
|
|
* - last 2K of flash memory is reserved for configuration storage
|
|
*/
|
|
|
|
#include <ch32v20x.h>
|
|
|
|
#include "periph/adc.h"
|
|
#include "periph/btn.h"
|
|
#include "periph/gat_gpio.h"
|
|
#include "periph/port_pwr.h"
|
|
#include "periph/rgbled.h"
|
|
#include "periph/rtc.h"
|
|
|
|
#include "usb/cdc.h"
|
|
#include "usb_lib.h"
|
|
|
|
|
|
|
|
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)
|
|
{
|
|
SysTick->CMP = (SystemCoreClock / 256) - 1; // we want a 256Hz interrupt
|
|
SysTick->CNT = 0; // clear counter
|
|
SysTick->CTLR = 0xF; // start counter in /1 mode, enable interrupts, auto-reset counter
|
|
SysTick->SR = 0; // clear count comparison flag
|
|
|
|
NVIC_EnableIRQ(SysTicK_IRQn); // enable interrupt
|
|
}
|
|
|
|
static void gpio_init()
|
|
{
|
|
GPIO_InitTypeDef gpio = {0};
|
|
|
|
gpio.GPIO_Speed = GPIO_Speed_2MHz;
|
|
|
|
// unused pins
|
|
gpio.GPIO_Mode = GPIO_Mode_IPD;
|
|
gpio.GPIO_Pin = GPIO_Pin_13;
|
|
GPIO_Init(GPIOC, &gpio);
|
|
|
|
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
|
|
GPIO_Init(GPIOD, &gpio);
|
|
|
|
gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
|
|
gpio.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_5 | GPIO_Pin_15;
|
|
GPIO_Init(GPIOB, &gpio);
|
|
|
|
// OSC32K: don't need to configure these pins from defaults
|
|
// enabling RTC does whatever is needed for these pins (assumed from example)
|
|
|
|
// RGBLED (PA0, PA1, PA2)
|
|
RGBLED_PORT->BSHR = RGBLED_PIN_R | RGBLED_PIN_G | RGBLED_PIN_B;
|
|
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
gpio.GPIO_Pin = RGBLED_PIN_R | RGBLED_PIN_G | RGBLED_PIN_B;
|
|
GPIO_Init(RGBLED_PORT, &gpio);
|
|
|
|
// GAT power enable (PA3)
|
|
GAT_EN_PORT->BCR = GAT_EN_PIN;
|
|
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
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;
|
|
GPIO_Init(USB2_EN_PORT, &gpio);
|
|
|
|
// GAT overcurrent detect (PA4)
|
|
gpio.GPIO_Mode = GPIO_Mode_IPU;
|
|
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);
|
|
|
|
// GAT GPIO is configured in gat_gpio.c
|
|
|
|
// USB PA11, PA12 will be configured later
|
|
|
|
// unused pins that are used for I2C passthrough
|
|
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
|
gpio.GPIO_Pin = GPIO_Pin_15;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
gpio.GPIO_Pin = GPIO_Pin_3;
|
|
GPIO_Init(GPIOB, &gpio);
|
|
|
|
// USB PB6, PB7 will be configured later
|
|
|
|
// I2C (PB8, PB9) - remapped
|
|
GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
|
|
gpio.GPIO_Speed = GPIO_Speed_10MHz;
|
|
gpio.GPIO_Mode = GPIO_Mode_AF_OD;
|
|
gpio.GPIO_Mode = GPIO_Pin_8 | GPIO_Pin_9;
|
|
GPIO_Init(GPIOB, &gpio);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
// configure core
|
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
|
|
SystemCoreClockUpdate();
|
|
|
|
// enable peripheral clocks
|
|
RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_BKP |
|
|
RCC_APB1Periph_I2C1 | RCC_APB1Periph_TIM2, ENABLE);
|
|
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA |
|
|
RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD |
|
|
RCC_APB2Periph_ADC1, ENABLE);
|
|
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_USBHS, ENABLE);
|
|
|
|
|
|
// configure gpio pins
|
|
gpio_init();
|
|
|
|
// configure RTC
|
|
if (rtc_init()) {
|
|
// rtc failed to initialize. let the end user know.
|
|
// todo
|
|
}
|
|
|
|
// initialize buttons
|
|
btn_init();
|
|
btn[0].cb_push = btn_top_push_cb;
|
|
btn[1].cb_push = btn_bot_push_cb;
|
|
|
|
// set GAT GP pins weak pull to address the addon
|
|
gat_gpio_init();
|
|
|
|
// set output ports to saved state, or on if no batt / first boot
|
|
port_pwr_init();
|
|
|
|
// start up rgbled
|
|
rgbled_init();
|
|
|
|
// initialize light sense stuff
|
|
adc_init();
|
|
|
|
// get the system tick interrupt going
|
|
systick_init();
|
|
|
|
// initialize USB device for console shell
|
|
usb_conf_clksource();
|
|
USB_Init();
|
|
usb_intr_init();
|
|
|
|
// let's do this
|
|
while (1) {
|
|
__WFI();
|
|
}
|
|
}
|
|
|
|
|
|
uint8_t st_tick;
|
|
volatile uint32_t uptime;
|
|
|
|
__attribute__((interrupt("WCH-Interrupt-fast")))
|
|
void SysTick_Handler(void)
|
|
{
|
|
st_tick++;
|
|
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();
|
|
|
|
if (!(st_tick & 0x3)) {
|
|
rgbled_update();
|
|
}
|
|
|
|
// clear comparison flag
|
|
SysTick->SR = 0;
|
|
|
|
if (SysTick->SR) {
|
|
while (1);
|
|
}
|
|
}
|