mirror of https://github.com/radex/radmatrix.git
audio from sd
parent
111700b0e9
commit
cd49ebf186
|
@ -13,7 +13,5 @@ platform = raspberrypi
|
|||
board = pico
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
fastled/FastLED@^3.6.0
|
||||
; arduino-libraries/SD@^1.2.4
|
||||
khoih-prog/RP2040_SD@^1.0.1
|
||||
|
||||
|
|
|
@ -55,3 +55,10 @@ with open("src/audio_sample.h", "w") as f:
|
|||
f.write(m68code)
|
||||
|
||||
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/sync.h" // wait for interrupt
|
||||
#include "hardware/gpio.h"
|
||||
#include "audio.h"
|
||||
|
||||
#include "audio_sample.h"
|
||||
// #include "audio_sample.h"
|
||||
|
||||
// Adapted from https://github.com/rgrosset/pico-pwm-audio
|
||||
|
||||
#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
|
||||
|
@ -21,21 +29,23 @@ int wav_position = 0;
|
|||
*/
|
||||
void pwm_interrupt_handler() {
|
||||
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
|
||||
// allow the pwm value to repeat for 8 cycles this is >>3
|
||||
pwm_set_gpio_level(AUDIO_PIN, WAV_DATA[wav_position>>3]);
|
||||
wav_position++;
|
||||
pwm_set_gpio_level(AUDIO_PIN, wav_buffer[pwm_position>>3]);
|
||||
pwm_position++;
|
||||
} else {
|
||||
// reset to start
|
||||
wav_position = 0;
|
||||
// reset to start, flip to other buffer
|
||||
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
|
||||
#define SYS_CLOCK 125000000.0f
|
||||
#define AUDIO_WRAP 250.0f
|
||||
#define AUDIO_RATE 11000.0f
|
||||
#define AUDIO_CLK_DIV (SYS_CLOCK / AUDIO_WRAP / 8 / AUDIO_RATE)
|
||||
|
||||
void init_audio() {
|
||||
|
@ -49,7 +59,7 @@ void init_audio() {
|
|||
|
||||
// set the handle function above
|
||||
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
|
||||
pwm_config config = pwm_get_default_config();
|
||||
|
@ -60,3 +70,17 @@ void init_audio() {
|
|||
|
||||
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 audio_stop();
|
||||
void audio_start();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -75,6 +75,8 @@ void setup() {
|
|||
|
||||
setupSD();
|
||||
|
||||
sd_getAudio();
|
||||
|
||||
return;
|
||||
|
||||
memset(framebuffer, 0, sizeof(framebuffer));
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <Arduino.h>
|
||||
#include <RP2040_SD.h>
|
||||
#include <SPI.h>
|
||||
#include <RP2040_SD.h>
|
||||
#include "sd.h"
|
||||
#include "audio.h"
|
||||
|
||||
#define SD_DET_PIN 28
|
||||
|
||||
|
@ -39,22 +41,23 @@ void printDirectory(File dir, int numTabs);
|
|||
void setupSD() {
|
||||
SPI.begin();
|
||||
|
||||
printSDConfig();
|
||||
// printSDConfig();
|
||||
|
||||
if (!SD.begin(PIN_SPI_SS)) {
|
||||
Serial.println("SD Initialization failed!");
|
||||
// Serial.print("Error code: ");
|
||||
// Serial.println(SD.card.errorCode(), HEX);
|
||||
while (true) {}
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("SD Initialization done");
|
||||
|
||||
testSDCard();
|
||||
// testSDCard();
|
||||
// printSDStats(SD.volume);
|
||||
|
||||
File root = SD.open("/");
|
||||
printDirectory(root, 0);
|
||||
// File root = SD.open("/");
|
||||
// printDirectory(root, 0);
|
||||
}
|
||||
|
||||
void printSDConfig() {
|
||||
|
@ -151,3 +154,54 @@ void printSDStats(RP2040_SdVolume volume) {
|
|||
Serial.print("Volume size (GB): ");
|
||||
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 setupSD();
|
||||
|
||||
bool isSDCardInserted();
|
||||
|
||||
void sd_getAudio();
|
||||
|
|
Loading…
Reference in New Issue