Browse Source

a little piece of code doing 1000Hz Sawtooth synthesis via PWM

master
Weird Constructor 1 year ago
commit
874f270ca0
  1. 19
      pwm_dac_saw_sampling/.cargo/config
  2. 16
      pwm_dac_saw_sampling/.gitignore
  3. 3
      pwm_dac_saw_sampling/.vscode/settings.json
  4. 85
      pwm_dac_saw_sampling/Cargo.toml
  5. 31
      pwm_dac_saw_sampling/build.rs
  6. 13
      pwm_dac_saw_sampling/memory.x
  7. 111
      pwm_dac_saw_sampling/src/example_1000hz_saw.rs
  8. 111
      pwm_dac_saw_sampling/src/main.rs

19
pwm_dac_saw_sampling/.cargo/config

@ -0,0 +1,19 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-run-rp --chip RP2040"
rustflags = [
"-C", "linker=flip-link",
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
# Code-size optimizations.
# trap unreachable can save a lot of space, but requires nightly compiler.
# uncomment the next line if you wish to enable it
# "-Z", "trap-unreachable=no",
"-C", "inline-threshold=5",
"-C", "no-vectorize-loops",
]
[build]
target = "thumbv6m-none-eabi"

16
pwm_dac_saw_sampling/.gitignore vendored

@ -0,0 +1,16 @@
**/*.rs.bk
.#*
.gdb_history
Cargo.lock
target/
# editor files
.vscode/*
!.vscode/*.md
!.vscode/*.svd
!.vscode/launch.json
!.vscode/tasks.json
!.vscode/extensions.json
!.vscode/settings.json
*.history

3
pwm_dac_saw_sampling/.vscode/settings.json vendored

@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}

85
pwm_dac_saw_sampling/Cargo.toml

@ -0,0 +1,85 @@
[package]
authors = ["the rp-rs team"]
edition = "2018"
readme = "README.md"
name = "rp2040-project-template"
version = "0.1.0"
resolver = "2"
[dependencies]
cortex-m = "0.7.3"
cortex-m-rt = "0.7.0"
embedded-hal = { version = "0.2.5", features=["unproven"] }
embedded-time = "0.12.0"
defmt = "0.2.0"
defmt-rtt = "0.2.0"
panic-probe = { version = "0.2.0", features = ["print-defmt"] }
rp2040-hal = { git = "https://github.com/rp-rs/rp-hal", branch="main", features=["rt"] }
rp2040-boot2 = { git = "https://github.com/rp-rs/rp2040-boot2-rs", branch="main" }
nb = "1.0"
[features]
default = [
"defmt-default",
]
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3
overflow-checks = false
# do not optimize proc-macro crates = faster builds from scratch
[profile.dev.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
[profile.release.build-override]
codegen-units = 8
debug = false
debug-assertions = false
opt-level = 0
overflow-checks = false
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true
incremental = false
opt-level = 3
overflow-checks = true
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 3

31
pwm_dac_saw_sampling/build.rs

@ -0,0 +1,31 @@
//! This build script copies the `memory.x` file from the crate root into
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
}

13
pwm_dac_saw_sampling/memory.x

@ -0,0 +1,13 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
RAM : ORIGIN = 0x20000000, LENGTH = 256K
}
SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;

111
pwm_dac_saw_sampling/src/example_1000hz_saw.rs

@ -0,0 +1,111 @@
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use defmt::*;
use defmt_rtt as _;
use embedded_hal::timer::CountDown;
use embedded_hal::PwmPin;
use embedded_time::duration::*;
use panic_probe as _;
use rp2040_hal as hal;
use hal::{
clocks::{init_clocks_and_plls},
pac,
sio::Sio,
watchdog::Watchdog,
};
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
#[entry]
fn main() -> ! {
info!("Program start");
let mut pac = pac::Peripherals::take().unwrap();
let _core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);
// External high-speed crystal on the pico board is 12Mhz
let external_xtal_freq_hz = 12_000_000u32;
let _clocks =
init_clocks_and_plls(
external_xtal_freq_hz,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog)
.ok()
.unwrap();
let timer = hal::timer::Timer::new(pac.TIMER, &mut pac.RESETS);
let mut cnt_down = timer.count_down();
let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
let pwm = &mut pwm_slices.pwm7;
pwm.enable();
pwm.set_div_int(1);
pwm.set_div_frac(0);
let pins =
hal::gpio::Pins::new(
pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);
let top = 200; // changing this changes the PWM frequency!
pwm.set_top(top);
let channel = &mut pwm.channel_b;
channel.output_to(pins.gpio15);
let mut phase = 0.0;
loop {
cnt_down.start((25_u32).microseconds());
channel.set_duty((phase * top as f32) as u16);
phase = phase + (1000.0 / 40000.0);
while phase > 1.0 { phase -= 1.0; }
let _ = nb::block!(cnt_down.wait());
}
}
// let mut delay =
// cortex_m::delay::Delay::new(
// core.SYST,
// clocks.system_clock.freq().integer());
// let mut led_pin = pins.gpio25.into_push_pull_output();
// info!("on!");
// led_pin.set_high().unwrap();
// info!("off!");
// led_pin.set_low().unwrap();
// duty = (duty + 1) % (steps + 1);
// channel.set_duty(duty * tPs);
// let h = rp2040_hal::rom_data::float_funcs::fsin(
// phase * 3.14159265359 * 2.0);

111
pwm_dac_saw_sampling/src/main.rs

@ -0,0 +1,111 @@
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use defmt::*;
use defmt_rtt as _;
use embedded_hal::timer::CountDown;
use embedded_hal::PwmPin;
use embedded_time::duration::*;
use panic_probe as _;
use rp2040_hal as hal;
use hal::{
clocks::{init_clocks_and_plls},
pac,
sio::Sio,
watchdog::Watchdog,
};
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
#[entry]
fn main() -> ! {
info!("Program start");
let mut pac = pac::Peripherals::take().unwrap();
let _core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);
// External high-speed crystal on the pico board is 12Mhz
let external_xtal_freq_hz = 12_000_000u32;
let _clocks =
init_clocks_and_plls(
external_xtal_freq_hz,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog)
.ok()
.unwrap();
let timer = hal::timer::Timer::new(pac.TIMER, &mut pac.RESETS);
let mut cnt_down = timer.count_down();
let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
let pwm = &mut pwm_slices.pwm7;
pwm.enable();
pwm.set_div_int(1);
pwm.set_div_frac(0);
let pins =
hal::gpio::Pins::new(
pac.IO_BANK0, pac.PADS_BANK0, sio.gpio_bank0, &mut pac.RESETS);
let top = 200; // changing this changes the PWM frequency!
pwm.set_top(top);
let channel = &mut pwm.channel_b;
channel.output_to(pins.gpio15);
let mut phase = 0.0;
loop {
cnt_down.start((25_u32).microseconds());
channel.set_duty((phase * top as f32) as u16);
phase = phase + (1000.0 / 40000.0);
while phase > 1.0 { phase -= 1.0; }
let _ = nb::block!(cnt_down.wait());
}
}
// let mut delay =
// cortex_m::delay::Delay::new(
// core.SYST,
// clocks.system_clock.freq().integer());
// let mut led_pin = pins.gpio25.into_push_pull_output();
// info!("on!");
// led_pin.set_high().unwrap();
// info!("off!");
// led_pin.set_low().unwrap();
// duty = (duty + 1) % (steps + 1);
// channel.set_duty(duty * tPs);
// let h = rp2040_hal::rom_data::float_funcs::fsin(
// phase * 3.14159265359 * 2.0);
Loading…
Cancel
Save