This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

VS1053 and NRF52832

Hello. I have SMARTMP3 Board and NRF52832. The vs1053 works fine on the arduino. But it doesn't work on the nrf52832.

I use these connections:

#define SCK_PIN     3
#define MOSI_PIN    4
#define MISO_PIN    28
#define CS_PIN        24

#define MP3_RESET 27
#define MP3_DREQ 23
#define MP3_XCS 24
#define MP3_XDCS 25 //Data Chip Select / BSYNC Pin

VCC to 3.3V (VDD)
GND to GND



For arduino I use this example https://github.com/ARISGames/arduino/blob/master/MP3_Player_Example/MP3_Player_Example.pde , I have also ported this code to the NRF52832, so they are the same. STATUS register should send me 0x48 value, but I receive only 0, that means it doesn't work. The SD Card (this board also has slot for sd card) works fine.

Parents
  • Hi Anar, 

    please verify that your connections are correct and that the correct VSxxxx mode is set on the vs1053

    Are you able to perform a logic trace of the SPI pins so that we can verify that the correct commands are sent to the vs1053?

    Lastly, please post the nRF52 code where you intialize the SPI driver and send data to the VS1053.

    Best regards

    Bjørn 

  • Hi Bjorn,

    the connections are okay, because the SD card on the same board works fine.

    I should receive 0x48 (what I receive on the arduino with the same code), but I receive only 0.

    Here is my code :

    /**
     * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    /** @file
     * @defgroup fatfs_example_main main.c
     * @{
     * @ingroup fatfs_example
     * @brief FATFS Example Application main file.
     *
     * This file contains the source code for a sample application using FAT filesystem and SD card library.
     *
     */
    
    
    #include "nrf.h"
    #include "bsp.h"
    #include "ff.h"
    #include "diskio_blkdev.h"
    #include "nrf_block_dev_sdc.h"
    #include "nrf_delay.h"
    #include "SEGGER_RTT.h"
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_drv_spi.h"
    
    #define FILE_NAME   "NORDIC.TXT"
    #define TEST_STRING "SD card example."
    
    #define SPI_INSTANCE 1
    
    #define SDC_SCK_PIN     3  ///< SDC serial clock (SCK) pin. 25   14
    #define SDC_MOSI_PIN    4 ///< SDC serial data in (DI) pin. 23  13
    #define SDC_MISO_PIN    28  ///< SDC serial data out (DO) pin. 24 12
    #define SDC_CS_PIN      24   ///< SDC chip select (CS) pin. 22    11
    
    #define MP3_RESET 27
    #define MP3_DREQ 23
    #define MP3_XCS 24
    #define MP3_XDCS 25 //Data Chip Select / BSYNC Pin
    
    //VS10xx SCI Registers
    #define SCI_MODE 0x00
    #define SCI_STATUS 0x01
    #define SCI_BASS 0x02
    #define SCI_CLOCKF 0x03
    #define SCI_DECODE_TIME 0x04
    #define SCI_AUDATA 0x05
    #define SCI_WRAM 0x06
    #define SCI_WRAMADDR 0x07
    #define SCI_HDAT0 0x08
    #define SCI_HDAT1 0x09
    #define SCI_AIADDR 0x0A
    #define SCI_VOL 0x0B
    #define SCI_AICTRL0 0x0C
    #define SCI_AICTRL1 0x0D
    #define SCI_AICTRL2 0x0E
    #define SCI_AICTRL3 0x0F
    
    static const nrf_drv_spi_t m_spi1 = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);
    
    static uint8_t rx_buffer[] = {0, 0};
    static FIL file;
    
    typedef struct {
        uint16_t length;
        uint8_t data[32];
    } fatfs_read_buffer_t;
    
    static fatfs_read_buffer_t fatfs_read_buffer = {.length = 0, .data = {0x00}};
    
    /**
     * @brief  SDC block device definition
     * */
    NRF_BLOCK_DEV_SDC_DEFINE(
            m_block_dev_sdc,
            NRF_BLOCK_DEV_SDC_CONFIG(
                    SDC_SECTOR_SIZE,
                    APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)
             ),
             NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")
    );
    
    /**
     * @brief Function for demonstrating FAFTS usage.
     */
    static void fatfs_example()
    {
        static FATFS fs;
        static DIR dir;
        static FILINFO fno;
    
        FRESULT ff_result;
        DSTATUS disk_state = STA_NOINIT;
    
        // Initialize FATFS disk I/O interface by providing the block device.
        static diskio_blkdev_t drives[] =
        {
                DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)
        };
    
        diskio_blockdev_register(drives, ARRAY_SIZE(drives));
    
        NRF_LOG_INFO("Initializing disk 0 (SDC)...");
        for (uint32_t retries = 10; retries && disk_state; --retries)
        {
            disk_state = disk_initialize(0);
        }
        if (disk_state)
        {
            NRF_LOG_INFO("Disk initialization failed.");
            return;
        }
    
        uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size;
        uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb;
        NRF_LOG_INFO("Capacity: %d MB", capacity);
    
        NRF_LOG_INFO("Mounting volume...");
        ff_result = f_mount(&fs, "", 1);
        if (ff_result)
        {
            NRF_LOG_INFO("Mount failed.");
            return;
        }
    
        NRF_LOG_INFO("\r\n Listing directory: /");
        ff_result = f_opendir(&dir, "/");
        if (ff_result)
        {
            NRF_LOG_INFO("Directory listing failed!");
            return;
        }
    
        do
        {
            ff_result = f_readdir(&dir, &fno);
            if (ff_result != FR_OK)
            {
                NRF_LOG_INFO("Directory read failed.");
                return;
            }
    
            if (fno.fname[0])
            {
                if (fno.fattrib & AM_DIR)
                {
                    NRF_LOG_RAW_INFO("   <DIR>   %s",(uint32_t)fno.fname);
                }
                else
                {
                    NRF_LOG_RAW_INFO("%9lu  %s", fno.fsize, (uint32_t)fno.fname);
                }
            }
        }
        while (fno.fname[0]);
        NRF_LOG_RAW_INFO("");
    		
    		NRF_LOG_RAW_INFO("\n");
    /*
        NRF_LOG_INFO("Writing to file " FILE_NAME "...");
        ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ".");
            return;
        }
    
        ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT *) &bytes_written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Write failed\r\n.");
        }
        else
        {
            NRF_LOG_INFO("%d bytes written.", bytes_written);
        }
              
        (void) f_close(&file);*/
        return;
    }
    
    
    void playMP3(char* fileName)
    {
      int need_data = 1; 
    	FRESULT ff_result;
    	uint32_t bytes_read;
    	fatfs_example();
    
      while(1) {	        
                ff_result = f_open(&file, fileName, FA_READ);
    					
                if (ff_result != FR_OK)
                {
    							NRF_LOG_INFO("Unable to open file \n");
    							return;
                }
    		
        //while(!nrf_gpio_pin_read(MP3_DREQ)) 
    						nrf_delay_ms(10);
    			{ 
    
          //If the MP3 IC is happy, but we need to read new data from the SD, now is a great time to do so
          if(need_data == 1) {
    				if((ff_result = f_read(&file, fatfs_read_buffer.data, fatfs_read_buffer.length, &bytes_read)) != FR_OK)
    				break;
            //Data reading ----------------------------
            //if no data break-------------------------
            need_data = 0;
          }
    
          nrf_delay_ms(100); //Do NOTHING - sounds fine
        }
    
    
        if(need_data == 1){ //This is here in case we haven't had any free time to load new data
    			if((ff_result = f_read(&file, fatfs_read_buffer.data, fatfs_read_buffer.length, &bytes_read)) != FR_OK)
    				break;
          //Data read-----------------------------
          //if no data break----------------------
          need_data = 0;
        }
    
        //Once DREQ is released (high) we now feed 32 bytes of data to the VS1053 from our SD read buffer
        nrf_gpio_pin_clear(MP3_XDCS); //Select Data
        //for(int y = 0 ; y < sizeof(fatfs_read_buffer.data) ; y++)
    		{
          // Send SPI byte
    			nrf_drv_spi_transfer(&m_spi1, fatfs_read_buffer.data, sizeof(fatfs_read_buffer.data), rx_buffer, sizeof(rx_buffer));
        }
    
        nrf_gpio_pin_set(MP3_XDCS); //Deselect Data
        need_data = 1; //We've just dumped 32 bytes into VS1053 so our SD read buffer is empty. Set flag so we go get more data
      }
    
     // while(!nrf_gpio_pin_read(MP3_DREQ)) ; //Wait for DREQ to go high indicating transfer is complete
    	nrf_delay_ms(10);
      nrf_gpio_pin_set(MP3_XDCS); //Deselect Data
      
      //Close out this track
    	
    	NRF_LOG_INFO("end of the song");
    	
    	f_close(&file);
    }
    
    
    uint8_t Mp3ReadRegister (uint8_t addressbyte){
      while(!nrf_gpio_pin_read(MP3_DREQ)){}; //Wait for DREQ to go high indicating IC is available
      // nrf_gpio_pin_clear(MP3_XCS); //here
    		nrf_delay_ms(10);
      //SCI consists of instruction byte, address byte, and 16-bit data word.
      nrf_drv_spi_transfer(&m_spi1, (uint8_t*)0x03, sizeof(uint8_t), NULL, sizeof(uint8_t));
      nrf_drv_spi_transfer(&m_spi1, &addressbyte, sizeof(uint8_t), NULL, sizeof(uint8_t));
    	
      nrf_drv_spi_transfer(&m_spi1, (uint8_t*)0xFF, sizeof(uint8_t), &rx_buffer[0], sizeof(uint8_t));
    	while(nrf_gpio_pin_read(MP3_DREQ)){}; //Wait for DREQ to go high indicating IC is available
      nrf_drv_spi_transfer(&m_spi1, (uint8_t*)0xFF, sizeof(uint8_t), &rx_buffer[1], sizeof(uint8_t));
    	while(nrf_gpio_pin_read(MP3_DREQ)){}; //Wait for DREQ to go high indicating IC is available
    	
      int resultvalue = rx_buffer[0] << 8;
      resultvalue |= rx_buffer[1];
    	
    	//nrf_gpio_pin_set(MP3_XCS); //here
    	
      return resultvalue;
    }
    
    
    
    
    //Set VS10xx Volume Register
    void Mp3SetVolume(uint8_t leftchannel, uint8_t rightchannel){
      Mp3WriteRegister(SCI_VOL, leftchannel, rightchannel);
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        SEGGER_RTT_Init ();
        SEGGER_RTT_SetTerminal(0);
    
        //NRF_LOG_INFO("\n\n\n\nFATFS example started. new8");  
        SEGGER_RTT_TerminalOut(0, "\nInitialization\n");
    
        //fatfs_example();	  
    	
              nrf_gpio_cfg_output(MP3_RESET);
    	  nrf_gpio_cfg_output(MP3_XDCS);
    	//  nrf_gpio_cfg_output(MP3_XCS);
    	  nrf_gpio_cfg_input(MP3_DREQ, NRF_GPIO_PIN_PULLDOWN);
    	
    	  nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin   = MP3_XCS;
        spi_config.miso_pin = SDC_MISO_PIN;
        spi_config.mosi_pin = SDC_MOSI_PIN;
        spi_config.sck_pin  = SDC_SCK_PIN;
    	  spi_config.frequency = SPI_FREQUENCY_FREQUENCY_M1;
        APP_ERROR_CHECK(nrf_drv_spi_init(&m_spi1, &spi_config, NULL, NULL));
    		
    		nrf_gpio_pin_clear(MP3_RESET);
    		nrf_gpio_pin_set(MP3_XDCS);
    		//nrf_gpio_pin_set(MP3_XCS);
    		
    		nrf_delay_ms(10);   
    	
    	  nrf_gpio_pin_set(MP3_RESET); //Bring up VS1053
    		
    		while(!nrf_gpio_pin_read(MP3_DREQ)){};
    		
    		nrf_drv_spi_transfer(&m_spi1, (uint8_t*)0xFF, sizeof(uint8_t), NULL, sizeof(uint8_t));
    		
    		nrf_delay_ms(10);
    		
    		//NRF_SPI0->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M4;
    		
    		//Mp3WriteRegister(SCI_CLOCKF, 0x60, 0x00); //Set multiplier to 3.0x
    		
    		int k = Mp3ReadRegister(SCI_STATUS);
    		
    		//NRF_LOG_INFO("status = %d\n status2 = %d", ((k >> 4) & 0x0F), k);
                    char str[255];
    
                    sprintf(str, "\nstatus = %d\n", k);
    
                    SEGGER_RTT_TerminalOut(0, str);
    			
    			
    		
    		//Mp3SetVolume(20, 20); //Set initial volume (20 = -10dB) LOUD
    		
    	//	fatfs_example();	
    		
    /*
      Mp3SetVolume(20, 20); //Set initial volume (20 = -10dB) LOUD
    	
    	int MP3Mode = Mp3ReadRegister(SCI_MODE);
      int MP3Status = Mp3ReadRegister(SCI_STATUS);
      int MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
    	
    	Mp3WriteRegister(SCI_CLOCKF, 0x60, 0x00); //Set multiplier to 3.0x
    	
    	MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
    */
     //playMP3("track.mp3");
    
        while (true)
        {
            __WFE();
        }
    }
    
    /** @} */
    

  • void app_error_handler_bare(unsigned int error_code=0x00000010)

  • According to nrf_drv_spi_transfer the 0x10 error code corresponds to:

    NRF_ERROR_INVALID_ADDR If the provided buffers are not placed in the Data RAM region.

    So maybe try doing this

    uint8_t tx_buffer = 0xFF

    APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, &tx_buffer , sizeof(uint8_t), &rx_buffer[0], sizeof(uint8_t)));

     

  • I have modified the code, so there are no hangs or errors anymore, however the result is the same - "0".

  • OK, thats one step in the right direction.

    Are you able to perform a logic trace of the SPI pins or scope them so that we can verify that the correct commands are sent to the vs1053?

Reply Children
  • OK, its hard  to debug the issue without a trace of the SPI lines as we do not know if the problem is on the nrf side or the vs1053 side. 

    We need to check if the data in the SPI TX buffer is sent to the vs1053 or not. If the correct data is sent on the SPI lines, then its either an issue  on the vs1053 side or it could be the nRF52 using thewrong SPI mode. You could try to  change the .mode member (nrf_drv_spi_mode_t) of  nrf_drv_spi_config_t and see if that solves the issue. 

  • In the arduino code I use SPI MODE 0, the same mode I have chosen in the NRF52.

    The vs1053 works well with arduino, I checked it 10 minutes ago, so the problem is definitely on the nrf side, just want to know what this problem can be related to?

  • I am afraid that I am out of ideas here. I really need to see a trace of the SPI lines in order to figure out whats going on here.



  • This is what I got with this code

    /**
     * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    /** @file
     * @defgroup fatfs_example_main main.c
     * @{
     * @ingroup fatfs_example
     * @brief FATFS Example Application main file.
     *
     * This file contains the source code for a sample application using FAT filesystem and SD card library.
     *
     */
    
    #include "SEGGER_RTT.h"
    #include "bsp.h"
    #include "diskio_blkdev.h"
    #include "ff.h"
    #include "nrf.h"
    #include "nrf_block_dev_sdc.h"
    #include "nrf_delay.h"
    
    #include "nrf_drv_spi.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define FILE_NAME "NORDIC.TXT"
    #define TEST_STRING "SD card example."
    
    #define SPI_INSTANCE 1
    
    #define SDC_SCK_PIN 3   ///< SDC serial clock (SCK) pin. 25   14
    #define SDC_MOSI_PIN 4  ///< SDC serial data in (DI) pin. 23  13
    #define SDC_MISO_PIN 28 ///< SDC serial data out (DO) pin. 24 12
    #define SDC_CS_PIN 24   ///< SDC chip select (CS) pin. 22    11
    
    #define MP3_RESET 27
    #define MP3_DREQ 23
    #define MP3_XCS 24
    #define MP3_XDCS 25 //Data Chip Select / BSYNC Pin
    
    //VS10xx SCI Registers
    #define SCI_MODE 0x00
    #define SCI_STATUS 0x01
    #define SCI_BASS 0x02
    #define SCI_CLOCKF 0x03
    #define SCI_DECODE_TIME 0x04
    #define SCI_AUDATA 0x05
    #define SCI_WRAM 0x06
    #define SCI_WRAMADDR 0x07
    #define SCI_HDAT0 0x08
    #define SCI_HDAT1 0x09
    #define SCI_AIADDR 0x0A
    #define SCI_VOL 0x0B
    #define SCI_AICTRL0 0x0C
    #define SCI_AICTRL1 0x0D
    #define SCI_AICTRL2 0x0E
    #define SCI_AICTRL3 0x0F
    
    static const nrf_drv_spi_t m_spi1 = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);
    
    static uint8_t rx_buffer[] = {0, 0};
    static FIL file;
    
    typedef struct {
      uint16_t length;
      uint8_t data[32];
    } fatfs_read_buffer_t;
    
    static fatfs_read_buffer_t fatfs_read_buffer = {.length = 0, .data = {0x00}};
    
    /**
     * @brief  SDC block device definition
     * */
    NRF_BLOCK_DEV_SDC_DEFINE(
        m_block_dev_sdc,
        NRF_BLOCK_DEV_SDC_CONFIG(
            SDC_SECTOR_SIZE,
            APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)),
        NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00"));
    
    /**
     * @brief Function for demonstrating FAFTS usage.
     */
    static void fatfs_example() {
      static FATFS fs;
      static DIR dir;
      static FILINFO fno;
    
      FRESULT ff_result;
      DSTATUS disk_state = STA_NOINIT;
    
      // Initialize FATFS disk I/O interface by providing the block device.
      static diskio_blkdev_t drives[] =
          {
              DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)};
    
      diskio_blockdev_register(drives, ARRAY_SIZE(drives));
    
      NRF_LOG_INFO("Initializing disk 0 (SDC)...");
      for (uint32_t retries = 10; retries && disk_state; --retries) {
        disk_state = disk_initialize(0);
      }
      if (disk_state) {
        NRF_LOG_INFO("Disk initialization failed.");
        return;
      }
    
      uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size;
      uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb;
      NRF_LOG_INFO("Capacity: %d MB", capacity);
    
      NRF_LOG_INFO("Mounting volume...");
      ff_result = f_mount(&fs, "", 1);
      if (ff_result) {
        NRF_LOG_INFO("Mount failed.");
        return;
      }
    
      NRF_LOG_INFO("\r\n Listing directory: /");
      ff_result = f_opendir(&dir, "/");
      if (ff_result) {
        NRF_LOG_INFO("Directory listing failed!");
        return;
      }
    
      do {
        ff_result = f_readdir(&dir, &fno);
        if (ff_result != FR_OK) {
          NRF_LOG_INFO("Directory read failed.");
          return;
        }
    
        if (fno.fname[0]) {
          if (fno.fattrib & AM_DIR) {
            NRF_LOG_RAW_INFO("   <DIR>   %s", (uint32_t)fno.fname);
          } else {
            NRF_LOG_RAW_INFO("%9lu  %s", fno.fsize, (uint32_t)fno.fname);
          }
        }
      } while (fno.fname[0]);
      NRF_LOG_RAW_INFO("");
    
      NRF_LOG_RAW_INFO("\n");
      /*
        NRF_LOG_INFO("Writing to file " FILE_NAME "...");
        ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ".");
            return;
        }
    
        ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT *) &bytes_written);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Write failed\r\n.");
        }
        else
        {
            NRF_LOG_INFO("%d bytes written.", bytes_written);
        }
              
        (void) f_close(&file);*/
      return;
    }
    
    void playMP3(char *fileName) {
      int need_data = 1;
      FRESULT ff_result;
      uint32_t bytes_read;
      fatfs_example();
    
      while (1) {
        ff_result = f_open(&file, fileName, FA_READ);
    
        if (ff_result != FR_OK) {
          NRF_LOG_INFO("Unable to open file \n");
          return;
        }
    
        //while(!nrf_gpio_pin_read(MP3_DREQ))
        nrf_delay_ms(10);
        {
    
          //If the MP3 IC is happy, but we need to read new data from the SD, now is a great time to do so
          if (need_data == 1) {
            if ((ff_result = f_read(&file, fatfs_read_buffer.data, fatfs_read_buffer.length, &bytes_read)) != FR_OK)
              break;
            //Data reading ----------------------------
            //if no data break-------------------------
            need_data = 0;
          }
    
          nrf_delay_ms(100); //Do NOTHING - sounds fine
        }
    
        if (need_data == 1) { //This is here in case we haven't had any free time to load new data
          if ((ff_result = f_read(&file, fatfs_read_buffer.data, fatfs_read_buffer.length, &bytes_read)) != FR_OK)
            break;
          //Data read-----------------------------
          //if no data break----------------------
          need_data = 0;
        }
    
        //Once DREQ is released (high) we now feed 32 bytes of data to the VS1053 from our SD read buffer
        nrf_gpio_pin_clear(MP3_XDCS); //Select Data
        //for(int y = 0 ; y < sizeof(fatfs_read_buffer.data) ; y++)
        {
          // Send SPI byte
          nrf_drv_spi_transfer(&m_spi1, fatfs_read_buffer.data, sizeof(fatfs_read_buffer.data), rx_buffer, sizeof(rx_buffer));
        }
    
        nrf_gpio_pin_set(MP3_XDCS); //Deselect Data
        need_data = 1;              //We've just dumped 32 bytes into VS1053 so our SD read buffer is empty. Set flag so we go get more data
      }
    
      // while(!nrf_gpio_pin_read(MP3_DREQ)) ; //Wait for DREQ to go high indicating transfer is complete
      nrf_delay_ms(10);
      nrf_gpio_pin_set(MP3_XDCS); //Deselect Data
    
      //Close out this track
    
      NRF_LOG_INFO("end of the song");
    
      f_close(&file);
    }
    
    uint8_t Mp3ReadRegister(uint8_t addressbyte) {
      while (!nrf_gpio_pin_read(MP3_DREQ)) {}; //Wait for DREQ to go high indicating IC is available
       nrf_gpio_pin_clear(MP3_XCS); //here
      nrf_delay_ms(10);
      //SCI consists of instruction byte, address byte, and 16-bit data word.
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0x03, sizeof(uint8_t), NULL, sizeof(uint8_t)));
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, &addressbyte, sizeof(uint8_t), NULL, sizeof(uint8_t)));
    
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0xFF, sizeof(uint8_t), &rx_buffer[0], sizeof(uint8_t)));
      while (!nrf_gpio_pin_read(MP3_DREQ)) {}; //Wait for DREQ to go high indicating IC is available
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0xFF, sizeof(uint8_t), &rx_buffer[1], sizeof(uint8_t)));
      while (!nrf_gpio_pin_read(MP3_DREQ)) {}; //Wait for DREQ to go high indicating IC is available
    
      int resultvalue = rx_buffer[0] << 8;
      resultvalue |= rx_buffer[1];
    
      nrf_gpio_pin_set(MP3_XCS); //here
    
      return resultvalue;
    }
    
    //Write to VS10xx register
    //SCI: Data transfers are always 16bit. When a new SCI operation comes in
    //DREQ goes low. We then have to wait for DREQ to go high again.
    //XCS should be low for the full duration of operation.
    void Mp3WriteRegister(uint8_t addressbyte, uint8_t highbyte, uint8_t lowbyte) {
      //while(!nrf_gpio_pin_read(MP3_DREQ)) ; //Wait for DREQ to go high indicating IC is available
      nrf_delay_ms(10);
      uint8_t temp = 0x02;
      //SCI consists of instruction byte, address byte, and 16-bit data word.
      nrf_drv_spi_transfer(&m_spi1, &temp, sizeof(temp), rx_buffer, sizeof(rx_buffer));
      nrf_delay_ms(50);
      nrf_drv_spi_transfer(&m_spi1, &addressbyte, sizeof(addressbyte), rx_buffer, sizeof(rx_buffer));
      nrf_delay_ms(50);
      nrf_drv_spi_transfer(&m_spi1, &highbyte, sizeof(highbyte), rx_buffer, sizeof(rx_buffer));
      nrf_delay_ms(50);
      nrf_drv_spi_transfer(&m_spi1, &lowbyte, sizeof(lowbyte), rx_buffer, sizeof(rx_buffer));
      nrf_delay_ms(10);
    }
    
    //Set VS10xx Volume Register
    void Mp3SetVolume(uint8_t leftchannel, uint8_t rightchannel) {
      Mp3WriteRegister(SCI_VOL, leftchannel, rightchannel);
    }
    
    void spi_event_handler(nrf_drv_spi_evt_t const *p_event,
        void *p_context) {
      //spi_xfer_done = true;
      NRF_LOG_INFO("Transfer completed.");
      if (rx_buffer[0] != 0) {
        NRF_LOG_INFO(" Received: %d", rx_buffer);
      }
    }
    
    /**
     * @brief Function for main application entry.
     */
    int main(void) {
      bsp_board_init(BSP_INIT_LEDS);
    
      APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
      NRF_LOG_DEFAULT_BACKENDS_INIT();
    
      SEGGER_RTT_Init();
      SEGGER_RTT_SetTerminal(0);
    
      //NRF_LOG_INFO("\n\n\n\nFATFS example started. new8");
      SEGGER_RTT_TerminalOut(0, "\nInitialization\n");
    
      //fatfs_example();
    
      nrf_gpio_cfg_output(MP3_RESET);
      nrf_gpio_cfg_output(MP3_XDCS);
      nrf_gpio_cfg_output(MP3_XCS);
      nrf_gpio_cfg_input(MP3_DREQ, NRF_GPIO_PIN_PULLDOWN);
    
      nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
      spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED;
      spi_config.miso_pin = SDC_MISO_PIN;
      spi_config.mosi_pin = SDC_MOSI_PIN;
      spi_config.sck_pin = SDC_SCK_PIN;
      spi_config.frequency = SPI_FREQUENCY_FREQUENCY_K125;
      APP_ERROR_CHECK(nrf_drv_spi_init(&m_spi1, &spi_config, NULL, NULL));
    
      nrf_gpio_pin_clear(MP3_RESET);
      nrf_gpio_pin_set(MP3_XDCS);
      nrf_gpio_pin_set(MP3_XCS);
    
      nrf_delay_ms(10);
    
      nrf_gpio_pin_set(MP3_RESET); //Bring up VS1053
    
      while (!nrf_gpio_pin_read(MP3_DREQ)) {
      };
    
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0xFF, sizeof(uint8_t), NULL, sizeof(uint8_t)));
    
      nrf_delay_ms(10);
    
      //NRF_SPI0->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M4;
    
      //Mp3WriteRegister(SCI_CLOCKF, 0x60, 0x00); //Set multiplier to 3.0x
    
      int k = Mp3ReadRegister(SCI_STATUS);
    
      //NRF_LOG_INFO("status = %d\n status2 = %d", ((k >> 4) & 0x0F), k);
      char str[255];
    
      sprintf(str, "\nstatus = %d\n", k);
    
      SEGGER_RTT_TerminalOut(0, str);
    
      //Mp3SetVolume(20, 20); //Set initial volume (20 = -10dB) LOUD
    
      //	fatfs_example();
    
      /*
      Mp3SetVolume(20, 20); //Set initial volume (20 = -10dB) LOUD
    	
    	int MP3Mode = Mp3ReadRegister(SCI_MODE);
      int MP3Status = Mp3ReadRegister(SCI_STATUS);
      int MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
    	
    	Mp3WriteRegister(SCI_CLOCKF, 0x60, 0x00); //Set multiplier to 3.0x
    	
    	MP3Clock = Mp3ReadRegister(SCI_CLOCKF);
    */
      //playMP3("track.mp3");
    
      while (true) {
        __WFE();
      }
    }
    
    /** @} */

  • So from you main() code I see that you're performing the following SPI transactions

      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0xFF, sizeof(uint8_t), NULL, sizeof(uint8_t)));
    
      int k = Mp3ReadRegister(SCI_STATUS);

    where Mp3ReadRegister is called with SCI_STATUS(0x01) as an argument. 

    uint8_t Mp3ReadRegister(uint8_t addressbyte) {
      while (!nrf_gpio_pin_read(MP3_DREQ)) {}; //Wait for DREQ to go high indicating IC is available
       nrf_gpio_pin_clear(MP3_XCS); //here
      nrf_delay_ms(10);
      //SCI consists of instruction byte, address byte, and 16-bit data word.
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0x03, sizeof(uint8_t), NULL, sizeof(uint8_t)));
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, &addressbyte, sizeof(uint8_t), NULL, sizeof(uint8_t)));
    
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0xFF, sizeof(uint8_t), &rx_buffer[0], sizeof(uint8_t)));
      while (!nrf_gpio_pin_read(MP3_DREQ)) {}; //Wait for DREQ to go high indicating IC is available
      APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0xFF, sizeof(uint8_t), &rx_buffer[1], sizeof(uint8_t)));
      while (!nrf_gpio_pin_read(MP3_DREQ)) {}; //Wait for DREQ to go high indicating IC is available
    
      int resultvalue = rx_buffer[0] << 8;
      resultvalue |= rx_buffer[1];
    
      nrf_gpio_pin_set(MP3_XCS); //here
    
      return resultvalue;
    }

    So from the first SPI transaction you should only see the single 0xFF byte being transmitted on the MOSI line and then you'll get some garbage data back on the MISO line. 

    From the transactions in Mp3ReadRegister() you should see the 0x03 0xFF 0xFF and then you will get 3 bytes back on the MISO line. However you're seeing 

    MOSI: 0xE4 0xE5 0xE6 

    MISO: 0xE5 0xE6 0xE7

    which does not match any of the transactions we're expecting, so there is something that is not right. Can you configure the Salea analyzer to start capturing from the point where the MP3_XDCS pin goes high so that we get the first transaction as well? You can also attach the the logic trace file to the case instead of posting a screenshot. 

    Bjørn

Related