Cannot use Teensy as I2C slave when sgtl audio is enabled

Status
Not open for further replies.

jeraymond

Member
Hello,

I have a Teensy setup with the Audio Adaptor Board and am able to play sound. I'm looking to be able to send a message to the Teensy to tell it which audio to play. In my project I'm using the I2C for other communications and would like to use the audio Teensy also as an I2C slave to receive the play command.

I'm able to use the Teensy as an I2C slave stand alone, and as an audio player stand alone. However when I try to do both, using the Teensy as an I2C slave fails. I see errors on the sending master side when trying to talk to the Teensy. In the Teensy code snippet below, once sgtl5000_1.enabled() is called the Teensy no longer works as a I2C slave. (Audio is still playable. I have the play code stripped out the example below.)

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

// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=167,181
AudioMixer4              mixer1;         //xy=368,155
AudioAnalyzePeak         peak2;          //xy=418,342
AudioAnalyzePeak         peak1;          //xy=419,305
AudioOutputI2S           i2s1;           //xy=546,193
AudioConnection          patchCord1(playSdWav1, 0, peak1, 0);
AudioConnection          patchCord2(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord3(playSdWav1, 1, peak2, 0);
AudioConnection          patchCord4(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord5(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=165,264
// GUItool: end automatically generated code

// Receive interrupt callback
void on_receive(int num_bytes) {
  while (Wire.available()) {
    char c = Wire.read();
    Serial.print(c);
  }
}

// Send interrupt callback
void on_request() {
  Serial.print("request\n");
}

void setup() {
  Wire.begin(0x35);
  Wire.onReceive(on_receive);
  Wire.onRequest(on_request);
  AudioMemory(10);

  // When enabled using Teensy as I2C slave no longer works
  // When commented out I2C slave receive is OK
  sgtl5000_1.enable();

  Serial.print("Setup complete\n");
}

void loop() {
  // Unused
}

Should this work? My suspicion is that it doesn't because when the sgtl is enabled the Teensy now acts as an I2C master to talk to the Audio Board and can no longer work as a slave. Is this presumption correct or is the problem something else. Any suggestions on fixing this? Ideally I'd like to talk to the Teensy as an I2C slave to trigger the audio.
 
Sure, the shield uses I2C with Teensy as the master. It can't be Master AND Slave ! Which Teensy you are using ? The Teensy 3.5 & 3.6 have two I2c intefaces.
 
Sure, the shield uses I2C with Teensy as the master. It can't be Master AND Slave !

Correct, however, after initialization of the SGTL5000 and no SGTL5000 commands in the loop() function, it should be possible to reuse the I2C in slave mode, or am I wrong?
 
Don't know.. never tried that with the Wire library. Theoretically yes, but is this supported by the lib ?
Edit: The posted sketch uses sgtl5000_1.enable() (which uses I2C as master) ; after setting up the slave. Maybe it works with moving this line to the top ?
 
Success!

I'm using a Teensy 3.2. Reordering the initialization worked. I change is such that I have

Code:
// Audio setup
AudioMemory(10);
sgtl5000_1.enable();
sgtl5000_1.volume(0.75);

// I2C slave setup
Wire.begin(0x35);
Wire.onReceive(on_receive);
Wire.onRequest(on_request);

I'm now able to receive the I2C commands as a slave, store the command in the call back on_receive, and then play some audios based upon that data from the main loop.

Re-reading the Audio Board page I see

The I2C pins SDA and SCL are used to control the chip and adjust parameters.

Something I've not tried is to see if I'm now still able to adjust sgtl5000 parameters after setting up the Wire library as in I2C slave. I suspect this may not work. Perhaps one can switch between the master and slave modes using sgtl5000.enable() before each time a audio config change and then switch back to I2C slave mode with Wire.(0x53). For my use case I just need to configure the sgtl5000 once, so doing so then switching to I2C slave works for me.

Thanks for the suggestions.
 
The Teensy 3.2 I'm using also has a secondary I2C interface. I used pin 29 and 30 pads on the bottom of the board and moved the control communications to that secondary I2C and used Wire1 in my sketch, keeping the first I2C interface for the audio board control only.
 
Very little testing has been done with master mode when Wire.begin(addr) is used to configure for slave mode.

It might work. Or it might not. If it does work at all, there might be possible issues with bus arbitration, which could be really frustrating random or intermittent failures. In theory this stuff is all supposed to work with I2C. But in practice, the Wire library has been tested in 2 use cases, exclusively master mode and exclusively slave mode. Mixing the 2 of going far off the well-worn path.

Using 2 separate ports is probably a much safer choice.
 
Status
Not open for further replies.
Back
Top