Compare commits

..

2 Commits

Author SHA1 Message Date
true 261f5bdfbf ignore accelerometer if it isn't found 2024-10-24 17:23:51 -07:00
true bc300e522a main program tick interrupt now works
CH58x/CH59x only has one main system clock and all timers are referenced to this clock. Other than watchdog, there's only one timer that runs independently: RTC. Thankfully the RTC has a mode to interrupt at rates faster than one second. this is being used for the program tick interrupt.

Also added OLED initialization code since that was forgotten before.
2024-10-24 17:22:20 -07:00
5 changed files with 80 additions and 31 deletions

View File

@ -562,7 +562,7 @@ void RTC_TRIGFunCfg(uint32_t cyc)
*
* @return none
*/
void RTC_ModeFunDisable(RTC_MODETypeDef m)
void RTC_TRIGFunDisable(RTC_MODETypeDef m)
{
uint8_t i = 0;

View File

@ -260,7 +260,7 @@ void RTC_TMRFunCfg(RTC_TMRCycTypeDef t);
*
* @param m -
*/
void RTC_ModeFunDisable(RTC_MODETypeDef m);
void RTC_TRIGFunDisable(RTC_MODETypeDef m);
/**
* @brief RTC中断标志

View File

@ -49,6 +49,8 @@
#define FLAG_OLED_UPDATE (1 << 0)
#define FLAG_RGBLED_RUN_PROG (1 << 1)
#define PROG_TICK_RATE (32768 / 256)
const uint8_t vers[] = "241015a";
@ -72,17 +74,43 @@ static uint8_t oled_tick = 0; // oled framerate counter
void ch59x_xtal_conf()
{
HSECFG_Current(HSE_RCur_125);
HSECFG_Capacitance(HSECap_14p);
}
void systick_init()
/*
* the CPU will change clockspeed depending on what it is doing.
* all timers are tied to system clock and cannot be derived from the crystal directly,
* except for RTC which can use the LSI. RTC also has a neat feature where it can
* trigger an interrupt when bits match a mask. at this time we're not using the RTC
* for anything else so putting RTC should suffice for our main tick interrupt.
*/
void rtc_reset_trig()
{
sys_safe_access_enable();
R8_RTC_FLAG_CTRL |= RB_RTC_TRIG_CLR;
R32_RTC_TRIG = 0;
R8_RTC_MODE_CTRL |= RB_RTC_LOAD_HI;
sys_safe_access_disable();
while((R32_RTC_TRIG & 0x3FFF) != (R32_RTC_CNT_DAY & 0x3FFF));
sys_safe_access_enable();
R32_RTC_TRIG = 0;
R8_RTC_MODE_CTRL |= RB_RTC_LOAD_LO;
sys_safe_access_disable();
RTC_TRIGFunCfg(PROG_TICK_RATE);
}
void rtcisr_init()
{
LClk32K_Cfg(Clk32K_LSI, ENABLE); // enable internal oscillator
Calibration_LSI(Level_128); // calibrate LSI fromm HSE
rtc_reset_trig();
PFIC_EnableIRQ(RTC_IRQn);
}
void oled_update_done()
@ -170,6 +198,7 @@ int main()
// configure clock
ch59x_xtal_conf();
SetSysClock(SYSCLK_FREQ_USEI2C);
// note that system clock speed is decreased after every use of I2C.
// enable DC-DC converter; brings significant power saving
PWR_DCDCCfg(ENABLE);
@ -199,10 +228,12 @@ int main()
// configure port-based interrupts (used for ch32sub interrupt)
port_intr_init();
// note that system clock speed is decreased after every use of I2C.
// start up the OLED
ssd1306fb_set_target(&oled);
ssd1306_init(1); // we'll try to init later too, since sometimes they fail
// configure system tick
systick_init();
// configure main program tick interrupt
rtcisr_init();
while(1) {
// sleep when we're doing nothing
@ -242,8 +273,13 @@ int main()
}
void SysTick_Handler(void)
__INTERRUPT
__HIGH_CODE
void RTC_IRQHandler(void)
{
// clear interrupt flag and reset RTC
rtc_reset_trig();
st_tick++;
if (!st_tick) {
@ -276,7 +312,7 @@ void SysTick_Handler(void)
}
}
// read accelerometer data
// read accelerometer data at 32Hz
if ((st_tick & 0x7) == 0x7) {
accel_poll();
}

View File

@ -19,6 +19,7 @@
// user data
AccelData accel;
uint8_t accel_found = 0;
int16_t movement;
@ -27,6 +28,7 @@ static stmdev_ctx_t dev_ctx;
int32_t accel_i2c_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
{
(void)(handle);
@ -50,40 +52,47 @@ void accel_init()
{
uint8_t devid;
uint8_t reset;
uint16_t timeout = 1000;
dev_ctx.write_reg = accel_i2c_write;
dev_ctx.read_reg = accel_i2c_read;
// make sure we've got the right device
lis2dw12_device_id_get(&dev_ctx, &devid);
if (devid != LIS2DW12_ID) {
while (1) {
// might as well crash the user's badge
}
if (devid == LIS2DW12_ID) {
accel_found = 1;
}
// reset accelerometer
lis2dw12_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lis2dw12_reset_get(&dev_ctx, &reset);
} while (reset);
if (accel_found) {
lis2dw12_reset_set(&dev_ctx, PROPERTY_ENABLE);
do {
lis2dw12_reset_get(&dev_ctx, &reset);
if (!reset) {
timeout = 0;
accel_found = 1;
}
} while (timeout);
}
// disable block update
// data in output registers is updated immediately; FIFO is disabled
lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_DISABLE);
if (accel_found) {
// disable block update
// data in output registers is updated immediately; FIFO is disabled
lis2dw12_block_data_update_set(&dev_ctx, PROPERTY_DISABLE);
// configure scale, power mode
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_CONT_LOW_PWR_LOW_NOISE_4);
// configure scale, power mode
lis2dw12_full_scale_set(&dev_ctx, LIS2DW12_2g);
lis2dw12_power_mode_set(&dev_ctx, LIS2DW12_CONT_LOW_PWR_LOW_NOISE_4);
// configure filter chain
// low pass filter enabled for 6D (not currently used)
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT);
// digital LPF2 filter of output data
lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_4);
// configure filter chain
// low pass filter enabled for 6D (not currently used)
lis2dw12_filter_path_set(&dev_ctx, LIS2DW12_LPF_ON_OUT);
// digital LPF2 filter of output data
lis2dw12_filter_bandwidth_set(&dev_ctx, LIS2DW12_ODR_DIV_4);
// configure output data rate
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_200Hz);
// configure output data rate
lis2dw12_data_rate_set(&dev_ctx, LIS2DW12_XL_ODR_200Hz);
}
}
void accel_poll()
@ -91,6 +100,8 @@ void accel_poll()
uint8_t reg = 1;
uint16_t xyz[3];
if (!accel_found) return;
while (reg) {
// read output only if new value is available
lis2dw12_flag_data_ready_get(&dev_ctx, &reg);

View File

@ -27,6 +27,8 @@ typedef struct AccelData {
extern AccelData accel;
extern uint8_t accel_found;
extern uint16_t movement_worst;