Skip to content

Commit 42a73cf

Browse files
committed
WIP: Audio out using the CS43L22 DAC
1 parent 46b7528 commit 42a73cf

File tree

6 files changed

+165
-6
lines changed

6 files changed

+165
-6
lines changed

.vscode/launch.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@
2929
"cwd": "${workspaceRoot}",
3030
"preLaunchTask": "cargo build --examples",
3131
"runToMain": true,
32-
"executable": "./target/thumbv7em-none-eabihf/debug/{{project-name}}",
32+
// "executable": "./target/thumbv7em-none-eabihf/debug/{{project-name}}",
3333
/* Run `cargo build --example itm` and uncomment this line to run itm example */
3434
// "executable": "./target/thumbv7em-none-eabihf/debug/examples/itm",
35+
"executable": "./target/thumbv7em-none-eabihf/debug/examples/audio",
3536
"device": "STM32F407VGT6",
3637
"configFiles": ["openocd.cfg"],
3738
"svdFile": "${workspaceRoot}/.vscode/STM32F407.svd",
3839
"swoConfig": {
3940
"enabled": true,
40-
"cpuFrequency": 16000000,
41+
"cpuFrequency": 168000000,
4142
"swoFrequency": 2000000,
4243
"source": "probe",
4344
"decoders": [{ "type": "console", "label": "ITM", "port": 0 }]

Cargo.toml

+16-2
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,32 @@ cortex-m = "0.6"
2424
cortex-m-rt = "0.6"
2525
lis302dl = "0.1.0"
2626

27+
[dependencies.cs43l22]
28+
# git = "https://github.com/maxekman/cs43l22/"
29+
# branch = "master"
30+
path = "../cs43l22"
31+
2732
[dependencies.embedded-hal]
33+
# TODO: Update version when I2S proposal is finalized:
34+
# https://github.com/rust-embedded/embedded-hal/pull/204
2835
features = ["unproven"]
29-
version = "0.2"
36+
# version = "0.2.3"
37+
# git = "https://github.com/eldruin/embedded-hal/"
38+
# branch = "i2s"
39+
path = "../embedded-hal"
3040

3141
[dependencies.stm32f4xx-hal]
3242
default-features = false
3343
features = ["rt", "stm32f407"]
34-
version = "0.8.2"
44+
# version = "0.8.2"
45+
# git = "https://github.com/maxekman/stm32f4xx-hal/"
46+
# branch = "i2s"
47+
path = "../stm32f4xx-hal"
3548

3649
[dev-dependencies]
3750
ssd1306 = "0.2"
3851
nb = "0.1"
52+
cortex-m-log = { version = "~0.6", features = ["itm"] }
3953
panic-halt = "0.2"
4054
panic-itm = "0.4"
4155

examples/audio.rs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//! Plays a test tone through the DAC with headphone amp.
2+
3+
#![no_main]
4+
#![no_std]
5+
6+
extern crate panic_itm;
7+
8+
use cortex_m::peripheral::Peripherals;
9+
use cortex_m_rt::entry;
10+
11+
use stm32f407g_disc as board;
12+
13+
use crate::board::{audio_out::AudioOut, hal::delay::Delay, hal::prelude::*, hal::stm32};
14+
15+
use cortex_m_log::println;
16+
use cortex_m_log::{destination::Itm, printer::itm::InterruptSync as InterruptSyncItm};
17+
18+
#[entry]
19+
fn main() -> ! {
20+
let p = stm32::Peripherals::take().unwrap();
21+
let cp = Peripherals::take().unwrap();
22+
23+
let mut log = InterruptSyncItm::new(Itm::new(cp.ITM));
24+
25+
let gpioa = p.GPIOA.split();
26+
let gpiob = p.GPIOB.split();
27+
let gpioc = p.GPIOC.split();
28+
let gpiod = p.GPIOD.split();
29+
30+
// TODO: Use frequency when setting up clocks.
31+
let audio_freq = 48000;
32+
33+
// Set clock to 64 MHz and freeze.
34+
let rcc = p.RCC.constrain();
35+
let clocks = rcc
36+
.cfgr
37+
.use_hse(8.mhz())
38+
.sysclk(168.mhz())
39+
.plli2sclk(audio_freq.hz())
40+
.freeze();
41+
42+
// Get delay provider.
43+
let mut delay = Delay::new(cp.SYST, clocks);
44+
45+
println!(log, "\nSetup audio output");
46+
let mut audio_out = AudioOut::new(
47+
p.I2C1, p.SPI3, gpioa, gpiob, gpioc, gpiod, clocks, &mut delay, audio_freq, 128,
48+
);
49+
50+
println!(log, "Starting audio");
51+
let mut s: u16 = 0;
52+
let mut y: u16 = 100;
53+
loop {
54+
// Send both left and right word.
55+
audio_out.i2s.send(s).unwrap();
56+
audio_out.i2s.send(s).unwrap();
57+
58+
// Sawtooth with incrementing pitch each cycle.
59+
if s >= (65535 - y) {
60+
s = 0;
61+
y += 1;
62+
if y > 400 {
63+
y = 100
64+
}
65+
}
66+
s += y;
67+
}
68+
}

openocd.gdb

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@ break main
2020
monitor tpiu config internal itm.txt uart off 168000000
2121

2222

23-
# OR: make the microcontroller SWO (PB3) pin output compatible with UART (8N1)
24-
# 8000000 is the frequency of the SWO pin
23+
# # send captured ITM to the file itm.fifo
24+
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
25+
# # 16000000 must match the core clock frequency
26+
monitor tpiu config internal itm.txt uart off 168000000
27+
28+
# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
29+
# # 8000000 is the frequency of the SWO pin
2530
# monitor tpiu config external uart off 8000000 2000000
2631

2732
# # enable ITM port 1

src/audio_out.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//! CS43L22 DAC with headphone amp.
2+
3+
use crate::hal::prelude::*;
4+
5+
use crate::hal::gpio::gpioa::{self, PA4};
6+
use crate::hal::gpio::gpiob::{self, PB6, PB9};
7+
use crate::hal::gpio::gpioc::{self, PC10, PC12};
8+
use crate::hal::gpio::gpiod::{self, PD4};
9+
use crate::hal::gpio::{Alternate, AlternateOD, Output, PushPull, AF4, AF6};
10+
use crate::hal::i2c::*;
11+
use crate::hal::i2s::*;
12+
use crate::hal::rcc::Clocks;
13+
use crate::hal::stm32::{I2C1, SPI3};
14+
15+
use embedded_hal::blocking::delay::DelayMs;
16+
17+
pub use cs43l22;
18+
19+
pub struct AudioOut {
20+
pub cs43l22: cs43l22::CS43L22<
21+
I2c<I2C1, (PB6<AlternateOD<AF4>>, PB9<AlternateOD<AF4>>)>,
22+
PD4<Output<PushPull>>,
23+
>,
24+
pub i2s: I2s<
25+
SPI3,
26+
(
27+
PC10<Alternate<AF6>>,
28+
PA4<Alternate<AF6>>,
29+
PC12<Alternate<AF6>>,
30+
NoSdExt,
31+
),
32+
>,
33+
}
34+
35+
impl AudioOut {
36+
pub fn new<DELAY: DelayMs<u8>>(
37+
i2c1: I2C1,
38+
spi3: SPI3,
39+
gpioa: gpioa::Parts,
40+
gpiob: gpiob::Parts,
41+
gpioc: gpioc::Parts,
42+
gpiod: gpiod::Parts,
43+
clocks: Clocks,
44+
delay: &mut DELAY,
45+
audio_freq: u32,
46+
vol: u8,
47+
) -> Self {
48+
// Setup I2C1 using PB6 and PB9 pins at 100kHz bitrate.
49+
let scl = gpiob.pb6.into_alternate_af4().set_open_drain();
50+
let sda = gpiob.pb9.into_alternate_af4().set_open_drain();
51+
let i2c1 = I2c::i2c1(i2c1, (scl, sda), 100.khz(), clocks);
52+
53+
// CS43L22 reset pin.
54+
let reset = gpiod.pd4.into_push_pull_output();
55+
56+
// Set PC7 into AF6 to output the MCLK for I2S3.
57+
let _mck = gpioc.pc7.into_alternate_af6();
58+
59+
// Setup I2S3 for 48kHz audio.
60+
let ck = gpioc.pc10.into_alternate_af6();
61+
let ws = gpioa.pa4.into_alternate_af6();
62+
let sd = gpioc.pc12.into_alternate_af6();
63+
let i2s3 = I2s::i2s3(spi3, (ck, ws, sd, NoSdExt), audio_freq.hz(), clocks);
64+
65+
let cs43l22 = cs43l22::CS43L22::new(i2c1, reset, delay, vol)
66+
.expect("could not create CS43L22 driver");
67+
68+
AudioOut { cs43l22, i2s: i2s3 }
69+
}
70+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ pub use cortex_m::*;
1212
pub use cortex_m_rt::*;
1313

1414
pub mod accelerometer;
15+
pub mod audio_out;
1516
pub mod led;

0 commit comments

Comments
 (0)