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 Reply Children
  • 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();
        }
    }
    
    /** @} */
    

  • OK, are you able to do a logic trace of the SPI lines? 

    Also you should add APP_ERROR_CHECKs to your nrf_drv_spi_transfer() calls in Mp3ReadRegister(), i.e. 

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

    that way the code will assert if any of the transfers return an error code. 

  • Done.

    It gives me an error on the first transfer in Mp3ReadRegister();

    APP_ERROR_CHECK(nrf_drv_spi_transfer(&m_spi1, (uint8_t *)0x03, sizeof(uint8_t), NULL, sizeof(uint8_t))); //here

  • void app_error_handler_bare(unsigned int error_code=0x00000010)

Related