dc33-retro-tech-addon/firmware/retro_tech_fw/code/main.c
true f8a987a592 soft I2C implemented, LEDs are now lighting
copied over and modified for use my CH59x soft I2C.

CH32X GPIO does not have an open drain mode, so I have to implement this with RMW to the mode register. After doing this and adding missing functions needed for existing code, LED writes and EEPROM reads and writes.

using the AWU for system timing so the clock speed can change.

existing issues:
- changing clock speed divider in soft i2c routines causes the system to crash
- ADC seems to be reading, but result isn't being used
2025-07-24 06:19:24 -07:00

169 lines
4.6 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)
{
AWU_SetPrescaler(AWU_Prescaler_2);
AWU_SetWindowValue(47);
AutoWakeUpCmd(ENABLE);
// if rising edge and interrupt isn't set on EXTI line 27,
// interrupt won't fire.
EXTI->RTENR = EXTI_RTENR_TR27;
EXTI->INTENR = EXTI_INTENR_MR27;
NVIC_EnableIRQ(AWU_IRQn);
}
void gpio_init()
{
GPIO_InitTypeDef gpio = {0};
gpio.GPIO_Speed = GPIO_Speed_50MHz;
// jogwheel digital inputs, active low (PA4-PA6)
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->BSHR = GPIO_Pin_7;
GPIO_Init(GPIOA, &gpio);
// potentiometer (PB1, A9)
gpio.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOB, &gpio);
// lightsense LED anode
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) - 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 SCL, SCA for addon header
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_Init(GPIOA, &gpio);
// software I2C, SCL for on-board devices
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
gpio.GPIO_Mode = GPIO_Mode_IPU;
gpio.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Init(GPIOA, &gpio);
}
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, hard buttons (used 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();
}
}
}