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:
- Desired sample frequency (in Hz)
- Master clock frequency (in Hz)
Then sample pairs:
- Left sample
- 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:
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;
}