diff --git a/examples/app_spdif_tx_example/src/main.xc b/examples/app_spdif_tx_example/src/main.xc index f9e3bf7..270933c 100644 --- a/examples/app_spdif_tx_example/src/main.xc +++ b/examples/app_spdif_tx_example/src/main.xc @@ -20,6 +20,7 @@ on tile[1]: out buffered port:32 p_spdif_tx = XS1_PORT_1A; on tile[1]: in port p_mclk_in = XS1_PORT_1D; on tile[1]: clock clk_audio = XS1_CLKBLK_1; +#define USE_DEDICATED_CLKBLK 0 // This allows larger ratios of MCLK_FREQ/SAMPLE_FREQ (>768) but requires a dedicated clock block. #define SAMPLE_FREQUENCY_HZ 96000 #define MCLK_FREQUENCY_48 24576000 #define WORD_LENGTH (24) @@ -95,7 +96,11 @@ int main(void) { on tile[1]: { spdif_tx_port_config(p_spdif_tx, clk_audio, p_mclk_in, 7); start_clock(clk_audio); +#if USE_DEDICATED_CLKBLK + spdif_tx_lld(p_spdif_tx, c_spdif, clk_audio); +#else spdif_tx(p_spdif_tx, c_spdif); +#endif } on tile[1]: generate_samples(c_spdif); } diff --git a/lib_spdif/api/spdif.h b/lib_spdif/api/spdif.h index b8b0b65..f3a32c4 100644 --- a/lib_spdif/api/spdif.h +++ b/lib_spdif/api/spdif.h @@ -199,5 +199,25 @@ void spdif_tx_output(chanend c_spdif_tx, unsigned lsample, unsigned rsample); */ void spdif_tx_shutdown(chanend c); +/** S/PDIF transmit function low level. + * + * This function provides an S/PDIF transmit component. + * It is capable of 44100, 48000, 88200, 96000, and 192000 Hz sample + * rates and 16, 20 or 24 bits of sample word lengths. + * + * The sample rate or word length can be dynamically changed during the operation + * of the component. Note that the first API call to this component + * should be to reconfigure the sample rate and the word length (using the + * spdif_tx_reconfigure_sample_rate() function). + * + * Setting the clk to NULL will force clock division in software (allowing + * sharing of clock block) otherwise division is carried out in the clock + * block. + * + * \param p_spdif The output port to transmit to + * \param c chanend to connect to the application + * \param clk the clock that the S/PDIF component will use + */ +void spdif_tx_lld(buffered out port:32 p, chanend c, clock ?clk); #endif /* _SPDIF_H_ */ diff --git a/lib_spdif/src/SpdifTransmit.xc b/lib_spdif/src/SpdifTransmit.xc index f2a550e..25023e0 100644 --- a/lib_spdif/src/SpdifTransmit.xc +++ b/lib_spdif/src/SpdifTransmit.xc @@ -262,6 +262,11 @@ unsigned build_consumer_channel_status(uint32_t chanStat_L[6], uint32_t chanStat /* S/PDIF transmit thread */ void spdif_tx(buffered out port:32 p, chanend c_in) +{ + spdif_tx_lld(p, c_in, NULL); +} + +void spdif_tx_lld(buffered out port:32 p, chanend c_in, clock ?clk) { chkct(c_in, XS1_CT_END); while(1) @@ -297,6 +302,15 @@ void spdif_tx(buffered out port:32 p, chanend c_in) /* Calculate required divide */ divide = mclkFreq / (samFreq * 2 * 32 * 2); + + if (!isnull(clk)) + { + /* Set clock divider in clock block */ + stop_clock(clk); + set_clock_div(clk, (divide>>1)); + start_clock(clk); + divide = 1; /* Don't do clock division in software */ + } if((divide != 1) && (divide != 2) && (divide != 4) && (divide != 6)) error++;