diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d899f65 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.wav filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 438602a..e1bb5ff 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -49,6 +49,8 @@ jobs: libraries: | # Install the library from the local path. - source-path: ./ + - source-url: https://github.com/facchinm/USBHostMbed5.git + version: test_hs_in_fs sketch-paths: | - examples enable-deltas-report: true diff --git a/examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav b/examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav new file mode 100644 index 0000000..0e956d9 --- /dev/null +++ b/examples/Beginner/Audio_Playback/AUDIO_SAMPLE.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c17298498cf2a99c95f8dcf246691be4852eaddf8da24268b62854e0056c796 +size 1426086 diff --git a/examples/Beginner/Audio_Playback/Audio_Playback.ino b/examples/Beginner/Audio_Playback/Audio_Playback.ino new file mode 100644 index 0000000..a860e43 --- /dev/null +++ b/examples/Beginner/Audio_Playback/Audio_Playback.ino @@ -0,0 +1,157 @@ +/* + * GIGA R1 - Audio Playback + * Simple wav format audio playback via 12-Bit DAC output by reading from a USB drive. + * In order for this sketch to work you need to rename 'USB_DRIVE' to the name of your USB stick drive. + * Furthermore you need to store the provided audio file AUDIO_SAMPLE.wav on it. +*/ + +#include <Arduino_AdvancedAnalog.h> +#include <DigitalOut.h> +#include <USBHostMbed5.h> +#include <FATFileSystem.h> + +AdvancedDAC dac1(A12); + +USBHostMSD msd; +mbed::FATFileSystem usb("USB_DRIVE"); + +FILE * file = nullptr; +int sample_size = 0; +int samples_count = 0; + + +void setup() +{ + Serial.begin(115200); + 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 GIGA's USB 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); + return; + } + + Serial.println("Opening audio file ..."); + + /* 16-bit PCM Mono 16kHz realigned noise reduction */ + file = fopen("/USB_DRIVE/AUDIO_SAMPLE.wav", "rb"); + if (file == nullptr) + { + Serial.print("Error opening audio file: "); + Serial.println(strerror(errno)); + return; + } + + Serial.println("Reading audio header ..."); + struct wav_header_t + { + char chunkID[4]; //"RIFF" = 0x46464952 + unsigned long chunkSize; //28 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + sum(sizeof(chunk.id) + sizeof(chunk.size) + chunk.size) + char format[4]; //"WAVE" = 0x45564157 + char subchunk1ID[4]; //"fmt " = 0x20746D66 + unsigned long subchunk1Size; //16 [+ sizeof(wExtraFormatBytes) + wExtraFormatBytes] + unsigned short audioFormat; + unsigned short numChannels; + unsigned long sampleRate; + unsigned long byteRate; + unsigned short blockAlign; + unsigned short bitsPerSample; + }; + + wav_header_t header; + fread(&header, sizeof(header), 1, file); + + Serial.println("WAV File Header read:"); + char msg[64] = {0}; + snprintf(msg, sizeof(msg), "File Type: %s", header.chunkID); + Serial.println(msg); + snprintf(msg, sizeof(msg), "File Size: %ld", header.chunkSize); + Serial.println(msg); + snprintf(msg, sizeof(msg), "WAV Marker: %s", header.format); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Format Name: %s", header.subchunk1ID); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Format Length: %ld", header.subchunk1Size); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Format Type: %hd", header.audioFormat); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Number of Channels: %hd", header.numChannels); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Sample Rate: %ld", header.sampleRate); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Sample Rate * Bits/Sample * Channels / 8: %ld", header.byteRate); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Bits per Sample * Channels / 8: %hd", header.blockAlign); + Serial.println(msg); + snprintf(msg, sizeof(msg), "Bits per Sample: %hd", header.bitsPerSample); + Serial.println(msg); + + /* Find the data section of the WAV file. */ + struct chunk_t + { + char ID[4]; + unsigned long size; + }; + + chunk_t chunk; + snprintf(msg, sizeof(msg), "id\t" "size"); + Serial.println(msg); + /* Find data chunk. */ + while (true) + { + fread(&chunk, sizeof(chunk), 1, file); + snprintf(msg, sizeof(msg), "%c%c%c%c\t" "%li", chunk.ID[0], chunk.ID[1], chunk.ID[2], chunk.ID[3], chunk.size); + Serial.println(msg); + if (*(unsigned int *) &chunk.ID == 0x61746164) + break; + /* Skip chunk data bytes. */ + fseek(file, chunk.size, SEEK_CUR); + } + + /* Determine number of samples. */ + sample_size = header.bitsPerSample / 8; + samples_count = chunk.size * 8 / header.bitsPerSample; + snprintf(msg, sizeof(msg), "Sample size = %i", sample_size); Serial.println(msg); + snprintf(msg, sizeof(msg), "Samples count = %i", samples_count); Serial.println(msg); + + /* Configure the advanced DAC. */ + if (!dac1.begin(AN_RESOLUTION_12, header.sampleRate, 256, 16)) + { + Serial.println("Failed to start DAC1 !"); + return; + } +} + +void loop() +{ + if (dac1.available() && !feof(file)) + { + /* Read data from file. */ + uint16_t sample_data[256] = {0}; + fread(sample_data, sample_size, 256, file); + + /* Get a free buffer for writing. */ + SampleBuffer buf = dac1.dequeue(); + + /* Write data to buffer. */ + for (size_t i = 0; i < buf.size(); i++) + { + /* Scale down to 12 bit. */ + uint16_t const dac_val = ((static_cast<unsigned int>(sample_data[i])+32768)>>4) & 0x0fff; + buf[i] = dac_val; + } + + /* Write the buffer to DAC. */ + dac1.write(buf); + } +} diff --git a/src/AdvancedADC.h b/src/AdvancedADC.h index 044a2ac..647250b 100644 --- a/src/AdvancedADC.h +++ b/src/AdvancedADC.h @@ -21,6 +21,9 @@ #include "DMABuffer.h" #include "AdvancedAnalog.h" +#ifndef ARDUINO_ADVANCED_ADC_H_ +#define ARDUINO_ADVANCED_ADC_H_ + struct adc_descr_t; class AdvancedADC { @@ -45,3 +48,5 @@ class AdvancedADC { int begin(uint32_t resolution, uint32_t sample_rate, size_t n_samples, size_t n_buffers); int stop(); }; + +#endif /* ARDUINO_ADVANCED_ADC_H_ */ diff --git a/src/AdvancedDAC.h b/src/AdvancedDAC.h index 679e292..57707ee 100644 --- a/src/AdvancedDAC.h +++ b/src/AdvancedDAC.h @@ -21,6 +21,9 @@ #include "DMABuffer.h" #include "AdvancedAnalog.h" +#ifndef ARDUINO_ADVANCED_DAC_H_ +#define ARDUINO_ADVANCED_DAC_H_ + struct dac_descr_t; class AdvancedDAC { @@ -47,3 +50,5 @@ class AdvancedDAC { int begin(uint32_t resolution, uint32_t frequency, size_t n_samples=0, size_t n_buffers=0); int stop(); }; + +#endif /* ARDUINO_ADVANCED_DAC_H_ */