Question about Teensy 4.1+Audio Shield / I2S Overclocking and EMI

idiotech

New member
Hi there! I am building a synthesizer instrument using the Teensy 4.1 and Audio Shield, connected to each other via stacking headers and socketed into a PCB containing several potentiometer and button inputs and I2C peripherals (external ADC, DAC, OLED).

I recently went to get an FCC Part 15 B radiated emissions test and got very strong, seemingly harmonically spaced peaks in both the 30-200MHz and 200M-1GHz ranges. My worst offenders being 173, 192, 274 and 422 MHz (images below)... I am using code from El Supremo (attached below) to set my I2S audio sample rate from the default 44100 to 96000 to avoid high frequency aliasing. I suspect that the MCLK of I2S is the main culprit, given these frequencies are close-ish to integer multiples of the resulting 24.576MHz MCLK i'd get from the oversampling.

While I definitely have room to improve my enclosure's shielding and PCB-chassis ground tie-in to mitigate this noise, and I've attempted using the following code to change slew rate and gain of the MCLK, LRCLK, and BCLK - is there anything else obvious I can try to reduce the amplitude of these ringings? Or is there something else I may be missing that is contributing to this noise?

Thanks in advance!
~Joe

C++:
void setI2SPadSafeProfile() {
  // apply ALT0 for I2S0 on each pin
  for (int i=0;i<3;i++) *(mux_regs[i]) = 0;

  // Helper to set SRE=0 and DSE to chosen value
  auto setPad = [](volatile uint32_t *padReg, uint8_t dseVal, uint8_t sreVal){
    uint32_t p = *padReg;
    p &= ~((7u << 3) | (1u << 0));   // clear DSE[3..5], SRE[0]
    p |= ((uint32_t)(dseVal & 0x7) << 3);
    if (sreVal & 1u) p |= (1u << 0); // set fast if requested; else leave slow
    *padReg = p;
  };

  // Choose values (tweak after listening)
  setPad(pad_regs[IDX_MCLK], 3, 0); // MCLK DSE=3 (~48Ω), slow
  setPad(pad_regs[IDX_BCLK], 1, 0); // BCLK DSE=1 (~34Ω), slow
  setPad(pad_regs[IDX_LR],   1, 0); // LRCLK DSE=1, slow
  // setPad(pad_regs[IDX_TXD],  1, 0); // TXD0  DSE=1, slow
}

C++:
#include <utility/imxrt_hw.h>

int setI2SFreq(int freq) {
  int n1;
  // PLL between 27*24 = 648MHz und 54*24=1296MHz
  // Fudge to handle 8kHz - El Supremo
  if (freq > 8000) {
    n1 = 4;  //SAI prescaler 4 => (n1*n2) = multiple of 4
  } else {
    n1 = 8;
  }
  int n2 = 1 + (24000000 * 27) / (freq * 256 * n1);
  Serial.println(n2);
  if (n2 > 63) {
    // n2 must fit into a 6-bit field
    Serial.printf("ERROR: n2 exceeds 63 - %d\n", n2);
    return 0;
  }
  double C = ((double)freq * 256 * n1 * n2) / 24000000;
  //  Serial.printf("%6d : n1 = %d, n2 = %d, C = %12.6f ",freq,n1,n2,C);
  int c0 = C;
  int c2 = 10000;
  int c1 = C * c2 - (c0 * c2);
  //  Serial.printf("c0 = %d, c1 = %d, c2 = %d\n",c0,c1,c2);
  set_audioClock(c0, c1, c2, true);
  CCM_CS1CDR = (CCM_CS1CDR & ~(CCM_CS1CDR_SAI1_CLK_PRED_MASK | CCM_CS1CDR_SAI1_CLK_PODF_MASK))
               | CCM_CS1CDR_SAI1_CLK_PRED(n1 - 1)   // &0x07
               | CCM_CS1CDR_SAI1_CLK_PODF(n2 - 1);  // &0x3f

  //START//Added afterwards to make the SAI2 function at the desired frequency as well.

  CCM_CS2CDR = (CCM_CS2CDR & ~(CCM_CS2CDR_SAI2_CLK_PRED_MASK | CCM_CS2CDR_SAI2_CLK_PODF_MASK))
               | CCM_CS2CDR_SAI2_CLK_PRED(n1 - 1)   // &0x07
               | CCM_CS2CDR_SAI2_CLK_PODF(n2 - 1);  // &0x3f)
                                                    //END//Added afterwards to make the SAI2 function at the desired frequency as well.
  // For compatibility with my T3.6 version
  return freq;
}
plot0423.gif



plot0424.gif

plot0425.gif

plot0426.gif
 
Do you have pictures of the DUT, device under test ???
Do you have cables with length corresponding to these wavelength ???
~0.5-2 meters for the 150-600MHz range? And then half or quarter of these length.
If emissions are comming from the cables, ferrites will help.
 
Sorry I don’t have the best picture of the DUT (I will attempt to upload shortly) but these results were from the bare device with only the 9V DC adapter and without any peripheral cables (MIDI, audio, cv, headphone) attached. Each of these user-supplied optional cables could likely vary in length within the range you mentioned (0.5-2m).

They did also warn me about the antenna effect of attached cables so I’d be interested in potentially putting ferrites near these ports if I can fit them into the PCB space.
 
You probably measured some frequencies present in your device, which are using the DC adapter cable as antennas
When I made tests, I use a battery pack. This ensure I don't measure my power supplies quality.
And when I should use a power supply, cables are inserted in multiples lab ferrites, which are 50cm long.

You can insert some ferrites at pcb level, with ceramic capacitors, or clip ferrites on the cables. Check your PC cables, you will find some examples.
 
We did clip a ferrite onto the DC adapter cable at one point and that slightly (but not significantly) dampened the frequencies...

That's interesting about the battery idea. I had brought a certified power supply (Boss PSA-120) thinking they'd want to see it with a typical power supply that the end user would use. My circuit draws about 250mA at peak.

Difficult question to answer, I know, but do you think the frequencies shown/being amplified could be something other than from the Teensy clock?
 
As the power supply is not part of what you sell, I would test with a battery having a typical cable lenght, about 1-1.5 meters.
The high frequencies could also come from fast switching signals. I had problems with simple TO92 FETs switching some mA. Putting a R-C filter in the gate to slower the switching resolved my problem.
 
Firstly at 600MHz the T4 is noisy, there's no getting round that. Probably wise to shield it, or at least have good low-inductance ground bonding to the metal work, and ferrites on every wire leaving the circuit boards. Feeding wires twice through a ferrite core makes it 4 times as effective, note. You can get clip-on ferrites for leads with fat connectors on both ends.
 
Back
Top