175 lines
4.9 KiB
C
175 lines
4.9 KiB
C
/*
|
|
* RETRO TECH 2025
|
|
* GAT Addon Firmware
|
|
* by true
|
|
*
|
|
* version 0.1.1
|
|
* Last Update 20250723
|
|
*
|
|
* code was made for different random addons I designed for dc32,
|
|
* then adapted to each one. it worked OK. this code was then more
|
|
* or less directly ported to another MCU. so things might be a mess.
|
|
*
|
|
* I had only a few hours on and off over a week to get the code done.
|
|
* lots of shit was copied from demo code and adapted to work. certainly
|
|
* isn't the best way to get this done.
|
|
*
|
|
* I know I could save some power, but seeing as all the badges burn it in
|
|
* LEDs and almost nobody else power optimizes their badge code, who cares?
|
|
*
|
|
* sorry. wasn't procrastination I swear. all the ideas were last minute.
|
|
*/
|
|
|
|
#include <ch32x035.h>
|
|
#include <stdint.h>
|
|
|
|
#include "src/adc.h"
|
|
#include "src/btn.h"
|
|
#include "src/config.h"
|
|
#include "src/i2c_soft.h"
|
|
#include "src/led.h"
|
|
#include "src/led_rgbprog.h"
|
|
#include "src/rand.h"
|
|
#include "src/ui.h"
|
|
|
|
#include "global.h"
|
|
|
|
|
|
|
|
/*
|
|
void systick_init(void)
|
|
{
|
|
SysTick->CMP = (SystemCoreClock / 512) - 1; // we want a 512Hz 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
|
|
}
|
|
*/
|
|
|
|
void awu_init(void)
|
|
{
|
|
// these magic numbers set a ~498.6Hz update rate
|
|
// 48000000 (HSI) / 1024 / Prescale / Window
|
|
AWU_SetPrescaler(AWU_Prescaler_2);
|
|
AWU_SetWindowValue(47);
|
|
AutoWakeUpCmd(ENABLE);
|
|
|
|
// in order to fire AWU interrupt, enable EXTI interrupt on rising edge on EXTI line 27.
|
|
// this isn't explicitly stated in the DS, but AWU interrupt == EXTI line27 interrupt.
|
|
EXTI->RTENR = EXTI_RTENR_TR27;
|
|
EXTI->INTENR = EXTI_INTENR_MR27;
|
|
|
|
NVIC_EnableIRQ(AWU_IRQn);
|
|
}
|
|
|
|
void gpio_init()
|
|
{
|
|
GPIO_InitTypeDef gpio = {0};
|
|
|
|
// only one GPIO speed on this bad boy, and it must be defined
|
|
gpio.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
|
// jogwheel digital inputs (PA4-PA6) (active low)
|
|
gpio.GPIO_Mode = GPIO_Mode_IPU;
|
|
gpio.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
|
|
// lightsense LED cathode (PA7, A8)
|
|
gpio.GPIO_Mode = GPIO_Mode_AIN;
|
|
gpio.GPIO_Pin = GPIO_Pin_7;
|
|
GPIOA->BCR = GPIO_Pin_7;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
|
|
// potentiometer (PB1; A9)
|
|
gpio.GPIO_Pin = GPIO_Pin_1;
|
|
GPIO_Init(GPIOB, &gpio);
|
|
|
|
// lightsense LED anode (PB7)
|
|
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
gpio.GPIO_Pin = GPIO_Pin_7;
|
|
GPIOB->BCR = GPIO_Pin_7;
|
|
GPIO_Init(GPIOB, &gpio);
|
|
|
|
// USB (unused in application...for now) (PC16, PC17)
|
|
|
|
// debug (not changed in application) (PC18, PC19)
|
|
|
|
// EEP_WP EEPROM write protect (PA9) (active high)
|
|
// IS_SDB IS31FL3729 shutdown pin (PC3) (active low)
|
|
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
GPIOA->BCR = GPIO_Pin_9;
|
|
gpio.GPIO_Pin = GPIO_Pin_9;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
GPIOC->BCR = GPIO_Pin_3;
|
|
gpio.GPIO_Pin = GPIO_Pin_3;
|
|
GPIO_Init(GPIOC, &gpio);
|
|
|
|
// I2C SDA, SCL for addon header (PA10, PA11)
|
|
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
gpio.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
|
|
// software I2C SDA, SCL for on-board devices (PA0, PA1)
|
|
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
|
GPIOA->BCR = GPIO_Pin_0 | GPIO_Pin_1;
|
|
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
|
|
// UART RX/TX on addon header (not currently used) (PA2, PA3)
|
|
gpio.GPIO_Mode = GPIO_Mode_IPU;
|
|
gpio.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
|
|
GPIO_Init(GPIOA, &gpio);
|
|
}
|
|
|
|
|
|
// here we go
|
|
int main(void)
|
|
{
|
|
// configure core
|
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
|
|
|
|
// enable peripheral clocks
|
|
RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR | RCC_APB1Periph_I2C1, ENABLE);
|
|
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA |
|
|
RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
|
|
RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM1, ENABLE);
|
|
|
|
// configure gpio pins, including buttons (need button for settings reset)
|
|
gpio_init();
|
|
|
|
// get saved settings, or reset if BTN1 is pushed
|
|
i2cm_init();
|
|
userconf_load((BTN_PORT->INDR & (1 << BTN2_PIN)) ? 0 : 1);
|
|
|
|
// configure hardware
|
|
adc_init();
|
|
btn_init();
|
|
led_init();
|
|
|
|
// configure random
|
|
tinymt32_init(&tinymt32_s, DBGMCU_GetCHIPID() | userconf.checksum);
|
|
|
|
// configure UI
|
|
ui_init();
|
|
|
|
// configure auto-wakeup to run at ~498Hz
|
|
awu_init();
|
|
|
|
// set up LEDs initially
|
|
led_rgb_firstrun();
|
|
|
|
// do system shit
|
|
while(1) {
|
|
__WFI();
|
|
|
|
// after sending LEDs, run LED render program
|
|
// to update the LED buffer for next time
|
|
// we have approx 7ms to render... plenty of time
|
|
if ((ticnt & 0x3) == 0) {
|
|
ui_render();
|
|
}
|
|
}
|
|
}
|