/* * The GAT Stand * GAT Host Firmware * by true * * version 0.0.1 * * * notes: * * - last 2K of flash memory is reserved for configuration storage * * * project todo: * * - implement config storage * * - implement USB CDC command shell * * - when USB is not active, go into super low power state * - light sensor is only checked once every two seconds or so * - buttons are on wakeup */ #include #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 "periph/usb/cdc.h" #include "usb_lib.h" #include "console/console.h" #include "../usblib/config/usb_pwr.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(); // then initialize shell console_set_gets(usb_cdc_gets); console_set_puts(usb_cdc_puts); console_init(); // let's do this while (1) { // process usb data cdc_from_host_process(); cdc_send_host_process(); // process console if (bDeviceState == CONFIGURED) { console_process(); } else { console_stop(); } __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); } }