From 3eb410c796cba623f53f83d6312c5afdc350234f Mon Sep 17 00:00:00 2001 From: sigil-03 Date: Sun, 26 Oct 2025 08:20:19 -0600 Subject: [PATCH] move most of the system functions out of main.rs --- ch32v-insert-coin/src/main.rs | 160 ++++---------------------------- ch32v-insert-coin/src/system.rs | 145 +++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 143 deletions(-) create mode 100644 ch32v-insert-coin/src/system.rs diff --git a/ch32v-insert-coin/src/main.rs b/ch32v-insert-coin/src/main.rs index cecf6da..19c3869 100644 --- a/ch32v-insert-coin/src/main.rs +++ b/ch32v-insert-coin/src/main.rs @@ -3,7 +3,12 @@ #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_assoc_type)] +// app stuff mod insert_coin; + +// system stuff +mod system; + use ch32_hal::{adc::AdcChannel, interrupt::typelevel::Handler, timer::low_level::OutputPolarity}; use insert_coin::{CoreConfig, InsertCoin, SimplePwmCore}; @@ -84,139 +89,6 @@ pub enum SystemState { Active, } -/// enter standby (SLEEPDEEP) mode, with WFE enabled. -/// from CH32V003 reference manual 2.3.1: -/// entry: -/// 1. configure core register control bit: SLEEPDEEP=1 | PDDS = 1 -/// 2. configure external interrupt register to mask all but EXTI7_0 -/// 3. execute WFI or WFE (optionally SEVONPEND) and SLEEPONEXIT -/// * (probably WFI?) -/// exit: -/// 1. any interrupt/event (set in external interrupt register) -unsafe fn enter_standby(pin: usize) { - critical_section::with(|_| { - use hal::pac::Interrupt; - use qingke_rt::CoreInterrupt; - - // configure core register control bit (SLEEPDEEP=1 | PDDS=1) - let pfic = &hal::pac::PFIC; - pfic.sctlr().modify(|w| { - // we only want to wake on enabled interrupts - w.set_sevonpend(false); - // we want to enable deep sleep - w.set_sleepdeep(true); - w.set_wfitowfe(false); - w.set_sleeponexit(false); - }); - - // set PDDS=1: - // get current value of PWR_CTLR - let mut reg: u32 = 0x4000_7000; - let mut val: u32 = 0; - unsafe { - val = (reg as *mut u32).read_volatile(); - } - // modify PDDS - val |= 1 << 1; // PWR_CTLR[1] -> PDDS - unsafe { - (reg as *mut u32).write_volatile(val); - } - - // // disable all exti interrupts - let exti = &hal::pac::EXTI; - // exti.intenr().write(| w| { - // w.0 = 0x00000000; - // // w.set_mr(pin, true); - // // w.set_mr(pin, true); - // }); - - // clear all pending exti interrupts - let bits = 0xFFFFFFFF; - exti.intfr().write(|w| w.0 = bits); - - // enable all exti interrupts - let exti = &hal::pac::EXTI; - exti.intenr().write(|w| { - w.0 = 0x00FFFFFF; - // w.set_mr(pin, true); - // w.set_mr(pin, true); - }); - - unsafe { - qingke::pfic::disable_interrupt(CoreInterrupt::SysTick as u8); - qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); - } - - // execute WFI - #[cfg(feature = "enable_print")] - println!("WFI CONFIGURED HOPEFULLY"); - }); -} - -unsafe fn init_gpio_irq(pin: u8, port: u8, rising: bool, falling: bool) { - critical_section::with(|_| { - #[cfg(feature = "enable_print")] - println!("init_gpio_irq"); - let exti = &hal::pac::EXTI; - let afio = &hal::pac::AFIO; - - let port = port as u8; - let pin = pin as usize; - - // let b = afio.exticr().read(); - afio.exticr().modify(|w| w.set_exti(pin, port)); - - exti.intenr().modify(|w| w.set_mr(pin, true)); // enable interrupt - exti.rtenr().modify(|w| w.set_tr(pin, rising)); - exti.ftenr().modify(|w| w.set_tr(pin, falling)); - }); -} - -fn clear_interrupt(coin_pin: u8, button_pin: u8) { - let exti = &hal::pac::EXTI; - - let coin_pin = coin_pin as usize; - let button_pin = button_pin as usize; - - exti.intenr().modify(|w| w.set_mr(coin_pin, false)); // disable interrupt - exti.intenr().modify(|w| w.set_mr(button_pin, false)); // disable interrupt - - let bits = exti.intfr().read(); - - // We don't handle or change any EXTI lines above 24. - let bits = bits.0 & 0x00FFFFFF; - - // coin_flag - if (bits & (0x1 << coin_pin)) != 0x0 { - #[cfg(feature = "enable_print")] - println!("coin irq!"); - unsafe { - INPUT_FLAGS.coin_flag = true; - } - } - - // button_flag - if (bits & (0x1 << button_pin)) != 0x0 { - #[cfg(feature = "enable_print")] - println!("button irq!"); - unsafe { - INPUT_FLAGS.button_flag = true; - } - } - - // Clear pending - Clears the EXTI's line pending bits. - exti.intfr().write(|w| w.0 = bits); - - use hal::pac::Interrupt; - unsafe { - qingke::pfic::unpend_interrupt(Interrupt::EXTI7_0 as u8); - }; - - // exti.intenr().modify(|w| w.0 = w.0 & !bits); - exti.intenr().modify(|w| w.set_mr(coin_pin, true)); // enable interrupt - exti.intenr().modify(|w| w.set_mr(button_pin, true)); // enable interrupt -} - #[derive(Debug)] struct InputFlags { coin_flag: bool, @@ -233,8 +105,8 @@ impl Handler for Test { unsafe fn on_interrupt() { #[cfg(feature = "enable_print")] println!("on_interrupt()"); - critical_section::with(|_| { - clear_interrupt(2, 6); + critical_section::with(|_| unsafe { + INPUT_FLAGS = system::clear_interrupt(2, 6); }); } } @@ -254,12 +126,12 @@ fn debug_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { // button pin setup let button_pin = p.PD6; - unsafe { init_gpio_irq(button_pin.pin(), button_pin.port(), false, true) }; + unsafe { system::init_gpio_irq(button_pin.pin(), button_pin.port(), false, true) }; let mut button_input = Input::new(button_pin, Pull::Up); delay.delay_ms(1000); - unsafe { enter_standby(4) }; + unsafe { system::enter_standby(4) }; delay.delay_ms(1000); riscv::asm::wfi(); @@ -357,8 +229,8 @@ fn app_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { // 2025-09-10 00:32:23.515: push pin: 6 | push port: 3 // set up interrupts - unsafe { init_gpio_irq(coin_pin.pin(), coin_pin.port(), false, true) }; - unsafe { init_gpio_irq(button_pin.pin(), button_pin.port(), true, true) }; + unsafe { system::init_gpio_irq(coin_pin.pin(), coin_pin.port(), false, true) }; + unsafe { system::init_gpio_irq(button_pin.pin(), button_pin.port(), true, true) }; // coin debouncer (100ms) let mut coin_input = DebouncedGPIO::new(coin_pin.degrade(), core_config.tick_rate_hz, 100); @@ -411,7 +283,8 @@ fn app_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { let tick_interval_us = 1000000 / interfaces.config.tick_rate_hz - 10; // dac data - let coin_sound = include_bytes!("../audio/coin.raw"); + // let coin_sound = include_bytes!("../audio/coin.raw"); + let coin_sound = include_bytes!("../audio/sweep_dpcm_u4.raw"); // let button_sound = include_bytes!("../audio/coinMixTest1_dpcm_u4.raw"); let mut system_state = SystemState::Active; @@ -425,7 +298,7 @@ fn app_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { // use qingke_rt::CoreInterrupt; // qingke::pfic::unpend_interrupt(Interrupt::EXTI7_0 as u8); - clear_interrupt(2, 6); + system::clear_interrupt(2, 6); qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); // qingke::pfic::enable_interrupt(CoreInterrupt::SysTick as u8); } @@ -540,7 +413,7 @@ fn app_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { match system_state { SystemState::DeepSleep => { // TODO: make this REALLY deep sleep - unsafe { enter_standby(4) }; + unsafe { system::enter_standby(4) }; loop { riscv::asm::wfi(); let mut config = hal::Config::default(); @@ -600,7 +473,8 @@ fn main() -> ! { let mut delay = Delay; delay.delay_ms(1000); - debug_main(p, delay); + // debug_main(p, delay); + app_main(p, delay); } #[panic_handler] diff --git a/ch32v-insert-coin/src/system.rs b/ch32v-insert-coin/src/system.rs new file mode 100644 index 0000000..0a3212b --- /dev/null +++ b/ch32v-insert-coin/src/system.rs @@ -0,0 +1,145 @@ +use ch32_hal as hal; +use hal::println; + +pub unsafe fn init_gpio_irq(pin: u8, port: u8, rising: bool, falling: bool) { + critical_section::with(|_| { + #[cfg(feature = "enable_print")] + println!("init_gpio_irq"); + let exti = &hal::pac::EXTI; + let afio = &hal::pac::AFIO; + + let port = port as u8; + let pin = pin as usize; + + // let b = afio.exticr().read(); + afio.exticr().modify(|w| w.set_exti(pin, port)); + + exti.intenr().modify(|w| w.set_mr(pin, true)); // enable interrupt + exti.rtenr().modify(|w| w.set_tr(pin, rising)); + exti.ftenr().modify(|w| w.set_tr(pin, falling)); + }); +} + +// FIXME: should return a vec of the interrupts +pub fn clear_interrupt(coin_pin: u8, button_pin: u8) -> crate::InputFlags { + let mut input_flags = crate::InputFlags { + coin_flag: false, + button_flag: false, + }; + + let exti = &hal::pac::EXTI; + + let coin_pin = coin_pin as usize; + let button_pin = button_pin as usize; + + exti.intenr().modify(|w| w.set_mr(coin_pin, false)); // disable interrupt + exti.intenr().modify(|w| w.set_mr(button_pin, false)); // disable interrupt + + let bits = exti.intfr().read(); + + // We don't handle or change any EXTI lines above 24. + let bits = bits.0 & 0x00FFFFFF; + + // coin_flag + if (bits & (0x1 << coin_pin)) != 0x0 { + #[cfg(feature = "enable_print")] + println!("coin irq!"); + input_flags.coin_flag = true; + // unsafe { + // INPUT_FLAGS.coin_flag = true; + // } + } + + // button_flag + if (bits & (0x1 << button_pin)) != 0x0 { + #[cfg(feature = "enable_print")] + println!("button irq!"); + input_flags.button_flag = true; + // unsafe { + // INPUT_FLAGS.button_flag = true; + // } + } + + // Clear pending - Clears the EXTI's line pending bits. + exti.intfr().write(|w| w.0 = bits); + + use hal::pac::Interrupt; + unsafe { + qingke::pfic::unpend_interrupt(Interrupt::EXTI7_0 as u8); + }; + + // exti.intenr().modify(|w| w.0 = w.0 & !bits); + exti.intenr().modify(|w| w.set_mr(coin_pin, true)); // enable interrupt + exti.intenr().modify(|w| w.set_mr(button_pin, true)); // enable interrupt + + input_flags +} + +/// enter standby (SLEEPDEEP) mode, with WFE enabled. +/// from CH32V003 reference manual 2.3.1: +/// entry: +/// 1. configure core register control bit: SLEEPDEEP=1 | PDDS = 1 +/// 2. configure external interrupt register to mask all but EXTI7_0 +/// 3. execute WFI or WFE (optionally SEVONPEND) and SLEEPONEXIT +/// * (probably WFI?) +/// exit: +/// 1. any interrupt/event (set in external interrupt register) +pub unsafe fn enter_standby(pin: usize) { + critical_section::with(|_| { + use hal::pac::Interrupt; + use qingke_rt::CoreInterrupt; + + // configure core register control bit (SLEEPDEEP=1 | PDDS=1) + let pfic = &hal::pac::PFIC; + pfic.sctlr().modify(|w| { + // we only want to wake on enabled interrupts + w.set_sevonpend(false); + // we want to enable deep sleep + w.set_sleepdeep(true); + w.set_wfitowfe(false); + w.set_sleeponexit(false); + }); + + // set PDDS=1: + // get current value of PWR_CTLR + let mut reg: u32 = 0x4000_7000; + let mut val: u32 = 0; + unsafe { + val = (reg as *mut u32).read_volatile(); + } + // modify PDDS + val |= 1 << 1; // PWR_CTLR[1] -> PDDS + unsafe { + (reg as *mut u32).write_volatile(val); + } + + // // disable all exti interrupts + let exti = &hal::pac::EXTI; + // exti.intenr().write(| w| { + // w.0 = 0x00000000; + // // w.set_mr(pin, true); + // // w.set_mr(pin, true); + // }); + + // clear all pending exti interrupts + let bits = 0xFFFFFFFF; + exti.intfr().write(|w| w.0 = bits); + + // enable all exti interrupts + let exti = &hal::pac::EXTI; + exti.intenr().write(|w| { + w.0 = 0x00FFFFFF; + // w.set_mr(pin, true); + // w.set_mr(pin, true); + }); + + unsafe { + qingke::pfic::disable_interrupt(CoreInterrupt::SysTick as u8); + qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); + } + + // execute WFI + #[cfg(feature = "enable_print")] + println!("WFI CONFIGURED HOPEFULLY"); + }); +}