From b9130dc0ae7f094e21b5e54150484b45a971fc6c Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 22 Jun 2025 14:30:09 +0200 Subject: [PATCH] multicore working barely --- soundcube-firmware/ringbuffer.h | 2 +- soundcube-firmware/soundcube-firmware.ino | 623 ++++++++++++---------- 2 files changed, 337 insertions(+), 288 deletions(-) diff --git a/soundcube-firmware/ringbuffer.h b/soundcube-firmware/ringbuffer.h index c3f5339..3bf1349 100644 --- a/soundcube-firmware/ringbuffer.h +++ b/soundcube-firmware/ringbuffer.h @@ -53,5 +53,5 @@ class RingBuffer{ int counter = 0; int write = 0; int read = 0; - T *buffer; + volatile T *buffer; }; diff --git a/soundcube-firmware/soundcube-firmware.ino b/soundcube-firmware/soundcube-firmware.ino index d22181f..a2d6b7f 100644 --- a/soundcube-firmware/soundcube-firmware.ino +++ b/soundcube-firmware/soundcube-firmware.ino @@ -14,6 +14,7 @@ #include "wavestream.h" bool core1_separate_stack = true; +bool core1_disable_systick = true; #define HAPTIC 1 #define AURAL 1 @@ -62,10 +63,14 @@ int32_t position = 0; CRGB ui_leds[74]; CRGB edge_leds[11]; -volatile bool buttonChanged = false; +volatile bool setup0_finished = false; +volatile bool setup1_finished = false; -bool ui_click = false; -bool ui_beep = false; +volatile bool buttonChanged = false; +volatile bool sdInitialized = false; + +volatile bool ui_click = false; +volatile bool ui_beep = false; bool amp = false; volatile bool streams_loaded = false; bool speakerToggle = false; @@ -318,30 +323,41 @@ struct Vibration{ }; Vibration vibration; +// -------------------------------------------- SETUP 0 + void setup() { Serial.begin(); - delay(1000); + delay(500); + + i2s.setSysClk(48000); + 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); - pinMode(19, OUTPUT); // MCLK enable - digitalWrite(19, HIGH); // enable MCLK - - pinMode(20, OUTPUT); // CODEC reset (enable) - digitalWrite(20, HIGH); - - pinMode(12, OUTPUT); - pinMode(13, OUTPUT); + i2s.setBuffers(6, BUFFERSIZE * sizeof(int16_t) / sizeof(uint32_t)); + 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); - bool sdInitialized = SD.begin(22, 23, 24); - delay(100); - if(!sdInitialized) sdInitialized = SD.begin(22, 23, 24); // hack to prevent SD card from not initializing after soft reset + while(!sdInitialized){ + sdInitialized = SD.begin(22, 23, 24); + delay(250); + Serial.println("0: Initializing SD Card"); + } if(sdInitialized) loadConfiguration(config); @@ -349,33 +365,8 @@ void setup() { 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; - pinMode(6, OUTPUT); // Vibration Motor - pinMode(7, OUTPUT); // UI Amp Enable - - ui_snd.onTransmit(pwm_audio_callback); - ui_snd.begin(UI_SAMPLERATE); - - digitalWrite(7, LOW); // UI amp off - - while(!codec_ready){ - delay(5); - } - - //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.setBitsPerSample(16); - - //i2s.setBuffers(6, BUFFERSIZE * sizeof(int16_t) / sizeof(uint32_t)); + config_loaded = true; if(sdInitialized) { streams_loaded = load_samples(); @@ -387,11 +378,19 @@ void setup() { } } + while(!codec_ready){ + delay(250); + Serial.println("0: Waiting for codec"); + } + if(!i2s.begin(48000)){ - Serial.println("I2S error!"); + Serial.println("0: I2S error!"); while(100); } - Serial.println("I2S OK"); + Serial.println("0: I2S OK"); + + + Serial.print("0: STARTUP COMPLETE"); digitalWrite(6, HIGH); delay(25); @@ -400,47 +399,84 @@ void setup() { digitalWrite(6, HIGH); delay(25); digitalWrite(6, LOW); + setup0_finished = true; } void setup1(){ - while(!config_loaded){ - delay(5); - } + Serial.print("1: STARTUP"); + Serial.print("1: INIT LEDS: "); + FastLED.addLeds(edge_leds, 11); + FastLED.addLeds(ui_leds, 74); + Serial.println("SUCCESS"); + + Serial.print("1: INIT SPI: "); SPI1.setSCK(10); SPI1.setTX(11); SPI1.begin(); + Serial.println("SUCCESS"); + Serial.print("1: INIT DAC: "); dac.begin(); + Serial.println("SUCCESS"); - FastLED.addLeds(edge_leds, 11); - FastLED.addLeds(ui_leds, 74); - - Serial.println("INIT WIRE"); + Serial.print("1: INIT WIRE: "); Wire1.setSDA(2); Wire1.setSCL(3); Wire1.begin(); Serial.println("SUCCESS"); + delay(100); - Serial.println("INIT TCA"); + Serial.print("1: INIT TCA: "); TCA.begin(); TCA.pinMode16(0xFFFF); TCA.setPolarity16(0x0000); - Serial.println("SUCCESS"); + Serial.println(" SUCCESS"); - Serial.println("INIT INTERRUPT"); + Serial.print("1: INIT TCA INTERRUPT: "); pinMode(1, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(1), tca_irq, FALLING); Serial.println("SUCCESS"); - // Rotary Encoder + Serial.print("1: INIT ROTARY ENCODER: "); ENC.begin(); // set direction pin. ENC.setDirection(AS5600_CLOCK_WISE); ENC.resetCumulativePosition(); - + Serial.println("SUCCESS"); + + while(!config_loaded){ + delay(250); + Serial.println("1: Waiting for config"); + } + + Serial.print("1: ENABLE I2S MCLK: "); + pinMode(19, OUTPUT); // MCLK enable + digitalWrite(19, HIGH); // enable MCLK + Serial.println("SUCCESS"); + delay(10); + + Serial.print("1: ENABLE CODEC: "); + pinMode(20, OUTPUT); // CODEC reset (enable) + digitalWrite(20, HIGH); + Serial.println("SUCCESS"); + delay(10); + + Serial.print("1: INIT CODEC: "); codec.begin(&Wire1); + Serial.println("SUCCESS"); delay(100); + + pinMode(6, OUTPUT); // Vibration Motor + pinMode(7, OUTPUT); // UI Amp Enable + + ui_snd.onTransmit(pwm_audio_callback); + ui_snd.begin(UI_SAMPLERATE); + + digitalWrite(7, LOW); // UI amp off + + Serial.print("1: STARTUP COMPLETE"); codec_ready = true; + setup1_finished = true; } uint32_t last = 0; @@ -454,273 +490,286 @@ int16_t encdelta_raw = 0; int16_t encdeltadiv = 512; void loop1() { - position = ENC.getCumulativePosition(); - angle = ENC.readAngle(); - encdelta_raw += (position - position_last); + if(setup0_finished && setup0_finished){ + position = ENC.getCumulativePosition(); + angle = ENC.readAngle(); + encdelta_raw += (position - position_last); - // Serial.print(encdelta_raw); - // Serial.print(" \t"); + // Serial.print(encdelta_raw); + // Serial.print(" \t"); - int encdelta = 0; - if(abs(encdelta_raw) > encdeltadiv) { - encdelta = encdelta_raw > 0 ? 1 : -1; - encdelta_raw = 0; - } + int encdelta = 0; + if(abs(encdelta_raw) > encdeltadiv) { + encdelta = encdelta_raw > 0 ? 1 : -1; + encdelta_raw = 0; + } - // Serial.print(angle); - // Serial.print(" \t"); - // Serial.print(position); - // Serial.print(" \t"); - // Serial.print(position_last); - // Serial.print(" \t"); - // Serial.print(encdelta_raw); - // Serial.print(" \t"); - // Serial.println(encdelta); + // Serial.print(angle); + // Serial.print(" \t"); + // Serial.print(position); + // Serial.print(" \t"); + // Serial.print(position_last); + // Serial.print(" \t"); + // Serial.print(encdelta_raw); + // Serial.print(" \t"); + // Serial.println(encdelta); - uint32_t delta_bpm = floor((60000 / config.bpm) / 16); + uint32_t delta_bpm = floor((60000 / config.bpm) / 16); - if(millis() - last >= delta_bpm) { - bar = (bar + 1) % 16; - last = millis(); - } + if(millis() - last >= delta_bpm) { + bar = (bar + 1) % 16; + last = millis(); + } - sd_card_detected = !digitalRead(21); - edge_leds[8] = sd_card_detected ? CRGB(0,10,0) : CRGB(10,0,0); + sd_card_detected = !digitalRead(21); + edge_leds[8] = sd_card_detected ? CRGB(0,10,0) : CRGB(10,0,0); - // EDGE LEDs - for (int i = 0; i < 8; i++) { - edge_leds[i] = CRGB(config.edge_color.r, config.edge_color.g, config.edge_color.b); - } + // EDGE LEDs + for (int i = 0; i < 8; i++) { + edge_leds[i] = CRGB(config.edge_color.r, config.edge_color.g, config.edge_color.b); + } + + // LED Ring leeren + for (int i = 0; i < 48; i++) { + ui_leds[i + 3] = CRGB(0, 0, 0); + } + + // Rotary button LEDs + ui_leds[0] = CRGB(0, 0, 0); + ui_leds[1] = CRGB(0, 0, 0); + ui_leds[2] = CRGB(0, 0, 0); + + // buttonChanged = true when a button is pushed + if (buttonChanged) { + int buttonValues = TCA.read16(); + + bool buttonsNew[16] = {false}; + + bool buttonUp = false; + bool buttonDown = false; + + for(int i = 0; i < 16; i++){ + buttonsNew[i] = ~(buttonValues >> i) & 0x01; + if(buttonsNew[i] == true && buttons[i] == false) { + buttonsDir[i] = -1; + buttonDown = true; + } + if(buttonsNew[i] == false && buttons[i] == true) { + buttonsDir[i] = 1; + buttonUp = true; + } + buttons[i] = buttonsNew[i]; + } + + // Make vibration + if(HAPTIC && buttonDown) { + vibration.trigger(1, 25, 25); + } + + // Make beep + if(AURAL && buttonDown) { + digitalWrite(7, HIGH); + ui_click = true; + } + + if(buttons[TEMPO] && buttonDown){ + state = CTEMPO; + } + + if(buttons[BACK] && buttonDown){ + } + + switch(state){ + case BANK: + encdeltadiv = 512; + encdelta_raw = 0; + encdelta = 0; + if(buttons[SELECT] && buttonDown){ + state = SAMPLE; + } + break; + case SAMPLE: + encdeltadiv = 512; + encdelta_raw = 0; + encdelta = 0; + if(buttons[SELECT] && buttonDown){ + state = SEQUENCE; + } + if(buttons[BACK] && buttonDown){ + state = BANK; + } + break; + case SEQUENCE: + encdeltadiv = 256; + encdelta_raw = 0; + encdelta = 0; + if(buttons[SELECT] && buttonDown){ + int n = steps[set_bar].len; + steps[set_bar].samples[n] = &samples[selected_bank*4 + selected_sample]; + steps[set_bar].len = (steps[set_bar].len + 1) % 4; + } + if(buttons[BACK] && buttonDown){ + state = SAMPLE; + } + break; + case CTEMPO: + encdeltadiv = 64; + encdelta_raw = 0; + encdelta = 0; + if(buttons[SELECT] && buttonDown){ + state = BANK; + } + if(buttons[BACK] && buttonDown){ + state = BANK; + } + break; + } + + // Set bar + // if(buttons[BACK]) set_bar++; + // if(buttons[POWER]) set_bar--; + + if(buttons[SELECT]){ + // Flash encoder leds + ui_leds[0] = CRGB(0, 100, 50); + ui_leds[1] = CRGB(0, 100, 50); + ui_leds[2] = CRGB(0, 100, 50); + } + + if(buttons[DEBUG1]) { + Serial.println("vol down"); + codec.volumeDown(); + } + + if(buttons[DEBUG3]) { + Serial.println("vol up"); + codec.volumeUp(); + } + + if(buttons[DEBUG2]) { + speakerToggle = !speakerToggle; + speaker(speakerToggle); + } + + + Serial.println(codec.getVolumeL()); + + buttonChanged = false; + } + + // if(position < 0) position += 4096; - // LED Ring leeren - for (int i = 0; i < 48; i++) { - ui_leds[i + 3] = CRGB(0, 0, 0); - } - - // Rotary button LEDs - ui_leds[0] = CRGB(0, 0, 0); - ui_leds[1] = CRGB(0, 0, 0); - ui_leds[2] = CRGB(0, 0, 0); - - // buttonChanged = true when a button is pushed - if (buttonChanged) { - int buttonValues = TCA.read16(); - - bool buttonsNew[16] = {false}; - - bool buttonUp = false; - bool buttonDown = false; - - for(int i = 0; i < 16; i++){ - buttonsNew[i] = ~(buttonValues >> i) & 0x01; - if(buttonsNew[i] == true && buttons[i] == false) { - buttonsDir[i] = -1; - buttonDown = true; - } - if(buttonsNew[i] == false && buttons[i] == true) { - buttonsDir[i] = 1; - buttonUp = true; - } - buttons[i] = buttonsNew[i]; - } - - // Make vibration - if(HAPTIC && buttonDown) { - vibration.trigger(1, 25, 25); - } - - // Make beep - if(AURAL && buttonDown) { - digitalWrite(7, HIGH); - ui_click = true; - } - - if(buttons[TEMPO] && buttonDown){ - state = CTEMPO; - } - - if(buttons[BACK] && buttonDown){ - } - switch(state){ case BANK: - encdeltadiv = 512; - encdelta_raw = 0; - encdelta = 0; - if(buttons[SELECT] && buttonDown){ - state = SAMPLE; - } + selected_bank += encdelta; + if(selected_bank == 4) selected_bank = 0; + if(selected_bank == -1) selected_bank = 3; break; case SAMPLE: - encdeltadiv = 512; - encdelta_raw = 0; - encdelta = 0; - if(buttons[SELECT] && buttonDown){ - state = SEQUENCE; - } - if(buttons[BACK] && buttonDown){ - state = BANK; - } + selected_sample += encdelta; + if(selected_sample == 4) selected_sample = 0; + if(selected_sample == -1) selected_sample = 3; break; case SEQUENCE: - encdeltadiv = 256; - encdelta_raw = 0; - encdelta = 0; - if(buttons[SELECT] && buttonDown){ - int n = steps[set_bar].len; - steps[set_bar].samples[n] = &samples[selected_bank*4 + selected_sample]; - steps[set_bar].len = (steps[set_bar].len + 1) % 4; - } - if(buttons[BACK] && buttonDown){ - state = SAMPLE; - } + set_bar += encdelta; + if(set_bar == 16) set_bar = 0; + if(set_bar == -1) set_bar = 15; break; case CTEMPO: - encdeltadiv = 64; - encdelta_raw = 0; - encdelta = 0; - if(buttons[SELECT] && buttonDown){ - state = BANK; - } - if(buttons[BACK] && buttonDown){ - state = BANK; - } + config.bpm += encdelta; + if(config.bpm < 15) config.bpm = 15; + if(config.bpm > 300) config.bpm = 300; break; } - // Set bar - // if(buttons[BACK]) set_bar++; - // if(buttons[POWER]) set_bar--; - - if(buttons[SELECT]){ - // Flash encoder leds - ui_leds[0] = CRGB(0, 100, 50); - ui_leds[1] = CRGB(0, 100, 50); - ui_leds[2] = CRGB(0, 100, 50); + + //dac.setValue(0, dactest ? 0 : sin((float)millis() / 100.0f) * 32768 + 32768); + + // empty LED matrix + for (int i = 0; i < 4; i++) { + ui_leds[lut_banks[i]] = CRGB(0, 0, 0); + ui_leds[lut_samples[i]] = CRGB(0,0,0); } - if(buttons[DEBUG1]) { - Serial.println("vol down"); - codec.volumeDown(); + // set active LED matrix LED + ui_leds[lut_banks[selected_bank]] = CRGB(100, 50, 50); + ui_leds[lut_samples[selected_sample]] = CRGB(100, 0, 50); + + for(int i = 0; i < 48; i++){ + int step = floor(i/3); + if(step == set_bar){ + ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r_active, config.ring_color.g_active, config.ring_color.b_active); + } + if(step == bar){ + ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r, config.ring_color.g, config.ring_color.b); + } + if(steps[step].len > 0) { + ui_leds[lut_ring_cw[i]] = CRGB(0, 10, 0); + } + } - if(buttons[DEBUG3]) { - Serial.println("vol up"); - codec.volumeUp(); + if(bar != bar_old){ + if(steps[bar].len > 0) { + steps[bar].trigger(); + Serial.print("trigger "); + Serial.println(bar); + } } - if(buttons[DEBUG2]) { - speakerToggle = !speakerToggle; - speaker(speakerToggle); + // // set active LED ring LED + // for(int i = 0; i < active_led_ring; i++){ + // ui_leds[lut_ring_ccw[i]] = CRGB(config.ring_color.r, config.ring_color.g, config.ring_color.b); + // } + + FastLED.show(); + + if(buttonChanged){ + for(int i = 0; i < 16; i++){ + if(buttonsDir[i] == 1) buttonsDir[i] = 0; + } } - - Serial.println(codec.getVolumeL()); - - buttonChanged = false; + //delay(20); // wait 1ms + bar_old = bar; + vibration.update(); + position_last = position; + delay(1); } - -// if(position < 0) position += 4096; - - switch(state){ - case BANK: - selected_bank += encdelta; - if(selected_bank == 4) selected_bank = 0; - if(selected_bank == -1) selected_bank = 3; - break; - case SAMPLE: - selected_sample += encdelta; - if(selected_sample == 4) selected_sample = 0; - if(selected_sample == -1) selected_sample = 3; - break; - case SEQUENCE: - set_bar += encdelta; - if(set_bar == 16) set_bar = 0; - if(set_bar == -1) set_bar = 15; - break; - case CTEMPO: - config.bpm += encdelta; - if(config.bpm < 15) config.bpm = 15; - if(config.bpm > 300) config.bpm = 300; - break; - } - - - //dac.setValue(0, dactest ? 0 : sin((float)millis() / 100.0f) * 32768 + 32768); - - // empty LED matrix - for (int i = 0; i < 4; i++) { - ui_leds[lut_banks[i]] = CRGB(0, 0, 0); - ui_leds[lut_samples[i]] = CRGB(0,0,0); - } - - // set active LED matrix LED - ui_leds[lut_banks[selected_bank]] = CRGB(100, 50, 50); - ui_leds[lut_samples[selected_sample]] = CRGB(100, 0, 50); - - for(int i = 0; i < 48; i++){ - int step = floor(i/3); - if(step == set_bar){ - ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r_active, config.ring_color.g_active, config.ring_color.b_active); - } - if(step == bar){ - ui_leds[lut_ring_cw[i]] = CRGB(config.ring_color.r, config.ring_color.g, config.ring_color.b); - } - if(steps[step].len > 0) { - ui_leds[lut_ring_cw[i]] = CRGB(0, 10, 0); - } - - } - - if(bar != bar_old){ - if(steps[bar].len > 0) { - steps[bar].trigger(); - Serial.print("trigger "); - Serial.println(bar); - } - } - - - // // set active LED ring LED - // for(int i = 0; i < active_led_ring; i++){ - // ui_leds[lut_ring_ccw[i]] = CRGB(config.ring_color.r, config.ring_color.g, config.ring_color.b); - // } - - FastLED.show(); - - if(buttonChanged){ - for(int i = 0; i < 16; i++){ - if(buttonsDir[i] == 1) buttonsDir[i] = 0; - } - } - - //delay(20); // wait 1ms - bar_old = bar; - vibration.update(); - position_last = position; } +//int sc = 0; void loop(){ - int16_t l, r; - i2s.read16(&l, &r); + if(setup1_finished && setup0_finished){ + // int16_t l, r; + // i2s.read16(&l, &r); + // for(int k = 0; k < NSTREAMS; k++){ + // int16_t sample_l = 0; + // int16_t sample_r = 0; + // sample_l = stream[k].get(); + // sample_r = stream[k].get(); + // l += sample_l >> 2; + // r += sample_r >> 2; + // } + // i2s.write16(l, r); + // i2s.flush(); - for(int k = 0; k < NSTREAMS; k++){ - int16_t sample_l = 0; - int16_t sample_r = 0; - sample_l = stream[k].get(); - sample_r = stream[k].get(); - l += sample_l >> 2; - r += sample_r >> 2; - } + // //Serial.println(sc); + // // Serial.print(" "); + // // Serial.print(l); + // // Serial.print(" "); + // // Serial.println(r); - i2s.write16(l, r); - - if(streams_loaded) { - for(int i = 0; i < NSTREAMS; i++){ - stream[i].stream(); + if(streams_loaded) { + for(int i = 0; i < NSTREAMS; i++){ + stream[i].stream(); + } } - } + if(i2s.getOverflow()) Serial.println("overflow"); + if(i2s.getUnderflow()) Serial.println("underflow"); + //sc++; + } }