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()

    This function has the following 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

    This function has the following 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;
       setupPll();
       par {
          transmitSpdif(c);
          generate(c);
          clockGen();
       }
    }
    
    int main(void) {
       par {
          on stdcore[1]: example();
       }
       return 0;
    }