I2S on XMC Relax Lite Kit

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hi@all,

I'm a very beginner to the XMC platform. Since there is no sample application for I2S (IIS) at the moment I tried it myself to bring it to run as a slave for receiving data. I succeed in starting up the USIC module for configuration and I can see the DX2S bit in PSR_IISMode register changing frequently indication a changing WA signal, as well as a frequently change of all input pins (P1.0 for WA, P1.1 for clock and P1.4 for serial in). But unfortunately there are no data in the expected registers RBUF0 and RBUF1.

The codeing I did looks like this.

// set clock and release reset for USIC0
SCU_CLK->CGATCLR0 = SCU_CLK_CGATCLR0_USIC0_Msk;
SCU_RESET->PRCLR0 |= ((1 << SCU_RESET_PRSET0_USIC0RS_Pos) & SCU_RESET_PRSET0_USIC0RS_Msk);

// USIC0 basic settings
USIC0_CH0->KSCFG |= (USIC_CH_KSCFG_BPMODEN_Msk | USIC_CH_KSCFG_MODEN_Msk);

USIC0_CH0->CCR = 0;
USIC0_CH0->SCTR |= USIC_CH_SCTR_TRM_Msk;

USIC0_CH0->DX0CR = (1 << USIC_CH_DX0CR_DSEL_Pos) | (1 << USIC_CH_DX0CR_INSW_Pos); // SIN
USIC0_CH0->DX1CR = (0 << USIC_CH_DX1CR_DSEL_Pos) | (1 << USIC_CH_DX1CR_INSW_Pos) | (1 << USIC_CH_DX1CR_DPOL_Pos); // CLK
USIC0_CH0->DX2CR = (0 << USIC_CH_DX2CR_DSEL_Pos) | (1 << USIC_CH_DX2CR_INSW_Pos); // WA

USIC0_CH0->PCR_IISMode = (0 << USIC_CH_PCR_IISMode_WAGEN_Pos);


USIC0_CH0->CCR |= (3 << USIC_CH_CCR_MODE_Pos);

I hope someone has a good idea
Greets
Uwe
0 Likes
12 Replies
User6412
Level 4
Level 4
Hello UHeller,

SCU_CLK->CGATCLR0 = SCU_CLK_CGATCLR0_USIC0_Msk;


I am not sure, but check out the way you use the masks, normally they need also positioning.
0 Likes
Not applicable
Hi Dimitry,

thanks for the hint but I think it is quite OK that way. The macro goes to

#define USIC_CH_SCTR_TRM_Pos 8 /*!< USIC_CH SCTR: TRM Position */
#define USIC_CH_SCTR_TRM_Msk (0x03UL << USIC_CH_SCTR_TRM_Pos) /*!< USIC_CH SCTR: TRM Mask */

and the "3" is at the correct postion in the register afterwards as it is requested in the manual.

Greets
Uwe
0 Likes
Not applicable
Anybody there from Infineon who feels responsible for that peripheral?
0 Likes
Not applicable
Hi UHeller,

We are looking at this now.
Do you mind to provide your code snippet on how you get the data from RBUF? Do you use interrupt or polling method?
0 Likes
Not applicable
Hi Jackson,

first of all thanks very much for your help. I'm a newbee for that processor family (more into PowerPC from Freescale so far) and I'm sure it is a pure beginner fault I did.

To the problem: I do not read out the RBUF registers at the moment but I looked to the registers view in the DAVE environment (manual run/stop). There I can see the L/R signal changing frequently (DX2S bit in PSR_IISMode register) as well as all three signal from the I2S-master at the input registers for the pins. But RBUF0 and RBUF1 remains zero. It seems that no data from the input pin is taken over to the receive buffer.

from Germany
Uwe
0 Likes
Not applicable
Hi UHeller,

Can you replace SCTR register initialization into your code?

USIC0_CH0->SCTR = (15 << USIC_CH_SCTR_WLE_Pos) | (15 << USIC_CH_SCTR_FLE_Pos ) | (3 << USIC_CH_SCTR_TRM_Pos) | (1 << USIC_CH_SCTR_SDIR_Pos);


and also PCR_IISMode register

USIC0_CH0->PCR_IISMode = (1 << USIC_CH_PCR_IISMode_DTEN_Pos) | (0 << USIC_CH_PCR_IISMode_WAGEN_Pos);


and give it a try?
0 Likes
Not applicable
Hi Jackson,

thanks very much. It is working that way and I understand better what the different bits are for in combination to IIS.

I read out the incoming values like that, and they seem to fit. Shall I provide a commented main-routine here until DAVE will come up with a slave example ??


while (!(USIC0_CH0->PSR_IISMode & USIC_CH_PSR_IISMode_DX2S_Msk)){}
valL = (USIC0_CH0->RBUF << 16) + USIC0_CH0->RBUF;
USIC0_CH0->PSR_IISMode = USIC_CH_PSR_IISMode_RIF_Msk;

while (USIC0_CH0->PSR_IISMode & USIC_CH_PSR_IISMode_DX2S_Msk){}
valR = (USIC0_CH0->RBUF << 16) + USIC0_CH0->RBUF;
USIC0_CH0->PSR_IISMode = USIC_CH_PSR_IISMode_RIF_Msk;
0 Likes
Not applicable
Hi UHeller,

Yes, that would be great if you could provide that.
I believe there are users who might need this code too.
Thank you. 🙂
0 Likes
Not applicable
Hi@all,

since my IIS code is running now I like to share it with you. Maybe somebody waits for it badly as I did. 🙂

The basis of that code is a DAVE3 application enlarged by GPIO.h from the DAVE examples. So I limit the post to the main routine.

Many thanks to Jackson for his help !

Greets
Uwe



#include "GPIO.h"

// signed 32bit data expected
int32_t val_A, val_B;

int main(void)
{
// Initialization of DAVE Apps
DAVE_Init();

// Initialize LED for WS signal
P0_1_set_mode(OUTPUT_PP_GP);
P0_1_set_driver_strength(STRONG);

// set clock and release reset for USIC0
SCU_CLK->CGATCLR0 = SCU_CLK_CGATCLR0_USIC0_Msk;
SCU_RESET->PRCLR0 |= ((1 << SCU_RESET_PRSET0_USIC0RS_Pos) & SCU_RESET_PRSET0_USIC0RS_Msk);

// enable USIC0 module with write access
USIC0_CH0->KSCFG |= (USIC_CH_KSCFG_BPMODEN_Msk | USIC_CH_KSCFG_MODEN_Msk);

// configure all parameters while CCR.MODE = 0
USIC0_CH0->CCR = 0;
// shift control with 16 (15+1) wordlength, 32 (31+1) framelength, MSB first and transfer after every edge
USIC0_CH0->SCTR = (15 << USIC_CH_SCTR_WLE_Pos) | (31 << USIC_CH_SCTR_FLE_Pos ) |
(3 << USIC_CH_SCTR_TRM_Pos) | (1 << USIC_CH_SCTR_SDIR_Pos);

// get SIN from P1.4 (DX0B) as input
USIC0_CH0->DX0CR = (1 << USIC_CH_DX0CR_DSEL_Pos) | (1 << USIC_CH_DX0CR_INSW_Pos);
// get clock from P1.1 (DX1A) as input
USIC0_CH0->DX1CR = (0 << USIC_CH_DX1CR_DSEL_Pos) | (1 << USIC_CH_DX1CR_INSW_Pos) | (1 << USIC_CH_DX1CR_DPOL_Pos);
// get WA from P1.0 (DX2A) as input
USIC0_CH0->DX2CR = (0 << USIC_CH_DX2CR_DSEL_Pos) | (1 << USIC_CH_DX2CR_INSW_Pos);

// datatransfer enable and no WA generation (slave)
USIC0_CH0->PCR_IISMode = (1 << USIC_CH_PCR_IISMode_DTEN_Pos) | (0 << USIC_CH_PCR_IISMode_WAGEN_Pos);

// now switch to IIS mode
USIC0_CH0->CCR |= (3 << USIC_CH_CCR_MODE_Pos);

// here: run forever
while(1)
{
// wait for falling edge of DX2A pin (channel_A)
while (!(USIC0_CH0->PSR_IISMode & USIC_CH_PSR_IISMode_DX2S_Msk)){}
// get most significant word (16bit) with first pop and least significant word with second pop
val_A = (int32_t)((uint32_t)(USIC0_CH0->RBUF << 16) + (uint32_t)USIC0_CH0->RBUF);
// clear receive flag
USIC0_CH0->PSR_IISMode = USIC_CH_PSR_IISMode_RIF_Msk;
// toggle pin for oscilloscope
P0_1_toggle();

// wait for rising edge of DX2A pin (channel_B)
while (USIC0_CH0->PSR_IISMode & USIC_CH_PSR_IISMode_DX2S_Msk){}
// get most significant word (16bit) with first pop and least significant word with second pop
val_B = (int32_t)((uint32_t)(USIC0_CH0->RBUF << 16) + (uint32_t)USIC0_CH0->RBUF;
// clear receive flag
USIC0_CH0->PSR_IISMode = USIC_CH_PSR_IISMode_RIF_Msk;
// toggle pin for oscilloscope
P0_1_toggle();

}
return 0;
}
0 Likes
Not applicable
Hi
I have tried to use this with XMC4500 and deduced that this code is specific to XMC4400 or earlier. Of note is the clock gating which has no equivalent in XMX4500 (as far as I can tell).
So, can Infineon or UHeller please help by providing an equivalent I2S Slave solution for XMC4500? And yes, I badly need this.
0 Likes
Not applicable
Hi SharmanJ,

The USIC configuration provided by UHeller should work for other device.
This is because the USIC register is the same across all the XMC device family.
Just ignore the configuration for:
SCU_CLK->CGATCLR0 = SCU_CLK_CGATCLR0_USIC0_Msk; 


Other codes are applicable.
0 Likes
Not applicable
Hello,

I started working with I2S for Audio interface. I am using DAVE app library I2S002 API's to transmit data, start/stop etc...

Firstly, I am using the proper example?, secondly, in the example the data from the user buffer is transmitted to I2S channel, Is this interface to CODEC ? or extra work is needed for getting the output!.

Thanks in advance.
0 Likes