-
Notifications
You must be signed in to change notification settings - Fork 264
/
Copy pathembassy_i2s_sound.rs
117 lines (100 loc) · 3.3 KB
/
embassy_i2s_sound.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! This shows how to transmit data continuously via I2S.
//!
//! Without an additional I2S sink device you can inspect the BCLK, WS
//! and DOUT with a logic analyzer.
//!
//! You can also connect e.g. a PCM510x to hear an annoying loud sine tone (full
//! scale), so turn down the volume before running this example.
//!
//! The following wiring is assumed:
//! - BCLK => GPIO2
//! - WS => GPIO4
//! - DOUT => GPIO5
//!
//! PCM510x:
//! | Pin | Connected to |
//! |-------|-----------------|
//! | BCK | GPIO1 |
//! | DIN | GPIO3 |
//! | LRCK | GPIO2 |
//! | SCK | Gnd |
//! | GND | Gnd |
//! | VIN | +3V3 |
//! | FLT | Gnd |
//! | FMT | Gnd |
//! | DEMP | Gnd |
//! | XSMT | +3V3 |
//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use esp_backtrace as _;
use esp_hal::{
dma_buffers,
i2s::master::{DataFormat, I2s, Standard},
time::Rate,
timer::timg::TimerGroup,
};
use esp_println::println;
const SINE: [i16; 64] = [
0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244, 28897, 30272, 31356,
32137, 32609, 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169, 20787, 18204,
15446, 12539, 9511, 6392, 3211, 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787, -23169,
-25329, -27244, -28897, -30272, -31356, -32137, -32609, -32767, -32609, -32137, -31356, -30272,
-28897, -27244, -25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
];
#[esp_hal_embassy::main]
async fn main(_spawner: Spawner) {
println!("Init!");
let peripherals = esp_hal::init(esp_hal::Config::default());
let timg0 = TimerGroup::new(peripherals.TIMG0);
esp_hal_embassy::init(timg0.timer0);
cfg_if::cfg_if! {
if #[cfg(any(feature = "esp32", feature = "esp32s2"))] {
let dma_channel = peripherals.DMA_I2S0;
} else {
let dma_channel = peripherals.DMA_CH0;
}
}
let (_, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(0, 32000);
let i2s = I2s::new(
peripherals.I2S0,
Standard::Philips,
DataFormat::Data16Channel16,
Rate::from_hz(44100),
dma_channel,
rx_descriptors,
tx_descriptors,
)
.into_async();
let i2s_tx = i2s
.i2s_tx
.with_bclk(peripherals.GPIO2)
.with_ws(peripherals.GPIO4)
.with_dout(peripherals.GPIO5)
.build();
let data =
unsafe { core::slice::from_raw_parts(&SINE as *const _ as *const u8, SINE.len() * 2) };
let buffer = tx_buffer;
let mut idx = 0;
for i in 0..usize::min(data.len(), buffer.len()) {
buffer[i] = data[idx];
idx += 1;
if idx >= data.len() {
idx = 0;
}
}
let mut filler = [0u8; 10000];
let mut idx = 32000 % data.len();
println!("Start");
let mut transaction = i2s_tx.write_dma_circular_async(buffer).unwrap();
loop {
for i in 0..filler.len() {
filler[i] = data[(idx + i) % data.len()];
}
println!("Next");
let written = transaction.push(&filler).await.unwrap();
idx = (idx + written) % data.len();
println!("written {}", written);
}
}