I2S

HI

I am using the I2S on the nRF52840DK I have constructed an array and all works well except once I start it , it continues to run, I cant get it to play the sample just once, how can I do this

Start Code

NRF_I2S->ENABLE = 1;

// Configure data pointer
NRF_I2S->TXD.PTR = (uint32_t)&sine_table2[0];
NRF_I2S->RXTXD.MAXCNT = sizeof(sine_table2) / sizeof(uint32_t);

NRF_I2S->TASKS_START = 1;

for (;;)
{

    __WFE();

}

Any assistance would be appreciated.

Kind Regards

David

Parents Reply Children
  • Here you go:

    #include <nrf.h>
    
    #define PIN_MCK    (13)
    #define PIN_SCK    (14)
    #define PIN_LRCK   (15)
    #define PIN_SDOUT  (16)
    
    int main(void)
    {
      // Sine table (stereo, so every value is duplicated)
      int16_t sine_table[] = { 0, 0, 23170, 23170, 32767, 32767, 23170, 23170, 0, 0, -23170, -23170, -32768, -32768, -23170, -23170};
      
      // Enable transmission
      NRF_I2S->CONFIG.TXEN = (I2S_CONFIG_TXEN_TXEN_ENABLE << I2S_CONFIG_TXEN_TXEN_Pos);
      
      // Enable MCK generator
      NRF_I2S->CONFIG.MCKEN = (I2S_CONFIG_MCKEN_MCKEN_ENABLE << I2S_CONFIG_MCKEN_MCKEN_Pos);
      
      // MCKFREQ = 4 MHz
      NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV11  << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
      
      // Ratio = 64 
      NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_64X << I2S_CONFIG_RATIO_RATIO_Pos;
        
      // Master mode, 16Bit, left aligned
      NRF_I2S->CONFIG.MODE = I2S_CONFIG_MODE_MODE_MASTER << I2S_CONFIG_MODE_MODE_Pos;
      NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos;
      NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_LEFT << I2S_CONFIG_ALIGN_ALIGN_Pos;
      
      // Format = I2S
      NRF_I2S->CONFIG.FORMAT = I2S_CONFIG_FORMAT_FORMAT_I2S << I2S_CONFIG_FORMAT_FORMAT_Pos;
      
      // Use stereo 
      NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_STEREO << I2S_CONFIG_CHANNELS_CHANNELS_Pos;
      
      // Configure pins
      NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos);
      NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos); 
      NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos); 
      NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos);
      
      
      // Configure data pointer
      NRF_I2S->TXD.PTR = (uint32_t)&sine_table[0];
      NRF_I2S->RXTXD.MAXCNT = sizeof(sine_table) / sizeof(uint32_t);
      
      //Enable interrupt and IRQ
      NRF_I2S->INTENSET = I2S_INTENSET_TXPTRUPD_Enabled << I2S_INTENSET_TXPTRUPD_Pos;
    
      
      NVIC_EnableIRQ(I2S_IRQn);
      
      NRF_I2S->ENABLE = 1;
      // Start transmitting I2S data
      NRF_I2S->TASKS_START = 1;
      
      
      // Since we are not updating the TXD pointer, the sine wave will play over and over again.
      // The TXD pointer can be updated after the EVENTS_TXPTRUPD arrives.
      while (1)
      {
        //__WFE();
      }
    }
    
    //IRQ handler
    
    void I2S_IRQHandler(void)
    {
      if (NRF_I2S->EVENTS_TXPTRUPD == 1)
      {
          NRF_I2S->EVENTS_TXPTRUPD = 0;
          NRF_I2S->TASKS_STOP = 1;
    
      }
    }

  • Hi Jared

    Thank for sending this code, the only problem is, when I put in 

    //IRQ handler

    void I2S_IRQHandler(void)
    {
    if (NRF_I2S->EVENTS_TXPTRUPD == 1)
    {
    NRF_I2S->EVENTS_TXPTRUPD = 0;
    NRF_I2S->TASKS_STOP = 1;

    }
    }

    I get these errors please see attached

     

    Thank you for all your help

    David

  • Hi,

    It's because you have included a source file which already contains the definition of the IRQ handler, the error message specifies that this is first defined in nrfx_I2S. I suggest omitting the driver from the project if you're only going to use the peripheral bare metal.

    regards

    Jared 

  • Hi Jared

    Thanks for getting back so promptly, I am trying to use your driver please see code below (first time I have used Nordic), I think I am mixing both, but it does work can you please amend so I am only using your driver and I am able to use the interrupt.

    #include <stdio.h>
    #include "nrf_drv_i2s.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "boards.h"

    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"

    #include <nrf.h>

    #include "sounds.h"

    #define PIN_MCK (41) //P1.09
    #define PIN_BCLK (40) //P1.08
    #define PIN_LRCK (38) //P1.06
    #define PIN_SDOUT (39) //P1.07

    #define Button 11
    #define LED 13


    static void data_handler(nrf_drv_i2s_buffers_t const * p_released,uint32_t status)
    {

    }


    int main(void)
    {
    uint32_t err_code = NRF_SUCCESS;

    err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_i2s_config_t config = NRF_DRV_I2S_DEFAULT_CONFIG;

    config.sck_pin = PIN_BCLK;
    config.lrck_pin = PIN_LRCK;
    config.sdout_pin = PIN_SDOUT;

    config.mode = I2S_CONFIG_MODE_MODE_Master;
    config.sample_width = I2S_CONFIG_SWIDTH_SWIDTH_16BIT;

    config.mck_setup = NRF_I2S_MCK_32MDIV8;
    config.ratio = NRF_I2S_RATIO_512X;
    config.channels = NRF_I2S_CHANNELS_RIGHT;

    err_code = nrf_drv_i2s_init(&config, data_handler);
    APP_ERROR_CHECK(err_code);



    // // Enable transmission
    NRF_I2S->CONFIG.TXEN = (I2S_CONFIG_TXEN_TXEN_ENABLE << I2S_CONFIG_TXEN_TXEN_Pos);

    // // Configure data pointer
    NRF_I2S->TXD.PTR = (uint32_t)&sine_table2[0];
    NRF_I2S->RXTXD.MAXCNT = sizeof(sine_table2) / sizeof(uint32_t);

    nrf_gpio_cfg_output(LED);
    nrf_gpio_cfg_input(Button, NRF_GPIO_PIN_PULLUP);

    NRF_I2S->ENABLE = 1;


    NRF_I2S->TASKS_START = 1;

    for (;;)
    {

    if(nrf_gpio_pin_read(Button) == 0)
    {
    nrf_gpio_pin_clear(LED);
    //printf("Button is Pressed \r\n");
    }
    else
    {
    nrf_gpio_pin_set(LED);
    //printf("Button is Released \r\n");
    }

    // Wait for an event.
    //__WFE();
    // Clear the event register.
    //__SEV();
    // __WFE();

    //NRF_LOG_FLUSH();

    }
    }

    Thank you

    David

  • Hi,

    Have you seen our I2S example in the SDK? It shows how you can use the driver to stop a transfer after the a specific number of data has been transferred. 

    regards

    Jared

Related