From ad035e69e226b4c2e7a77216517709ad4c4e8350 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 24 Jun 2025 01:28:47 +0200 Subject: [PATCH] dma and pointer optimization, but still no luck --- soundcube-firmware/ringbuffer.h | 24 ++ soundcube-firmware/soundcube-firmware.ino | 317 +++++++++++----------- soundcube-firmware/wavestream.h | 50 +++- 3 files changed, 225 insertions(+), 166 deletions(-) diff --git a/soundcube-firmware/ringbuffer.h b/soundcube-firmware/ringbuffer.h index 9e8eff7..8b78b68 100644 --- a/soundcube-firmware/ringbuffer.h +++ b/soundcube-firmware/ringbuffer.h @@ -34,6 +34,20 @@ class RingBuffer{ } return retval; } + + int16_t* getReadPointer(){ + return &buffer[read]; + } + + void pointerPop(int nbytes){ + for(int i=0; i 0) { + counter--; + read++;// % bufferSize; + if(read == bufferSize) read = 0; + } + } + } void pushDMA(int32_t *source){ if(counter < bufferSize){ @@ -47,6 +61,16 @@ class RingBuffer{ void* getWritePointer(){ return &buffer[write]; } + + void advance(int nbytes){ + for(int i = 0; i < nbytes/2; ++i){ + if(counter < bufferSize){ + write++; // % bufferSize; + if(write == bufferSize) write = 0; + counter++; + } + } + } void popDMA(int32_t *target){ if(counter > 0) { diff --git a/soundcube-firmware/soundcube-firmware.ino b/soundcube-firmware/soundcube-firmware.ino index d60a030..22fc9d0 100644 --- a/soundcube-firmware/soundcube-firmware.ino +++ b/soundcube-firmware/soundcube-firmware.ino @@ -8,7 +8,7 @@ #define FASTLED_FORCE_SOFTWARE_SPI #include -//#include +#include #include #include #include @@ -22,7 +22,7 @@ bool core1_disable_systick = true; #define AURAL 1 #define UI_SAMPLERATE 22050 -#define BUFFERSIZE 32 +#define BUFFERSIZE 64 #define NSTREAMS 16 I2S i2s(INPUT_PULLUP); @@ -38,7 +38,7 @@ AS5600 ENC(&Wire1); DAC8552 dac(9, &SPI1); -//PWMAudio ui_snd(8); +PWMAudio ui_snd(8); CRGB ui_leds[74]; CRGB edge_leds[11]; @@ -71,6 +71,8 @@ volatile bool setup1_finished = false; volatile bool buttonChanged = false; volatile bool sdInitialized = false; +volatile bool wire_ready = false; + volatile bool ui_click = false; volatile bool ui_beep = false; bool amp = false; @@ -170,14 +172,23 @@ void codec_transmit() { for(int i = 0; i < count; i+=2){ if(streams_loaded){ for(int k = 0; k < NSTREAMS; k++){ - int32_t twosamples; - stream[k].wavefile.buffer.popDMA(&twosamples); + //int32_t twosamples; + int16_t twosamples[2]; + stream[k].getDMA((int32_t*)&twosamples); - int16_t sample_l = sample_l = twosamples >> 16; - int16_t sample_r = sample_r = twosamples & 0xFFFF; - - buffer[i] += sample_l >> 3; - buffer[i+1] += sample_r >> 3; + int16_t sample_l = twosamples[0];// >> 16; + int16_t sample_r = twosamples[1];// & 0xFFFF; + + // int16_t *sample_l = stream[k].wavefile.buffer.getReadPointer(); //twosamples >> 16; + // stream[k].wavefile.buffer.pointerPop(2); + // int16_t *sample_r = stream[k].wavefile.buffer.getReadPointer(); //twosamples & 0xFFFF; + // stream[k].wavefile.buffer.pointerPop(2); + + // buffer[i] += (*sample_l / 16); + // buffer[i+1] += (*sample_r / 16); + + buffer[i] += (sample_l / 16); + buffer[i+1] += (sample_r / 16); } } } @@ -191,33 +202,33 @@ void codec_receive(){ } } -// void pwm_audio_callback() { -// while (ui_snd.availableForWrite()) { -// if(ui_click || ui_beep) { -// if(ui_beep) { -// ui_snd.write(ui_beep_snd[counter]); -// counter++; -// if(counter == beep_length) { -// counter = 0; -// ui_beep = false; -// } -// continue; -// } -// if(ui_click) { -// ui_snd.write(ui_click_snd[counter]); -// counter++; -// if(counter == click_length) { -// counter = 0; -// ui_click = false; -// } -// } -// } else { -// digitalWrite(7, LOW); -// ui_snd.write(0); -// counter = 0; -// } -// } -// } +void pwm_audio_callback() { + while (ui_snd.availableForWrite()) { + if(ui_click || ui_beep) { + if(ui_beep) { + ui_snd.write(ui_beep_snd[counter]); + counter++; + if(counter == beep_length) { + counter = 0; + ui_beep = false; + } + continue; + } + if(ui_click) { + ui_snd.write(ui_click_snd[counter]); + counter++; + if(counter == click_length) { + counter = 0; + ui_click = false; + } + } + } else { + digitalWrite(7, LOW); + ui_snd.write(0); + counter = 0; + } + } +} bool load_ui_sounds(const char* file, int16_t *buffer, uint16_t &length){ if(SD.exists(file)) { @@ -338,123 +349,34 @@ Vibration vibration; void setup() { i2s.setSysClk(48000); - Serial.begin(); - - while(!codec_ready){ - Serial.println("0: Waiting for codec"); - delay(250); - } - - // i2s.onTransmit(codec_transmit); - // i2s.onReceive(codec_receive); - - i2s.setDOUT(15); - i2s.setDIN(14); - i2s.setBCLK(16); // Note: LRCLK = BCLK + 1 - i2s.setMCLK(18); - i2s.setMCLKmult(512); // 256 = 12.288.000Hz 512 = 25MHz - i2s.swapClocks(); - - i2s.setFrequency(48000); - i2s.setBitsPerSample(16); - - i2s.setBuffers(6, BUFFERSIZE * sizeof(int16_t) / sizeof(uint32_t)); - - if(!i2s.begin(48000)){ - Serial.println("0: I2S error!"); - while(100); - } - Serial.println("0: I2S OK"); - - delay(100); - - i2s_ready = true; - - pinMode(12, OUTPUT); // speaker enable l - pinMode(13, OUTPUT); // speaker enable r - speaker(false); - - pinMode(21, INPUT_PULLUP); - sd_card_detected = !digitalRead(21); delay(500); - - while(!sdInitialized){ - sdInitialized = SD.begin(22, 23, 24); - delay(250); - Serial.println("0: Initializing SD Card"); - } - - if(sdInitialized) loadConfiguration(config); - - // if(sdInitialized){ - // load_ui_sounds("/ui/click.wav", ui_click_snd, click_length); - // load_ui_sounds("/ui/beep.wav", ui_beep_snd, beep_length); - // } - config_loaded = true; - - if(sdInitialized) { - streams_loaded = load_samples(); - } - - if(streams_loaded) { - for(int i = 0; i < NSTREAMS; i++){ - samples[i].file = &stream[i]; - } - } - - Serial.print("0: STARTUP COMPLETE"); - - digitalWrite(6, HIGH); - delay(25); - digitalWrite(6, LOW); - setup0_finished = true; -} - -void setup1(){ - Serial.print("1: ENABLE I2S MCLK: "); - pinMode(19, OUTPUT); // MCLK enable - digitalWrite(19, HIGH); // enable MCLK - Serial.println("SUCCESS"); - delay(100); - - Serial.print("1: ENABLE CODEC: "); - pinMode(20, OUTPUT); // CODEC reset (enable) - digitalWrite(20, HIGH); - Serial.println("SUCCESS"); - delay(100); - - Serial.print("1: STARTUP"); - Serial.print("1: INIT WIRE: "); Wire1.setSDA(2); Wire1.setSCL(3); Wire1.begin(); Serial.println("SUCCESS"); - delay(100); - Serial.print("1: INIT CODEC: "); - codec.begin(&Wire1); - Serial.println("SUCCESS"); - delay(500); - - codec_ready = true; + wire_ready = true; Serial.print("1: INIT SPI: "); SPI1.setSCK(10); SPI1.setTX(11); SPI1.begin(); Serial.println("SUCCESS"); - - Serial.print("1: INIT DAC: "); - dac.begin(); + delay(100); + + Serial.print("1: ENABLE CODEC: "); + pinMode(20, OUTPUT); // CODEC reset (enable) + digitalWrite(20, HIGH); + Serial.println("SUCCESS"); + + Serial.print("1: ENABLE I2S MCLK: "); + pinMode(19, OUTPUT); // MCLK enable + digitalWrite(19, HIGH); // enable MCLK Serial.println("SUCCESS"); - - while(!config_loaded){ - delay(250); - Serial.println("1: Waiting for config"); - } + Serial.print("1: STARTUP"); Serial.print("1: INIT TCA: "); TCA.begin(); @@ -473,6 +395,9 @@ void setup1(){ ENC.resetCumulativePosition(); Serial.println("SUCCESS"); + Serial.print("1: INIT DAC: "); + dac.begin(); + Serial.println("SUCCESS"); pinMode(6, OUTPUT); // Vibration Motor pinMode(7, OUTPUT); // UI Amp Enable @@ -486,12 +411,89 @@ void setup1(){ FastLED.addLeds(edge_leds, 11); FastLED.addLeds(ui_leds, 74); Serial.println("SUCCESS"); - + Serial.print("1: STARTUP COMPLETE"); setup1_finished = true; digitalWrite(6, HIGH); delay(25); digitalWrite(6, LOW); + Serial.begin(); + + Serial.print("0: INIT CODEC: "); + codec.begin(&Wire1); + Serial.println("SUCCESS"); + + codec_ready = true; + + pinMode(12, OUTPUT); // speaker enable l + pinMode(13, OUTPUT); // speaker enable r + speaker(false); + + pinMode(21, INPUT_PULLUP); + sd_card_detected = !digitalRead(21); + delay(500); + + while(!sdInitialized){ + sdInitialized = SD.begin(22, 23, 24); + delay(250); + Serial.println("0: Initializing SD Card"); + } + + if(sdInitialized) loadConfiguration(config); + + if(sdInitialized){ + load_ui_sounds("/ui/click.wav", ui_click_snd, click_length); + load_ui_sounds("/ui/beep.wav", ui_beep_snd, beep_length); + } + + config_loaded = true; + + if(sdInitialized) { + streams_loaded = load_samples(); + } + + if(streams_loaded) { + for(int i = 0; i < NSTREAMS; i++){ + samples[i].file = &stream[i]; + } + } + + + i2s.onTransmit(codec_transmit); + i2s.onReceive(codec_receive); + + i2s.setDOUT(15); + i2s.setDIN(14); + i2s.setBCLK(16); // Note: LRCLK = BCLK + 1 + i2s.setMCLK(18); + i2s.setMCLKmult(512); // 256 = 12.288.000Hz 512 = 25MHz + i2s.swapClocks(); + +// i2s.setFrequency(48000); + i2s.setBitsPerSample(16); + + i2s.setBuffers(4, BUFFERSIZE * sizeof(int16_t) / sizeof(uint32_t)); + + if(!i2s.begin(48000)){ + Serial.println("0: I2S error!"); + while(100); + } + Serial.println("0: I2S OK"); + + delay(100); + + i2s_ready = true; + + Serial.print("0: STARTUP COMPLETE"); + + digitalWrite(6, HIGH); + delay(25); + digitalWrite(6, LOW); + setup0_finished = true; + setup1_finished = true; +} + +void setup1(){ } uint32_t last = 0; @@ -731,7 +733,7 @@ void loop1() { } } //int sc = 0; - +int cnt = 0; void loop(){ if(setup1_finished && setup0_finished){ @@ -753,26 +755,29 @@ void loop(){ last = millis(); } + // stream[cnt].stream(); + // cnt++; + // if(cnt == 16) cnt = 0; if(streams_loaded) { for(int i = 0; i < NSTREAMS; i++){ - stream[i].stream(); + stream[i].streamChunk(); } } - int16_t sample_l = 0; - int16_t sample_r = 0; - - if(streams_loaded){ - for(int k = 0; k < NSTREAMS; k++){ - sample_l += stream[k].get() >> 2; - sample_r += stream[k].get() >> 2; - } - } - - int16_t l = 0, r = 0; - //i2s.read16(&l, &r); - l += sample_l; - r += sample_r; - i2s.write16(l, r); +// int16_t sample_l = 0; +// int16_t sample_r = 0; +// +// if(streams_loaded){ +// for(int k = 0; k < NSTREAMS; k++){ +// sample_l += stream[k].get() >> 2; +// sample_r += stream[k].get() >> 2; +// } +// } +// +// int16_t l = 0, r = 0; +// i2s.read16(&l, &r); +// l += sample_l; +// r += sample_r; +// i2s.write16(l, r); if(i2s.getOverflow()) Serial.println("overflow"); if(i2s.getUnderflow()) Serial.println("underflow"); diff --git a/soundcube-firmware/wavestream.h b/soundcube-firmware/wavestream.h index 3aaf539..fcfa46a 100644 --- a/soundcube-firmware/wavestream.h +++ b/soundcube-firmware/wavestream.h @@ -96,7 +96,22 @@ struct WaveFile{ void *bufferStart = buffer.getWritePointer(); file.read((uint8_t*)bufferStart, 4); - + buffer.advance(4); + + if(!file.available() && loop) file.seek(44, SeekSet); + if(!file.available() && !loop) { + file.seek(44, SeekSet); + return false; + } + return true; + } + + bool readblockDMA128(){ + void *bufferStart = buffer.getWritePointer(); + + file.read((uint8_t*)bufferStart, 128); + buffer.advance(128); + if(!file.available() && loop) file.seek(44, SeekSet); if(!file.available() && !loop) { file.seek(44, SeekSet); @@ -157,20 +172,35 @@ class WaveStream{ void pause(){playing = false;} void stream(){ - if(!wavefile.buffer.isFull() && playing){ - int cnt = 0; - while (!wavefile.buffer.isFull() && cnt < 1024) { - bool ok = wavefile.readblockDMA(); - if(!ok) playing = false; - cnt += 2; - } + int cnt = 0; + while (!wavefile.buffer.isFull() && cnt < 128 && playing) { + bool ok = wavefile.readblockDMA(); + if(!ok) playing = false; + cnt += 2; } } - + + void streamChunk(){ + if(!wavefile.buffer.isFull()){ + bool ok = wavefile.readblockDMA128(); + if(!ok) playing = false; + } + } + int16_t get(){ return playing ? wavefile.get() : 0; } + int16_t* getPointer(){ + int16_t* p = wavefile.buffer.getReadPointer(); + wavefile.buffer.pointerPop(2); + return p; + } + + void getDMA(int32_t *samples){ + if(playing) wavefile.buffer.popDMA(samples); + } + bool isPlaying(){ return playing; } @@ -182,4 +212,4 @@ class WaveStream{ bool playing = false; -}; \ No newline at end of file +};