Teensy 4.1 TDM issue

Status
Not open for further replies.
Hi, Teensy warriors!

I've run into a weird T4.1 issue. Currently working on a manufactured prototype PCB with two MCUs (T4.0 and T4.1), 4 I2S/TDM ΔΣ DACs (CS42448, PCM1681, PCM3060 and WM8731), 2 SPI TFTs (ILI9225 and ILI9341), additional 8-ch ADCs on SPI2, 16 pots multiplexed with 74HC4067, etc. The power section supplies ±12V for the op-amps, two separate +5V/800mA lines for the analog section and Teensy, and 3.3V/1000mA for digital. Digital signals are separated from the analog section (their traces never cross), SPI lines are as short as possible, every single component is thoroughly decoupled with adequate caps. I use a combination of star ground and digital / analog ground planes, connected together in the very center of the PCB.
With I2S / I2S2 everything works as it should on both MCUs. 12-bit ADC readings are rock steady even without analogReadAveraging / ResponsiveAnalogRead, no problem whatsoever. With T4.0 TDM / TDM2 audio works normally, but when I switch to T4.1 (they go into the same socket, I just swap them) everything suddenly goes haywire :confused: Periodical 150-200mV spikes are appearing in the audio signal on all channels, manifesting as audio crackling and high frequency noise. ADC readings are all over the place; I have to use both analogReadAveraging(16) and ResponsiveAnalogRead with setActivityThreshold(16) to get at least somewhat stable reading: I guess the same spikes are bleeding into the ADC. I tried literally everything, made another prototype without the rest of the electronics to try and locate the problem, but it persists in the exactly same manner :(

T41_I2S_02.jpg
T4.1 I2S audio

T41_TDM_02.jpg
T4.1 TDM audio

The problem is significantly reduced if I turn off SPI, but the spikes are still audible (not nearly as much as before) and I really really need SPI :D

T41_TDM_no_SPI_01.jpg

T4.0 doesn't suffer from the same problem. Here's the comparison I made on the protoboard with only Teensy and PCM1681 connected, without the ΔΣ multi-point filters and the rest of the components:

T40_TDM_01.jpg
T4.0 TDM audio, unfiltered

T41_TDM_no_filter_02.jpg
T4.1 TDM audio, unfiltered

Please help, I've bumped into the wall and have no idea what else to try :confused:
 
No Idea.
I only know that 4.0 and 4.1 use the same code for audio. And the hardware is (almost) identical.
So I would focus on the few differences.
 
Initial guesses....

This looks like a software problem, maybe a bug, maybe not enough buffers allocated with AudioMemory()

sc.png


The small spikes look like an analog problem, mostly likely a ground loop.
 
Initial guesses....
This looks like a software problem, maybe a bug, maybe not enough buffers allocated with AudioMemory()

I'm almost positive it's a bug :( My initial setup was with 40 buffers allocated, I tried 64 and 96 with no difference whatsoever. I also tested my firmware with only 2 channels active, AudioMemoryUsageMax() reports 6-8 buffers are used but the problem remains... And it works normally with T4.0 :(

Thank you Paul for your insight, you're my only hope. I wouldn't even post on this board and take your valuable time if I didn't try every possible solution beforehand.

View attachment 26229
The small spikes look like an analog problem, mostly likely a ground loop.

I would suspect exactly the same if I2S/I2S2 would produce the same result, but it doesn't - works absolutely perfect (as you can see on the first pic; it's exactly the same Teensy and the same PCB). Digital and analog ground planes are separated, connected only in one place in the middle of the PCB... The same TDM setup also works great with T4.0 plugged in, this happens only when I use T4.1 :confused: Mysterious SPI affecting TDM signal makes me suspect some internal multiplexing error or high current spikes, because outside the Teensy breakout board these two signals are nowhere near each other (they are on the different PCBs) :confused:
 
Last edited:
I'm almost positive it's a bug :(

Can you create a small program which reproduces this problem without depending on analog signals from pots and other inputs?

I would like to investigate and fix this bug (if it is indeed a bug) but I can't even start until I have a program which reproduces the problem.
 
Can you create a small program which reproduces this problem without depending on analog signals from pots and other inputs?

I would like to investigate and fix this bug (if it is indeed a bug) but I can't even start until I have a program which reproduces the problem.

Sure! Here's a piece of code I used to test my setup. There's a dummy drawRect in the loop just to push SPI data at 30MHz (#define ILI9341_SPICLOCK 30000000).

Code:
#include <Audio.h>
#include <SPI.h>
#include "ILI9341_t3.h"

#define TFT_DC   29
#define TFT_CS   10

AudioOutputTDM           tdm;
AudioSynthWaveformSine   sine1;
AudioSynthWaveformSine   sine2;
AudioConnection          patchCord1(sine1, 0, tdm, 0);
AudioConnection          patchCord2(sine2, 0, tdm, 2);

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

elapsedMillis fps1;

void setup()
{
    AudioNoInterrupts();
    Serial.begin(9600);
    delay(300);
    AudioMemory(64);
    analogReadRes(10);
    analogReadAveraging(12);
    sine1.frequency(20.f);
    sine2.frequency(10.f);
    sine1.amplitude(0.95f);
    sine2.amplitude(0.95f);
    tft.begin();
    tft.setRotation(3);
    tft.fillScreen(ILI9341_BLACK);
    AudioInterrupts();
}

void loop()
{
    tft.drawRect(20, 20, 50, 50, ILI9341_GREEN);
    if (fps1 > 1000)
    {
        fps1 = 0;
        Serial.printf("CPU: %f (%f)\n", AudioProcessorUsage(), AudioProcessorUsageMax());
        Serial.printf("MEM: %i (%i)\n\n", AudioMemoryUsage(), AudioMemoryUsageMax());
    }
}
 
Thanks, Frank. If I only knew what the differences are... ;)

What just comes to mind:
Hardware - different PCB, different layout, additional inbuilt SD, more pins.
Software:

- startup.c detects and initializes PSRAM
- Different linker file (ok, its just a different size I think - did not look)
- other details - use a tool that can search in all files and search for "ARDUINO_TEENSY41"

All T4 set MPU for FlexRAM even if they don't have the solder pads - that's a bug btw ( i stopped reporting bugs - there was a (unmerged)PR that fixed most - We have seen in a other MPU related bug that it does not like wrong settings and is bitchy - and there are many more wrong settings, too.I wouldn't be very surprised if this causes other mysterious phenomens too. The fixed issue caused mysterious 1.7sec cpu stalls for example)
 
Last edited:
I'm running the program here on a Teensy 4.1 plugged into this ADAU1966A test board. So far I have not connected a ILI9341 display, but it definitely is generating the SPI activity. The orange LED is glowing due to the SPI clock on pin 13.

sc.jpg

I can't seem to reproduce either problem. I don't see the yellow waveform ever change. I also don't see the small spikes on both waveforms.

file1.png

To make sure I'm not missing an infrequent event, I set my scope to infinite persistence mode. If the waveforms are wrong even once, the screen will retain a faint record of the whatever appeared. But after running for several minutes, I can't see any sign of those problems.

file2.png

I did need to add code to activate the ADAU1966A chip. Here is the exact program I ran.

Code:
#include <Audio.h>
#include <SPI.h>
#include <Wire.h>
#include "ILI9341_t3.h"

#define TFT_DC   29
#define TFT_CS   10

AudioOutputTDM           tdm;
AudioSynthWaveformSine   sine1;
AudioSynthWaveformSine   sine2;
AudioConnection          patchCord1(sine1, 0, tdm, 0);
AudioConnection          patchCord2(sine2, 0, tdm, 2);

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

elapsedMillis fps1;

void setup()
{
    AudioNoInterrupts();
    Serial.begin(9600);
    delay(300);
    if (adau1966_begin()) Serial.println("DAC ok");
    AudioMemory(64);
    analogReadRes(10);
    analogReadAveraging(12);
    sine1.frequency(20.f);
    sine2.frequency(10.f);
    sine1.amplitude(0.95f);
    sine2.amplitude(0.95f);
    tft.begin();
    tft.setRotation(3);
    tft.fillScreen(ILI9341_BLACK);
    AudioInterrupts();
}

void loop()
{
    tft.drawRect(20, 20, 50, 50, ILI9341_GREEN);
    if (fps1 > 1000)
    {
        fps1 = 0;
        Serial.printf("CPU: %f (%f)\n", AudioProcessorUsage(), AudioProcessorUsageMax());
        Serial.printf("MEM: %i (%i)\n\n", AudioMemoryUsage(), AudioMemoryUsageMax());
    }
}


#define ADAU1966A_PLL_CLK_CTRL0  0x00
#define ADAU1966A_PLL_CLK_CTRL1  0x01
#define PDN_THRMSENS_CTRL_1      0x02
#define ADAU1966A_DAC_CTRL0      0x06
#define ADAU1966A_DAC_CTRL1      0x07
#define ADAU1966A_DAC_CTRL2      0x08
uint8_t i2c_addr = 0x04;

bool write(uint8_t address, uint32_t data) {
  Wire.beginTransmission(i2c_addr);
  Wire.write(address);
  Wire.write(data);
  if (Wire.endTransmission() != 0) return false;
  return true;
}

uint8_t read(uint8_t address) {
  Wire.beginTransmission(i2c_addr);
  Wire.write(address);
  if (Wire.endTransmission(false) != 0) return 0;
  if (Wire.requestFrom((int)i2c_addr, 1) < 1) return 0;
  return Wire.read();
}


// 1. Apply power to the ADAU1966A
// 2. Assert the PU/RST pin high after power supplies are stable.
// 3. Set the PUP bit to 1.
// 4. Program all necessary registers for the desired settings.
// 5. Set the MMUTE bit to 0 to unmute all channels.

bool adau1966_begin() {
  Wire.begin();
  // 3. Set the PUP bit to 1.  (also disable crystal oscillator)
  if (!write(ADAU1966A_PLL_CLK_CTRL0, 0x00110101)) return false;

  // 4. Program all necessary registers for the desired settings.
  //  using external MCLK

  // set MCLK from MCLKI or XTALI
  if (!write(ADAU1966A_PLL_CLK_CTRL1, 0b00110011)) return false;

  // When using the ADAU1966A in direct master clock mode, power
  // down the PLL in the PDN_THRMSENS_CTRL_1 register.
  if (!write(PDN_THRMSENS_CTRL_1, 0b00100010)) return false;

  // TDM16 needs LRCLK_MODE set to pulse
  if (!write(ADAU1966A_DAC_CTRL1, 0b01000000)) return false;

  // TDM16 needs 16 bits per slot
  if (!write(ADAU1966A_DAC_CTRL2, 0b00010000)) return false;

  // 5. Set the MMUTE bit to 0 to unmute all channels.
  //  sets TDM16 mode

  if (!write(ADAU1966A_DAC_CTRL0, 0b00100000)) return false;

  return true;
}
 
I think it is not completely impossible that bottlenecks can occur when both fast SPI and TDM are supplied via the slower OCRAM (DMA). Esp, as there not reads only, but writes too and the cache is too small for the display.
 
I repeated the test with a ILI9341 display connected. Exact same code and setup at msg #10.

sc.jpg

Still can't reproduce the problem. I see no spikes or wrong waveform segments.

I have no idea why you're seeing those problems with Teensy 4.1, but I'm pretty sure it's not a bug in these libraries or the Teensy 4.1 hardware.
 
Frank, did I send you the CS42448 test board for Teensy 4.x?

I know I built 1 and sent it to someone. I have 2 more blank OSH Park boards here, and one of the older version for Teensy 3.x which is built. So it seems the ADAU1966A test board is the only ready-to-use TDM test hardware I have at this moment. Will probably build another of those new CS42448 boards later this year, just in case another TDM test is needed.
 
@Subfanatic - Going to consider this a non-reproducible problem and take it off my list of issues to investigate.

I'm pretty sure it's some sort of issue with the hardware you've built. If Teensy 4.0 works in the same socket, maybe the next trying soldering only 14 pin headers to the left hand side of a Teensy 4.1 (or otherwise do something so only the first 14 pins are used) and plug it into the socket as a Teensy 4.0 would plug in. My best guess is something is very wrong is connecting on those other 20 right-side pins, like maybe a signal trying to drive the 3.3V power or GND pins?
 
@Subfanatic - Going to consider this a non-reproducible problem and take it off my list of issues to investigate.

I'm pretty sure it's some sort of issue with the hardware you've built. If Teensy 4.0 works in the same socket, maybe the next trying soldering only 14 pin headers to the left hand side of a Teensy 4.1 (or otherwise do something so only the first 14 pins are used) and plug it into the socket as a Teensy 4.0 would plug in. My best guess is something is very wrong is connecting on those other 20 right-side pins, like maybe a signal trying to drive the 3.3V power or GND pins?

Thank you guys so much for trying. I can't understand why the problem doesn't appear with your equipment, because it's definitely not an issue with the hardware I've built: even if we disregard the fact I have a master's degree in electronics and 20+ years of experience in the field, the tests were repeated on the breadboard with only 2 x 14 pins connected, then with only I2S/TDM and TFT pins connected, as well as on the PCB built only for testing purposes. With 2 different TFT screens and 2 different TDM DAC ICs. And if I made a mistake - sure, it can happen to anybody - why would I2S work normally (and it uses exactly the same pins) if it's a hardware error? The only thing left to try is to get another T4.1 and check if by some bad luck I've got a defective specimen :(
 
attachment.php

This image (the circled part) does not look like transmission errors. The circled part shows linearly increasing (green) and decreasing (yellow) data. The probability of this happening randomly is pretty low. To me it looks like this is really transmitted data.
I've seen similar things when I wrote I2S code which was buggy.. that does not mean that the TDM has a bug. But it might be something something that causes a similar effect..

Was the code you posted exactly the code you use? (That would be really important to know)

Edit:
With T4.0 TDM / TDM2 audio works normally, but when I switch to T4.1 (they go into the same socket, I just swap them) everything suddenly goes haywire
Does not really sound like a hardware-issue, too.
 
Last edited:
Do you have any extra 14 pin headers & 14 pin sockets? Maybe solder them together and plug them into the main 24 pin sockets, so then you can plug the Teensy 4.1 into *ONLY* the same 28 pins as Teensy 4.0 uses.

Teensy 4.0 and 4.1 are nearly identical hardware. So those extra 20 pins on your circuit board are the thing which is most likely different.

While it may involve some kludgey soldering to make an adaptor, just plugging the troublesome Teensy 4.1 into only the first 28 pins is relatively "easy", so why not give that a try?
 
Hm. Wait! I see no codec init code in your program.
- Which TDM chip you are using?
- Are you sure it does not mix the inputs with the outputs with the default settings?
- are the inputs connected to something?
 
Hm. Wait! I see no codec init code in your program.
- Which TDM chip you are using?
- Are you sure it does not mix the inputs with the outputs with the default settings?
- are the inputs connected to something?

Like I wrote in the initial post, my preferred DAC is 8-ch Texas Instruments PCM1681. I've used both PCM1681PWPR-Q1 and PCM1681PWP in several T3.6/T4.0 synth projects during last 2 years and everything is working smooth and without any issues. The main reason I decided to use this DAC is because it uses external hardware configuration (4 pins connected via resistor to either 0V or 3.3V) instead of I2C that consumes 2 analog pins. But I also tested the same thing on CS42448 with exactly the same results, inputs are currently unconnected (I have solder jumpers on both inputs and outputs) :(
 
Ok, i have the cs42488 here. Please post your HEX file! I can test, and perhaps confirm that. If i see the same effect, we'll know it's not your setup and I have some ideas how to debug that.
 
Status
Not open for further replies.
Back
Top