Using TDA1543A with Teensy 4.0

Status
Not open for further replies.

layetri

Member
Hello!
I am trying to port Pazi's original TDA1543A code (https://forum.pjrc.com/threads/29284-Dual-channel-16bit-dac-PT8211/page5?p=141314#post141314) to work with my Teensy 4.0. So far, I have the CLK and FS signals working, but I haven't been so lucky with getting the DATA line to give me any output. I'm pretty new to low level coding like this, and this is what I came up with by looking at the datasheet (the excessive comments are me trying to understand the code). Am I missing anything? Are there obvious mistakes?

output_tda.h:
Code:
/* Audio Library for Teensy 3.X
 * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
 */

#ifndef output_tda_h_
#define output_tda_h_

#include "Arduino.h"
#include "AudioStream.h"
#include "DMAChannel.h"

class AudioOutputTDA : public AudioStream
{
public:
    AudioOutputTDA(void) : AudioStream(2, inputQueueArray) { begin(); }
    virtual void update(void);
    void begin(void);
protected:
    static void configureI2S(void);
    static audio_block_t *block_left_1st;
    static audio_block_t *block_right_1st;
    static bool update_responsibility;
    static DMAChannel dma;
    static void isr(void);
private:
    static audio_block_t *block_left_2nd;
    static audio_block_t *block_right_2nd;
    static uint16_t block_left_offset;
    static uint16_t block_right_offset;
    audio_block_t *inputQueueArray[2];

    static void configureDMA();
    static void receiveAudioBlock(audio_block_t*& index,
                                  uint16_t& blockOffset,
                                  audio_block_t*& block_1st,
                                  audio_block_t*& block_2nd);
    static uint32_t scaleInputTo32Bit(uint16_t input);
    static void copyAndScaleInputToOutput(uint32_t*& dest,
                                          uint16_t& blockOffset,
                                          audio_block_t*& block_1st,
                                          audio_block_t*& block_2nd);
    static uint32_t* getDestination();
};

#endif

output_tda.cpp:
Code:
/* Audio Library for Teensy 3.X
 *
 * TDA1543A DAC interface
 *
 * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
 * Original Teensy 3.X version by user Pazi
 *    (https://forum.pjrc.com/threads/29284-Dual-channel-16bit-dac-PT8211/page5?p=141314#post141314)
 *
 * Adapted for Teensy 4.0 by Daniël Kamp, with help from Wouter Ensink
 *
 */

#include "output_tda.h"
#include "utility/imxrt_hw.h"

audio_block_t * AudioOutputTDA::block_left_1st = NULL;
audio_block_t * AudioOutputTDA::block_right_1st = NULL;
audio_block_t * AudioOutputTDA::block_left_2nd = NULL;
audio_block_t * AudioOutputTDA::block_right_2nd = NULL;

uint16_t  AudioOutputTDA::block_left_offset = 0;
uint16_t  AudioOutputTDA::block_right_offset = 0;

bool AudioOutputTDA::update_responsibility = false;

DMAMEM __attribute__((aligned(32))) static uint32_t i2s_tx_buffer[AUDIO_BLOCK_SAMPLES * 2];

DMAChannel AudioOutputTDA::dma(false);

// ==============================================
//  Do setup things
// ==============================================
void AudioOutputTDA::begin(void)
{
  // Allocate memory and init DMAChannel
  memset(i2s_tx_buffer, 0, sizeof(i2s_tx_buffer));
  dma.begin(true);

  block_left_1st = NULL;
  block_right_1st = NULL;

  // Do protocol configuration
  configureI2S_2();

  // Config pin 7 for use with SAI
  CORE_PIN7_CONFIG  = 3;  //1:TX_DATA0

  // Flush cache
  arm_dcache_flush_delete(i2s_tx_buffer, sizeof(i2s_tx_buffer));
  configureDMA();

  // Set enable bits for I2S transmitter and receiver
  I2S1_RCSR |= I2S_RCSR_RE;
  I2S1_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE;

  update_responsibility = update_setup();

  // Attach isr() function to DMA interrupt
  dma.attachInterrupt(isr);
}

void AudioOutputTDA::configureDMA() {
  // Set DMA source address
  dma.TCD->SADDR = i2s_tx_buffer;
  // Set DMA source offset
  dma.TCD->SOFF = 4;
  // Set DMA attribute bits
  dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
  // Set DMA's number of bytes to transfer per request
  dma.TCD->NBYTES_MLNO = 4;
  // Set DMA source last address
  dma.TCD->SLAST = -sizeof(i2s_tx_buffer);
  // Set DMA destination offset
  dma.TCD->DOFF = 0;
  // Set DMA current major iterator count [6.6.5.28.4, page 166]
  dma.TCD->CITER_ELINKNO = sizeof(i2s_tx_buffer) / 4;
  // Set address for error handling? AFAIK not applicable right now, might look into this later
  dma.TCD->DLASTSGA = 0;
  // Set DMA beginning major iterator count [6.6.5.32, page 171]
  dma.TCD->BITER_ELINKNO = sizeof(i2s_tx_buffer) / 4;
  // Set DMA CSR config bits
  dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
  // Set DMA destination address
  dma.TCD->DADDR = (void *)((uint32_t)&I2S1_TDR0);
  // Link DMA to SAI1 hardware event
  dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SAI1_TX);
  // Enable the DMA
  dma.enable();
}
void AudioOutputTDA::configureI2S(void) {
  CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);

  // TODO: understand what this does
  //PLL:
  int fs = AUDIO_SAMPLE_RATE_EXACT;
  // PLL between 27*24 = 648MHz und 54*24=1296MHz
  int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
  int n2 = 1 + (24000000 * 27) / (fs * 256 * n1);

  double C = ((double)fs * 256 * n1 * n2) / 24000000;
  int c0 = C;
  int c2 = 10000;
  int c1 = C * c2 - (c0 * c2);
  set_audioClock(c0, c1, c2);

  // Clear SAI1_CLK register locations
  CCM_CSCMR1 = (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK))
               | CCM_CSCMR1_SAI1_CLK_SEL(2); // (0,1,2): PLL3PFD0, PLL5, PLL4
  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

  // Select MCLK
  IOMUXC_GPR_GPR1 = (IOMUXC_GPR_GPR1 & ~(IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL_MASK))
                    | (IOMUXC_GPR_GPR1_SAI1_MCLK_DIR | IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL(0));
  // TODO: end of confusion

  // Don't continue setup sequence if I2S1_TCSR_TE (Transmit Enable) is already set
  if (I2S1_TCSR & I2S_TCSR_TE) return;

  // Configure BCK and CS pins
  CORE_PIN21_CONFIG = 3;  //1:RX_BCLK
  CORE_PIN20_CONFIG = 3;  //1:RX_SYNC

  // ==========================================================
  // Configure the I2S register
  // Datasheet: page 1987 onwards
  // ==========================================================

  // Setup transmitter
  constexpr int bitwidth = 31;
  I2S1_TMR = 0;
  I2S1_TCR1 = I2S_TCR1_RFW(0);
  I2S1_TCR2 = I2S_TCR2_SYNC(0) | I2S_TCR2_BCP | I2S_TCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
  I2S1_TCR3 = I2S_TCR3_TCE;
  I2S1_TCR4 = I2S_TCR4_FRSZ(1) | I2S_TCR4_SYWD(bitwidth) | I2S_TCR4_MF | I2S_TCR4_FSE | I2S_TCR4_FSP | I2S_TCR4_FSD;
  I2S1_TCR5 = I2S_TCR5_WNW(bitwidth) | I2S_TCR5_W0W(bitwidth) | I2S_TCR5_FBT(bitwidth);

  // Setup receiver (unnecessary afaik, but the example did it too)
  I2S1_RMR = 0;
  I2S1_RCR1 = I2S_RCR1_RFW(0);
  I2S1_RCR2 = I2S_RCR2_SYNC(1) | I2S_RCR2_BCP | I2S_RCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
  I2S1_RCR3 = I2S_RCR3_RCE;
  I2S1_RCR4 = I2S_RCR4_FRSZ(1) | I2S_RCR4_SYWD(bitwidth) | I2S_RCR4_MF | I2S_RCR4_FSE | I2S_RCR4_FSP | I2S_RCR4_FSD;
  I2S1_RCR5 = I2S_RCR5_WNW(bitwidth) | I2S_RCR5_W0W(bitwidth) | I2S_RCR5_FBT(bitwidth);
}

// ==============================================
//  Handle incoming audio blocks
// ==============================================
void AudioOutputTDA::update(void) {
  // Receive left channel
  auto* block_left = receiveReadOnly(0);
  receiveAudioBlock(block_left, block_left_offset, block_left_1st, block_left_2nd);

  // Receive right channel
  auto* block_right = receiveReadOnly(1);
  receiveAudioBlock(block_right, block_right_offset, block_right_1st, block_right_2nd);
}

void AudioOutputTDA::receiveAudioBlock(audio_block_t*& block, uint16_t& blockOffset, audio_block_t*& block_1st, audio_block_t*& block_2nd) {
  if (block) {
    // Deny interrupt requests while buffer is being moved
    __disable_irq();
    // Move the block into whichever buffer is empty...
    if (block_1st == NULL) {
      block_1st = block;
      blockOffset = 0;
      __enable_irq();
    } else if (block_2nd == NULL) {
      block_2nd = block;
      __enable_irq();
    }
    // ...or shift the buffers and fill the last one
    else {
      audio_block_t *tmp = block_1st;
      block_1st = block_2nd;
      block_2nd = block;
      blockOffset = 0;
      __enable_irq();
      release(tmp);
    }
  }
}

// ==============================================
//  Handle outgoing audio blocks
// ==============================================
void AudioOutputTDA::isr(void) {
  dma.clearInterrupt();
  auto* dest = getDestination();

  // Copy and scale left channel
  copyAndScaleInputToOutput(dest, block_left_offset, block_left_1st, block_left_2nd);
  // Move back to beginning(+1) of buffer
  dest -= AUDIO_BLOCK_SAMPLES - 1;
  // Copy and scale right channel
  copyAndScaleInputToOutput(dest, block_right_offset, block_right_1st, block_right_2nd);
//  Serial.println(*dest);
}

uint32_t* AudioOutputTDA::getDestination()
{
  const auto saddr = (uint32_t)(dma.TCD->SADDR);

  // Fill the part of the buffer that the DMA isn't currently transmitting
  if (saddr < (uint32_t)i2s_tx_buffer + sizeof(i2s_tx_buffer) / 2) {
    auto* temp = (uint32_t *)&i2s_tx_buffer[AUDIO_BLOCK_SAMPLES];

    // TODO: figure out what this does (something IRQ?)
    if (AudioOutputTDA::update_responsibility)
      AudioStream::update_all();
    return temp;
  } else {
    return (uint32_t *)i2s_tx_buffer;
  }
}
uint32_t AudioOutputTDA::scaleInputTo32Bit(uint16_t input)
{
  // 0x8000 == 0b1000'0000'0000'0000
  // AND-ing with 0x8000 gives us the unsigned 16-bit version of the input

  // 0xff000000 == 1111'1111'0000'0000'0000'0000'0000'0000
  // 32-bit input == 0000'0000'bbbb'bbbb'bbbb'bbbb'0000'0000
  // OR-ing these together gives us the correct format for the TDA1543A chip

  return ((uint32_t)input << 9) | ((input & 0x8000) != 0 ? 0xff000000 : 0);
}
void AudioOutputTDA::copyAndScaleInputToOutput(uint32_t*& dest,
                                               uint16_t& blockOffset,
                                               audio_block_t*& block_1st,
                                               audio_block_t*& block_2nd)
{
  if (block_1st) {
    auto offset = blockOffset;
    auto* src = &block_1st->data[offset];

    for (int i = 0; i < AUDIO_BLOCK_SAMPLES/2; ++i) {
      *dest = scaleInputTo32Bit(*src++);
      dest += 2;
    }

    offset += AUDIO_BLOCK_SAMPLES/2;
    if (offset < AUDIO_BLOCK_SAMPLES) {
      blockOffset = offset;
    } else {
      blockOffset = 0;
      AudioStream::release(block_1st);
      block_1st = block_2nd;
      block_2nd = NULL;
    }
  } else {
    for (int i = 0; i < AUDIO_BLOCK_SAMPLES/2; ++i) {
      *dest = 0;
      dest += 2;
    }
  }
}

Any help would be very much appreciated!
 
Last edited:
By means of extensive serial printing, I've figured out that the most likely problem is with the I2S setup. Could someone take a look at the configuration and tell me whether there are any mistakes? I've tried to do this myself, but I don't think I'm advanced enough to fully understand the IMXRT datasheet.
 
From what I've been able to find, the AudioOutputPT8211 class that is supplied delivers 16 bits per CS cycle, while the A flavor of the TDA1543 expects 24/32 bits (if I understand correctly). Using the original gives me this:
tda1543_at_its_finest.png
(applying the modifications that are commented out in the original gives me the same output).
I figured it would have something to do with the fact that this Japanese format expects a higher bit count, and since the OP of the original thread got it to work, I thought it'd be worthwhile to try and port their code to run on my T4.
 
I'm not sure the A flavor of THD1543 requires/expects 24/32 bits. It's a 16bit DAC after all. The attached datasheet doesn't mention it as far as I can tell.
Perhaps you should give this code a quick try:
Code:
// TDA1543A     Teensy 4.x
// VDD          Vin
// GND          GND
// WS           20            LRCK 176.4 KHz
// DATA          7
// BCK          21            5.6469 MHz = 32.LRCK

#include <Audio.h>

AudioSynthWaveformSine   sine1;
AudioOutputPT8211        pt8211_1;
AudioConnection          patchCord1(sine1, 0, pt8211_1, 0);
AudioConnection          patchCord2(sine1, 0, pt8211_1, 1);

void setup(){
  AudioMemory(1);
  sine1.frequency(1000);
  sine1.amplitude(0.50);  // -6dB
}

void loop(){
}

Regards,
Paul

View attachment Philips TDA1543A.pdf
 
Am I mistaken if I read page 9 of the datasheet as the chip expecting 8 bits of MSB before the actual data starts? And thus requiring at least 24 CLK cycles to receive a full 16 bit message? This was also the issue in the original thread, and OP solved it by modifying the existing header to work with 32-bit signals instead, where both the MSB and LSB filled 8 additional bits.
The attached scope screenshot from my last post was the result of code similar to what you posted. This is (as far as my understanding goes) a result of the chip only interpreting the last 8 of the 16 bits, due to it expecting the first 8 to only be MSB.
 
Am I mistaken if I read page 9 of the datasheet as the chip expecting 8 bits of MSB before the actual data starts? And thus requiring at least 24 CLK cycles to receive a full 16 bit message?

It does look that way in figure 5, where "MSB" is shown as constant for several clock cycles. But figure 4 seems to show each clock gets a new data bit. Probably some experimentation needed to know how this DAC chip really works.
 
After some tinkering, I've noticed that when setting a very small amplitude (0.001 or lower), the output signal is correct. This leads me to assume that the chip indeed only considers the last 8 bits in the current setup (the current setup being the one that PaulS proposed earlier).
 
Last edited:
I remember we had used and tested this chip when filldling withh code for the pt8211.
Unfortunateley it is so long ago, and I don't remember any details. I searched the chip in my drawers but could not find it anymore..
Sorry, I'm getting older :) ( But I bought an electric guitar some weeks ago and try to practice every day *g*, so sorry, that I'm not that often here anymore - I whish I had begun some decades earlier..)
Well, I openend the PT821 source, and found this:

Code:
//    I2S0_TCR4 = I2S_TCR4_FRSZ(1) | I2S_TCR4_SYWD(15) | I2S_TCR4_MF | I2S_TCR4_FSE | I2S_TCR4_FSP | I2S_TCR4_FSD; //TDA1543
    I2S0_TCR4 = I2S_TCR4_FRSZ(1) | I2S_TCR4_SYWD(15) | I2S_TCR4_MF /*| I2S_TCR4_FSE*/ | I2S_TCR4_FSP | I2S_TCR4_FSD; //PT8211
Not sure if it was for the A Version or not.. but maybe it can help a little bit. Just open the PT8211 code and take a look.. - as first step, ignore the oversampling stuff.
 
I tried this fix already and got exactly the same outcome as with the original PT8211 code.

As to my own attempt at porting the original thread's driver: when looking at the I2S and DMA configuration in the code, are there any obvious problems with my code that could cause this behavior? (BCK and WS working, DATA line empty)
003.png
 
I'm most worried about this part of the code. Am I doing something wrong here? (I think the most obvious culprit would be a mistake in the transmitter setup)
Code:
  CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);

  // TODO: understand what this does
  //PLL:
  int fs = AUDIO_SAMPLE_RATE_EXACT;
  // PLL between 27*24 = 648MHz und 54*24=1296MHz
  int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
  int n2 = 1 + (24000000 * 27) / (fs * 256 * n1);

  double C = ((double)fs * 256 * n1 * n2) / 24000000;
  int c0 = C;
  int c2 = 10000;
  int c1 = C * c2 - (c0 * c2);
  set_audioClock(c0, c1, c2);

  // Clear SAI1_CLK register locations
  CCM_CSCMR1 = (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK))
               | CCM_CSCMR1_SAI1_CLK_SEL(2); // (0,1,2): PLL3PFD0, PLL5, PLL4
  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

  // Select MCLK
  IOMUXC_GPR_GPR1 = (IOMUXC_GPR_GPR1 & ~(IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL_MASK))
                    | (IOMUXC_GPR_GPR1_SAI1_MCLK_DIR | IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL(0));
  // TODO: end of confusion

  // Don't continue setup sequence if I2S1_TCSR_TE (Transmit Enable) is already set
  if (I2S1_TCSR & I2S_TCSR_TE) return;

  // Configure BCK and CS pins
  CORE_PIN21_CONFIG = 3;  //1:RX_BCLK
  CORE_PIN20_CONFIG = 3;  //1:RX_SYNC

  // ==========================================================
  // Configure the I2S register
  // Datasheet: page 1987 onwards
  // ==========================================================

  // Setup transmitter
  constexpr int bitwidth = 31;
  I2S1_TMR = 0;
  I2S1_TCR1 = I2S_TCR1_RFW(0);
  I2S1_TCR2 = I2S_TCR2_SYNC(0) | I2S_TCR2_BCP | I2S_TCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
  I2S1_TCR3 = I2S_TCR3_TCE;
  I2S1_TCR4 = I2S_TCR4_FRSZ(1) | I2S_TCR4_SYWD(bitwidth) | I2S_TCR4_MF | I2S_TCR4_FSE | I2S_TCR4_FSP | I2S_TCR4_FSD;
  I2S1_TCR5 = I2S_TCR5_WNW(bitwidth) | I2S_TCR5_W0W(bitwidth) | I2S_TCR5_FBT(bitwidth);

  // Setup receiver (unnecessary afaik, but the example did it too)
  I2S1_RMR = 0;
  I2S1_RCR1 = I2S_RCR1_RFW(0);
  I2S1_RCR2 = I2S_RCR2_SYNC(1) | I2S_RCR2_BCP | I2S_RCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
  I2S1_RCR3 = I2S_RCR3_RCE;
  I2S1_RCR4 = I2S_RCR4_FRSZ(1) | I2S_RCR4_SYWD(bitwidth) | I2S_RCR4_MF | I2S_RCR4_FSE | I2S_RCR4_FSP | I2S_RCR4_FSD;
  I2S1_RCR5 = I2S_RCR5_WNW(bitwidth) | I2S_RCR5_W0W(bitwidth) | I2S_RCR5_FBT(bitwidth);
 
Like Frank B, I vaguely remember that I have been playing with the TDA1543A as well.
But I also could not find the chips in my drawers anymore...
Since I have a working setup with the TDA1543 non-A version as pictured below [on a T3.2], I just ordered 2pcs TDA1543A here.

TDA1543 setup.jpg

With a bit of luck, they will arrive within a week and I can start testing on a Teensy 3.2 & 4.0.

Regards,
Paul
 
Well, finally received the TDA1543A's today.
Replaced the TDA1543 from the setup pictured above with a fresh TDA1543A and uploaded a simple sketch that works with a PT8211 [I verified it]:
Code:
// TDA1543A       Teensy 3.2
// 8 Vdd          5V          10uF + 100nF to GND
// 4 GND          GND
// 2 WS           23          LRCK 176.4 KHz
// 3 DATA         22
// 1 BCK          9           5.6469 MHz = 32.LRCK
//
// 7 Vref                     reference voltage, 1K to GND
// 6 AOL                      left current output, 1K to GND
// 8 AOR                      right current output, 1K to GND

#include <Audio.h>

AudioSynthWaveformSine   sine1;
AudioOutputPT8211        pt8211_1;
AudioConnection          patchCord1(sine1, 0, pt8211_1, 0);
AudioConnection          patchCord2(sine1, 0, pt8211_1, 1);

void setup(){
  AudioMemory(1);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  sine1.frequency(1000);
  sine1.amplitude(1.0);
}

void loop(){
}
Unfortunately no sine output from the TDA1543A but the same garbage as in Layetri's message #4 above.
So the japanese format that works for the PT8211 does not work for the TDA1543A. The TDA1543A should be able to handle the 176.4 KHz samplerate.
I also tried Frank's suggestion as in his message #9 but without success.

@Frank: since I received 2pcs TDA1543A, I could send one piece to you for investigation [if you want to besides your guitar endeavours].

Regards,
Paul
 
Sure, with pleasure.
It's very unlikely that I'll be anywhere near as good as your compatriot Van Halen. Besides, my fingers hurt a little when I practice too much. So I will find time for the chip :)



Oh my.. It will be 30 years before I even come close.
But then I'll look at the grass from below.
 
Eddie Van Halen's Eruption is quite a target :)
Thanks, I will send you an email for your postal address.

Gruesse,
Paul
 
@PaulS have you tried the solution that the other thread had? I can’t test this myself as I don’t own a T3x. If that code works, the problem must be somewhere with my low-level coding.
 
You mean Pazi's code? No, I did not try it. I believe Pazi's when he says that it works.
I would not be surprised that the DMA engine and specific registers are different between a Teensy 3.x and a Teensy 4.x since the processors are quite different.

Paul
 
This is what I’ve been trying to address with my code from my first post, and it’s exactly where I suspect the problem to be. It’d be great if someone who knows more about this specific hardware could take a look at the setup of the DMA and registers to find possible mistakes.
 
@Frank: since I received 2pcs TDA1543A, I could send one piece to you for investigation [if you want to besides your guitar endeavours].

Got your chip today. Thank you, Paul!
Will give it a try tonight. After dinner.
To do this I need to set up my scope again, find a breadbord and find cables.... The chip -output is also a current source like the TDA1543, right? I'm not connecting an op-amp to it. Which resistor should I use? (I think you have already done this, and I can save myself thinking about it ;)
 
The resistor needs to be small enough to prevent the output straying from the compliance range, which is typically less than a diode drop.
 
Which resistor should I use?
Code:
// TDA1543A       Teensy 3.2
// 8 Vdd          5V          10uF + 100nF to GND
// 4 GND          GND
// 2 WS           23          LRCK 176.4 KHz
// 3 DATA         22
// 1 BCK          9           5.6469 MHz = 32.LRCK
//
[COLOR="#FF0000"]// 7 Vref                     reference voltage, 1K to GND
// 6 AOL                      left current output, 1K to GND
// 8 AOR                      right current output, 1K to GND[/COLOR]

1K will do to give a decent signal on your scope.

No hurries...

Paul
 
Code:
No hurries...

[/QUOTE]

Nope :) 
I have no beer anymore. Ich gehe gleich mal zur Tankstelle.. :)

I'm outputing a 1 Hz sine. The Scope shows a left or right justified sawtooth swapping every 1/2 second. Not too bad...
Will try more when I'm back.
 
The Scope shows a left or right justified sawtooth swapping every 1/2 second. Not too bad...

Sometimes i wish i'd bought a 4 channel scope..
As far I can tell, the format is OK and looks like the one from the datasheet. This leads to the "sawtooth" however.
Tried playing with the i2s format-bts with no effort so far.
Perhaps we indeed have to switch to 24 or 32 bit transfers.. At the weekend, perhaps..
 
Just modfied the code by PAZI for a T4.
Code is attached.

On my Scope, it looks like a sine (just 1k between vref and out).

Note, i see no difference between
Code:
*dest = ((uint32_t)*src << 9) /*| ((*src & 0x8000) != 0 ? 0xff000000 : 0)*/;
and
Code:
*dest = ((uint32_t)*src << 9) | ((*src & 0x8000) != 0 ? 0xff000000 : 0);

Perhaps you want to investigate this.
 

Attachments

  • TDA1543A-210716a.zip
    4.7 KB · Views: 62
Status
Not open for further replies.
Back
Top