If you are slave on one side and master on the then you don't need any SRC at all? Can't the I2S master drive the I2S slave LRCLK and BCLK lines?
Did you mean that if the data path is spdif in->spdif rx(xmos)->i2s slave(xmos) -> i2s master(dsp) then I don't need to use the asrc or the ssrc lib function ?
I have modify the main.xc in
SPDIF Receive to I2S output using Asynchronous Sample Rate Conversion.
Code: Select all
// Copyright (c) 2016, XMOS Ltd, All rights reserved
//Standard includes
#include <xs1.h>
#include <platform.h>
#include <string.h>
//Supporting libraries
#include "src.h"
#include "spdif.h"
#include "i2s.h"
#include "i2c.h"
#include "gpio.h"
#include "assert.h"
//Application specific includes
#include "main.h"
#include "block_serial.h"
#include "cs4384_5368.h" //CODEC setup
#include "app_config.h" //General settings
//Debug includes
#include <debug_print.h> //Enabled by -DDEBUG_PRINT_ENABLE=1 in Makefile
#include <xscope.h>
//These port assignments all correspond to XU216 multichannel audio board 2V0
//The port assignments can be changed for a different port map.
#define AUDIO_TILE 0
in buffered port:32 ports_i2s_adc[4] = on tile[AUDIO_TILE]: {XS1_PORT_1I,
XS1_PORT_1J,
XS1_PORT_1K,
XS1_PORT_1L};
port port_i2s_mclk = on tile[AUDIO_TILE]: XS1_PORT_1F;
clock clk_mclk = on tile[AUDIO_TILE]: XS1_CLKBLK_2;
out buffered port:32 port_i2s_bclk = on tile[AUDIO_TILE]: XS1_PORT_1H;
out buffered port:32 port_i2s_wclk = on tile[AUDIO_TILE]: XS1_PORT_1G;
clock clk_i2s = on tile[AUDIO_TILE]: XS1_CLKBLK_1;
out buffered port:32 ports_i2s_dac[4] = on tile[AUDIO_TILE]: {XS1_PORT_1M,
XS1_PORT_1N,
XS1_PORT_1O,
XS1_PORT_1P};
#define SPDIF_TILE 1
port port_spdif_rx = on tile[SPDIF_TILE]: XS1_PORT_1P;
clock clk_spdif_rx = on tile[SPDIF_TILE]: XS1_CLKBLK_1;
out port port_leds_col = on tile[SPDIF_TILE]: XS1_PORT_4C; //4x4 LED matrix
out port port_leds_row = on tile[SPDIF_TILE]: XS1_PORT_4D;
port port_i2c = on tile[AUDIO_TILE]: XS1_PORT_4A; //I2C for CODEC configuration
port port_audio_config = on tile[AUDIO_TILE]: XS1_PORT_8C;
char pin_map_audio_cfg[5] = {0, 1, 5, 6, 7};
/* Bit map for XS1_PORT_8C
* 0 DSD_MODE
* 1 DAC_RST_N
* 2 USB_SEL0
* 3 USB_SEL1
* 4 VBUS_OUT_EN
* 5 PLL_SELECT
* 6 ADC_RST_N
* 7 MCLK_FSEL
*/
port port_buttons = on tile[AUDIO_TILE]: XS1_PORT_4D; //Buttons and switch
char pin_map_buttons[1] = {0}; //Port map for buttons GPIO task. We are just interested in bit 0
out port port_debug_tile_1 = on tile[SPDIF_TILE]: XS1_PORT_1N; //MIDI OUT. A good test point to probe..
out port port_debug_tile_0 = on tile[AUDIO_TILE]: XS1_PORT_1D; //SPDIF COAX TX. A good test point to probe..
//zhengyang
typedef interface get_sample {
unsigned get_counts(void);
}get_sample;
#define SR_CALC_PERIOD 2000000 //20ms The period over which we count samples to find the rate
//Because we timestamp at 10ns resolution, we get 20000000/10 = 21bits of precision
//Application task prototypes. For functionality of these tasks, see comments in implementations below
void spdif_handler(streaming chanend c_spdif_rx, streaming chanend c_temp);
//void i2s_handler(server i2s_callback_if i2s, client serial_transfer_pull_if i_serial_out, client audio_codec_config_if i_codec, server buttons_if i_buttons, client get_sample i_sample);
void i2s_handler(server i2s_callback_if i2s, client audio_codec_config_if i_codec, streaming chanend c_temp);
int main(void){
streaming chan c_aud_dsp;
interface audio_codec_config_if i_codec;
interface i2c_master_if i_i2c[1];
interface output_gpio_if i_gpio[5]; //See mapping of bits 0..7 above in port_audio_config
interface i2s_callback_if i_i2s;
input_gpio_if i_button_gpio[1];
streaming chan c_spdif_rx;
//zhengyang
get_sample i_sample;
par{
on tile[SPDIF_TILE]: spdif_rx(c_spdif_rx, port_spdif_rx, clk_spdif_rx, DEFAULT_FREQ_HZ_SPDIF);
on tile[AUDIO_TILE]: {
spdif_handler(c_spdif_rx, c_aud_dsp);
}
on tile[AUDIO_TILE]: audio_codec_cs4384_cs5368(i_codec, i_i2c[0], CODEC_IS_I2S_SLAVE, i_gpio[0], i_gpio[1], i_gpio[3], i_gpio[4]);
on tile[AUDIO_TILE]: i2c_master_single_port(i_i2c, 1, port_i2c, 10, 0 /*SCL*/, 1 /*SDA*/, 0);
on tile[AUDIO_TILE]: output_gpio(i_gpio, sizeof(pin_map_audio_cfg), port_audio_config, pin_map_audio_cfg);
on tile[AUDIO_TILE]: {
configure_clock_src(clk_mclk, port_i2s_mclk); //Connect MCLK clock block to input pin
start_clock(clk_mclk);
debug_printf("Starting I2S\n");
i2s_master(i_i2s, ports_i2s_dac, 1, ports_i2s_adc, 1, port_i2s_bclk, port_i2s_wclk, clk_i2s, clk_mclk);
}
on tile[AUDIO_TILE]: i2s_handler(i_i2s, i_codec, c_aud_dsp);
}
return 0;
}
//Shim task to handle setup and streaming of SPDIF samples from the streaming channel to the interface of serial2block
void spdif_handler(streaming chanend c_spdif_rx, streaming chanend c_temp)
{
unsigned index; //Channel index
signed long sample;
signed long sample_temp[2]={0}; //Sample received from SPDIF
delay_microseconds(10000); //Bug 17263 workaround (race condition in distributable task init)
while (1) {
select {
case spdif_receive_sample(c_spdif_rx, sample, index):
if(index == 0){
for(int i=0; i<2; i++){
c_temp <: sample_temp[i];
}
}
xscope_int(CH_0, sample);
sample_temp[index] = sample;
break;
}
}
}
#define MUTE_MS_AFTER_SR_CHANGE 350 //350ms. Avoids incorrect rate playing momentarily while new rate is detected
//Shim task to handle setup and streaming of I2S samples from block2serial to the I2S module
//[[distributable]]
#pragma unsafe arrays //Performance optimisation of i2s_handler task
void i2s_handler(server i2s_callback_if i2s, client audio_codec_config_if i_codec, streaming chanend c_temp)
{
unsigned sample_rate = DEFAULT_FREQ_HZ_I2S;
unsigned mclk_rate;
unsigned restart_status = I2S_NO_RESTART;
unsigned mute_counter; //Non zero indicates mute. Initialised on I2S init SR change
// timer t_case;
// unsigned t_temp;
// t_case :> t_temp;
// t_temp += SR_CALC_PERIOD;
unsigned long sample_temp[2] = {0};
while (1) {
select {
case i2s.init(i2s_config_t &?i2s_config, tdm_config_t &?tdm_config):
if (!(sample_rate % 48000)) mclk_rate = MCLK_FREQUENCY_48; //Initialise MCLK to appropriate multiple of sample_rate
else mclk_rate = MCLK_FREQUENCY_44;
i2s_config.mclk_bclk_ratio = mclk_rate / (sample_rate << 6);
i2s_config.mode = I2S_MODE_I2S;
i_codec.reset(sample_rate, mclk_rate);
debug_printf("Initializing I2S to %dHz and MCLK to %dHz\n", sample_rate, mclk_rate);
restart_status = I2S_NO_RESTART;
mute_counter = (sample_rate * MUTE_MS_AFTER_SR_CHANGE) / 1000; //Initialise to a number of milliseconds
break;
//Start of I2S frame
case i2s.restart_check() -> i2s_restart_t ret:
ret = restart_status;
break;
//Get samples from ADC
case i2s.receive(size_t index, int32_t sample):
break;
//Send samples to DAC
case i2s.send(size_t index) -> int32_t sample:
if(index == 0){
for(int i=0; i< 2; i++){
c_temp :> sample_temp[i];
}
}
sample = sample_temp[index];
break;
}
}
}
It works well with sample rate between 44.1kHz and 192kHz without using FIFO or buffer . But the sound from the Line Out has some slight noise, I guess may be the reason is that the clock is not syschronous. How do you think about this ?