R4.3 TDM Serial Port Modules

R4.3 TDM Serial Port Modules

Notice: Pre-Release Documentation
This document is part of a prerelease and is currently a work in progress. Some content may be incomplete, subject to change, or marked as TBD. We are actively updating this documentation and will continue to provide the most accurate and up-to-date information as development progresses. Thank you for your understanding!

Release 4.1 added

  • 64-channel TDM support (requires updated baseline)

  • Synchronous TDM ports time align themselves automatically to within 1 sample

Release 4.2 added

  • Ports can be on different Hexagon DSPs

  • TDM initialization follows a prescribed sequence including initializing bitclk first followed by the frame sync.

Future Releases

  • Asynchronous serial ports including an ASRC and output data at a fixed sample rate and block size.

Synchronization Modes

The serial port modules support synchronous and asynchronous operation. In synchronous operation, the serial ports are all clocked off the same master clock (the share the same bit clock). In asynchronous operation, the serial port has a different clock that is not equal to the master clock. Operation can be further classified as

Synchronous Master - Operates at the smallest block size and generates the primary interrupt. This port must be on the Primary Audio Core (PAC) which is specified in the system configuration file. Only one serial port in the system can be defined as the Synchronous Master.

Synchronous Aligned – the serial ports start simultaneously and remain in lock step throughout. This requires external hardware connections to share serial port clocks and framesyncs. On the SA8255, this is achieved by tying the serial ports to the master clock, starting DMA, and then starting the frame sync.

This is achieved on SA8797 by configuring the serial ports to use the master clock together with the Group Bonding mechanism to start all DMA simultaneously. All synchronous serial ports must be on the same audio processor (TDM bonding only works on a single core.

Synchronous Aligned serial ports are able to achieve the lowest possible input to output latency (equal to 2 times the block size). This is the ideal solution for low latency applications like RNC.

Synchronous Unaligned – the serial ports are driven off the master clock but do not start synchronously. The data stream is driven by the same clock source/root as the master clock, but is misaligned in time. The vast majority of custom designs will use this approach, and the Audio Weaver TDM modules are able to time align these ports to within 1 sample of the Synchronous Master.

Asynchronous – the serial port uses its own clock source / domain. It has a double buffer and hooks its own DMA completion interrupt. In its interrupt handler, audio data is copied from the DMA double buffer to the input buffer of an Asynchronous Sample Rate Converter. Then in the module’s processing function, sample rate conversion occurs and data is copied from (to) the temporary buffer to the Audio Weaver wire buffer.

We will refer to these different synchronization schemes throughout this document and will use the abbreviations SM, SA, SU, and AS for Synchronous Master, Synchronous Aligned, Synchronous Unaligned, and Asynchronous operation.

The SM TDM port has special meaning for Audio Weaver. This is the I/O device which generates the master clock for all audio processing inside of Audio Weaver, and based on this, the Audio Weaver framework will generate interrupts for all audio processing cores. The SM TDM port can be configured to use an internal clock or an external clock. The SU ports compare DMA time stamps with the SM and use this information to time align themselves (within 1 sample).

The SM TDM port must be the first TDM port started and must therefore be on the early audio DSP. Once the SM port is running, it continues to run until either the system shuts down or enters a low power stage. It is also not possible to change the SM port at run-time. (For example, you can’t have TDM A be the SM for early audio and then switch to TDM B later on when the late audio system is up and running.)

There will be two different Audio Weaver modules for interfacing to the TDM ports, The SnapdragonSyncTDMPort will handle all of the synchronous use cases and will support input and output ports. The SnapdragonAsyncTDMPort will handle the asynchronous use cases. [Note that the SnapdragonAsyncTDMPort will not be available until a later release. It is not in the Audio Weaver R4.4 release.]

The Sync TDM ports begin running at system startup and continue to run until the system enters Low Power or Deep Sleep mode. The Async TDM modules can be stopped / started at run-time and the application code can reconfigure them while stopped.

The serial ports on the Snapdragon record a 64-bit time stamp upon buffer completion (the ping/pong switch). This time stamp has a resolution of 19.2 MHz and is written by the hardware peripherals. It is very accurate and does not rely on a software interrupt which may have jitter. This time stamp information will be used to align unaligned transfers and for the ASRC control loop needed for AS ports.

There are separate synchronous and asynchronous port interface modules as shown below. Each module can be used for input or output.

We describe the Synchronous and Asynchronous ports separately.

Hexagon TDM Port - Synchronous

This module supports all of the Synchronous clocking schemes described above.

Module Arguments

The module has a large number of arguments.

image-20250515-002907.png

 

direction - specifies whether this is a sink device (=0) or a source device (=1):

When configured as a TDM_SOURCE, the module has an audio output port (on the right), and a Timing Information port (TI) located on the top:

When configured as a TDM_SINK, the module has an input port on the left side and a Timing Information port (TI) located on the top:

numChannels, blockSize, and sampleRate - specify the properties of the TDM port. If this is an input module, then these values will also specify the properties of the output wire. If this is an output port, then the wire properties at the input must match these values. The sampleRate value is taken from a droplist:

clockingMode - specifies the clocking properties that was described above:

All other properties are taken directly from the AudioLite APIs and are used when opening the port. Here is a short explanation of the settings, more information can be found in Qualcomm documentation.

{lpaifIdx, lpaifType} - this pair of settings uniquely the port on the Snapdragon SOC. The lpaifType is only used in Gen 4 silicon and identifies different hardware subsystems on the SOC. For Gen 5 silicon, all TDM ports are included in the same hardware subsystem and this setting is ignored. lpaifIdx is the “port index” and specifies the port within a specific subsystem.

dataFormat - taken from AudioLite. You should only use “DATAFORMAT_FIXED_POINT”.

syncSrc - Specifies the source of the frame sync signal. Options include INTERNAL_SOURCE (generated by SoC as the clock master) or EXTERNAL_SOURCE (from an external clock input into the SoC).

slotMask - Bitmask specifying which active TDM slots to use. Each bit represents a time slot in the TDM frame. For example, 0x03 enables slots 0 and 1 (bits 0 and 1 set). This is an unsigned 32-bit value since a TDM port can have up to 32 slots.

slotCount - Total number of TDM slots in each frame. For example, set this to 2 for stereo data or 8 for 8 channel data. The number of bits in slotMask equals slotCount.

slotWidth - Width of each individual slot, in bits. Typical values are 8, 16, and 32. This controls slot packing and data padding.

syncMode - Specifies how the type of frame sync signal operates. Options are TDM_SHORT_SYNC_BIT_MODE (1-bit sync pulse) or TDM_LONG_SYNC_MODE (sync active for half of the full frame) or TDM_SHORT_SYNC_SLOT_MODE (sync active for the first slot of the full frame).

invertSync - Boolean setting to invert frame sync signal polarity. Used when the external codec expects opposite sync edge (e.g., active-low instead of active-high).

dataDelay - Number of bit clocks between the frame sync and valid data. Typical values are 0,1, or 2, affecting word alignment.

laneMask - Bitmask specifying which physical data lanes are active. E.g., 0x1 for lane 0 only, or 0x3 for lanes 0 and 1. Used in multichannel/multilane modes.

bitWidth - Total valid bit width per sample on the wire. Must be equal to or less than slotWidth.

invertBclk - Boolean setting to invert bit clock polarity.

A single TDM port can connect with multiple data lines. Each data line is called a “lane” and a port can have up to 8 individual lanes. The laneMask is a bit field that specifies which lane(s) (or data lines) are used by the port. The number of lanes equals the number of nonzero bits in the laneMask. Using more lanes increases the number of channels in the port.

Each data line / lane on a physical TDM port can be configured to be either an input or an output. In this mode, the input and output will share the same frame sync and bit clock, and the user must assure that the two ports are configured with matching parameters: bitWidth / slotCount / slotWidth / invertSync / dataDelay / syncMode / syncSrc / slotMask / dataFormat.

Each lane of a port has a total of slotCount channels in the TDM frame structure. slotMask is a bit field which specifies which of the slots will be used. The number of active slots equals the number of non-zero bits in the slotMask. For example, you can have slotCount = 32 and be connected to an A2B network. However if slotMask = 0xFF, you are only reading/writing 8 slots of the 32 available.

The total number of channels at the output (or input) of the port equals the numChannels argument. This must match (number of lanes) x (active slot count). This is checked within the Designer code and you will receive an error if this condition is not satisfied.

 

Timing Information Output Pin

This pin has a size of 6x1 samples and contains integer data. (This is a control signal with 6 channels and a block size of 1). It has a sample rate of sampleRate/blockSize. It contains these values:

isStarted - Boolean value indicating whether the device has been enabled

timeStampL - the low 32-bits of the time stamp when the ping/pong buffer of the module last flipped.

timeOffsetFromMaster - time skew between this port and the SM. In microseconds. This is measured based on the DMA time stamps.

rwOffset - computed offset used to index early or late in the DMA buffer

sampleLatencyFromMaster - the final latency in samples relative to the SM port.

Module Inspector

Start - User Parameter. Allows you to turn the port on or off.

DMA Safety Delay - User Parameter. Additional use specified time delay that will be used in the offset calculation. This will be used for testing and for situations when we want to give more time for the DMA to complete. The actual math used is:

DMA Offset = floor((TS_SM - TS_SU + dmaSafeDelay) / (Sample Period))

Startup Settling Count - User Parameter. This specifies how many blocks pump cycles the module will do and continue to output zero data. This gives the module time to calculate its read/write offset so that it doesn’t introduce a pop or click when it changes.

Startup Latency - User Parameter. The BSP will wait the specified number of microseconds before enabling the serial port clocks. This value is used for testing and will allow us to play with the alignment between ports. During normal usage, it should be set to 0.

Error Status - Read Back State. Reports errors in startup or operation. 0 indicates no error.

Pump Counter - Read Back State. Increments every time the module’s processing function is called.

Time Offset to Master - Read Back State. This is the computed time skew between this port and the SM This is a floating-point number and represents microseconds.

DMA Ptr RW Offset - Read Back State. This is the computed sample offset when accessing the DMA buffer. This is calculated per block. Instead of accessing the buffer at the expected start of the ping or pong buffer, this offset is added.

Offset to Master - Read Back State. This is the true offset in samples relative to the SM device. It is used to add compensating delay in the system. If a SU device has a latency of +1 samples, then the SM should be delayed by 1 sample.

Time Alignment Between Synchronous Devices

The SM and all SA devices operate off the same clocks and will be completely synchronized; 0 sample latency.

When operating as a SU port, there is internal logic which uses the time stamp of each port’s DMA interrupt to align the data with the SM port. If you have dmaSafetyDelay set to 0 then the SU port will be aligned to within 1 sample for input and output ports. This could be a fractional sample delay since the clocks start independently.

If dmaSafetyDelay is nonzero, then this will add additional latency. dmaSafetyDelay is specified in microseconds and you end up with different latency from boot-to-boot. Fortunately, the timing output pin reports the actual latency (in samples) in sampleLatencyFromMaster and you can use this to time align signals in your layout. For example, if the SU port reports a sampleLatencyFromMaster of 1 sample, then it means that the SU port is 1 sample delayed relative to the SM. To align the ports, you need to add 1 sample of delay to the output of the SM port.

Audio Startup Sequence

When a system is built using Audio Weaver Designer, or when an AWB file is loaded, the TDM modules are individually constructed based on their location in the signal flow. The TDM ports, however, are not started until the “audio_start” command is received. (This is usually the last command when building or loading a system.)

The Snapdragon BSP starts SM and SA TDM ports using the following sequence:

  1. Enable the bit clock for the SM port

  2. Enable DMA for the SA ports. This enables the DMA but does not start interrupts.

  3. Enable SM port framesync. At this point, the SM and SA ports will be operational and generating interrupts synchronously.

After the SM and SA ports are running, then the SU and AS ports are started. There are no special startup requirements for the SU and AS ports.

On the SA8255, the TDM ports can be placed on different Hexagon cores. Each DSP boots in order and the serial ports on each core follow the sequence shown above. On the SA8255, all SM and SA ports must be on the PAC; you cannot place them on different DSPs.

During early audio, the TDM ports are started as follows:

  1. The Primary Audio Core (PAC) initializes and loads its AWB first.

    1. All TDM ports on the PAC are initialized using the sequence above.

    2. Audio start command starts DMA on the PAC. Audio is active.

  2. PAC signals GPDSP0 to start initializing

    1. GPDSP0 loads its own AWB

    2. GPDSP0 initializes the TDM modules in its AWB

    3. TDM audio interrupts start on GPDSP0

    4. GPDSP0 signals the PAC that it is done initializing

    5. The PAC signals GPDSP0 to pump audio

  3. PAC signals GPDSP1 to start initializing

    1. GPDSP1 loads its own AWB

    2. GPDSP1 initializes the TDM modules in its AWB

    3. Audio interrupts start on GPDSP1

    4. GPDSP1 signals the PAC that it is done initializing

    5. The PAC signals GPDSP1 to pump audio

  4. Early audio is fully initialized

TDM Port Latency

The input to output latency on the SA8255 ADP was measured using a loopback test. The signal path was:

TDM Output → A2B → DAC → ADC → A2B → TDM Input

The measurement included the digital buffering latency of Audio Weaver and also the latency through the analog codec. With a 0.25 msec block size (12 samples at 48 kHz), we measured a total delay of 1.6 msec. This corresponded to a 0.5 msec Audio Weaver processing delay, and a 1.1 msec analog delay. More details can be found here.

Usage Guidelines / Restrictions

  1. You are only allowed to define a single TDM port as being the Synchronous Master. If you define multiple ports as Synchronous Master, then you will get a build error. Similarly, if you have no TDM ports configured as the Synchronous Master, then you will get an error.

  2. The Synchronous Master TDM port must be on instance 0 (core 0). Keep in mind that you can assign any DSP core to be instance 0 in the YAML configuration file. Thus, it is possible to place the Synchronous Master device on GPDSP0 or GPDSP1.

  3. An input or output TDM port can be used as the Synchronous Master device.

  4. All Synchronous TDM ports have have the same block size and sample rate, and they all must be configured with a clockDivider of 1.

  5. Although there is no absolute minimum for the block size of a TDM port, we recommend that you keep it at 12 samples or larger (0.25 msec at 48 kHz). Smaller blocks have higher overhead.

  6. The clock speed (bit rate) of a single lane of your port equals sampleRate x slotWidth x slotCount. The maximum supported clock speed is 24.576 MHz. If you need to get more data into a TDM port, then you need to use multiple lanes.

  7. If any 2 TDM ports shared exactly the same {direction, lpaifIdx, lpaifType} settings, then this is an error.

  8. The same TDM port {lpaifIdx, lpaifType} can be used simultaneously as input (Rx) and output (Tx). This requires 2 different TDM port modules in your signal flow. The Rx and Tx TDM ports must be placed on the same Hexagon DSP core and there are additional restrictions:

    1. They must have the same bitWidth, slotWidth, slotCount, sampleRate, syncMode, invertSync, dataDelay, syncSrc, and invertBclk settings.

    2. The lane masks must not be overlapped. That is, the input and output ports have to use distinct lanes. That is: (bitand(input.laneMask, output.laneMask) == 0).

  9. The numChannels settings of a port must equal (number of lanes) x (slots per lane).

  10. The bitWidth of a port has to be equal to or less than the slotWidth.

  11. On the Gen 4 SOC, some of the TDM I/O lines are muxed between ports. The following combinations are not allowed:

    1. {lpaifType = LPAIF_CORE, lpaifIdx = INTFC1} and {lpaifType = LPAIF_SDR, lpaifIdx = INTFC3}

    2. {lpaifType = LPAIF_CORE, lpaifIdx = INTFC2} and {lpaifType = LPAIF_SDR, lpaifIdx = INTFC4}

  12. However, on Gen4, the following are supported:

    1. {lpaifType = LPAIF_CORE, lpaifIdx = INTFC1} and {lpaifType = LPAIF_CORE, lpaifIdx = INTFC3}

    2. {lpaifType = LPAIF_CORE, lpaifIdx = INTFC2} and {lpaifType = LPAIF_CORE, lpaifIdx = INTFC4}

  13. Do not make the block sizes of your TDM ports too large. There is a limited amount of DMA memory on the Snapdragon and you may exceed this. (Audio Weaver testing has been with block sizes up to 5.0 msec.)

  14. Large block sizes lead to more efficient operation. You should restrict the small block sizes (0.25 and 0.5 msec) for use cases that require low latency. For other non-latency sensitive operations (like playback or Bluetooth), you should use the ChangeThread module to buffer up to a larger block size.

  15. If you stop a port, it will stop the audio DMA and interrupts. The DMA memory is freed up. When you start the port, DMA memory is reallocated and DMA interrupts start again. SA ports will restart and be time aligned to the SM port. SU ports will restart and resynchronize themselves to the SM port.

  16. The SM, SA, and SU ports have a single block size argument. This block size is used to set the block size of the DMA interrupt and also the block size at the output (or input) audio pins in Audio Weaver.

  17. The AS port has separate sample rates and block sizes for the device configuration and the Audio Weaver configuration. After stopping an AS device, you can change the device block size and sample rate, and these new values will be used when the port is restarted. This feature is specifically for interfacing with Bluetooth devices.

  18. TDM ports can only be accessed from the Hexagon DSPs. They are not available on the Arm.

  19. On the SA8255, the DSPs are all part of the early audio boot sequence and thus all TDM ports must be initialized during early audio. On SA8797/SA8397, only DSP0 is part of the early boot sequence. TDM ports can be on DSP0 and on DSP1 or DSP2 which are part of the late boot sequence.