S/PDIF receive

xcore devices can support S/PDIF receive up to 192 kHz - see lib_spdif for full specifications.

The S/PDIF receiver module uses a clock-block and a buffered one-bit port. The clock-block is divided off a 100 MHz reference clock. The one bit port is buffered to 32 bits. The receiver code uses this clock to over sample the input data.

The receiver outputs audio samples over a streaming channel end where data can be input using the built-in input operator. lib_spdif also provides API functions that wrap up this communication.

The S/PDIF receive function never returns. The 32-bit value from the channel input comprises of fields shown in Table 39.

Table 39 S/PDIF receive word structure

Bits

0:3

A tag (see below)

4:28

PCM encoded sample value

29:31

User bits (parity, etc)

The tag has one of three values, as shown in Table 40.

Table 40 S/PDIF receive tags

Tag

Meaning

FRAME_X

Sample on channel 0 (Left for stereo)

FRAME_Y

Sample on another channel (Right if for stereo)

FRAME_Z

Sample on channel 0 (Left), and the first sample of a frame; can be used if the user bits need to be reconstructed.

See S/PDIF, IEC 60958-3:2006, specification for further details on format, user bits etc.

Usage and integration

Since S/PDIF is a digital stream, the device’s master clock must be synchronised to it. This is typically done with an external device or the xcore.ai secondary PLL. See External clock recovery (Clock Gen).

Note

Due to the requirement for this clock recovery S/PDIF receive can only be used in Asynchronous mode.

The S/PDIF receive function communicates with the Clock Gen thread, which in turn passes audio data to the Audio Hub thread. The Clock Gen thread also handles locking to the S/PDIF clock source. Again, see External clock recovery (Clock Gen).

The parity of each word/sample received is checked. This is done using the spdif_rx_check_parity() function provided by lib_spdif:

                /* Check parity and ignore if bad */
                if(spdif_rx_check_parity(spdifRxData))
                    continue;

If bad parity is detected the word/sample is ignored, otherwise the tag is inspected for channel (i.e. left or right) and the sample stored.

The following code snippet illustrates how the output of the S/PDIF receive component is fundamentally used. Note the use of helper defines/macros for frame identification and sample data extraction, provided by lib_spdif:

while(1)
{
   c_spdif_rx :> data;

   if(spdif_check_parity(data)
     continue;

   tag = data & SPDIF_RX_PREAMBLE_MASK;

   /* Extract 24bit audio sample */
   sample = SPDIF_RX_EXTRACT_SAMPLE(data);

   switch(tag)
   {
     case SPDIF_FRAME_X:
     case SPDIF_FRAME_X:
       // Store left sample
       break;

     case SPDIF)FRAME_Z:
       // Store right sample
       break;
   }
}

The Clock Gen thread stores samples in a small FIFO before they are communicated to the Audio Hub thread.