Teensy 4.0 + audio shield spontaneously resets

JeppeRas

Member
Hi friends. Sorry in advance for the long post...
For several weeks now, I’ve been attempting to implement a program on the Teensy 4.0 which is a development of code that was previously working fine on the T3.2. The program is the “OHMs” or “Open Horn Music System”, which uses the Audio adapter, and is much too large to usefully share in this forum. So I’ve shared the full code on github https://github.com/KontinuumLab/newOHMs/tree/main/newOHMs_nov22_024_exp , and put just the main .ino file here below. This code is not complete, or in any way functional as an instrument, but I’m unable to keep developing it until I solve this more immediate problem.

Code:
//#####################################################
//#####################################################
// New Open Horn Midi system / "New OHMs"
// Teensy 3.2 - Main Code v1.00
// Copyright 2022, Jeppe Tofthøj Rasmussen

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <EEPROM.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#include "Adafruit_MPR121.h"
Adafruit_MPR121 capA = Adafruit_MPR121();
Adafruit_MPR121 capB = Adafruit_MPR121();
uint16_t MPRbinaryA = 0;
uint16_t MPRbinaryB = 0;


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWavetable      wavetable1; //xy=178.56666564941406,463.99998474121094
AudioSynthWavetable      wavetable2; //xy=197.56666564941406,504.99998474121094
AudioSynthWavetable      wavetable3; //xy=200.56666564941406,546.9999847412109
AudioSynthWavetable      wavetable4; //xy=211.56666564941406,586.9999847412109
AudioMixer4              voice;         //xy=362.56666564941406,523.9999847412109
AudioFilterStateVariable filter1;        //xy=483.56666564941406,574.9999847412109
AudioFilterStateVariable filter2;        //xy=609.5666656494141,625.9999847412109
AudioFilterStateVariable filter3;        //xy=725.5666656494141,687.9999847412109
AudioMixer4              filter_mix;     //xy=829.5666656494141,563.9999847412109
AudioEffectBitcrusher    bitcrusher1;    //xy=965.5666656494141,623.9999847412109
AudioMixer4              distortion_mix; //xy=1128.566665649414,549.9999847412109
AudioEffectFreeverb      freeverb1;      //xy=1286.566650390625,588
AudioMixer4              reverb_mix;     //xy=1459.566665649414,582.9999847412109
AudioEffectDelay         delay1;         //xy=1633,806
AudioMixer4              delay_feedback_mix; //xy=1648,649
AudioMixer4              delay_mix; //xy=1862,602
AudioOutputI2S           i2s1;           //xy=2034.566650390625,601
AudioConnection          patchCord1(wavetable1, 0, voice, 0);
AudioConnection          patchCord2(wavetable2, 0, voice, 1);
AudioConnection          patchCord3(wavetable3, 0, voice, 2);
AudioConnection          patchCord4(wavetable4, 0, voice, 3);
AudioConnection          patchCord5(voice, 0, filter1, 0);
AudioConnection          patchCord6(voice, 0, filter_mix, 0);
AudioConnection          patchCord7(filter1, 0, filter_mix, 1);
AudioConnection          patchCord8(filter1, 0, filter2, 0);
AudioConnection          patchCord9(filter2, 0, filter_mix, 2);
AudioConnection          patchCord10(filter2, 0, filter3, 0);
AudioConnection          patchCord11(filter3, 0, filter_mix, 3);
AudioConnection          patchCord12(filter_mix, 0, distortion_mix, 0);
AudioConnection          patchCord13(filter_mix, bitcrusher1);
AudioConnection          patchCord14(bitcrusher1, 0, distortion_mix, 1);
AudioConnection          patchCord15(distortion_mix, freeverb1);
AudioConnection          patchCord16(distortion_mix, 0, reverb_mix, 0);
AudioConnection          patchCord17(freeverb1, 0, reverb_mix, 1);
AudioConnection          patchCord18(reverb_mix, 0, delay_feedback_mix, 0);
AudioConnection          patchCord19(reverb_mix, 0, delay_mix, 0);
AudioConnection          patchCord20(delay1, 0, delay_feedback_mix, 1);
AudioConnection          patchCord21(delay_feedback_mix, delay1);
AudioConnection          patchCord22(delay_feedback_mix, 0, delay_mix, 1);
AudioConnection          patchCord23(delay_mix, 0, i2s1, 0);
AudioConnection          patchCord24(delay_mix, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=2043.566650390625,504
// GUItool: end automatically generated code

#define LOGO16_GLCD_WIDTH  16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000
};

#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif


unsigned long displayTimer = 0;
unsigned long lastDisplay = 0;




//-------------------------------------------------------
// -------------------- PINS: ---------------------------
//-------------------------------------------------------

// touchRead() pins:
const int octavePin1 = 0;
const int octavePin2 = 16;
const int octavePin3 = 17;

const int mpTouchPin = 11;
//const int mpTouchPin2 = 33;
//
//// Multiplexer pins:
//const int muxPin1 = 5;
//const int muxPin2 = 4;
//const int muxPin3 = 3;
//const int muxPin4 = 2;
//const int mux1SensorPin = 1;

// Encoder pins:
const int encButtonPin = 9;
const int encPin1 = 4;
const int encPin2 = 5;

// BreathPin:
const int breathPin = 14;

// Pitchbend pins:
const int pitchbendPin1 = 22;
const int pitchbendPin2 = 17;

const int switchPin1 = 2;
const int switchPin2 = 3;

const int knob1Pin = 15;
const int knob2Pin = 16;

//-------------------------------------------------------
// ------------------ VARIABLES: ------------------------
//-------------------------------------------------------

//Keys / notes:
int keyTouchVal[15];
int octTouchVal[4];

bool keysPressed[15];
bool octPressed[4];

uint16_t keyThreshold[15];
uint16_t octThreshold[4];

bool newNote;
bool correct;

byte baseNote;
byte currentNote;
byte lastNote;
int octave = 0;
int lastOctave = 0;


//"Must be pressed", "0", "Must be open", "0", "Special funct"([< 12]), "Note"([12])
// byte note1[] = {6, 14, 0, 7, 9, 10, 0, 0, 0, 0, 0, 0, 63};
static byte ActiveFingSet[20][13];

// Factory Fingering Set:
static byte fingerings[20][13] = {
//  {0, 8, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 63}, // High Eb
//  {0, 100, 8, 100, 0, 0, 0, 0, 0, 0, 0, 0, 62}, // High D
  {100, 1, 3, 100, 0, 0, 0, 0, 0, 0, 0, 0, 61}, // C#
  {3, 100, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 60}, // C
  {1, 100, 2, 3, 100, 0, 0, 0, 0, 0, 0, 0, 59}, // B
  {1, 2, 100, 3, 100, 0, 0, 0, 0, 0, 0, 0, 58}, // Extra Bb
  {1, 3, 7, 100, 4, 100, 0, 0, 0, 0, 0, 0, 58}, // Side Bb
  {1, 3, 100, 4, 7, 100, 0, 0, 0, 0, 0, 0, 57}, // A
  {1, 3, 4, 5, 100, 9, 10, 100, 0, 0, 0, 0, 56}, // Ab
  {1, 3, 4, 100, 5, 9, 10, 100, 0, 0, 0, 0, 55}, // G
  {1, 3, 4, 10, 100, 9, 100, 0, 0, 0, 0, 0, 54}, // F#
  {1, 3, 4, 9, 100, 10, 100, 0, 0, 0, 0, 0, 53}, // F
  {1, 3, 4, 9, 10, 100, 11, 100, 0, 0, 0, 0, 52}, // E
  {1, 3, 4, 9, 10, 11, 12, 100, 13, 100, 0, 0, 51}, // Eb
  {1, 3, 4, 9, 10, 11, 100, 6, 12, 13, 100, 0, 50}, // D
  {1, 3, 4, 5, 9, 10, 11, 13, 100, 6, 100, 0, 49}, // C#
  {1, 3, 4, 9, 10, 11, 13, 100, 5, 6, 100, 0, 48}, // C
  {1, 3, 4, 6, 9, 10, 11, 100, 12, 13, 100, 0, 47}, // B
  {1, 3, 4, 6, 9, 10, 11, 13, 100, 100, 0, 0, 46}, // Bb
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};


// biphonic modes:
const int biphonicModeKeys[2] = {0, 8};

bool splitActive = 0;
bool lastSplitActive = 0;


byte currentSplitHighNote;
byte duplicateSplitHighNote;
byte currentSplitLowNote;
byte lastSplitHighNote;
byte lastSplitLowNote;
byte currentSplitNote;
byte lastSplitNote;

byte splitHighPressed;
byte splitLowPressed;

bool newHighNote = 0;
bool newLowNote = 0;

byte currentSustainNote;
byte lastSustainNote;
bool sustainActive = 0;
bool lastSustainActive = 0;

byte sustainInterval;

byte currentIntervalNote;
bool intervalActive = 0;
bool lastIntervalActive = 0;



//Encoder:
long encDir;
bool currentEncButton = 0;
bool encBtnPressed;
bool encBtnReleased;

int encCounter;
int lastEncCounter;

int encVal1 = 0;
int encVal2 = 0;
int encLastVal1 = 0;
int encLastVal2 = 0;
int encButtonVal = 0;
int encButtonLastVal = 0;
bool newValueBool = 0;

bool pin1Flag;
bool pin2Flag;
int reading;

long unsigned extEncTimer;

//Breath:
int breath;
int lastBreath;
int breathRaw;
int lastBreathRaw;
uint16_t breathMin;
uint16_t breathMax;


// Pitchbend
int pitchbend;
int lastPitchbend;

int pitchbendVal1;
int pitchbendVal2;
int lastPitchbendVal1;
int lastPitchbendVal2;

int pitchbendVal1Raw;
int pitchbendVal2Raw;
int lastPitchbendVal1Raw;
int lastPitchbendVal2Raw;

int16_t pitchbendVal1Min;
int16_t pitchbendVal2Min;
int16_t pitchbendVal1Max;
int16_t pitchbendVal2Max;


//mpTouchSensors:
int mpTouchVal;
int lastmpTouchVal;
int mpTouchVal2;
int lastMpTouchVal2;

int mpTouchValRaw;
int lastmpTouchValRaw;
int mpTouchVal2Raw;
int lastMpTouchVal2Raw;

uint16_t mpTouchValMin;
uint16_t mpTouchValMax;
uint16_t mpTouchVal2Min;
uint16_t mpTouchVal2Max;



int mode = 0; // 0 = play / 1 = menu
int lastMode;

int16_t calibrateState;

int16_t midiChannel1 = 1;     //done
int16_t midiChannel2 = 2;     //done 
int16_t transpose = 0;        //done 
int16_t splitOctave = 0;      //done 
int16_t detune = 0;                  // Not done yet
int16_t midiOutputOn = 0;     //done
int16_t audioOutputOn = 1;    //done
int16_t breathCC = 2;         //done
int16_t extraBreathCC = 0;    //done
int16_t lipCC = 112;        //done
int16_t pitchbendLowRes = 1;  //done
int16_t pitchbendHighRes = 0; //done
int16_t activeInstrument = 0; //done
int16_t filterLayers = 2;     //done
int16_t filterFreqMin = 0;    //done
int16_t filterFreqMax = 10000;//done
int16_t filterResonance = 0;  //done
int16_t vibratoSpeed;                // Haven't even started      
int16_t extraFilter;          //done (bitcrusher)
int16_t pitchbendRange = 2;   //done
int16_t pitchbendVal1Curve;   //done
int16_t pitchbendVal2Curve;   //done
int16_t reverbRoomSize = 2;   //done 
int16_t reverbDamping = 2;    //done
int16_t reverbMix;            //done
         //
int16_t breathCurve;          //done
int16_t mpTouchValCurve;     //done
int16_t mpTouchVal2Curve;     //done
 
int16_t keySensitivity;       //done (uses "keyThreshold at calibration)
int16_t keyResponsiveness;           // Like a "debounce" but for the capacitive keys
        // encoderMode:
int16_t encoderInstr = 1;     //done
int16_t encoderVol = 0;       //done
int16_t encoderNone = 0;      //done

int16_t audioVolume = 5;
float tempVol;            // INCLUDE AS MENU OPTION

int16_t breathSpeed;          //done  
int16_t pitchbendSpeed;       //done
int16_t lipSpeed;             //done

int16_t bitcrusherBits = 16;  //done

//>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//>>>>>>>>>>>>>>>>>>>>>>>>> NEW: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

int knob1ValRaw;
int lastKnob1ValRaw;
int knob2ValRaw;
int lastKnob2ValRaw;

int16_t switch1DelayRec;
int16_t switch1Reverb;
int16_t switch1SecondaryFilter;
int16_t switch2DelayType;
int16_t switch2Reverb;
int16_t switch2LipFilter;

uint16_t knob1ValMin;
uint16_t knob1ValMax;
uint16_t knob2ValMin;
uint16_t knob2ValMax;

uint16_t knob1Curve;
uint16_t knob1Speed;
uint16_t knob2Curve;
uint16_t knob2Speed;

uint16_t delayTime;
uint16_t delayFeedback;
uint16_t delayMix;


//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

long unsigned menuBtnTimer; 
// Audio variables;
int midiOn;

float Fpitchbend;
float floatBreath;

int Wind1CurrentWavetable;
float Wind1currentWavetableFreq;

int Wind2CurrentWavetable;
float Wind2currentWavetableFreq;

const float DIV127 = (1.0 / 127.0);
const float DIV64 = (1.0 / 64.0);


// Woodwind:
#include "altosax_samples.h"
#include "clarinet_samples.h"
#include "oboe_samples.h"
// Flutes:
//#include "flute_samples.h"
#include "ocarina_samples.h"
#include "panflute_samples.h"
// Brass:
#include "brass_samples.h"
#include "trumpet_samples.h"
#include "mutedtrumpet_samples.h"
#include "trombone_samples.h"
// Other reed instruments:
#include "accordian_samples.h"
//#include "harmonica_samples.h"
//#include "organ_samples.h"
#include "eorgan_samples.h"
// Waveforms:
#include "squarewave_samples.h"
#include "sawStack_samples.h"

#include "InstrSelectFunctions.h"
#include "Memory.h"
#include "MiscFunctions.h"
#include "Calibration.h"
#include "Keys.h"
#include "Mouthpiece.h"
#include "SynthFunctions.h"
#include "MenuContent.h"
#include "MenuFunctions.h"


void setup() {
  Serial.begin(115200);
//  pinMode(muxPin1, OUTPUT);
//  pinMode(muxPin2, OUTPUT);
//  pinMode(muxPin3, OUTPUT);
//  pinMode(muxPin4, OUTPUT);

  pinMode(encPin1, INPUT_PULLUP);
  pinMode(encPin2, INPUT_PULLUP);
  pinMode(encButtonPin, INPUT_PULLUP);
  pinMode(switchPin1, INPUT_PULLUP);
  pinMode(switchPin2, INPUT_PULLUP);

  // INTERRUPT HANDLING:
  attachInterrupt(encPin1, isrEncPin1, CHANGE); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
  attachInterrupt(encPin2, isrEncPin2, CHANGE); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)

  // Set analog sensor resolution (0-4095)
//  analogReadResolution(12);
  
  if (!capA.begin(0x5A)) {
    Serial.println("MPR121 on 0x5A NOT found");
  }
  else {
    Serial.println("MPR121 on 0x5A active");
//    activeMPR121[0] = 1;
  }
  if (!capB.begin(0x5B)) {
    Serial.println("MPR121 on 0x5B NOT found");
  }
  else {
    Serial.println("MPR121 on 0x5B active");
//    activeMPR121[1] = 1;
  }
  
// MPR121 setup:
  capA.writeRegister(0x2E, 0b11111111);
  capA.writeRegister(0x32, 0b11111111);
  capA.writeRegister(0x35, 0b11111111);
  capA.setThresholds(20, 16);

  capB.writeRegister(0x2E, 0b11111111);
  capB.writeRegister(0x32, 0b11111111);
  capB.writeRegister(0x35, 0b11111111);
  capB.setThresholds(20, 16);


  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(18);

  // turn on the output
  sgtl5000_1.enable();


  wavetable1.setInstrument(altosax);
  wavetable2.setInstrument(altosax);
  wavetable3.setInstrument(altosax);
  wavetable4.setInstrument(altosax);
  WindWavetableAmplitude(1.0);
  Wind1CurrentWavetable = 1;
  Wind2CurrentWavetable = 3;

  bitcrusher1.bits(16);
  bitcrusher1.sampleRate(44100);
  distortion_mix.gain(0, 1.0);
  distortion_mix.gain(1, 0.0);

  loadSettings(1);  // fix memory.h ???
  
  audioVolume = 5;  // Always start on volume = 0.5
  tempVol = float(audioVolume) / 10;
  sgtl5000_1.volume(tempVol);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  delay(500);
  display.clearDisplay();
  display.display();

  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(20, 10);
  display.print("Loading settings");
  display.display();
  Serial.println("Loading settings");
//  delay(500);
  display.clearDisplay();
  display.display();
//  Serial.println("hello!");
  //  filter1.frequency(7000);
}


void loop() {
//  Serial.println("hello!");
  // Read encoder - calibration
  // - Press encButton to start mouthpiece calibration
  // - Release button to go to key calibration
  // - Press again to save settings.
  lastMode = mode;
  encRead();
  Serial.println(encBtnPressed);
  if(mode == 0){
    if(encBtnPressed == 1){
      encBtnPressed = 0;
      menuBtnTimer = millis();
      while(encBtnReleased != 1){
        encRead();
        if(millis() - menuBtnTimer > 500){
          mode = 1;
          menu = 0;
          menuItem = 1;
          displayBasicMenuPage(mainMenu, mainMenuSize);
//          display.setTextSize(1);
//          display.setTextColor(WHITE, BLACK);
//          display.setCursor(30, 13);
//          display.print("Opening menu");
//          display.display();
        }
      }
      encBtnReleased = 0;
    }
  }
  Serial.println("After 'mode=0'");
  if(mode == 1){
    if(encBtnPressed == 1){
      encBtnPressed = 0;
      menuBtnTimer = millis();
      while(encBtnReleased != 1){
        encRead();
        if(millis() - menuBtnTimer > 500){
          mode = 0;
          menu = 0;
          menuItem = 1;
          display.clearDisplay();
          display.display();
        }
      }
    }
  }
  //  if(encBtnPressed == 1){
  //    prepareCalibration();
  //
  //    while(encBtnReleased != 1){
  //      mpCalibration();
  //      encRead();
  //    }
  //    display.clearDisplay();
  //    display.display();
  //    while(encBtnPressed == 0){
  //      keysCalibration();
  //      encRead();
  //    }
  //    saveSettings();
  //    display.clearDisplay();
  //    display.display();
  //    display.setTextSize(1);
  //    display.setTextColor(WHITE, BLACK);
  //    display.setCursor(3, 8);
  //    display.print("saving settings");
  //    display.display();
  //    delay(1500);
  //    display.clearDisplay();
  //    display.display();
  //  }

  //  if(lastEncCounter != encCounter){
  //    instrSelection();
  //  }
  //  lastEncCounter = encCounter;
  //  lastBreath = breath;
  readBreath();
  readKeys();

  readPitchbend();
  readMpTouch();
  Serial.println("After 'readMpTouch'");

  //  int lastMidiOn = midiOn;
  //  midiOn = digitalRead(switchPin);
  //  if(lastMidiOn != midiOn){
  //    display.clearDisplay();
  //    display.display();
  //    display.setTextSize(1);
  //    display.setTextColor(WHITE, BLACK);
  //    display.setCursor(22, 8);
  //    if(midiOn == 1){
  //      display.print("MIDI output on");
  //    }
  //    else{
  //      display.print("AUDIO output on");
  //    }
  //    display.display();
  //    delay(1500);
  //    display.clearDisplay();
  //    display.display();
  //  }
  //
  //
  //  if(midiOn == 1){
  //    midiOutput();
  //  }
//  lastMode = mode;
//  mode = digitalRead(switchPin);
  if (mode == 1) {

    updateMenu();
    Serial.println("After 'updateMenu'");
  }
  
  else {
    // Set volume or instrument on encoder wheel input:
    if(extEncTimer != 0){
      if(millis() - extEncTimer >= 1000){
        display.clearDisplay();
        display.display();  
        extEncTimer = 0;    
      }
    }
    if(encDir != 0){
      extEncTimer = millis();
      if(encoderVol == 1){ // if encoder mode set to "volume":
        audioVolume = audioVolume + encDir;
        audioVolume = constrain(audioVolume, 0, 10);
        tempVol = float(audioVolume) / 10;
        sgtl5000_1.volume(tempVol);
        display.clearDisplay();
        display.display();
        display.setTextSize(1);
        display.setTextColor(WHITE, BLACK);
        display.setCursor(20, 10);
        display.print("Audio Volume: ");
        display.print(audioVolume);
        display.display();
      }
      else if(encoderInstr == 1){ // if encoder mode set to "instrument":
        activeInstrument = activeInstrument + encDir;
        activeInstrument = constrain(activeInstrument, 0, 12);
        instrSelection();
        display.clearDisplay();
        display.display();
        display.setTextSize(1);
        display.setTextColor(WHITE, BLACK);
        display.setCursor(20, 10);
        display.print("Active Instrument: ");
        display.setCursor(20, 19);
        display.print(setInstrumentMenu[activeInstrument + 2]);
        display.display();
      }
      encDir = 0;
    }
    
    if (midiOutputOn == 1) {
      midiOutput();
    }
    if (audioOutputOn == 1) {
      audioOutput();
    }
  }
Serial.println("End of loop");
}


void audioOutput() {
  
  //---------------------------------------------
  //----------Filter adjustments: ----------------
  //---------------------------------------------
  if(filterLayers == 0){
    filter_mix.gain(0, 1.0);
    filter_mix.gain(1, 0.0);
    filter_mix.gain(2, 0.0);
    filter_mix.gain(3, 0.0);
  }
  else if(filterLayers == 1){
    filter_mix.gain(0, 0.0);
    filter_mix.gain(1, 1.0);
    filter_mix.gain(2, 0.0);
    filter_mix.gain(3, 0.0);
  }
  else if(filterLayers == 2){
    filter_mix.gain(0, 0.0);
    filter_mix.gain(1, 0.0);
    filter_mix.gain(2, 1.0);
    filter_mix.gain(3, 0.0);
  }
  else if(filterLayers == 3){
    filter_mix.gain(0, 0.0);
    filter_mix.gain(1, 0.0);
    filter_mix.gain(2, 0.0);
    filter_mix.gain(3, 1.0);
  }
  
//  chorus_mix.gain(0, 0.0);
//  chorus_mix.gain(1, 1.0);
//  chorus_mix.gain(2, 0.0);
//  chorus_mix.gain(3, 0.0);

  
  float reverbMixPos = float(reverbMix) / 10;
  reverb_mix.gain(1, reverbMixPos);
  reverbMixPos = 1 - (float(reverbMix) / 10);
  reverb_mix.gain(0, reverbMixPos);
  
  float room = float(reverbRoomSize) / 10; 
  freeverb1.roomsize(room);
  float damp = float(reverbDamping) / 10; 
  freeverb1.damping(damp);



//  int tempMin = breathMin - breathMax;
//  floatBreath = float(breathRaw) / tempMin;
  int tempBreath = map(breath, 0, 127, 0, 127); // Skip lower breath range because of instability
  floatBreath = float(tempBreath) / 127.0;
  floatBreath = constrain(floatBreath, 0.0, 1.0);
//  Serial.println(floatBreath);
  //// ---------------------------------------------------------
  //// ------------ Pitchbend calculation section: -------------
  ////----------------------------------------------------------
  Fpitchbend = float(pitchbend);
  
  byte secondaryNote;
  byte primaryNote;
  if (splitActive == 1) {
    secondaryNote = currentSplitLowNote;
    primaryNote = currentSplitHighNote;
  }
  else {
    secondaryNote = currentSustainNote;
    primaryNote = currentNote;
  }
  if (pitchbend < 0) {
    float lowFreq = noteToFreq(primaryNote - pitchbendRange);
    Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
    lowFreq = noteToFreq(secondaryNote - pitchbendRange);
    Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
  }
  else if (pitchbend > 0) {
    float highFreq = noteToFreq(primaryNote + pitchbendRange);
    Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
    highFreq = noteToFreq(secondaryNote + pitchbendRange);
    Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
  }
  else if (pitchbend == 0) {
    Wind1currentWavetableFreq = noteToFreq(primaryNote);
    Wind2currentWavetableFreq = noteToFreq(secondaryNote);
  }
  Wind1WavetableSetFreq(Wind1currentWavetableFreq);
  Wind2WavetableSetFreq(Wind2currentWavetableFreq);
  //// ----------------------------------------------
  //// -------- Key / note output section: ----------
  ////-----------------------------------------------
  if (breath != 0) {
    if (splitActive == 0) {

      if (lastSustainActive == 0) {
        currentSustainNote = currentNote;
      }
      else if (sustainActive == 1 && intervalActive == 1) {
        if (lastIntervalActive == 0) {
          sustainInterval = currentSustainNote - currentNote;
        }
        lastSustainNote = currentSustainNote;
        currentSustainNote = currentNote + sustainInterval;
      }


      Wind1currentWavetableFreq = noteToFreq(currentNote);
      Wind2currentWavetableFreq = noteToFreq(currentSustainNote);
      if (pitchbend < 0) {
        float lowFreq = noteToFreq(currentNote - pitchbendRange);
        Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
        lowFreq = noteToFreq(currentSustainNote - pitchbendRange);
        Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
      }
      else if (pitchbend > 0) {
        float highFreq = noteToFreq(currentNote + pitchbendRange);
        Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
        highFreq = noteToFreq(currentSustainNote + pitchbendRange);
        Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
      }
      
      if (lastSplitActive == 1) {
        //        usbMIDI.sendNoteOn(currentSplitLowNote, 0, 1);
        //        usbMIDI.sendNoteOn(currentSplitHighNote, 0, 2);
        WindWavetableStop(Wind1CurrentWavetable);
        WindWavetableStop(Wind2CurrentWavetable);
        WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
      }
      if (sustainActive == 1) {
        if (lastSustainActive == 0) {
          WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
          WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
        }
      }


      else if (lastSustainActive == 1) {
        //        usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
        //        usbMIDI.sendNoteOn(currentNote, 0, 2);
        WindWavetableStop(Wind1CurrentWavetable);
        WindWavetableStop(Wind2CurrentWavetable);
        WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
      }


      if (newNote == 1) {
        // stop old note:
        WindWavetableStop(Wind1CurrentWavetable);

        // Change wavetable:
        if (Wind1CurrentWavetable == 1) {
          Wind1CurrentWavetable = 2;
        }
        else {
          Wind1CurrentWavetable = 1;
        }

        // sustain/split:
        if (sustainActive == 1) {
          WindWavetableStop(Wind2CurrentWavetable);
          // Change wavetable:
          if (Wind2CurrentWavetable == 3) {
            Wind2CurrentWavetable = 4;
          }
          else {
            Wind2CurrentWavetable = 3;
          }
          //sustain:
          if (sustainActive == 1) {
            Wind1currentWavetableFreq = noteToFreq(currentNote);
            Wind2currentWavetableFreq = noteToFreq(currentSustainNote);
            if (pitchbend < 0) {
              float lowFreq = noteToFreq(currentNote - pitchbendRange);
              Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
              lowFreq = noteToFreq(currentSustainNote - pitchbendRange);
              Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
            }
            else if (pitchbend > 0) {
              float highFreq = noteToFreq(currentNote + pitchbendRange);
              Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
              highFreq = noteToFreq(currentSustainNote + pitchbendRange);
              Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
            }
          }

          // start new note:
          WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
          WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
        }


        // single note:
        else {
          Wind1currentWavetableFreq = noteToFreq(currentNote);
          if (pitchbend < 0) {
            float lowFreq = noteToFreq(currentNote - pitchbendRange);
            Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
          }
          else if (pitchbend > 0) {
            float highFreq = noteToFreq(currentNote + pitchbendRange);
            Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
          }

          // start new note:
          WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
        }
      }
    }

    // SPLIT OUTPUT SECTION:
    else if (splitActive == 1) {
      Wind1currentWavetableFreq = noteToFreq(currentSplitHighNote);
      Wind2currentWavetableFreq = noteToFreq(currentSplitLowNote);
      if (pitchbend < 0) {
        float lowFreq = noteToFreq(currentSplitHighNote - pitchbendRange);
        Wind1currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind1currentWavetableFreq);
        lowFreq = noteToFreq(currentSplitLowNote - pitchbendRange);
        Wind2currentWavetableFreq = mapfloat(Fpitchbend, -64.0, 0.0, lowFreq, Wind2currentWavetableFreq);
      }
      else if (pitchbend > 0) {
        float highFreq = noteToFreq(currentSplitHighNote + pitchbendRange);
        Wind1currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind1currentWavetableFreq, highFreq);
        highFreq = noteToFreq(currentSplitLowNote + pitchbendRange);
        Wind2currentWavetableFreq = mapfloat(Fpitchbend, 0.0, 64.0, Wind2currentWavetableFreq, highFreq);
      }
      if (newHighNote == 1) {
        // Change wavetable:
        if (Wind1CurrentWavetable == 1) {
          WindWavetableStop(Wind1CurrentWavetable);
          Wind1CurrentWavetable = 2;
        }
        else {
          WindWavetableStop(Wind1CurrentWavetable);
          Wind1CurrentWavetable = 1;
        }

        WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
      }

      if (newLowNote == 1 && splitLowPressed != 0) {
        if (Wind2CurrentWavetable == 3) {
          WindWavetableStop(Wind2CurrentWavetable);
          Wind2CurrentWavetable = 4;
        }
        else {
          WindWavetableStop(Wind2CurrentWavetable);
          Wind2CurrentWavetable = 3;
        }

        WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
      }
      else if (splitLowPressed == 0) {
        WindWavetableStop(Wind2CurrentWavetable);
      }
    }
  }


  // ----------------------------------------------
  // ---------- Breath output section: -------------
  //------------------------------------------------
  WindWavetableAmplitude(floatBreath);

  if (breath != lastBreath) {

//    WindWavetableAmplitude(floatBreath);
    if (breath == 0) {
      WindWavetableStop(Wind1CurrentWavetable);
      // Change wavetable:
      if (Wind1CurrentWavetable == 1) {
        Wind1CurrentWavetable = 2;
      }
      else {
        Wind1CurrentWavetable = 1;
      }
      if (sustainActive == 1 || splitActive == 1) {
        WindWavetableStop(Wind2CurrentWavetable);
        // Change wavetable:
        if (Wind2CurrentWavetable == 3) {
          Wind2CurrentWavetable = 4;
        }
        else {
          Wind2CurrentWavetable = 3;
        }
      }
    }
    else if (lastBreath == 0) {
      if (correct == 1) {

        //        usbMIDI.sendControlChange(2, breath, 1);
        //        usbMIDI.sendControlChange(2, breath, 2);
        if (splitActive == 0) {
          if (sustainActive == 1) {
            //            Wind2currentWavetableFreq = noteToFreq(currentSustainNote);
            WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
            WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
          }
          else {
            WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
          }
        }
        else {
          //          Wind1currentWavetableFreq = noteToFreq(currentSplitLowNote);
          //          Wind2currentWavetableFreq = noteToFreq(currentSplitHighNote);
          WindWavetablePlayFreq(Wind1CurrentWavetable, Wind1currentWavetableFreq);
          WindWavetablePlayFreq(Wind2CurrentWavetable, Wind2currentWavetableFreq);
        }
      }
    }
  }






  // ----------------------------------------------
  // ------------ Misc output section: -------------
  //------------------------------------------------

  if (breath != lastBreath) {
    filter1.frequency(filterFreqMax * (breath * DIV127) + 10);
    filter2.frequency(filterFreqMax * (breath * DIV127) + 10);
    filter3.frequency(filterFreqMax * (breath * DIV127) + 10);
    if(filterResonance == 0){
      filter1.resonance((4.3 * (breath * DIV127)) + 0.7);
      filter2.resonance((4.3 * (breath * DIV127)) + 0.7);
      filter3.resonance((4.3 * (breath * DIV127)) + 0.7);
    }
    else{
      filter1.resonance(filterResonance);
      filter2.resonance(filterResonance);
      filter3.resonance(filterResonance);
    }
    
    //      Serial.print(mpTouchVal);
    //      Serial.print(" - ");
  }
//    if(mpTouchVal != lastmpTouchVal){
//      LFOdepth = mpTouchVal * DIV127;
//    }


  bitcrusher1.bits(bitcrusherBits);
  
  if(mpTouchVal2 != lastMpTouchVal2){
    if(bitcrusherBits == 1){
      mpTouchVal2 = mpTouchVal2 * 0.4;
    }
    else if(bitcrusherBits == 2){
      mpTouchVal2 = mpTouchVal2 * 0.65;
    }
    float tempMix = (float)mpTouchVal2 / 127.0;
    float tempOtherMix = 1 - tempMix;
    distortion_mix.gain(0, tempOtherMix);
    distortion_mix.gain(1, tempMix);
//      Serial.print(tempMix);
//      Serial.println();
  }
      
}


void midiOutput() {
  // ----------------------------------------------
  // ---------- Breath output section: -------------
  //------------------------------------------------
  if (breath != lastBreath) {
    if (breath == 0) {
      usbMIDI.sendControlChange(123, 0, midiChannel1);
      usbMIDI.sendControlChange(123, 0, midiChannel2);


      //      if(splitActive == 1){
      ////        usbMIDI.sendControlChange(123, 0, 1);
      ////        usbMIDI.sendControlChange(123, 0, 2);
      //        usbMIDI.sendNoteOn(currentSplitLowNote, 0, 1);
      //        usbMIDI.sendNoteOn(currentSplitHighNote, 0, 2);
      //      }
      //      else{
      //        if(sustainActive == 1){
      ////          usbMIDI.sendControlChange(2, 0, 1);
      ////          usbMIDI.sendControlChange(2, 0, 2);
      //          usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
      //          usbMIDI.sendNoteOn(currentNote, 0, 2);
      //          }
      //        else{
      ////          usbMIDI.sendControlChange(2, 0, 1);
      //          usbMIDI.sendNoteOn(currentNote, 0, 1);
      //        }
      //      }
    }

    else if (lastBreath == 0) {
      if (correct == 1) {
        usbMIDI.sendControlChange(breathCC, breath, midiChannel1);
        usbMIDI.sendControlChange(breathCC, breath, midiChannel2);
        if(extraBreathCC != 0){
          usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel1);
          usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel2);          
        }
        if (splitActive == 0) {
          if (sustainActive == 1) {
            usbMIDI.sendNoteOn(currentSustainNote, 127, midiChannel1);
            usbMIDI.sendNoteOn(currentNote, 127, midiChannel2);
          }
          else {
            usbMIDI.sendNoteOn(currentNote, 127, midiChannel1);
          }
        }
        else {
          usbMIDI.sendNoteOn(currentSplitLowNote, 127, midiChannel1);
          usbMIDI.sendNoteOn(currentSplitHighNote, 127, midiChannel2);
        }
      }
    }
    else {
      usbMIDI.sendControlChange(breathCC, breath, midiChannel1);
      usbMIDI.sendControlChange(breathCC, breath, midiChannel2);
      if(extraBreathCC != 0){
        usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel1);
        usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel2);          
      }
    }
  }

  // ----------------------------------------------
  // -------- Key / note output section: ----------
  //-----------------------------------------------
  if (breath != 0) {
    if (splitActive == 0) {
      if (lastSplitActive == 1) {
        //        usbMIDI.sendNoteOn(currentSplitLowNote, 0, 1);
        //        usbMIDI.sendNoteOn(currentSplitHighNote, 0, 2);
        usbMIDI.sendControlChange(123, 0, midiChannel1);
        usbMIDI.sendControlChange(123, 0, midiChannel2);
        usbMIDI.sendNoteOn(currentNote, 127, midiChannel1);
      }
      if (sustainActive == 1 && intervalActive == 0) {
        if (lastSustainActive == 0) {
          currentSustainNote = currentNote;
          usbMIDI.sendNoteOn(currentNote, 127, midiChannel2);
        }
      }
      else if (sustainActive == 1 && intervalActive == 1) {
        if (lastIntervalActive == 0) {
          sustainInterval = currentSustainNote - currentNote;
        }
        lastSustainNote = currentSustainNote;
        currentSustainNote = currentNote + sustainInterval;
      }
      else if (lastSustainActive == 1) {
        //        usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
        //        usbMIDI.sendNoteOn(currentNote, 0, 2);
        usbMIDI.sendControlChange(123, 0, midiChannel1);
        usbMIDI.sendControlChange(123, 0, midiChannel2);
        if(extraBreathCC != 0){
          usbMIDI.sendControlChange(extraBreathCC, 0, midiChannel1);
          usbMIDI.sendControlChange(extraBreathCC, 0, midiChannel2);          
        }
        usbMIDI.sendNoteOn(currentNote, breath, midiChannel1);
        if(extraBreathCC != 0){
          usbMIDI.sendControlChange(extraBreathCC, breath, midiChannel1);         
        }
      }

      if (newNote == 1) {
        if (sustainActive == 1) {
          usbMIDI.sendNoteOn(lastNote, 0, midiChannel2);
          usbMIDI.sendNoteOn(currentNote, 127, midiChannel2);
          if (intervalActive == 1) {
            usbMIDI.sendNoteOn(lastSustainNote, 0, midiChannel1);
            usbMIDI.sendNoteOn(currentSustainNote, 127, midiChannel1);
          }
        }
        else {
          usbMIDI.sendNoteOn(lastNote, 0, midiChannel1);
          usbMIDI.sendNoteOn(currentNote, 127, midiChannel1);
        }
      }
    }
    else if (splitActive == 1) {
      if (lastSplitActive == 0) {
        //        if(sustainActive == 1){
        //          usbMIDI.sendNoteOn(currentNote, 0, 2);
        //          usbMIDI.sendNoteOn(currentSustainNote, 0, 1);
        //        }
        //        else{
        //          usbMIDI.sendNoteOn(currentNote, 0, 1);
        //        }
        usbMIDI.sendControlChange(123, 0, midiChannel1);
        usbMIDI.sendControlChange(123, 0, midiChannel2);
        usbMIDI.sendNoteOn(currentSplitLowNote, 127, midiChannel1);
        usbMIDI.sendNoteOn(currentSplitHighNote, 127, midiChannel2);
      }
      else {
        if (currentSplitLowNote != lastSplitLowNote) {
          usbMIDI.sendNoteOn(lastSplitLowNote, 0, midiChannel1);
          usbMIDI.sendNoteOn(currentSplitLowNote, 127, midiChannel1);
        }
        if (currentSplitHighNote != lastSplitHighNote) {
          usbMIDI.sendNoteOn(lastSplitHighNote, 0, midiChannel2);
          usbMIDI.sendNoteOn(currentSplitHighNote, 127, midiChannel2);
        }
      }
    }
  }
  else {
    if (sustainActive == 1 && intervalActive == 0) {
      if (lastSustainActive == 0) {
        currentSustainNote = currentNote;
        //        usbMIDI.sendNoteOn(currentNote, breath, 2);
      }
    }
    else if (sustainActive == 1 && intervalActive == 1) {
      if (lastIntervalActive == 0) {
        sustainInterval = currentSustainNote - currentNote;
      }
      lastSustainNote = currentSustainNote;
      currentSustainNote = currentNote + sustainInterval;
    }
  }

  // ----------------------------------------------
  // ------------ Misc output section: -------------
  //------------------------------------------------
  if (lastPitchbend != pitchbend) {
    if(pitchbendLowRes == 1){
      usbMIDI.sendPitchBend(pitchbend << 7, midiChannel1);
      usbMIDI.sendPitchBend(pitchbend << 7, midiChannel2);
    }
    else if(pitchbendHighRes == 1){
      usbMIDI.sendPitchBend(pitchbend, midiChannel1);
      usbMIDI.sendPitchBend(pitchbend, midiChannel2);
    }
    //      Serial.print(pitchbend);
    //      Serial.print(" - ");
  }
  if (mpTouchVal != lastmpTouchVal) {
    usbMIDI.sendControlChange(lipCC, mpTouchVal, midiChannel1);
    usbMIDI.sendControlChange(lipCC, mpTouchVal, midiChannel2);
    //      Serial.print(mpTouchVal);
    //      Serial.print(" - ");
  }
  //    Serial.println();
}

I’m using Arduino 1.8.19 and Teensy loader 1.57, on Ubuntu 18.04.5
When I run this code, I get the first few Serial messages, up until “After ‘readMpTouch’”, plus the first text on the OLED, and then the Teensy 4.0 resets, giving the same output again after a pause. The whole cycle takes about 10 seconds.
Screenshot:
NewOHMs_Fail_03.png
I’m assuming that the problem is one of two things. Either electrical issues, or problems in my code.

I considered that all the external components might be overloading the 3.3v output of the Teensy, but some research seems to indicate that this isn’t the case. Here are the main current consumption candidates:
  • CNY70 LED - 50 ma (abs. max)
  • CNY70 transistor - 50 ma (abs. max)
  • OLED display - 20.7 ma (max)
  • 49E hall effect x2 - 5ma x2
  • MPR121x2 - 29ua x2
  • + A couple of potentiometers, switches and an encoder
  • Audio adapter
I’ve only found one reference to the audio adapter power consumption, here: https://forum.pjrc.com/threads/32542-Audio-board-power-consumption-etc, where Paul says that a Teensy 3.1 with two audio adapters use 67 ma, so the shield itself can’t be using much power.
Given that the Teensy 3.3v can provide 250ma, the power consumption of external components doesn’t appear to be the problem.

For normal operation of the instrument I run the Teensy off of a 1s lipo connected to Vin. (USB and Vin have been separated at the pads of course) The battery is connected through an Adafruit Lipo backpack, which is powered from the USB pin on the Teensy for charging I’ve checked the voltage at the Teensy Vin pin, which is at 4.15v, so that should work. But just in case, I’ve also tried supplying a stable 5v directly to Vin to bypass the whole battery/backpack setup, which doesn’t solve the problem.

The audio adapter works. I’ve added a line out jack, and when running the “PlaySynthMusic” example I get good outputs on both headphone and line out.
The Teensy is soldered straight to the audio adapter with extra long pins. And under that, an improvised breakout board is soldered straight to those same pins. The whole setup has to fit in a small space inside the instrument, and the final version will have an actual pcb instead of the home-grown breakout (if I ever get it to work…)

I’ve tested all the sensors and outputs separately, and they all work, although some tests revealed similar “spontaneous reset” problems.
For example: While running the code below, which just tests the two MPR121 capacitive sensors, the Serial output freezes at about 2000 ms in, and then picks up again after a couple of seconds, clearing the Serial monitor as shown in the screenshots. So it’s not a complete cyclical reset as in the actual “OHMs” code, but still similar symptoms.
NewOHMs_Fail_01.png
NewOHMs_Fail_02.png
Code:
#include <Wire.h>
#include "Adafruit_MPR121.h"


int activeMPR121[4] = {0, 0};

int mprAReadings[12];
int mprBReadings[12];


Adafruit_MPR121 capA = Adafruit_MPR121();
Adafruit_MPR121 capB = Adafruit_MPR121();

uint16_t MPRbinaryA = 0;

uint16_t MPRbinaryB = 0;

uint16_t lasttouched = 0;
uint16_t currtouched = 0;




void setup() {
  Serial.begin(9600);
  delay(1000);
  Serial.println("Adafruit MPR121 Capacitive Touch sensor test");
  if (!capA.begin(0x5A)) {
    Serial.println("MPR121 on 0x5A NOT found");
  }
  else {
    Serial.println("MPR121 on 0x5A active");
    activeMPR121[0] = 1;
  }
  if (!capB.begin(0x5B)) {
    Serial.println("MPR121 on 0x5B NOT found");
  }
  else {
    Serial.println("MPR121 on 0x5B active");
    activeMPR121[1] = 1;
  }

  delay(100);
  //  if(activeMPR121[0] == 1){
  capA.writeRegister(0x2E, 0b11111111);
  capA.writeRegister(0x32, 0b11111111);
  capA.writeRegister(0x35, 0b11111111);
  capA.setThresholds(20, 16);
  //  }
  //  if(activeMPR121[1] == 1){
  capB.writeRegister(0x2E, 0b11111111);
  capB.writeRegister(0x32, 0b11111111);
  capB.writeRegister(0x35, 0b11111111);
  capB.setThresholds(20, 16);
  //  }

}

void loop() {
  int lastMPRbinaryA = MPRbinaryA;
  int lastMPRbinaryB = MPRbinaryB;

  if (activeMPR121[0] == 1) {
    MPRbinaryA = capA.touched();
  }
  if (activeMPR121[1] == 1) {
    MPRbinaryB = capB.touched();
  }
  Serial.print(millis());
  Serial.print(" - ");
  Serial.print(MPRbinaryA, BIN);
  Serial.print(" - ");
  Serial.print(MPRbinaryB, BIN);
  Serial.print(" - ");
  Serial.print(capA.filteredData(11));
  Serial.println();
  delay(20);
}

I’m including a couple of photos of my setup, although given the ratsnest that it is, I don’t know how useful it will be. However, as I’m able to get all the sensors, audio and display to work separately (except for the "reset problems"), my conclusion is that there are no shorts or other such problems. The pins used for each component can be seen in the first part of the .ino file. I’ve taken care not to use the pins that are reserved for audio adapter functionality.
1668356055301b.jpg
1668356055132b.jpg
So that leaves me with a possible code problem, which I’ve not been able to find.

Of course I've googled a lot, mostly ending up right here on the forum, but haven't been able to find the solution
I realize this is quite a mouthful, and that maybe there are too many variables at play here for anyone to be able to untangle the problem. Even so, I thought I’d give it a shot, sharing as much info as possible.
Thanks in advance for any info, advice, or even just good questions that might set me on the right track.
Jeppe
 
So that leaves me with a possible code problem, which I’ve not been able to find.

Jeppe

Try putting the following at the beginning of your setup() function to see if it gives any clues:

Code:
if (CrashReport)Serial.print(CrashReport);

Mark J Culross
KD5RXT
 
Thanks Mark.
This is what the output from that looks like:
OHMs_CrashReport.png
Looks like I'm getting somewhere! Seems there is a bug to squash....
So it tells me to "Run "addr2line -e mysketch.ino.elf 0xCE26" for filename & line number."
Been trying to do that in terminal, but it's not working.
This:
Code:
/OHMs/NewOHMs_Code/Main_NewOHMs/newOHMs_nov22_024_exp$ addr2line -e newOHMs_nov22_024_exp.ino 0xCE26
gives this output: "File format not recognized"
And this:
Code:
 /NewOHMs_Code/Main_NewOHMs/newOHMs_nov22_024_exp$ addr2line -e newOHMs_nov22_024_exp.ino.elf 0xCE26
gives: "No such file"

Never used addr2line before. What's with the ".elf" extension?
Should I be using it differently?
Thanks!
 
I figured out the addr2line functionality.
For anyone else looking for this. You have to compile your sketch with verbose output turned on. Then you'll be able to find the location of the temporary ".ino.elf" file that's generated automatically, in the Arduino IDE output window below your code.
My file was at: /tmp/arduino_build_429277/newOHMs_nov22_024_exp.ino.elf
Then you can use that as an input for addr2line.

Here's the output I got from addr2line:
"/arduino-1.8.19/hardware/teensy/avr/libraries/Audio/synth_wavetable.cpp:152"

which is the first line of this function:
Code:
/**
 * @brief Set various integer offsets to values that will produce intended frequencies
 * @details the main integer offset, tone_incr, is used to step through the current sample's 16-bit PCM audio sample.
 * Specifically, the tone_incr is the rate at which the interpolation code in update() steps through uint32_t space.
 * The remaining offset variables represent a minimum and maximum offset allowed for tone_incr, which allows for low-frequency
 * variation in playback frequency (aka vibrato). Further details on implementation in update() and in sample_data.h.
 *
 * @param freq frequency of the generated output (between 0 and the board-specific sample rate)
 */
void AudioSynthWavetable::setFrequency(float freq) {
	float tone_incr_temp = freq * current_sample->PER_HERTZ_PHASE_INCREMENT;
	tone_incr = tone_incr_temp;
	vib_pitch_offset_init = tone_incr_temp * current_sample->VIBRATO_PITCH_COEFFICIENT_INITIAL;
	vib_pitch_offset_scnd = tone_incr_temp * current_sample->VIBRATO_PITCH_COEFFICIENT_SECOND;
	mod_pitch_offset_init = tone_incr_temp * current_sample->MODULATION_PITCH_COEFFICIENT_INITIAL;
	mod_pitch_offset_scnd = tone_incr_temp * current_sample->MODULATION_PITCH_COEFFICIENT_SECOND;
}

So it looks like the code crashes while setting the wavetable frequency....
Anyone have an idea why Teensy would crash in the middle of this: "float tone_incr_temp = freq * current_sample->PER_HERTZ_PHASE_INCREMENT;"
The comments to the function say that: "Specifically, the tone_incr is the rate at which the interpolation code in update() steps through uint32_t space.", but I'm afraid I'm unable to turn that into actionable information that might help me solve my problem.
 
The sample for all 4 wavetables is set in void setup() at line 508+ with this:
Code:
  wavetable1.setInstrument(altosax);
  wavetable2.setInstrument(altosax);
  wavetable3.setInstrument(altosax);
  wavetable4.setInstrument(altosax);

altosax.h has a list of samples for different pitch ranges, which looks like this:

Code:
extern const uint32_t sample_0_altosax_asaxc2[640];

extern const uint32_t sample_1_altosax_asaxe2[640];

extern const uint32_t sample_2_altosax_asaxg2[896];

extern const uint32_t sample_3_altosax_asaxd3[384];

extern const uint32_t sample_4_altosax_asaxf3[512];

extern const uint32_t sample_5_altosax_asaxc4[640];

extern const uint32_t sample_6_altosax_ssaxdx4[640];

and here is a section of the call to one of those samples from altosax.cpp:
Code:
    (int16_t*)sample_0_altosax_asaxc2, // sample
    true, // LOOP
    11, // LENGTH_BITS
    (1 << (32 - 11)) * WAVETABLE_CENTS_SHIFT(36) * 44100.0 / AudioSynthWavetable::noteToFreq(71) / AUDIO_SAMPLE_RATE_EXACT + 0.5, // PER_HERTZ_PHASE_INCREMENT
    ((uint32_t)1149 - 1) << (32 - 11), // MAX_PHASE
    ((uint32_t)1145 - 1) << (32 - 11), // LOOP_PHASE_END
    (((uint32_t)1145 - 1) << (32 - 11)) - (((uint32_t)1054 - 1) << (32 - 11)), // LOOP_PHASE_LENGTH
    uint16_t(UINT16_MAX * WAVETABLE_DECIBEL_SHIFT(-4.5)), // INITIAL_ATTENUATION_SCALAR
    uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DELAY_COUNT
    uint32_t(6.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // ATTACK_COUNT
    uint32_t(20.01 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // HOLD_COUNT
//    uint32_t(20.01 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
//    uint32_t(100.02 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
    uint32_t(10.01 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // DECAY_COUNT
    uint32_t(50.02 * AudioSynthWavetable::SAMPLES_PER_MSEC / AudioSynthWavetable::ENVELOPE_PERIOD + 0.5), // RELEASE_COUNT
    int32_t((1.0 - WAVETABLE_DECIBEL_SHIFT(-4.4)) * AudioSynthWavetable::UNITY_GAIN), // SUSTAIN_MULT
    uint32_t(0.00 * AudioSynthWavetable::SAMPLES_PER_MSEC / (2 * AudioSynthWavetable::LFO_PERIOD)), // VIBRATO_DELAY
    uint32_t(0.1 * AudioSynthWavetable::LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // VIBRATO_INCREMENT
    (WAVETABLE_CENTS_SHIFT(0) - 1.0) * 4, // VIBRATO_PITCH_COEFFICIENT_INITIAL
    (1.0 - WAVETABLE_CENTS_SHIFT(0)) * 4, // VIBRATO_COEFFICIENT_SECONDARY
    uint32_t(260.01 * AudioSynthWavetable::SAMPLES_PER_MSEC / (2 * AudioSynthWavetable::LFO_PERIOD)), // MODULATION_DELAY
    uint32_t(5.0 * AudioSynthWavetable::LFO_PERIOD * (UINT32_MAX / AUDIO_SAMPLE_RATE_EXACT)), // MODULATION_INCREMENT
    (WAVETABLE_CENTS_SHIFT(9) - 1.0) * 4, // MODULATION_PITCH_COEFFICIENT_INITIAL
    (1.0 - WAVETABLE_CENTS_SHIFT(-9)) * 4, // MODULATION_PITCH_COEFFICIENT_SECOND
    int32_t(UINT16_MAX * (WAVETABLE_DECIBEL_SHIFT(0) - 1.0)) * 4, // MODULATION_AMPLITUDE_INITIAL_GAIN
    int32_t(UINT16_MAX * (1.0 - WAVETABLE_DECIBEL_SHIFT(0))) * 4, // MODULATION_AMPLITUDE_FINAL_GAIN
  },

And here is the data for that specific sample:
Code:
const uint32_t sample_0_altosax_asaxc2[640] = {
0x00000000,0x04450304,0x0235017f,0x0204024b,0x025f022e,0x01e20214,0x003b01dd,0xff46ff02,
0xfe8afe77,0xfd59fefa,0xfddefe03,0xfcaefc6e,0xfb49fc87,0xfb8efb4c,0xfdb0fc67,0xfba0fd14,
0xfd2ffcb6,0xfd5efc12,0xfe36fe0c,0x00af0024,0x011b0113,0x014200a8,0x00f100d8,0x02f5029b,
0x01a60165,0x0252035b,0x030801be,0x03230343,0x020f0291,0x01f001b7,0xff9c0109,0xffb1ffb7,
0xfd80fea5,0xfd3cfcd1,0xfaa9fb37,0xf9b4fb6d,0xf9c4f9ae,0xfa17fa87,0xfa2bf969,0xf9f4f9b3,
0xfc5dfae7,0xfcfafd69,0xff90fe67,0x01b800b1,0x01f001b2,0x044d033d,0x05a2048e,0x064c0699,
0x0585059d,0x065905a3,0x0583059c,0x04e0058a,0x037e04ea,0x02e20282,0x016e01e8,0x0173019e,
0xfdc4fff1,0xfcdefd09,0xfc13fce9,0xfa89fb1b,0xfa15fa9d,0xf8f1f94b,0xf92df93f,0xf89df86a,
0xfbb3fafb,0xfd22fb7d,0xfd3bfdc7,0xfee8fea0,0x00e9fff8,0x02c90151,0x039f037f,0x04a1045e,
0x050c04be,0x05d204e9,0x04ea05e1,0x04e60484,0x0534045c,0x04da0531,0x02de03d5,0xffca0172,
0x0058fefe,0xfd410031,0xf95dfa48,0xf59ff95a,0xf4d2f48f,0xf454f2e0,0xf4b8f4ca,0xf61df524,
0xf94ff760,0xfcbefaf8,0xff97feb5,0x034400ff,0x054003de,0x06cd0603,0x087207a0,0x09cd0968,
0x0b380a37,0x0ae40b25,0x0a4a0ad1,0x08b209d5,0x068f071d,0x0414046c,0x024d0349,0xffa300ee,
0xfe03ff0d,0xfd0ffe19,0xf954fb35,0xf742f817,0xf3eaf4b2,0xf5ddf5bc,0xf4e7f543,0xf622f50e,
0xf631f58e,0xfa82f898,0xfe13fca9,0x0124ffc3,0x033f0241,0x053c038c,0x06a1068f,0x08520782,
0x0808088c,0x09a608c7,0x08910914,0x090c08d5,0x06e5078c,0x077707ac,0x0748072a,0x0554056d,
0x020504b5,0xfd91ff6e,0xfb04fd56,0xee18f4d8,0xe4dfe860,0xe554e418,0xeaa9e815,0xef95ed60,
0xf8a2f3d9,0xfe02fbbb,0x032c00e9,0x05ac0496,0x079606e7,0x09530820,0x0e080b2a,0x11160fd1,
0x138d1260,0x12221391,0x0efb105e,0x0a630cec,0x061c07aa,0x02090440,0x0108011f,0x0177019b,
0xffa30108,0xfc8cfeac,0xfa38fa19,0xf535f84b,0xeeb8f2a8,0xed3ced90,0xeb4beb2e,0xef0fed3c,
0xf5fef260,0xfb0bf8a1,0xffa1fd1d,0x044b0290,0x074e0563,0x087a0857,0x0acc0949,0x0aab0b41,
0x0bce0b2e,0x0b250c1c,0x0a130a15,0x085608f2,0x08440877,0x09d608b4,0x0c760a9d,0x102f0e49,
0x11a3106d,0x08df1080,0xd36ff5d4,0xc589b9f9,0xe84bdd73,0xeecbf332,0xc94dd31c,0xed3ed735,
0x0621fb16,0x0c8a0d23,0x08380b04,0x007c0400,0x04180050,0x0e7608d5,0x19c71529,0x1bc11a1e,
0x1d211ec7,0x16dd1960,0x0df31475,0x05590869,0xfd32019d,0xfedffd9c,0xffc5fd24,0x01a90006,
0x06b10524,0x03bb05fd,0xfb1a010e,0xf0a1f535,0xec3aee58,0xe99eea55,0xe9f3e8b9,0xed80ebc0,
0xf6e9f2ef,0x0036fb52,0x05b90388,0x0869076e,0x0912081e,0x0bfe0a67,0x0adf0c6c,0x068f08af,
0x05fa0547,0x07e60695,0x09b808c7,0x09130967,0x0bc30995,0x166810c4,0x24721d65,0x281d29d1,
0xe32b19c3,0xb60ea105,0xe7c0f38a,0xcba7cc88,0xb826b425,0xd020ba15,0x0cc8fe36,0x18771339,
0x0c651716,0xfafa04d5,0xfd14f417,0x0330041c,0x121308c3,0x18e7172a,0x2900231c,0x260725d4,
0x2186278b,0x0866133f,0xfba4037c,0xfa03f700,0x0002f6bd,0xf7d9fc8b,0x086106bc,0x0b860970,
0x09a40dc9,0x00e00264,0xf555f920,0xf09bf074,0xeb9beed0,0xeb95ebf7,0xf1c6ed57,0xf96df5a8,
0x0381fdc8,0x05ce0645,0x0a8007e4,0x0cdc0c85,0x06fe0bf5,0x01470322,0xfa4efe55,0xfeacf9a6,
0x019e0130,0x040b01ca,0x079a05d2,0x16640e96,0x28f81e8b,0x3de23677,0x109c3a8a,0x941eb18f,
0xeb8cdee8,0xc71dbe13,0xb247b848,0xab68b83a,0xff14d686,0x189a0e5d,0x1e13222a,0x0a45145e,
0xfcb4fbfb,0xfea003ef,0x03dbfc36,0x10930d66,0x269a1983,0x2c482826,0x2d5b311b,0x132b2044,
0x04ae0b8a,0xfce0faaf,0xf858f286,0xed9ffe4f,0x0760fc1e,0x0b3406f4,0x12ae10d3,0x09a50cfa,
0xfb8801dd,0xf2def539,0xf0f5efc9,0xef60f1f5,0xf78ef094,0xfd9afb61,0x05270007,0x0b020b4f,
0x09120985,0x0d2f0d8c,0x09af0af3,0x001b0538,0xf472fa4c,0xf033eee4,0xf6dcf447,0xfafaf8fe,
0x01b2ff47,0x141407c7,0x2ef220a7,0x4a7a4179,0x0e58427a,0x9cacac77,0xe1c9e5fb,0xc2efb908,
0xbb47aeb5,0xa0a4bf5a,0xdf02b50e,0x14010059,0x2ebf2929,0x130620fe,0x05920462,0x02bc0992,
0x03a0ff1c,0x0d580b41,0x1d401571,0x28f51eee,0x30063278,0x1edc2713,0x0ac9174b,0x02f00138,
0xfbf7f3ac,0xec8dfc8f,0x0181f95f,0x065502f3,0x0f670e60,0x117b1099,0x00b60918,0xf541f925,
0xf2d4ef5a,0xf286f4fc,0xfcb4f516,0x001ffd40,0x0a190476,0x107d0f9e,0x0deb0ff7,0x0ffd0eca,
0x08810c04,0x00fa0615,0xf0c8f9a6,0xea45ea9e,0xefb2ec3e,0xf69ef382,0xfe26fa48,0x0f1502a2,
0x2e961ee7,0x4f50446c,0xfcc94441,0xa68b987d,0xd74cf089,0xbae1b787,0xc580a63d,0x9ab4bb51,
0xcae9a62b,0x0e96f3d7,0x376e2ae0,0x145b2b3e,0x0b0c0579,0x091f0d53,0x0c9b06cd,0x111612f6,
0x18e917d4,0x2541183d,0x2ddd30ab,0x1fe026c3,0x0b901a57,0x050b06c3,0x0431f772,0xef69f9b6,
0x0146fc4e,0x05500431,0x0cb60cd7,0x0fa70f62,0xfefa0812,0xf6a2fa98,0xf5eff396,0xf131f481,
0xff44f621,0x046700eb,0x0d1e073e,0x15661313,0x147916a4,0x136113be,0x07170b99,0xff230597,
0xeb16f626,0xe65ee506,0xeb32e7ab,0xf774f103,0x0034fc67,0x132304c3,0x3778255f,0x51624bcc,
0xc4592ac2,0xd23d8d60,0xbcd6ec29,0xa696b3cc,0xcd30b074,0x9856a927,0xc944a352,0x13b9f696,
0x38ab2de3,0x0ef129a0,0x11910a61,0x0dfb0e49,0x190a10ba,0x1c1b1d48,0x17351cbc,0x2ad61b1a,
0x26b6305e,0x1fd6217f,0x0a4f157f,0xfad108f7,0x02f8fe53,0xf7fcf28e,0x0243fd76,0x08e70528,
0x0bd30bad,0x0ecb1002,0xfc3b0602,0xf372f517,0xf4baf3d6,0xf09df2a1,0x006cfa6a,0x08360305,
0x106c0c22,0x15931352,0x1988198d,0x1636193e,0x090f0d7d,0xfe8004fd,0xe7f5f345,0xe2eee2c3,
0xe6f4e444,0xf63ced4d,0x044afe11,0x1d8a0c34,0x451031f2,0x416d558f,0x9378e918,0xf130ba81,
0xafbeca70,0xa0dea393,0xb4eec875,0x96cf9916,0xdc62ade3,0x1eda0358,0x34cc342c,0x0acb1c1a,
0x13431330,0x12881016,0x21e51905,0x28c5281d,0x19b31d57,0x2f542577,0x1fa52b4b,0x1a5d1d50,
0x0aa30bf8,0xf952fcb2,0xf5ed0511,0xfc2cf532,0x0484fe30,0x0bab07bf,0x0bb00a91,0x0840106d,
0xf530ff54,0xf3a1f174,0xf4b4f4b6,0xf6fef217,0xfffafd2b,0x0a970599,0x12bc0fc9,0x188d13b3,
0x1d691d3e,0x14d11d81,0x0ac70de3,0xf7ab0357,0xe515eab7,0xe3cbe375,0xe584e2be,0xf8b4ef1b,
0x0af701e8,0x310c1a01,0x574746e3,0xee4a49e9,0xbd73955e,0xd1c7f87b,0x9c04b177,0xc7f19ab4,
0x9765b68d,0xa1208f39,0xf775cd23,0x2c421475,0x207235ce,0x13740afc,0x11291603,0x1a3c13cb,
0x2b5f228f,0x26413134,0x28891c08,0x306c3354,0x1e3e259d,0x0f321c32,0xff7d0dc7,0x03c7f656,
0xf698f676,0xf9f7fbf7,0x05d80156,0x09db0a66,0x0fdc092c,0x005607bb,0xee5cf646,0xf1aff0de,
0xf30af36d,0xfc88f68a,0x0361fed3,0x104b09da,0x15a7159e,0x20031864,0x209521ff,0x0e54179a,
0x066c0b17,0xe96ffa87,0xe21ee3c3,0xe2b7e473,0xe76fdf27,0x005ef44b,0x1ad50ba2,0x47333037,
0x4ba15519,0x97b7f6d0,0xfd54bce2,0xb5d3d70d,0x98629d97,0xb809c7af,0x8961956f,0xc8c69b26,
0x0ccaf0a6,0x325825eb,0x0a4122d0,0x15120f3a,0x14ef11b3,0x21121b23,0x306b2bce,0x1f242852,
0x371629e8,0x28ef3347,0x1e472222,0x0f4d1160,0xf6bd00bf,0xf6d10327,0xfc38f681,0x001ef9b6,
0x09cf0505,0x09290a02,0x07ee0fba,0xf6460051,0xf08aee5c,0xf290f124,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,

};
altosax.cpp and altosax.h are both included before setup(). This sample, as well as all the others have been thoroughly tested in my previous version of the instrument on the Teensy 3.2, and nothing in those files has been changed.

wavetable.setfrequency is indeed called even if the note is not playing, meaning if the amplitude of that wavetable is set to 0, but that's never been a problem before.

The only function that calls "wavetable.setfrequency" is "void Wind1WavetableSetFreq(float freq)" in the synthfunctions.h file.
That function is only called twice (one for each set of wavetables) at line 801 and 802 in the main .ino file.
 
Last edited:
The sample for all 4 wavetables is set in void setup() at line 508+ with this:
Code:
  wavetable1.setInstrument(altosax);
  wavetable2.setInstrument(altosax);
  wavetable3.setInstrument(altosax);
  wavetable4.setInstrument(altosax);

wavetable.setfrequency is indeed called even if the note is not playing, meaning if the amplitude of that wavetable is set to 0, but that's never been a problem before..
So, there’s your problem:
Code:
 	/**
	 * @brief Set the instrument_data struct to be used as the playback instrument.
	 *
	 * A wavetable uses a set of samples to generate sound.
	 * This function is used to set the instrument samples.
	 * @param instrument a struct of type instrument_data, commonly prodced from a
	 * decoded SoundFont file using the SoundFont Decoder Script which accompanies this library.
	 */
	void setInstrument(const instrument_data& instrument) {
		cli();
		this->instrument = &instrument;
		[COLOR="#FF0000"][B]current_sample = NULL;[/B][/COLOR]
		env_state = STATE_IDLE;
		state_change = true;
		sei();
	}
Might not have been a problem before, but it clearly is now. It’s poor coding on the part of the library authors, but what can you expect when their idea of documentation is “blah blah”.
 
Thank you so much h4yn0nnym0u5e

I'm trying to wrap my head around this.
Are you saying that there have been changes in the audio library (specifically to synth_wavetable.h) that means my code doesn't work? Or am I misunderstanding you completely?

Having a look on github at pauls original commit of the wavetable sections from 2018, it looks like the section you mention is exactly the same.
Code:
void setInstrument(const instrument_data& instrument) {
		cli();
		this->instrument = &instrument;
		current_sample = NULL;
		env_state = STATE_IDLE;
		state_change = true;
		sei();
	}

I have just now confirmed that by commenting out all calls to the audio sections of my code in void loop(), the reset doesn't happen. But my previous (working) implementation using the Teensy 3.2 uses the exact same code for the audio sections, so I still don't understand what the problem is.
Can you point me to what I would have to change specifically, in the call to setInstrument or setFrequency or the general setup?
 
I’d guess that a Teensy 3.2 doesn’t catch a write via a NULL pointer, so you didn’t see the issue before. I’d need to check over the memory map to see if it could cause mayhem.

For now, I’d suggest you never call setFrequency() for an object that isn’t playing, or setInstrument() for one that is playing. In the longer term, the AudioSynthWavetable object needs some bugs fixed… and some documentation.
 
Yes!!
I put a call to "wavetable.stop();" before my instrument changes, and "if(wavetable.isPlaying())" before setting the frequency, and I'm now out of reset-land.
Thank you h4yn0nnym0u5e!!

PS: I get it now :D
but what can you expect when their idea of documentation is “blah blah”.
Blah blah.png
 
Back
Top