/* * 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 #include #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(); } } }