Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AdvancedI2S: Add I2S input, output and full-duplex support. #58

Merged
merged 2 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions examples/Advanced/I2S_DAC_Output/I2S_DAC_Output.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// This example demonstrates how to capture samples from an I2S mic,
// and output them on a DAC.

#include <Arduino_AdvancedAnalog.h>

AdvancedDAC dac1(A12);
// WS, CK, SDI, SDO, MCK
AdvancedI2S i2s(PG_10, PG_11, PG_9, PB_5, PC_4);

#define N_SAMPLES (256)
#define SAMPLE_AVERAGE(s0, s1) (((int16_t) s0 / 2) + ((int16_t) s1 / 2))

void setup() {
Serial.begin(9600);
while (!Serial) {
}

// Resolution, sample rate, number of samples per channel, queue depth.
if (!dac1.begin(AN_RESOLUTION_12, 32000, N_SAMPLES, 32)) {
Serial.println("Failed to start DAC1 !");
while (1);
}

// I2S mode, sample rate, number of samples per channel, queue depth.
if (!i2s.begin(AN_I2S_MODE_IN, 32000, N_SAMPLES, 32)) {
Serial.println("Failed to start I2S");
while (1);
}
}

void loop() {
if (i2s.available() && dac1.available()) {
SampleBuffer i2sbuf = i2s.read();
SampleBuffer dacbuf = dac1.dequeue();

// Write data to buffer.
for (int i=0; i<dacbuf.size(); i++) {
// Average the 2 samples, map to positive and down scale to 12-bit.
// Note that I2S always captures 2 channels.
dacbuf[i] = ((uint32_t) (SAMPLE_AVERAGE(i2sbuf[(i * 2)], i2sbuf[(i * 2) + 1]) + 32768)) >> 4;
}

// Write the buffer to DAC.
dac1.write(dacbuf);
i2sbuf.release();
}
}
32 changes: 32 additions & 0 deletions examples/Advanced/I2S_Full_Duplex/I2S_Full_Duplex.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This example demonstrates I2S in full-duplex mode. In the main loop, samples
// are continuously captured from the I2S input, and written back to I2S output.

#include <Arduino_AdvancedAnalog.h>

// WS, CK, SDI, SDO, MCK
AdvancedI2S i2s(PG_10, PG_11, PG_9, PB_5, PC_4);

void setup() {
Serial.begin(9600);
while (!Serial) {

}

// Resolution, sample rate, number of samples per channel, queue depth.
if (!i2s.begin(AN_I2S_MODE_INOUT, 32000, 512, 32)) {
Serial.println("Failed to start I2S");
while (1);
}
}

void loop() {
if (i2s.available()) {
SampleBuffer rxbuf = i2s.read();
SampleBuffer txbuf = i2s.dequeue();
for (size_t i=0; i<rxbuf.size(); i++) {
txbuf[i] = rxbuf[i];
}
rxbuf.release();
i2s.write(txbuf);
}
}
3 changes: 3 additions & 0 deletions examples/Beginner/Audio_Playback_I2S/AUDIO_SAMPLE.wav
Git LFS file not shown
80 changes: 80 additions & 0 deletions examples/Beginner/Audio_Playback_I2S/Audio_Playback_I2S.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// This example demonstrates how to playback a WAV file with I2S.
// To run this sketch, rename 'USB_DRIVE' to the name of your USB
// stick drive, and copy the provided audio sample to the drive.
#include <Arduino_AdvancedAnalog.h>
#include <Arduino_USBHostMbed5.h>
#include <FATFileSystem.h>
#include <DigitalOut.h>
#include <WavReader.h>

USBHostMSD msd;
mbed::FATFileSystem usb("USB_DRIVE");

WavReader wav;
// WS, CK, SDI, SDO, MCK
AdvancedI2S i2s(PG_10, PG_11, PG_9, PB_5, PC_4);
#define N_SAMPLES (512)

void setup() {
Serial.begin(9600);
while (!Serial) {

}

// Enable power for HOST USB connector.
pinMode(PA_15, OUTPUT);
digitalWrite(PA_15, HIGH);

Serial.println("Please connect a USB stick to the USB host port...");
while (!msd.connect()) {
delay(100);
}

Serial.println("Mounting USB device...");
int const rc_mount = usb.mount(&msd);
if (rc_mount) {
Serial.print("Error mounting USB device ");
Serial.println(rc_mount);
while (1);
}

Serial.println("Opening audio file ...");
if (!wav.begin("/USB_DRIVE/AUDIO_SAMPLE.wav", N_SAMPLES, 1, true)) {
Serial.print("Error opening audio file: ");
while (1);
}

// Resolution, sample rate, number of samples per channel, queue depth.
if (!i2s.begin(AN_I2S_MODE_OUT, wav.sample_rate(), N_SAMPLES, 64)) {
Serial.println("Failed to start I2S");
while (1);
}
Serial.println("Playing audio file ...");
}

void loop() {
if (i2s.available() && wav.available()) {
// Get a free I2S buffer for writing.
SampleBuffer i2s_buf = i2s.dequeue();

// Read a PCM samples buffer from the wav file.
SampleBuffer pcm_buf = wav.read();

// Write PCM samples to the I2S buffer.
for (size_t i = 0; i < N_SAMPLES * wav.channels(); i++) {
// Note I2S buffers are always 2 channels.
if (wav.channels() == 2) {
i2s_buf[i] = pcm_buf[i];
} else {
i2s_buf[(i * 2) + 0] = ((int16_t) pcm_buf[i] / 2);
i2s_buf[(i * 2) + 1] = ((int16_t) pcm_buf[i] / 2);
}
}

// Write back the I2S buffer.
i2s.write(i2s_buf);

// Release the PCM buffer.
pcm_buf.release();
}
}
Loading
Loading