From 58579ae6c24fd5ea0097cbd05c7cce8e9fab10f2 Mon Sep 17 00:00:00 2001 From: sigil-03 Date: Mon, 27 Oct 2025 21:10:36 -0600 Subject: [PATCH] first wavetable synth demo --- .gitmodules | 3 ++ ch32v-insert-coin/Cargo.lock | 5 +++ ch32v-insert-coin/Cargo.toml | 2 + ch32v-insert-coin/ext/wavetable-synth | 1 + ch32v-insert-coin/src/main.rs | 57 +++++++++++++++++---------- ch32v-insert-coin/src/synthesizer.rs | 36 +++++++++++++++++ 6 files changed, 84 insertions(+), 20 deletions(-) create mode 160000 ch32v-insert-coin/ext/wavetable-synth create mode 100644 ch32v-insert-coin/src/synthesizer.rs diff --git a/.gitmodules b/.gitmodules index fb915f4..e953eec 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "ch32v-insert-coin/ext/adpcm-pwm-dac"] path = ch32v-insert-coin/ext/adpcm-pwm-dac url = ssh://git@git.glyphs.tech:222/sigil-03/adpcm-pwm-dac.git +[submodule "ch32v-insert-coin/ext/wavetable-synth"] + path = ch32v-insert-coin/ext/wavetable-synth + url = https://git.glyphs.tech/sigil-03/wavetable-synth.git diff --git a/ch32v-insert-coin/Cargo.lock b/ch32v-insert-coin/Cargo.lock index dc8468c..7fd7006 100644 --- a/ch32v-insert-coin/Cargo.lock +++ b/ch32v-insert-coin/Cargo.lock @@ -78,6 +78,7 @@ dependencies = [ "panic-halt", "qingke 0.5.0", "qingke-rt", + "wavetable-synth", ] [[package]] @@ -626,3 +627,7 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "wavetable-synth" +version = "0.1.0" diff --git a/ch32v-insert-coin/Cargo.toml b/ch32v-insert-coin/Cargo.toml index facb4f1..e09776c 100644 --- a/ch32v-insert-coin/Cargo.toml +++ b/ch32v-insert-coin/Cargo.toml @@ -31,6 +31,8 @@ qingke = {path = "ext/qingke"} adpcm-pwm-dac = { path = "ext/adpcm-pwm-dac/" } +wavetable-synth = { path = "ext/wavetable-synth" } + critical-section = { version = "1.2.0" } [profile.release] diff --git a/ch32v-insert-coin/ext/wavetable-synth b/ch32v-insert-coin/ext/wavetable-synth new file mode 160000 index 0000000..9417e6e --- /dev/null +++ b/ch32v-insert-coin/ext/wavetable-synth @@ -0,0 +1 @@ +Subproject commit 9417e6edbf590f3fe777e39ad76efc21a024e01d diff --git a/ch32v-insert-coin/src/main.rs b/ch32v-insert-coin/src/main.rs index d59d44f..ac9bac5 100644 --- a/ch32v-insert-coin/src/main.rs +++ b/ch32v-insert-coin/src/main.rs @@ -9,6 +9,10 @@ mod insert_coin; // system stuff mod system; +// synthesizer :3 +mod synthesizer; +use synthesizer::AppSynthesizers; + use ch32_hal::{adc::AdcChannel, interrupt::typelevel::Handler, timer::low_level::OutputPolarity}; use insert_coin::{CoreConfig, InsertCoin, SimplePwmCore}; @@ -204,30 +208,40 @@ fn debug_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { use hal::gpio::{Level, Output}; let mut led0_pin = Output::new(p.PC3, Level::High, Default::default()); - // button pin setup - let button_pin = p.PD6; - 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 { system::enter_standby() }; - delay.delay_ms(1000); - riscv::asm::wfi(); + let tick_rate_hz = 100000; // 100khz + let tick_interval_us = 1000000 / tick_rate_hz; - // get the clocks re-initialized - let mut config = hal::Config::default(); - config.rcc = hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSI; - unsafe { - hal::rcc::init(config.rcc); - } + // DAC output setup + let dac_pin = PwmPin::new_ch4::<0>(p.PC4); + // let dac_ch = hal::timer::Channel::Ch4; + + // PWM timer setup + let mut pwm = SimplePwm::new( + p.TIM1, + None, + None, + None, + Some(dac_pin), + Hertz::khz(200), + CountingMode::default(), + ); + + let pwm_core = SimplePwmCore::new(pwm); + + // === synthesizer setup === + let mut synthesizer = AppSynthesizers::new(tick_rate_hz, pwm_core); + synthesizer.square.set_freq(440); #[cfg(feature = "enable_print")] println!("begin loop"); + led0_pin.toggle(); + loop { - led0_pin.toggle(); - delay.delay_ms(100); + synthesizer.service(); + delay.delay_us(tick_interval_us as u32); } } @@ -275,6 +289,11 @@ fn app_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { let core_config = CoreConfig::new(tick_rate_hz); + let pwm_core = SimplePwmCore::new(pwm); + + // === synthesizer setup === + // let synthesizer = AppSynthesizers::new(core_config.tick_rate_hz, pwm_core); + // === input setup === // adc @@ -327,8 +346,6 @@ fn app_main(mut p: hal::Peripherals, mut delay: Delay) -> ! { let mut light_ctrl_btn_input = DebouncedGPIO::new(light_ctrl_btn_pin.degrade(), core_config.tick_rate_hz, 100); - let pwm_core = SimplePwmCore::new(pwm); - let mut interfaces = InsertCoin::new(core_config, pwm_core); interfaces.set_active(true); // insert_coin.init(); @@ -631,8 +648,8 @@ fn main() -> ! { let mut delay = Delay; delay.delay_ms(1000); - // debug_main(p, delay); - app_main(p, delay); + debug_main(p, delay); + // app_main(p, delay); } #[panic_handler] diff --git a/ch32v-insert-coin/src/synthesizer.rs b/ch32v-insert-coin/src/synthesizer.rs new file mode 100644 index 0000000..ab50fe6 --- /dev/null +++ b/ch32v-insert-coin/src/synthesizer.rs @@ -0,0 +1,36 @@ +use crate::insert_coin::SimplePwmCore; +use ch32_hal::println; +use ch32_hal::timer::GeneralInstance16bit; +use wavetable_synth::{synthesizer::SimpleWavetableSynthesizer, wavetable::SimpleWavetable}; + +const SQUARE_WAVETABLE: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, +]; + +pub struct AppSynthesizers<'a, T: GeneralInstance16bit> { + pub square: SimpleWavetableSynthesizer>, + output: SimplePwmCore<'a, T>, +} + +impl<'a, T: GeneralInstance16bit> AppSynthesizers<'a, T> { + pub fn new(clock_freq_hz: usize, output: SimplePwmCore<'a, T>) -> Self { + let square_wt = SimpleWavetable::new(&SQUARE_WAVETABLE); + let square = SimpleWavetableSynthesizer::new(square_wt, clock_freq_hz); + + Self { square, output } + } + + pub fn service(&mut self) { + self.square.tick(); + if self.square.has_new_output() { + let out = self.square.get_output(); + // println!("OUTPUT: {out}"); + self.output.write_amplitude( + ch32_hal::timer::Channel::Ch4, + out / 2, + // (out as f32 * (u8::MAX as f32 / u32::MAX as f32)) as u8, + ); + } + } +}