Hello,
I am currently interfacing MP34DT05 with nRF52840 using I2S protocol. I have tried using nrfx I2S drivers but it gives me initialization error. I have used the sample code given as the solution in the following link as reference, but cant make it work for my DK.
Below is my main.c file for nRF52840. I have only defined 3 pins because i just want to read the data from sensor.
#include <zephyr.h>
#include <string.h>
#include "nrfx_i2s.h"
//#error Remember to define these pins before you run! // This assume you only have these 3 pins for I2S.
#define I2S_WS_PIN 20
#define I2S_SD_PIN 21
#define I2S_SCK_PIN 22
#define I2S_DATA_BLOCK_WORDS 512 //How many numbers do we want. time reorded = DATA_BLOCK_WORDS / freq
static uint32_t m_buffer_rx32u[I2S_DATA_BLOCK_WORDS];
static int32_t tmp[I2S_DATA_BLOCK_WORDS];
static nrfx_i2s_buffers_t initial_buffers;
static bool data_ready_flag = false;
ISR_DIRECT_DECLARE(i2s_isr_handler)
{
data_ready_flag = false;
nrfx_i2s_irq_handler();
ISR_DIRECT_PM(); /* PM done after servicing interrupt for best latency
*/
return 1; /* We should check if scheduling decision should be made */
}
static void data_handler(nrfx_i2s_buffers_t const *p_released, uint32_t status)
{
if (NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED == status)
{
nrfx_err_t err = nrfx_i2s_next_buffers_set(&initial_buffers);
if (err != NRFX_SUCCESS)
{
printk("Error!, continuing running as if nothing happened, but you should probably investigate.\n");
}
}
if (p_released)
{
if (p_released->p_rx_buffer != NULL)
{
data_ready_flag = true; //This is used in print_sound()
}
}
}
void print_sound()
{
while (!data_ready_flag)
{
k_sleep(K_MSEC(1));
//Wait for data. Since we do not want I2S_DATA_BLOCK_WORDS amount of prints inside the interrupt.
}
nrfx_i2s_stop();
data_ready_flag = false;
int64_t sum = 0;
int64_t words = I2S_DATA_BLOCK_WORDS;
for (int i = 0; i < I2S_DATA_BLOCK_WORDS; i++)
{
memcpy(tmp + i, m_buffer_rx32u + i, sizeof(uint32_t));
tmp[i] >>= 8;
sum += tmp[i];
}
int64_t mean = sum / words;
for (int i = 0; i < I2S_DATA_BLOCK_WORDS; i++)
{
tmp[i] -= mean;
printk("%d, ", tmp[i]);
k_sleep(K_MSEC(16));
}
printk("\n\n");
/** End of formatted data print*/
}
nrfx_err_t get_sound_init()
{
IRQ_DIRECT_CONNECT(I2S_IRQn, 0, i2s_isr_handler, 0);
memset(&m_buffer_rx32u, 0x00, sizeof(m_buffer_rx32u));
initial_buffers.p_rx_buffer = m_buffer_rx32u;
//YOu should probably change this config to fit your I2S microphone and audio preferences.
nrfx_i2s_config_t config =
NRFX_I2S_DEFAULT_CONFIG(I2S_SCK_PIN, I2S_WS_PIN,
NRFX_I2S_PIN_NOT_USED,
NRFX_I2S_PIN_NOT_USED, I2S_SD_PIN);
config.mode = NRF_I2S_MODE_MASTER; //Microphone requirement
config.ratio = NRF_I2S_RATIO_64X; //Microphone requirement
config.sample_width = NRF_I2S_SWIDTH_24BIT; //Microphone requirement
config.mck_setup = NRF_I2S_MCK_32MDIV31; //Preference freq = (MCKfreq/ratio) =16.129 KHz.
config.channels = NRF_I2S_CHANNELS_LEFT; //Preference
nrfx_err_t err_code = nrfx_i2s_init(&config, data_handler);
if (err_code != NRFX_SUCCESS)
{
printk("I2S init error\n");
return err_code;
}
err_code = nrfx_i2s_start(&initial_buffers, I2S_DATA_BLOCK_WORDS, 0); //start recording
if (err_code != NRFX_SUCCESS)
{
printk("I2S start error\n");
return err_code;
}
//nrfx_i2s_stop() //stop recording
k_sleep(K_SECONDS(2));
return err_code;
}
void main()
{
nrfx_err_t err;
err = get_sound_init();
if (err != NRFX_SUCCESS)
{
return;
}
while (1)
{
k_sleep(K_SECONDS(5));
print_sound();
}
}
Here is my project.conf file.
#I2S CONFIG_NRFX_I2S=y CONFIG_SPM_NRF_I2S0_NS=y #LOG CONFIG_LOG=y CONFIG_LOG_PRINTK=y CONFIG_LOG_BACKEND_SHOW_COLOR=n
I have also enabled I2S to be used in the non-secure area by following this post devzone.nordicsemi.com/.../adafruit-i2s-mems-microphone-breakout-with-the-nrf9160-dk
Can anyone suggest what else i have to do for initializing and reading data via I2S on nRF52840.