lpcware

LPC4357 I2S0 4-wire problem

Discussion created by lpcware Employee on Jun 15, 2016
Content originally posted in LPCWare by pgeloso on Tue Dec 29 09:26:21 MST 2015
Hi,
I've connected an LPC4357 to a AK4621 codec: LPC4357 is I2S master while codec is the I2S slave.
I need a 4 wire configuration, because transmitter and receiver share Word Select Clock and Bit Clock.
With CGU I've generated the 12.288MHz needed by the codec and I use the BASE_AUDIO to source the clock to I2S.

I'm using using LPCXpresso 7.8.0.

I set I2S0 TX as a master and sourced by BASE_AUDIO_CLOCK as explained in Fig 151 of the user manual: it works fine.
I set the IS0 RX as a 4-wire slave sourced by I2S0 TX according to Fig 157 of the user manual but I always read zeros, even if I can see the I2S activity on the receive pin.
I have I2S0 interrupts from the RX: it means that the RX is alive and it's reading data..but all zeros..

I guess I'm missing something in the I2S set up...but what?
Any suggestions?

Thanks
Pietro


void I2S0_IRQHandler(void)
{
uint8_t index;
index=0;
while (Chip_I2S_GetRxLevel(LPC_I2S0) > 0) {
Rx_Buf[index] = Chip_I2S_Receive(LPC_I2S0);
index++;
if (index == I2S_BUFF_MAX) break;
}
index=0;
while (Chip_I2S_GetTxLevel(LPC_I2S0) < 8) {
Chip_I2S_Send(LPC_I2S0, Tx_Buf[index]);
index++;
if (index == I2S_BUFF_MAX) break;
}
handler_i2s0=1;
return;
}

int main(void)
{
int i=0;
uint32_t j=0;
//uint8_t status;
I2S_AUDIO_FORMAT_T audio_Confg;

audio_Confg.SampleRate = AUDCFG_SAMPLE_RATE; //Hz
audio_Confg.ChannelNumber = I2S_CHANNELS;// Select audio data is 2 channels (1 is mono, 2 is stereo)
audio_Confg.WordWidth = I2S_BITS_PER_SAMPLE;// Select audio data is 16 bits

SystemCoreClockUpdate();
New_Board_Init();//new hardware..empty function, just for compilation

//CLK2 pin@12.288MHz for CODEC AK Main clock
Chip_SCU_ClockPinMuxSet(2, SCU_MODE_FUNC1);//SFSCLK2  ..CLK2, function 1: pin attivato!

i=InitAudioPLL();//AUDIO PLL0 12.288MHz generation with fractional divider
//if(i!=0) {fail!!}

my_leds_setup();//2 leds

//biquad filter init
//init_filter(&lpf1);
init_i2s_data_structure();
//calc_biquad_coeff(&lpf1, 2000.0, 1.4, LPF);//f0=2KHz,Q=1.4, low pass

//I2S0 pin: CODEC
Chip_SCU_PinMuxSet(9, 1, SCU_MODE_FUNC4 | SCU_MODE_INACT);  //SCU_MODE_INACT disable pull up/down  // I2S0_TX_WS: left right clock
Chip_SCU_PinMuxSet(3, 0, SCU_MODE_FUNC2 | SCU_MODE_INACT );  //I20_TX_SCK: bit clock
Chip_SCU_PinMuxSet(0xC, 12, SCU_MODE_FUNC6 | SCU_MODE_INACT); // I2S0_TX_SDA:
Chip_SCU_PinMuxSet(6, 2, SCU_MODE_FUNC3 | SCU_MODE_INACT );  // I20_RX_SDA
//pin right channel OVFR viene letto dal pin del micro C_11
Chip_SCU_PinMuxSet(0xC, 11, SCU_MODE_FUNC4 | SCU_MODE_INACT);  //SCU_MODE_INACT disable pull up/down.  GPIO pin
Chip_GPIO_SetPinDIRInput(LPC_GPIO_PORT, 0xC, 11);//input


//Chip_I2S_Init(LPC_I2S0);//APB1 clock..we use AUDIO_CLOCK
Chip_I2S_RxConfig_4wire(LPC_I2S0, &audio_Confg);//4-wire SLAVE : Rx uses SCK and WS of TX. RX setup before TX setup!
Chip_I2S_TxConfig_Master_Base_Audio(LPC_I2S0, &audio_Confg);//Base audio clock and Master..

Chip_I2S_RxStop(LPC_I2S0); //++added before TX
Chip_I2S_TxStop(LPC_I2S0);
Chip_I2S_DisableMute(LPC_I2S0);

Chip_I2S_Int_RxCmd(LPC_I2S0, ENABLE, 4);
Chip_I2S_Int_TxCmd(LPC_I2S0, ENABLE, 4);

NVIC_ClearPendingIRQ(I2S0_IRQn);
Chip_I2S_RxStart(LPC_I2S0);
Chip_I2S_TxStart(LPC_I2S0);
NVIC_EnableIRQ(I2S0_IRQn);//start!

while(1){

if(handler_i2s0==1){
handler_i2s0=0;
LED_HIGH;
memcpy(Tx_Buf, Rx_Buf, I2S_BUFF_MAX*4);//talkthrough
LED_LOW;
}
}

return 0;
}


/* Configure I2S for Audio Format input 4-wire added++*/
Status Chip_I2S_RxConfig_4wire(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format)
{
uint32_t temp;
//uint16_t xDiv, yDiv;
//uint32_t N;

//if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) {
//return ERROR;
//}
temp = pI2S->DAI & (~(I2S_DAI_WORDWIDTH_MASK | I2S_DAI_MONO | I2S_DAI_SLAVE | I2S_DAI_WS_HALFPERIOD_MASK));
if (format->WordWidth <= 8) {
temp |= I2S_WORDWIDTH_8;
}
else if (format->WordWidth <= 16) {
temp |= I2S_WORDWIDTH_16;
}
else {
temp |= I2S_WORDWIDTH_32;
}

temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO;
temp |=I2S_SLAVE_MODE;// I2S_MASTER_MODE; //I2S_SLAVE_MODE; -> in slave mode si blocca il clock
temp |= I2S_DAI_WS_HALFPERIOD(format->WordWidth - 1);
pI2S->DAI = temp;
pI2S->RXMODE = I2S_RXMODE_CLKSEL(2) ;//TX_MAINCLOCK..useless...
pI2S->RXMODE |= I2S_RXMODE_4PIN_ENABLE; //++added
pI2S->RXBITRATE = 3;//should be useless..
//pI2S->RXRATE = yDiv | (xDiv << 8);
return SUCCESS;
}
Status Chip_I2S_TxConfig_Master_Base_Audio(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format)
{
uint32_t temp;
//uint16_t xDiv, yDiv;
//uint32_t N;

//if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) {
//return ERROR;
//}
//Audio Clock @ 12.288 MHz from BASE_AUDIO

//CREG6[12]=1;
temp=LPC_CREG->CREG6;
LPC_CREG->CREG6 |= (1<<12);

temp = pI2S->DAO & (~(I2S_DAO_WORDWIDTH_MASK | I2S_DAO_MONO | I2S_DAO_SLAVE | I2S_DAO_WS_HALFPERIOD_MASK));
if (format->WordWidth <= 8) {
temp |= I2S_WORDWIDTH_8;
}
else if (format->WordWidth <= 16) {
temp |= I2S_WORDWIDTH_16;
}
else {
temp |= I2S_WORDWIDTH_32;
}

temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO;
temp |= I2S_MASTER_MODE;
temp |= I2S_DAO_WS_HALFPERIOD(format->WordWidth - 1);
pI2S->DAO = temp;
pI2S->TXMODE = I2S_TXMODE_CLKSEL(1);//?
pI2S->TXBITRATE = 3;//++ -> TX_MCLK/(3+1)=BitClock -> 12.288MHz/3.072MHz =4
//pI2S->TXRATE = yDiv | (xDiv << 8);// non serve...
return SUCCESS;
}

Outcomes