144 lines
4.1 KiB
Rust
144 lines
4.1 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
|
|
use esp_backtrace as _;
|
|
use esp_println::println;
|
|
use hal::{
|
|
clock::ClockControl,
|
|
dma::DmaPriority,
|
|
i2s::{DataFormat, I2s, I2s0New, NoMclk, PinsBclkWsDout, Standard, I2sWriteDma},
|
|
pdma::Dma,
|
|
peripherals::Peripherals,
|
|
prelude::*,
|
|
//Delay,
|
|
IO,
|
|
};
|
|
use libm::sinf;
|
|
|
|
const TBL_LEN: usize = 1024;
|
|
const RATE: u32 = 44100;
|
|
|
|
#[entry]
|
|
fn main() -> ! {
|
|
let mut wav_tbl: [i16; TBL_LEN] = [0; TBL_LEN];
|
|
|
|
println!("Generating wave table...");
|
|
for (i, sample) in wav_tbl.iter_mut().enumerate() {
|
|
*sample = sinf((2.0 * core::f32::consts::PI * (i as f32 / TBL_LEN as f32))
|
|
* core::i16::MAX as f32) as i16;
|
|
}
|
|
println!("Done generating wave table!");
|
|
|
|
let peripherals = Peripherals::take();
|
|
let system = peripherals.SYSTEM.split();
|
|
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
|
|
|
let clocks = ClockControl::max(system.clock_control).freeze();
|
|
//let mut delay = Delay::new(&clocks);
|
|
|
|
let dma = Dma::new(system.dma);
|
|
let dma_channel = dma.i2s0channel;
|
|
|
|
// HELP! FIXME! I have no idea how to size these.
|
|
// https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#subsection.6.3
|
|
let mut tx_descriptors = [0u32; 8 * 3];
|
|
let mut rx_descriptors = [0u32; 8 * 3];
|
|
|
|
let i2s = I2s::new(
|
|
peripherals.I2S0,
|
|
// MclkPin::new(io.pins.gpio4),
|
|
NoMclk {},
|
|
Standard::Philips,
|
|
DataFormat::Data16Channel16,
|
|
RATE.Hz(),
|
|
dma_channel.configure(
|
|
false,
|
|
&mut tx_descriptors,
|
|
&mut rx_descriptors,
|
|
DmaPriority::Priority0,
|
|
),
|
|
&clocks,
|
|
);
|
|
|
|
//let i2s_rx = i2s.i2s_rx.with_pins(PinsBclkWsDin::new(
|
|
let i2s_tx = i2s.i2s_tx.with_pins(PinsBclkWsDout::new(
|
|
io.pins.gpio1,
|
|
io.pins.gpio2,
|
|
io.pins.gpio5,
|
|
));
|
|
|
|
// Creating DMA buffer
|
|
static mut DMABUFFER: [u8; 4092 * 4] = [0u8; 4092 * 4];
|
|
let dma_buffer: &'static mut [u8; 4092 * 4] = unsafe { &mut DMABUFFER };
|
|
|
|
let mut working_buffer: [u8; 1024*4] = [0; 1024*4];
|
|
let mut phase: f32 = 0.0;
|
|
let phase_delta = (440.0 / RATE as f32) * TBL_LEN as f32;
|
|
|
|
let mut transfer = i2s_tx.write_dma_circular(dma_buffer).unwrap();
|
|
|
|
loop {
|
|
let avail = transfer.available();
|
|
if avail >= working_buffer.len() {
|
|
// Fill working buffer
|
|
let mut i = 0;
|
|
while i<working_buffer.len()-3 {
|
|
let sample: [u8; 2] = wav_tbl[phase as usize].to_ne_bytes();
|
|
phase = (phase + phase_delta) % (wav_tbl.len() as f32);
|
|
working_buffer[i..i+2].copy_from_slice(&sample);
|
|
i += 2;
|
|
working_buffer[i..i+2].copy_from_slice(&sample);
|
|
i += 2;
|
|
}
|
|
|
|
// write buffer
|
|
transfer.push(&working_buffer).unwrap();
|
|
}
|
|
}
|
|
|
|
/*
|
|
let mut transfer = i2s_rx.read_dma_circular(buffer).unwrap();
|
|
println!("Started transfer");
|
|
|
|
loop {
|
|
let avail = transfer.available();
|
|
|
|
if avail > 0 {
|
|
let mut rcv = [0u8; 5000];
|
|
transfer.pop(&mut rcv[..avail]).unwrap();
|
|
println!("Received {:x?}...", &rcv[..30]);
|
|
}
|
|
}
|
|
|
|
loop {
|
|
println!("Loop...");
|
|
delay.delay_ms(500u32);
|
|
}
|
|
*/
|
|
}
|
|
|
|
// struct SinGeni16 {
|
|
// phase: f32,
|
|
// lut: &[i16],
|
|
// }
|
|
// impl SinGeni16 {
|
|
// fn new(wave_table: &[i16]) -> Self {Self { phase: 0.0, lut: wave_table }}
|
|
// fn fill_buffer(&mut self, freq: f32, buffer: &mut [u8]) -> Option<()> {
|
|
// // buffer must be aligned for sterio i16 samples
|
|
// if buffer.len() % 4 != 0 {
|
|
// return None;
|
|
// }
|
|
// let phase_delta = (freq / RATE as f32) * TBL_LEN as f32;
|
|
// let mut i = 0;
|
|
// while i+3 < buffer.len() {
|
|
// let sample: [u8; 2] = self.lut[self.phase as usize].as_ne_bytes();
|
|
// self.phase = (phase + phase_delta) % (self.lut.len() as f32);
|
|
|
|
// buffer[i..i+2].copy_from_slice(&sample);
|
|
// buffer[i+2..i+4].copy_from_slice(&sample);
|
|
|
|
// i+=4;
|
|
// }
|
|
// Some(())
|
|
// }
|
|
// }
|