hsc26-artemis2/firmware/app/main.c
2026-05-08 17:48:27 -07:00

208 lines
4.7 KiB
C

/*
* HSC26 Artemis II
*
* 2026 true
*
* todo:
* - implement SPI master for accelerometer (done, blocking / basic)
* - configure ADC to get touchpads (done)
* - get main tick interrupt working
*
* - get user input working (buttons, touchpads)
* - configure accelerometer for wakeup / sleep
* - configure buttons to wake up in case of sleep
* - write lightshows
* - write userconfig stuff, save to end of FLASH
*/
#include "ch32x035_conf.h"
#include "comms/soft_i2c_master.h"
#include "comms/spi_master.h"
#include "driver/adc.h"
#include "led/matrix.h"
#include "led/ledprog.h"
/*
*@Note
***Only PA0--PA15 and PC16--PC17 support input pull-down.
*/
uint16_t cnt = 0;
volatile uint32_t wake_uptime = 0;
volatile uint8_t lp_render = 0;
void clk_init()
{
SystemCoreClockUpdate();
}
void periphclk_init()
{
// needed for GPIO, remap, ADC, SPI
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO |
RCC_APB2Periph_ADC1 | RCC_APB2Periph_SPI1, ENABLE);
// may be needed for AWU
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
// needed for DMA, USBPD
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 | RCC_AHBPeriph_USBPD, ENABLE);
}
void gpio_init()
{
GPIO_InitTypeDef gpio = {0};
gpio.GPIO_Speed = GPIO_Speed_50MHz;
// PA0-PA4 touch0-touch4
gpio.GPIO_Mode = GPIO_Mode_AIN;
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOA, &gpio);
// PB0 touch8
gpio.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOB, &gpio);
// PC0 VBAT, PC3 touch13
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
GPIO_Init(GPIOC, &gpio);
// PA5 SCK, PA7 MOSI
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_Init(GPIOA, &gpio);
// PA6 MISO
gpio.GPIO_Mode = GPIO_Mode_IPU;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &gpio);
// PB3 LIS_INT, PB8 soft I2C SCL, PB9 soft I2C SDA, PB11 btn0, PB12 btn1
gpio.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_Init(GPIOB, &gpio);
// PC10 USB DP (btn2), PC11 USB DM (unused)
gpio.GPIO_Mode = GPIO_Mode_IPD;
gpio.GPIO_Pin = GPIO_Pin_16 | GPIO_Pin_17;
GPIO_Init(GPIOC, &gpio);
// PB4 LSENS A, PB5 LSENS_K, PB6 SPI softCS, PB7 LED HWEN, PB10 STAT LED
GPIOB->BCR = 0x4f0;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
GPIO_Init(GPIOB, &gpio);
// PC14 CC1, PC15 CC2
// todo later
}
void awu_init()
{
NVIC_InitTypeDef nvic;
EXTI_InitTypeDef exti = {0};
// configure AWU
AWU_SetPrescaler(AWU_Prescaler_1);
AWU_SetWindowValue(0x2f);
AutoWakeUpCmd(ENABLE);
// configure EXTI line
exti.EXTI_Line = EXTI_Line27;
exti.EXTI_Mode = EXTI_Mode_Interrupt;
exti.EXTI_Trigger = EXTI_Trigger_Rising;
exti.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti);
// configure PFIC interrupt
nvic.NVIC_IRQChannel = AWU_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
clk_init();
periphclk_init();
gpio_init();
// initialize led programs
lp_ribbon_init();
// set up soft I2C and configure lighting controller
i2cm_init();
matrix_init();
// set up touchsensing and light sensing
adc_init();
// set up accelerometer
spim_init();
// configure AWU to provide ~997Hz wakeup interrupt for main program
// TODO: confirm if the counter is reset / preloaded
awu_init();
while (1) {
// low-priority tasks like
// rendering next LED program output frame
if (lp_render) {
lp_render = 0;
lp_ribbon_upward(200, 3, 4);
}
// stay a while
// __WFI();
PWR_EnterSTANDBYMode();
}
}
void AWU_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void AWU_IRQHandler(void)
{
// clear interrupt flag
EXTI_ClearFlag(EXTI_Line27);
// SetSysClock_HSI(HCLK_24MHZ);
cnt++;
if (cnt >= 1000) {
cnt = 0;
wake_uptime++;
}
// handle render new frame at ~100Hz
if ((cnt % 10) == 0) {
lp_render = 1;
}
// send led matrix data to matrix chip
matrix_send();
// handle ADC
adc_next();
// handle buttons
}