Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Speeding up application to send 24bit I2S data at 16 kHz via BLE

Hi,

I'm trying to send I2S data (~ 16 kHz, 24 bits) via BLE using the nRF52 DK and the nRF5 SDK 17.1.0. After I get the data from the I2S driver (by specification, they are in 32bit format), I add them to very simple ring buffer. The problem is, that this ring buffer becomes full too fast, overwriting older data (which has not been sent yet), which subsequently results in data loss.

Is there a way to speed up my application to avoid this or give higher priority to the application to be able to process the data faster (I guess the main problem is my loop which is casting the 32bit data into 24bit samples)?

Here is my applications logic together with the respective code:

global variables:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
/*----------------- I2S -----------------*/
#define I2S_DATA_BLOCK_WORDS 32
static bool i2s_active = false;
static bool i2s_transfer = false;
/*----------------- BUFFERS -----------------*/
#define RNG_BUF_SIZE (I2S_DATA_BLOCK_WORDS*4*60)
static uint32_t rng_buffer[RNG_BUF_SIZE];
static uint16_t rb_write_ptr = 0;
static uint16_t rb_read_ptr = 0;
static uint8_t m_array[243] = {0};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

main():

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(void)
{
bool erase_bonds;
uint32_t err_code;
// Initialize.
log_init();
timers_init();
buttons_leds_init(&erase_bonds);
power_management_init();
// Initialize TWI/ I2C & Setup ADC
twi_adc_configuration();
// Initialize i2s
err_code = i2s_init();
if (err_code == NRF_SUCCESS)
{
NRF_LOG_INFO("I2S successfully initialized.");
}
else
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

the i2s data handler and the function which adds the received 32bit samples to the ring buffer:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void write_rng_buffer(uint32_t const * p_block)
{
if ((rb_write_ptr+I2S_DATA_BLOCK_WORDS) > RNG_BUF_SIZE)
{
rb_write_ptr = 0;
write_cnt++;
NRF_LOG_INFO("writing finished %d", write_cnt);
}
memcpy(&rng_buffer[rb_write_ptr], p_block, (I2S_DATA_BLOCK_WORDS*4));
rb_write_ptr+=I2S_DATA_BLOCK_WORDS;
}
static void data_handler(nrf_drv_i2s_buffers_t const * p_released,
uint32_t status)
{
// 'nrf_drv_i2s_next_buffers_set' is called directly from the handler
// each time next buffers are requested, so data corruption is not
// expected.
ASSERT(p_released);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

any help and hint is appreciated!