<<

S/PDIF Transmit

This module is a single thread that receives samples over a channel and that outputs data on the port.

The S/PDIF transmit module require a one-bit buffered output port (with transfer width of 32), a clock block, and a master clock coming in on an unbuffered one-bit port.

API

Call SpdifTransmitPortConfig to set up the clock then SpdifTransmit to output data.

void SpdifTransmitPortConfig(out buffered port:32 p, clock cl, in port p_mclk)

Configure out port to be clocked by clock block, driven from master clock input.

Must be called before SpdifTransmit()

Parameters:
  • p – S/PDIF tx port
  • cl – Clock block to be used
  • p_mclk – Master-clock input port
void SpdifTransmit(buffered out port:32 p, chanend c)

Function expects a buffered single bit port clock from the master clock.

All channel communication is done via builtins (e.g. outuint, outct etc.)

On startup expects two words over the channel:

  1. Desired sample frequency (in Hz)
  2. Master clock frequency (in Hz)

Then sample pairs:

  1. Left sample
  2. Right sample

The data format is 24-bit signed left aligned in a 32-bit word.

If a XS1_CT_END token is received, the thread stops and waits for new sample/master freq pair

Parameters:
  • p – S/PDIF tx port
  • c – Channel-end for sample freq and samples

Example

This example generates a triangle sound wave on the SPDIF interface from a USB Audio 2.0 multichannel interface board. On this board the master clock input is from a PLL. The program is shown below (excluding code to set up the PLL on the board).

An output port, a master-clock input port and a clock block must be declared:

#include <xs1.h>
#include <platform.h>
#include "SpdifTransmit.h"

#define SAMPLE_FREQUENCY_HZ 96000
#define MASTER_CLOCK_FREQUENCY_HZ 12288000

on stdcore[1] : buffered out port:32 oneBitPort = XS1_PORT_1K;
on stdcore[1] : in port masterClockPort = XS1_PORT_1L;
on stdcore[1] : clock clockblock = XS1_CLKBLK_1;

In this example transmitSpdif sets up the clock and starts the transmit function to receive on a chanend.

void transmitSpdif(chanend c) {
    SpdifTransmitPortConfig(oneBitPort, clockblock, masterClockPort);
    SpdifTransmit(oneBitPort, c);
}

The generate function sends configuration settings over a channel then a triangle wave.

#define WAVE_LEN 512
void generate(chanend c) {
    int i = 0;
    outuint(c, SAMPLE_FREQUENCY_HZ);
    outuint(c, MASTER_CLOCK_FREQUENCY_HZ);
    while(1) {
       // Generate a triangle wave
       int sample = i;
       if (i > (WAVE_LEN / 4)) {
          // After the first quarter of the cycle
          sample = (WAVE_LEN / 2) - i;
       }
       if (i > (3 * WAVE_LEN / 4)) {
          // In the last quarter of the cycle
          sample = i - WAVE_LEN;
       }
       sample <<= 23; // Shift to highest but 1 bits
       outuint(c, sample); // Left channel
       outuint(c, sample); // Right channel

       i++;
       i %= WAVE_LEN;
    }
    //outct(c, XS1_CT_END); // to stop SpdifTransmit thread
}
The example starts by setting up the PLL on the board. Then it creates 3 threads:
  • S/PDIF transmit
  • the data generator
  • clock generator for the PLL

An XC channel connects the generator and the transmit thread.

void example(void) {
   chan c;
   setupclocking();
   par {
      transmitSpdif(c);
      generate(c);
      clockGen();
   }
}

int main(void) {
   par {
      on stdcore[1]: example();
   }
   return 0;
}