Strange error when reconnecting Teensy (audio board not working on reboot)

Status
Not open for further replies.

mattybrad

Member
Hi all,

I've got some odd behaviour in a sketch I've written. It's a fairly complicated synthesizer sketch but it works fine on my Teensy 3.2 with the audio board, until I unplug the Teensy and plug it back in again. When I do this, the LED on the Teensy is no longer lit and no audio comes out of the headphone socket, even though the sketch appears to be running normally (the Serial.println() commands still work).

This behaviour happens when I plug the Teensy back into my (Windows) computer, or if I just power it using a phone charger. Once the behaviour has happened, the only way I have found to get my sketch working again is to upload another audio board sketch (e.g. the PlaySynthMusic example). After uploading that sketch, I can then upload my sketch again and it works (until I unplug the Teensy!).

My sketch is rather huge and sprawls across lots of files, but I've pasted the main .ino file contents just in case anyone can spot an obvious mistake. I'm also doing a lot of stuff with pointers and references in this sketch, which I'm fairly new to, so please do say if it looks like I'm doing something silly with those that could be causing this issue.

Any help gratefully received!

GitHub link here in case that helps, too (slightly older version, before I started bug-hunting, but same problem): https://github.com/mattybrad/modularsynth2/tree/master/teensymodsynth

Matt

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

#include "Module.h"
#include "PatchCable.h"
#include "Output.h"
#include "VCO.h"
//#include "Mixer.h"
//#include "LFO.h"
//#include "VCF.h"
//#include "Noise.h"
//#include "Envelope.h"
//#include "VCA.h"

#define EMPTY_MODULE 0
#define OUTPUT_MODULE 1
#define VCO_MODULE 2
#define VCF_MODULE 3
#define VCA_MODULE 4
#define MIXER_MODULE 5
#define LFO_MODULE 6
#define NOISE_MODULE 7
#define ENVELOPE_MODULE 8

#define MODULE_SLOTS 8
#define SOCKET_RECEIVE_DATA_PIN 27
#define MODULE_ID_PIN 28
#define ANALOG_DATA_PIN 33
#define MAX_CABLES 100
const int NUM_SOCKETS = MODULE_SLOTS * 8;
const int SOCKET_SEND_ROOT_SELECT_PINS[] = {2,3,4};
const int SOCKET_RECEIVE_ROOT_SELECT_PINS[] = {17,20,21};
const int SOCKET_SEND_MODULE_SELECT_PINS[] = {5,8,16};
const int SOCKET_RECEIVE_MODULE_SELECT_PINS[] = {24,25,26};

Module *modules[MODULE_SLOTS]; // array of pointers to module instances
PatchCable *patchCables[MAX_CABLES];
byte moduleIdReadings[MODULE_SLOTS]; // readings of module IDs - changes will causes program to update module listing
boolean patchCableConnections[NUM_SOCKETS][NUM_SOCKETS];

AudioControlSGTL5000 sgtl;

void setup() {

  Serial.begin(9600);

  // initialise audio board
  AudioMemory(80);
  sgtl.enable();
  sgtl.volume(0.5);

  // initialise mux/demux pins
  for(int i=0;i<3;i++) {
    pinMode(SOCKET_SEND_ROOT_SELECT_PINS[i], OUTPUT);
    pinMode(SOCKET_SEND_MODULE_SELECT_PINS[i], OUTPUT);
    pinMode(SOCKET_RECEIVE_ROOT_SELECT_PINS[i], OUTPUT);
    pinMode(SOCKET_RECEIVE_MODULE_SELECT_PINS[i], OUTPUT);
  }
  pinMode(SOCKET_RECEIVE_DATA_PIN, INPUT);
  pinMode(MODULE_ID_PIN, INPUT);

  // read module slots
  for(int a=0;a<MODULE_SLOTS;a++) {
    digitalWrite(SOCKET_SEND_ROOT_SELECT_PINS[0],bitRead(a,0));
    digitalWrite(SOCKET_SEND_ROOT_SELECT_PINS[1],bitRead(a,1));
    digitalWrite(SOCKET_SEND_ROOT_SELECT_PINS[2],bitRead(a,2));
    
    for(int b=0;b<8;b++) {
      digitalWrite(SOCKET_SEND_MODULE_SELECT_PINS[0],bitRead(b,0));
      digitalWrite(SOCKET_SEND_MODULE_SELECT_PINS[1],bitRead(b,1));
      digitalWrite(SOCKET_SEND_MODULE_SELECT_PINS[2],bitRead(b,2));

      bitWrite(moduleIdReadings[a],b,digitalRead(MODULE_ID_PIN));
    }

    // test code, overrides actual readings
    if(true) {
      moduleIdReadings[a] = EMPTY_MODULE;
      moduleIdReadings[0] = OUTPUT_MODULE;
      moduleIdReadings[1] = VCO_MODULE;
    }

    switch(moduleIdReadings[a]) {
      case EMPTY_MODULE:
      modules[a] = NULL;
      break;

      case OUTPUT_MODULE:
      modules[a] = new Output();
      break;

      case VCO_MODULE:
      modules[a] = new VCO();
      break;

      case MIXER_MODULE:
      //modules[a] = new Mixer();
      break;

      case LFO_MODULE:
      //modules[a] = new LFO();
      break;

      case VCF_MODULE:
      //modules[a] = new VCF();
      break;

      case VCA_MODULE:
      //modules[a] = new VCA();
      break;

      case NOISE_MODULE:
      //modules[a] = new Noise();
      break;

      case ENVELOPE_MODULE:
      //modules[a] = new Envelope();
      break;

      default:
      modules[a] = NULL;
    }
  }

  AudioProcessorUsageMaxReset();
  AudioMemoryUsageMaxReset();

  delay(5000);
}

void loop() {

  boolean newConnectionReading;
  for(int a=0;a<8;a++) {
    // switch the root socket send channel
    digitalWrite(SOCKET_SEND_ROOT_SELECT_PINS[0],bitRead(a,0));
    digitalWrite(SOCKET_SEND_ROOT_SELECT_PINS[1],bitRead(a,1));
    digitalWrite(SOCKET_SEND_ROOT_SELECT_PINS[2],bitRead(a,2));
    
    for(int b=0;b<8;b++) {
      // switch the module socket send channel
      digitalWrite(SOCKET_SEND_MODULE_SELECT_PINS[0],bitRead(b,0));
      digitalWrite(SOCKET_SEND_MODULE_SELECT_PINS[1],bitRead(b,1));
      digitalWrite(SOCKET_SEND_MODULE_SELECT_PINS[2],bitRead(b,2));

      for(int c=0;c<8;c++) {
        // switch the root socket receive channel
        digitalWrite(SOCKET_RECEIVE_ROOT_SELECT_PINS[0],bitRead(c,0));
        digitalWrite(SOCKET_RECEIVE_ROOT_SELECT_PINS[1],bitRead(c,1));
        digitalWrite(SOCKET_RECEIVE_ROOT_SELECT_PINS[2],bitRead(c,2));

        for(int d=0;d<8;d++) {
          // switch the module socket receive channel
          digitalWrite(SOCKET_RECEIVE_MODULE_SELECT_PINS[0],bitRead(d,0));
          digitalWrite(SOCKET_RECEIVE_MODULE_SELECT_PINS[1],bitRead(d,1));
          digitalWrite(SOCKET_RECEIVE_MODULE_SELECT_PINS[2],bitRead(d,2));

          int socket1 = a*8+b;
          int socket2 = c*8+d;

          if(modules[d]) modules[d]->update();

          if(socket1 > socket2) {
            newConnectionReading = false;
            if(digitalRead(SOCKET_RECEIVE_DATA_PIN)) {
              newConnectionReading = true;
            }

            // testing code, overrides any actual connections
            if(true) {
              if(fakeConnection(socket1,socket2,1,1,0,0)) newConnectionReading = true;
            }
      
            if(newConnectionReading != patchCableConnections[socket1][socket2]) {
              if(newConnectionReading) {
                // make connection
                addPatchCable(socket1,socket2);
              } else {
                // break connection
                removePatchCable(socket1,socket2);
              }
            }
            patchCableConnections[socket1][socket2] = newConnectionReading;
          }
        }
      }
    }
  }
  Serial.println(AudioMemoryUsageMax());
  Serial.println(AudioProcessorUsageMax());
}

void addPatchCable(int highSocket, int lowSocket) {
  int foundIndex = -1;
  for(int i=0;i<MAX_CABLES&&foundIndex==-1;i++) {
    if(patchCables[i]==NULL) foundIndex = i;
  }
  if(foundIndex >= 0) {
    patchCables[foundIndex] = new PatchCable(highSocket, lowSocket, getSocket(highSocket), getSocket(lowSocket));
    Serial.println("ADDED CABLE");
  } else {
    Serial.println("CAN'T ADD NEW CABLE");
  }
}

void removePatchCable(int highSocket, int lowSocket) {
  for(int i=0;i<MAX_CABLES;i++) {
    if(patchCables[i]!=NULL) {
      // a cable exists in this slot
      if(highSocket==patchCables[i]->getHighSocket() && lowSocket==patchCables[i]->getLowSocket()) {
        // remove cable
        patchCables[i]->disconnect();
        delete patchCables[i];
        patchCables[i] = NULL;
        Serial.println("REMOVED CABLE");
      }
    }
  }
}

Socket &getSocket(int socketNumber) {
  int moduleNumber = socketNumber / 8;
  int moduleSocketNumber = socketNumber % 8;
  Serial.println(moduleNumber);
  Serial.println(moduleSocketNumber);
  return modules[moduleNumber]->getSocket(moduleSocketNumber);
}

boolean fakeConnection(int socket1, int socket2, int module1, int moduleSocket1, int module2, int moduleSocket2) {
  int testSocket1 = 8*module1 + moduleSocket1;
  int testSocket2 = 8*module2 + moduleSocket2;
  if(socket1==testSocket1 && socket2==testSocket2) return true;
  if(socket1==testSocket2 && socket2==testSocket1) return true;
  return false;
}
 
Hi all,

I've got some odd behaviour in a sketch I've written. It's a fairly complicated synthesizer sketch but it works fine on my Teensy 3.2 with the audio board, until I unplug the Teensy and plug it back in again. When I do this, the LED on the Teensy is no longer lit and no audio comes out of the headphone socket, even though the sketch appears to be running normally (the Serial.println() commands still work).

This behaviour happens when I plug the Teensy back into my (Windows) computer, or if I just power it using a phone charger. Once the behaviour has happened, the only way I have found to get my sketch working again is to upload another audio board sketch (e.g. the PlaySynthMusic example). After uploading that sketch, I can then upload my sketch again and it works (until I unplug the Teensy!).

It seems that your sketch is missing a proper audio update functionality.
(does the audiomemoryusagemax print indicate 0?)

Initialization of the sgtl5000 requires stable I2S clocks.
I cannot see any I2S audio object in your code, maybe you could simply add a dummy I2S_input/output object?
 
It seems that your sketch is missing a proper audio update functionality.
(does the audiomemoryusagemax print indicate 0?)

Initialization of the sgtl5000 requires stable I2S clocks.
I cannot see any I2S audio object in your code, maybe you could simply add a dummy I2S_input/output object?

Thanks for taking a look. There is an I2S audio object but it's in the Output.h class. The code is a bit unusual in that I'm trying to make a modular synth, where you can add and remove various physical modules, each of which represents part of the signal chain, so all the audio objects which would normally be declared statically at the start of the sketch are actually added dynamically (the Teensy checks to see which modules are present using digitalRead then creates the audio objects accordingly).

This sounds like a recipe for disaster, but the code does work as expected until the Teensy is unplugged. Audio is produced (a simple saw wave in the code I pasted) and AudioMemoryUsageMax is 4. Interestingly, even when I do disconnect and reconnect the Teensy, AudioMemoryUsageMax is still 4, even though audio is no longer audible.

I'll keep stripping out more of the code to see if I can find the source of the problem...
 
maybe you could simply add a dummy I2S_input/output object?

Okay, looks like you were right! I declared the output object at the beginning of the sketch (since there'll only ever be one of them anyway) and it now works. Thank you!
 
Status
Not open for further replies.
Back
Top