mirror of https://github.com/radex/radmatrix.git
audio from sd
parent
111700b0e9
commit
cd49ebf186
|
@ -13,7 +13,5 @@ platform = raspberrypi
|
||||||
board = pico
|
board = pico
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
fastled/FastLED@^3.6.0
|
|
||||||
; arduino-libraries/SD@^1.2.4
|
|
||||||
khoih-prog/RP2040_SD@^1.0.1
|
khoih-prog/RP2040_SD@^1.0.1
|
||||||
|
|
||||||
|
|
|
@ -55,3 +55,10 @@ with open("src/audio_sample.h", "w") as f:
|
||||||
f.write(m68code)
|
f.write(m68code)
|
||||||
|
|
||||||
print("done!")
|
print("done!")
|
||||||
|
|
||||||
|
print("writing blob...")
|
||||||
|
|
||||||
|
with open("audio/audio.bin", "wb") as f:
|
||||||
|
f.write(bytes(normalized))
|
||||||
|
|
||||||
|
print("done!")
|
||||||
|
|
|
@ -3,13 +3,21 @@
|
||||||
#include "hardware/pwm.h" // pwm
|
#include "hardware/pwm.h" // pwm
|
||||||
#include "hardware/sync.h" // wait for interrupt
|
#include "hardware/sync.h" // wait for interrupt
|
||||||
#include "hardware/gpio.h"
|
#include "hardware/gpio.h"
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
#include "audio_sample.h"
|
// #include "audio_sample.h"
|
||||||
|
|
||||||
// Adapted from https://github.com/rgrosset/pico-pwm-audio
|
// Adapted from https://github.com/rgrosset/pico-pwm-audio
|
||||||
|
|
||||||
#define AUDIO_PIN 23
|
#define AUDIO_PIN 23
|
||||||
int wav_position = 0;
|
|
||||||
|
#define MAX_PWM_POS (BUFFER_LEN << 3)
|
||||||
|
|
||||||
|
uint8_t wav_buffer_0[BUFFER_LEN] = {0};
|
||||||
|
uint8_t wav_buffer_1[BUFFER_LEN] = {0};
|
||||||
|
bool wav_buffer1_active = false;
|
||||||
|
volatile bool next_buffer_requested = false; // horrible, use some interrupt-based solution or at least locks or whatever
|
||||||
|
uint32_t pwm_position = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PWM Interrupt Handler which outputs PWM level and advances the
|
* PWM Interrupt Handler which outputs PWM level and advances the
|
||||||
|
@ -21,21 +29,23 @@ int wav_position = 0;
|
||||||
*/
|
*/
|
||||||
void pwm_interrupt_handler() {
|
void pwm_interrupt_handler() {
|
||||||
pwm_clear_irq(pwm_gpio_to_slice_num(AUDIO_PIN));
|
pwm_clear_irq(pwm_gpio_to_slice_num(AUDIO_PIN));
|
||||||
if (wav_position < (WAV_DATA_LENGTH<<3) - 1) {
|
if (pwm_position < MAX_PWM_POS - 1) {
|
||||||
|
auto wav_buffer = wav_buffer1_active ? wav_buffer_1 : wav_buffer_0;
|
||||||
// set pwm level
|
// set pwm level
|
||||||
// allow the pwm value to repeat for 8 cycles this is >>3
|
// allow the pwm value to repeat for 8 cycles this is >>3
|
||||||
pwm_set_gpio_level(AUDIO_PIN, WAV_DATA[wav_position>>3]);
|
pwm_set_gpio_level(AUDIO_PIN, wav_buffer[pwm_position>>3]);
|
||||||
wav_position++;
|
pwm_position++;
|
||||||
} else {
|
} else {
|
||||||
// reset to start
|
// reset to start, flip to other buffer
|
||||||
wav_position = 0;
|
pwm_position = 0;
|
||||||
|
next_buffer_requested = true;
|
||||||
|
wav_buffer1_active = !wav_buffer1_active;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 11 KHz is fine for speech. Phone lines generally sample at 8 KHz
|
// 11 KHz is fine for speech. Phone lines generally sample at 8 KHz
|
||||||
#define SYS_CLOCK 125000000.0f
|
#define SYS_CLOCK 125000000.0f
|
||||||
#define AUDIO_WRAP 250.0f
|
#define AUDIO_WRAP 250.0f
|
||||||
#define AUDIO_RATE 11000.0f
|
|
||||||
#define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8 / AUDIO_RATE)
|
#define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8 / AUDIO_RATE)
|
||||||
|
|
||||||
void init_audio() {
|
void init_audio() {
|
||||||
|
@ -49,7 +59,7 @@ void init_audio() {
|
||||||
|
|
||||||
// set the handle function above
|
// set the handle function above
|
||||||
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_interrupt_handler);
|
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_interrupt_handler);
|
||||||
irq_set_enabled(PWM_IRQ_WRAP, true);
|
// irq_set_enabled(PWM_IRQ_WRAP, true);
|
||||||
|
|
||||||
// Setup PWM for audio output
|
// Setup PWM for audio output
|
||||||
pwm_config config = pwm_get_default_config();
|
pwm_config config = pwm_get_default_config();
|
||||||
|
@ -60,3 +70,17 @@ void init_audio() {
|
||||||
|
|
||||||
pwm_set_gpio_level(AUDIO_PIN, 0);
|
pwm_set_gpio_level(AUDIO_PIN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void audio_stop() {
|
||||||
|
Serial.println("audio_stop");
|
||||||
|
irq_set_enabled(PWM_IRQ_WRAP, false);
|
||||||
|
pwm_set_gpio_level(AUDIO_PIN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_start() {
|
||||||
|
Serial.println("audio_start");
|
||||||
|
audio_stop();
|
||||||
|
pwm_position = 0;
|
||||||
|
wav_buffer1_active = false;
|
||||||
|
irq_set_enabled(PWM_IRQ_WRAP, true);
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef _audio_h
|
||||||
|
#define _audio_h
|
||||||
|
|
||||||
|
#define AUDIO_RATE 11000.0f
|
||||||
|
#define BUFFER_LEN 8192
|
||||||
|
#define BUFFER_LEN_MS (BUFFER_LEN / AUDIO_RATE) * 1000.0f
|
||||||
|
|
||||||
|
extern uint8_t wav_buffer_0[BUFFER_LEN];
|
||||||
|
extern uint8_t wav_buffer_1[BUFFER_LEN];
|
||||||
|
extern bool wav_buffer1_active;
|
||||||
|
extern volatile bool next_buffer_requested;
|
||||||
|
|
||||||
void init_audio();
|
void init_audio();
|
||||||
|
void audio_stop();
|
||||||
|
void audio_start();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -75,6 +75,8 @@ void setup() {
|
||||||
|
|
||||||
setupSD();
|
setupSD();
|
||||||
|
|
||||||
|
sd_getAudio();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(framebuffer, 0, sizeof(framebuffer));
|
memset(framebuffer, 0, sizeof(framebuffer));
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <RP2040_SD.h>
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
#include <RP2040_SD.h>
|
||||||
|
#include "sd.h"
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
#define SD_DET_PIN 28
|
#define SD_DET_PIN 28
|
||||||
|
|
||||||
|
@ -39,22 +41,23 @@ void printDirectory(File dir, int numTabs);
|
||||||
void setupSD() {
|
void setupSD() {
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
|
|
||||||
printSDConfig();
|
// printSDConfig();
|
||||||
|
|
||||||
if (!SD.begin(PIN_SPI_SS)) {
|
if (!SD.begin(PIN_SPI_SS)) {
|
||||||
Serial.println("SD Initialization failed!");
|
Serial.println("SD Initialization failed!");
|
||||||
// Serial.print("Error code: ");
|
// Serial.print("Error code: ");
|
||||||
// Serial.println(SD.card.errorCode(), HEX);
|
// Serial.println(SD.card.errorCode(), HEX);
|
||||||
|
while (true) {}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("SD Initialization done");
|
Serial.println("SD Initialization done");
|
||||||
|
|
||||||
testSDCard();
|
// testSDCard();
|
||||||
// printSDStats(SD.volume);
|
// printSDStats(SD.volume);
|
||||||
|
|
||||||
File root = SD.open("/");
|
// File root = SD.open("/");
|
||||||
printDirectory(root, 0);
|
// printDirectory(root, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printSDConfig() {
|
void printSDConfig() {
|
||||||
|
@ -151,3 +154,54 @@ void printSDStats(RP2040_SdVolume volume) {
|
||||||
Serial.print("Volume size (GB): ");
|
Serial.print("Volume size (GB): ");
|
||||||
Serial.println((float)volumesize / 1024.0);
|
Serial.println((float)volumesize / 1024.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File file;
|
||||||
|
|
||||||
|
void sd_getAudio() {
|
||||||
|
if (!SD.exists("/badapple/audio.bin")) {
|
||||||
|
Serial.println("Audio not found :(");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
file = SD.open("/badapple/audio.bin", FILE_READ);
|
||||||
|
Serial.println("Audio file opened");
|
||||||
|
|
||||||
|
audio_stop();
|
||||||
|
|
||||||
|
// load two buffers' worth of audio
|
||||||
|
if (file.read(&wav_buffer_0, BUFFER_LEN) < BUFFER_LEN) {
|
||||||
|
Serial.println("Could not read first sample");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.read(&wav_buffer_1, BUFFER_LEN) < BUFFER_LEN) {
|
||||||
|
Serial.println("Could not read second sample");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!next_buffer_requested) {
|
||||||
|
delay(50);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
next_buffer_requested = false;
|
||||||
|
|
||||||
|
auto next_buffer = wav_buffer1_active ? &wav_buffer_0 : &wav_buffer_1;
|
||||||
|
auto bytesRead = file.read(next_buffer, BUFFER_LEN);
|
||||||
|
|
||||||
|
if (bytesRead < BUFFER_LEN) {
|
||||||
|
Serial.println("End of audio file");
|
||||||
|
file.seek(0);
|
||||||
|
} else {
|
||||||
|
Serial.print("Read ");
|
||||||
|
Serial.print(bytesRead);
|
||||||
|
Serial.println(" bytes from audio file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
void setupSDPins();
|
void setupSDPins();
|
||||||
void setupSD();
|
void setupSD();
|
||||||
|
|
||||||
bool isSDCardInserted();
|
bool isSDCardInserted();
|
||||||
|
|
||||||
|
void sd_getAudio();
|
||||||
|
|
Loading…
Reference in New Issue