Skip to content
Snippets Groups Projects
Commit df9f7420 authored by Per Lindgren's avatar Per Lindgren
Browse files

ok pwm solotions for now

parent f24ec122
Branches
No related tags found
No related merge requests found
...@@ -134,19 +134,6 @@ const APP: () = { ...@@ -134,19 +134,6 @@ const APP: () = {
rprintln!("here"); rprintln!("here");
tim1.sr.modify(|_, w| w.uif().clear()); tim1.sr.modify(|_, w| w.uif().clear());
// loop {
// for i in 0..SINE_BUF_SIZE {
// // wait until next update event
// while tim1.sr.read().uif().is_clear() {}
// tim1.sr.modify(|_, w| w.uif().clear());
// tim1.ccr1
// .write(|w| unsafe { w.ccr().bits(SINE_BUF[i] as u16) });
// tim1.ccr2
// .write(|w| unsafe { w.ccr().bits(SINE_BUF[i] as u16) });
// }
// }
// pass on late resources // pass on late resources
cx.schedule.pwmout(cx.start + PERIOD.cycles()).ok(); cx.schedule.pwmout(cx.start + PERIOD.cycles()).ok();
init::LateResources { TIM1: tim1 } init::LateResources { TIM1: tim1 }
...@@ -172,7 +159,7 @@ const APP: () = { ...@@ -172,7 +159,7 @@ const APP: () = {
tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) }); tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) });
tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) }); tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) });
*INDEX = (*INDEX).wrapping_add(25oo); *INDEX = (*INDEX).wrapping_add(25);
cx.schedule.pwmout(cx.scheduled + PERIOD.cycles()).ok(); cx.schedule.pwmout(cx.scheduled + PERIOD.cycles()).ok();
*LEFT = SINE_BUF[*INDEX as usize] as u16; *LEFT = SINE_BUF[*INDEX as usize] as u16;
...@@ -190,4 +177,4 @@ const APP: () = { ...@@ -190,4 +177,4 @@ const APP: () = {
// We aim for a sampling rate of 48kHz, assuming that the input filter of the // We aim for a sampling rate of 48kHz, assuming that the input filter of the
// sound card used to sample the generated signal has an appropriate input filter // sound card used to sample the generated signal has an appropriate input filter
const PERIOD: u32 = 1000; // 48_000_000 / 48_000; const PERIOD: u32 = 2000; // 96_000_000 / 48_000;
//! cargo run --examples rtt-pwm-sine-timer-task --release
// #![deny(unsafe_code)]
// #![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m::{asm, peripheral::DWT};
use panic_rtt_target as _;
use rtic::cyccnt::{Instant, U32Ext as _};
use rtt_target::{rprint, rprintln, rtt_init_print};
use stm32f4xx_hal::{
gpio::Speed,
prelude::*,
pwm, stm32,
timer::{Event, Timer},
};
include!(concat!(env!("OUT_DIR"), "/sin_abs_const.rs"));
type Timer2 = Timer<stm32::TIM2>;
#[rtic::app(device = stm32f4xx_hal::stm32, monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
const APP: () = {
struct Resources {
// late resources
TIM1: stm32::TIM1,
timer2: Timer2,
}
#[init(schedule = [])]
fn init(mut cx: init::Context) -> init::LateResources {
rtt_init_print!();
rprintln!("init");
let dp = cx.device;
// Initialize (enable) the monotonic timer (CYCCNT)
cx.core.DCB.enable_trace();
cx.core.DWT.enable_cycle_counter();
let rcc = dp.RCC.constrain();
// Set up the system clock. 48 MHz?
let clocks = rcc
.cfgr
// .use_hse(8.mhz())
// .sysclk(48.mhz())
.sysclk(96.mhz())
.pclk1(24.mhz())
.freeze();
let gpioa = dp.GPIOA.split();
// we set the pins to VeryHigh to get the sharpest waveform possible
// (rise and fall times should have similar characteristics)
let channels = (
gpioa.pa8.into_alternate_af1().set_speed(Speed::VeryHigh),
gpioa.pa9.into_alternate_af1().set_speed(Speed::VeryHigh),
);
// Setup PWM RAW
let tim1 = dp.TIM1;
// Here we need unsafe as we are "stealing" the RCC peripheral
// At this point it has been contrained into SysConf and used to set clocks
let rcc = unsafe { &(*stm32::RCC::ptr()) };
rcc.apb2enr.modify(|_, w| w.tim1en().set_bit());
rcc.apb2rstr.modify(|_, w| w.tim1rst().set_bit());
rcc.apb2rstr.modify(|_, w| w.tim1rst().clear_bit());
// Setup chanel 1 and 2 as pwm_mode1
tim1.ccmr1_output()
.modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1());
tim1.ccmr1_output()
.modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1());
// The reference manual is a bit ambiguous about when enabling this bit is really
// necessary, but since we MUST enable the preload for the output channels then we
// might as well enable for the auto-reload too
tim1.cr1.modify(|_, w| w.arpe().set_bit());
let clk = clocks.pclk2().0 * if clocks.ppre2() == 1 { 1 } else { 2 };
// check that its actually 48_000_000
rprintln!("clk {}", clk);
// we want maximum performance, thus we set the prescaler to 0
let pre = 0;
rprintln!("pre {}", pre);
tim1.psc.write(|w| w.psc().bits(pre));
// we want 8 bits of resolution
// so our ARR = 2^8 - 1 = 256 - 1 = 255
let arr = 255;
rprintln!("arr {}", arr);
tim1.arr.write(|w| unsafe { w.bits(arr) });
// Trigger update event to load the registers
tim1.cr1.modify(|_, w| w.urs().set_bit());
tim1.egr.write(|w| w.ug().set_bit());
tim1.cr1.modify(|_, w| w.urs().clear_bit());
// Set main output enable of all Output Compare (OC) registers
tim1.bdtr.modify(|_, w| w.moe().set_bit());
// Set output enable for channels 1 and 2
tim1.ccer.write(|w| w.cc1e().set_bit().cc2e().set_bit());
// Setup the timer
tim1.cr1.write(|w| {
w.cms()
.bits(0b00) // edge aligned mode
.dir() // counter used as upcounter
.clear_bit()
.opm() // one pulse mode
.clear_bit()
.cen() // enable counter
.set_bit()
});
// Set main output enable of all Output Compare (OC) registers
tim1.bdtr.modify(|_, w| w.moe().set_bit());
// Set duty cycle of Channels
tim1.ccr1.write(|w| unsafe { w.ccr().bits(128) });
tim1.ccr2.write(|w| unsafe { w.ccr().bits(128) });
// Set preload for the CCx
tim1.cr2.write(|w| w.ccpc().set_bit());
// Enable update events
tim1.dier.write(|w| w.uie().enabled());
tim1.sr.modify(|_, w| w.uif().clear());
// Set divider to 4, (48_000_000/256)/4
// tim1.rcr.modify(|_, w| unsafe { w.rep().bits(4) });
while tim1.sr.read().uif().is_clear() {
rprint!("-");
}
rprintln!("here");
tim1.sr.modify(|_, w| w.uif().clear());
let mut tim2: Timer<stm32::TIM2> = Timer::tim2(dp.TIM2, 48000, clocks);
tim2.listen(Event::TimeOut);
init::LateResources {
TIM1: tim1,
timer2: tim2,
}
}
#[idle]
fn idle(_cx: idle::Context) -> ! {
rprintln!("idle");
// panic!("panic");
loop {
rprintln!("-");
continue;
}
}
#[task(binds = TIM2, resources = [TIM1, timer2])]
fn tim2(cx: tim2::Context) {
static mut INDEX: u8 = 0;
static mut LEFT: u16 = 0;
static mut RIGHT: u16 = 0;
cx.resources.timer2.clear_interrupt(Event::TimeOut);
let tim1 = cx.resources.TIM1;
tim1.ccr1.write(|w| unsafe { w.ccr().bits(*LEFT) });
tim1.ccr2.write(|w| unsafe { w.ccr().bits(*RIGHT) });
*INDEX = (*INDEX).wrapping_add(25);
*LEFT = SINE_BUF[*INDEX as usize] as u16;
*RIGHT = SINE_BUF[*INDEX as usize] as u16;
}
extern "C" {
fn EXTI0();
}
};
// We aim for a sampling rate of 48kHz, assuming that the input filter of the
// sound card used to sample the generated signal has an appropriate input filter
const PERIOD: u32 = 1000; // 48_000_000 / 48_000;
...@@ -104,7 +104,6 @@ const APP: () = { ...@@ -104,7 +104,6 @@ const APP: () = {
.set_bit() .set_bit()
}); });
// Set main output enable of all Output Compare (OC) registers // Set main output enable of all Output Compare (OC) registers
tim1.bdtr.modify(|_, w| w.moe().set_bit()); tim1.bdtr.modify(|_, w| w.moe().set_bit());
...@@ -115,6 +114,7 @@ const APP: () = { ...@@ -115,6 +114,7 @@ const APP: () = {
// Set preload for the CCx // Set preload for the CCx
tim1.cr2.write(|w| w.ccpc().set_bit()); tim1.cr2.write(|w| w.ccpc().set_bit());
// Enable update events
tim1.dier.write(|w| w.uie().enabled()); tim1.dier.write(|w| w.uie().enabled());
tim1.sr.modify(|_, w| w.uif().clear()); tim1.sr.modify(|_, w| w.uif().clear());
...@@ -142,22 +142,26 @@ const APP: () = { ...@@ -142,22 +142,26 @@ const APP: () = {
} }
} }
// [task(resources = [GPIOA], schedule = [toggle])] #[task(resources = [GPIOA], schedule = [toggle])]
// fn toggle(cx: toggle::Context) { fn toggle(cx: toggle::Context) {
// static mut TOGGLE: bool = false; static mut TOGGLE: bool = false;
// hprintln!("foo @ {:?}", Instant::now()).unwrap(); hprintln!("foo @ {:?}", Instant::now()).unwrap();
// if *TOGGLE { if *TOGGLE {
// cx.resources.GPIOA.bsrr.write(|w| w.bs5().set_bit()); cx.resources.GPIOA.bsrr.write(|w| w.bs5().set_bit());
// } else { } else {
// cx.resources.GPIOA.bsrr.write(|w| w.br5().set_bit()); cx.resources.GPIOA.bsrr.write(|w| w.br5().set_bit());
// } }
// *TOGGLE = !*TOGGLE; *TOGGLE = !*TOGGLE;
// cx.schedule cx.schedule
// .toggle(cx.scheduled + 8_000_000.cycles()) .toggle(cx.scheduled + 8_000_000.cycles())
// .unwrap(); .unwrap();
// } }
extern "C" {
fn EXTI0();
}
#[idle] #[idle]
fn idle(_cx: idle::Context) -> ! { fn idle(_cx: idle::Context) -> ! {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment