2023-11-15 21:22:06 -05:00

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(())
// }
// }