SDK example "evkmimxrt1010_sai_interrupt_record_playback"

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SDK example "evkmimxrt1010_sai_interrupt_record_playback"

Jump to solution
519 Views
LuigiV
Contributor III

Hello, I'm a generator of questions...:-)

anyway, the SDK example "evkmimxrt1010_sai_interrupt_record_playback" could be the solution of what I trying to do; anyone may help me to understand better in what way the code manage the SAI data transfer ?

I mean the type of transfer and the data structure; the code uses a data buffer --> 

AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t Buffer[BUFFER_NUMBER * BUFFER_SIZE], 4);

and a data structure to send dato to the SAI (and to receive)

xfer.data = Buffer + tx_index * BUFFER_SIZE;

xfer.dataSize = BUFFER_SIZE;

if (kStatus_Success == SAI_TransferSendNonBlocking(DEMO_SAI, &txHandle, &xfer))

 

I would like to understand better these parts of code.

 

Thank you.

 

Luigi

 

0 Kudos
Reply
1 Solution
484 Views
Gavin_Jia
NXP TechSupport
NXP TechSupport

Hi @LuigiV ,

Thanks for your interest in NXP MIMXRT series!

We can look at the main logic of this function together,while(1){...}:

An infinite loop is used here, constantly checking the status of the buffer and sending and receiving data.

- `emptyBlock` is an unsigned 8-bit integer that indicates how many sub-buffers in the buffer are empty, i.e., without data. Its initial value is `BUFFER_NUMBER`, which indicates that all sub-buffers are empty. Every time data is received from a sub-buffer, emptyBlock is decremented by one; every time data is sent from a sub-buffer, emptyBlock is incremented by one. This ensures that there is always data in the buffer to send without under or overflow.

- `if (emptyBlock > 0)` This judgment statement is used to check **<u> if there is an empty sub-buffer that can receive data </u>**. If there is, the `SAI_TransferReceiveNonBlocking` function is called to receive the data into the current sub-buffer. Then add one to rx_index to point to the next sub-buffer. If rx_index equals BUFFER_NUMBER, the end of the buffer has been reached, it is reset to 0, and reception starts from the beginning.

- `if (emptyBlock < BUFFER_NUMBER)` This judgment statement is used to check **<u> if there is a non-empty sub-buffer to which data can be sent </u>**. If there is, the `SAI_TransferSendNonBlocking` function is called to send the data to the SAI's transmitter. Then add one to tx_index to point to the next sub-buffer. If tx_index equals BUFFER_NUMBER, the end of the buffer has been reached, reset it to 0 and start sending from the beginning.

 

Then, we can look at the data structure:

`AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t Buffer[BUFFER_NUMBER * BUFFER_SIZE], 4);`

- A macro is used here to define a static unsigned 8-bit array whose size is `BUFFER_NUMBER` times `BUFFER_SIZE`, both of which can be modified as needed. Each element of this array is a byte, which is used to **<u> store the sample values of the audio data </u>**. The alignment of this array is 4 bytes, this is to improve access speed and avoid alignment errors

The transmission structure is defined as follows:

`sai_transfer_t xfer;`

- A structure type sai_transfer_t is used here, which is defined in the SAI driver library and contains two member variables: `data` and `dataSize`. data is a pointer to the starting address of the data to be transferred. dataSize is an unsigned 32-bit integer representing the number of bytes of data to be transferred. dataSize is an unsigned 32-bit integer that indicates the number of bytes of data to be transferred.

The transfer structure is assigned as follows:

`xfer.data = Buffer + tx_index * BUFFER_SIZE;`

`xfer.dataSize = BUFFER_SIZE;`

- A variable `tx_index` is used here, which is an unsigned 8-bit integer that indicates the index of the current buffer to be transferred. Because the buffer is divided into `BUFFER_NUMBER` sub-buffers, and the size of each sub-buffer is `BUFFER_SIZE`, the starting address of the data to be transferred is the buffer plus tx_index multiplied by the BUFFER_SIZE, and the number of bytes of data to be transferred is the BUFFER_SIZE.

 

Also, there is some information you can refer to:

1. https://www.nxp.com/docs/en/application-note/AN12090.pdf

2. https://www.nxp.com/docs/en/application-note/AN12202.pdf

 

Best regards,
Gavin

View solution in original post

0 Kudos
Reply
3 Replies
479 Views
LuigiV
Contributor III

Thank you Gavin for your support, I have a question: why does it use a 8 bit buffer instead of a 16 or 32 bit buffer ? Is it a requirement of the API function ?

 

Luigi

0 Kudos
Reply
471 Views
Gavin_Jia
NXP TechSupport
NXP TechSupport

Hi @LuigiV ,

This is due to the reason that the Buffer stores the sample values of the audio data inside it, and each sample value occupies one byte, so the uint_8 type is used. This makes it easy to align and transfer with the data registers of the SAI module.

 

Best regards,
Gavin

0 Kudos
Reply
485 Views
Gavin_Jia
NXP TechSupport
NXP TechSupport

Hi @LuigiV ,

Thanks for your interest in NXP MIMXRT series!

We can look at the main logic of this function together,while(1){...}:

An infinite loop is used here, constantly checking the status of the buffer and sending and receiving data.

- `emptyBlock` is an unsigned 8-bit integer that indicates how many sub-buffers in the buffer are empty, i.e., without data. Its initial value is `BUFFER_NUMBER`, which indicates that all sub-buffers are empty. Every time data is received from a sub-buffer, emptyBlock is decremented by one; every time data is sent from a sub-buffer, emptyBlock is incremented by one. This ensures that there is always data in the buffer to send without under or overflow.

- `if (emptyBlock > 0)` This judgment statement is used to check **<u> if there is an empty sub-buffer that can receive data </u>**. If there is, the `SAI_TransferReceiveNonBlocking` function is called to receive the data into the current sub-buffer. Then add one to rx_index to point to the next sub-buffer. If rx_index equals BUFFER_NUMBER, the end of the buffer has been reached, it is reset to 0, and reception starts from the beginning.

- `if (emptyBlock < BUFFER_NUMBER)` This judgment statement is used to check **<u> if there is a non-empty sub-buffer to which data can be sent </u>**. If there is, the `SAI_TransferSendNonBlocking` function is called to send the data to the SAI's transmitter. Then add one to tx_index to point to the next sub-buffer. If tx_index equals BUFFER_NUMBER, the end of the buffer has been reached, reset it to 0 and start sending from the beginning.

 

Then, we can look at the data structure:

`AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t Buffer[BUFFER_NUMBER * BUFFER_SIZE], 4);`

- A macro is used here to define a static unsigned 8-bit array whose size is `BUFFER_NUMBER` times `BUFFER_SIZE`, both of which can be modified as needed. Each element of this array is a byte, which is used to **<u> store the sample values of the audio data </u>**. The alignment of this array is 4 bytes, this is to improve access speed and avoid alignment errors

The transmission structure is defined as follows:

`sai_transfer_t xfer;`

- A structure type sai_transfer_t is used here, which is defined in the SAI driver library and contains two member variables: `data` and `dataSize`. data is a pointer to the starting address of the data to be transferred. dataSize is an unsigned 32-bit integer representing the number of bytes of data to be transferred. dataSize is an unsigned 32-bit integer that indicates the number of bytes of data to be transferred.

The transfer structure is assigned as follows:

`xfer.data = Buffer + tx_index * BUFFER_SIZE;`

`xfer.dataSize = BUFFER_SIZE;`

- A variable `tx_index` is used here, which is an unsigned 8-bit integer that indicates the index of the current buffer to be transferred. Because the buffer is divided into `BUFFER_NUMBER` sub-buffers, and the size of each sub-buffer is `BUFFER_SIZE`, the starting address of the data to be transferred is the buffer plus tx_index multiplied by the BUFFER_SIZE, and the number of bytes of data to be transferred is the BUFFER_SIZE.

 

Also, there is some information you can refer to:

1. https://www.nxp.com/docs/en/application-note/AN12090.pdf

2. https://www.nxp.com/docs/en/application-note/AN12202.pdf

 

Best regards,
Gavin

0 Kudos
Reply