Einleitung

Der VS1033D ist ein Decoder IC, welcher unter anderem MP3 Audiodateien in Echtzeit dekodieren und ausgeben kann.

Implementierung

Hier einige Überlegungen zur Implementierung. Es soll ein Mikrocontroller eingesetzt werden, welcher genügend RAM Speicher hat, um Daten zwischenspeichern zu können. In dem folgenden Beispiel wird ein Puffer von 1024 Bytes angenommen.

#define BLOCK_SIZE = 512 // default sd card data block
#define BUFFER_SIZE = 1024
#define CHUNK_SIZE = 32  // see VS10xx documentation

ueint08 do_vs_transfer = 0;
ueint08 do_sd_transfer = 0;
ueint16 s, v, lastPost;

check_sd_transfer() {
    if ((s > v) || (v-s) >= BLOCK_SIZE)
        bytesRead = do_read_sd_data(); // read sd data
        lastPos = (s + bytesRead) % BUFFER_SIZE;
        s = (s+BLOCK_SIZE) % BUFFER_SIZE;
        if (bytesRead < BLOCK_SIZE) {
            // eof 
            // stop sd transfer
            do_sd_transfer = 0;
        }
    }
}

check_vs_transfer() {
    ueint08 bytesLeft = (l+BUFFER_SIZE-v) % BUFFER_SIZE;
    if (bytesLeft < CHUNK_SIZE) {
        // transfer last chunk with bytesLeft bytes
        do_write_vs_data() // write data to vs
        // stop vs transfer
        do_vs_transfer = 0;
    }
    else {
        // transfer chunk
        do_write_vs_data() // write data to vs
        v = (v+CHUNK_SIZE) % BUFFER_SIZE;
    }
    if (v == s) {
        // eof
        // stop vs transfer
        do_vs_transfer = 0;
    }
}

init_transfer() {
    s = 0;
    v = 0;
    lastPost = 0;
}

platform_config.h

#define  VS_GPIOx GPIOD
#define  VS_GPIO_DREQ_PIN  GPIO_Pin_5
#define  VS_GPIO_RESET_PIN GPIO_Pin_6
#define  VS_SPIx SPI1

vs.c

#include "stm32f10x_lib.h"
#include "vs1002.h"

// VS1002 commands
#define VS1002_READ     0x03
#define VS1002_WRITE    0x02

#define F_CPU        	12000000               		/* Processor Speed */
#define CYCLES_PER_US 	((F_CPU+500000)/1000000) 	/* cpu cycles per microsecond */

#define WAIT_SPI_TX_EMPTY       while(SPI_I2S_GetFlagStatus(SPI_PORT, SPI_I2S_FLAG_TXE) == RESET)
#define WAIT_SPI_RX_NOT_EMPTY   while(SPI_I2S_GetFlagStatus(SPI_PORT, SPI_I2S_FLAG_RXNE) == RESET)   //  Wait for SPI data reception 
#define WAIT_BUSY               while(!GPIO_ReadInputDataBit(VS_CONTROL_GPIO, DREQ_PIN))
#define XCS_HIGH  GPIO_SetBits(VS_CONTROL_GPIO, XCS_PIN)
#define XCS_LOW  GPIO_ResetBits(VS_CONTROL_GPIO, XCS_PIN)

// global variables
GPIO_InitTypeDef GPIO_InitStructure;

// prototypes
void delay(vu32 nCount);
void write_spi(u8 data);


void vs_init_io(void) 
{
    /* Configure SPI1 pins: SCK, MISO and MOSI and NSS--------------------------*/
    GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(SPI_GPIO, &GPIO_InitStructure);
  
    /* Configure output push-pull */
    GPIO_InitStructure.GPIO_Pin =  XCS_PIN | RESET_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(VS_CONTROL_GPIO, &GPIO_InitStructure);

    /* Configure input */
    GPIO_InitStructure.GPIO_Pin =  DREQ_PIN;
    //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(VS_CONTROL_GPIO, &GPIO_InitStructure);

    XCS_HIGH;
}

void vs_init_chip(void) 
{
}


u8 write_byte_spi(u8 data)
{
    WAIT_SPI_TX_EMPTY;

    /* Send SPI1 data */
    SPI_I2S_SendData(SPI1, data);

    /* Wait for SPI1 Tx buffer empty */
    WAIT_SPI_TX_EMPTY;        
    
    /* Wait for SPI1 data reception */
    WAIT_SPI_RX_NOT_EMPTY;
        
    /* Read SPI1 received data */
    return SPI_I2S_ReceiveData(SPI1);
}	

void write_spi(u8 data)
{
    WAIT_SPI_TX_EMPTY;

    /* Send SPI1 data */
    SPI_I2S_SendData(SPI1, data);

    /* Wait for SPI1 Tx buffer empty */
    WAIT_SPI_TX_EMPTY;        
}	


void vs_SCI_write(u8 address, u16 data)
{		

    WAIT_BUSY;

    XCS_LOW;

	write_byte_spi(VS1002_WRITE);
	write_byte_spi(address);
    
	write_byte_spi(data >> 8);
	write_byte_spi(data);


    XCS_HIGH;
    
    delay(1000);

    WAIT_BUSY;
}


u16 vs_SCI_read(u8 address)
{
    WAIT_BUSY;


    XCS_LOW;
    
    u16 retData = 0;

    write_byte_spi(VS1002_READ);
    write_byte_spi(address);

    retData = write_byte_spi(0) << 8;
    retData |= write_byte_spi(0);

    XCS_HIGH;
    
    delay(1000);

    WAIT_BUSY;

    return retData;
}


void vs_reset(u8 reset_type) 
{
    if (reset_type == HARD_RESET)
    {
          GPIO_ResetBits(VS_CONTROL_GPIO, RESET_PIN);
          /* Insert delay */
          delay(10000);
          GPIO_SetBits(VS_CONTROL_GPIO, RESET_PIN);
          delay(10000);
    
          WAIT_BUSY;
    }
    else 
    {
          vs_SCI_write(0x00, 0x04);  
          delay(0xffff);
          
          WAIT_BUSY;

    }    
}

void vs_start_sinetest(u8 pitch) 
{
    XCS_HIGH;
    // 0x53, 0xEF, 0x6E, 126, 0, 0, 0, 0
    write_byte_spi(0x53);
    write_byte_spi(0xEF);
    write_byte_spi(0x6E);
    write_byte_spi(pitch);
    write_byte_spi(0);
    write_byte_spi(0);
    write_byte_spi(0);
    write_byte_spi(0);  
    XCS_LOW;
}

void vs_stop_sinetest(void) 
{
    XCS_HIGH;
    write_byte_spi(0x45);
    write_byte_spi(0x78);
    write_byte_spi(0x69);
    write_byte_spi(0x74);
    write_byte_spi(0);
    write_byte_spi(0);
    write_byte_spi(0);
    write_byte_spi(0);  
    XCS_LOW;
}

void vs_set_volume(u16 volume)
{
    vs_SCI_write(0x0b, volume);  
}

void vs_send_32(u8 *pData) 
{
    int i;
    XCS_HIGH;

	for (i=0; i<32; i++)
	{
        write_byte_spi(*pData++);    
    }

    XCS_LOW;

}

void vs_send_null_32()
{
    XCS_HIGH;
    int i;
	for (i=0; i<32; i++)
	{
        write_byte_spi(0);
    }
    XCS_LOW;
}

void delay(vu32 nCount)
{
    for(; nCount!= 0;nCount--);
}

main.c

/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : main.c
* Author             : MCD Application Team
* Date First Issued  : 02/05/2007
* Description        : Main program body
********************************************************************************
* History:
* 04/02/2007: V0.2
* 02/05/2007: V0.1
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "platform_config.h"
//#include "stdio.h"
#include "stdlib.h"
#include "vs1002.h"

//EFSL library

#include "efs.h"
#include "ls.h"


#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */


#define WAIT_BUSY               while(!GPIO_ReadInputDataBit(VS_CONTROL_GPIO, DREQ_PIN))

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
ErrorStatus HSEStartUpStatus;
SPI_InitTypeDef SPI_InitStructure;


/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void RCC_Configuration2(void);
void NVIC_Configuration(void);
void Delay(vu32 nCount);
void sendCh(u8 ch);
void itoa(u16 val, u8 base, char* buf);


//EFSL library
EmbeddedFileSystem efs;
DirList list;
EmbeddedFile file;

/* Function to test EFSL function */
void EFSL_Test(void);
void FILE_FormatFATName(u8 * pcSkad,u8 * pcDokond);



/* Private functions ---------------------------------------------------------*/

int main(void)
{

#ifdef DEBUG
  //debug();
#endif


  /* System Clocks Configuration */
  RCC_Configuration();

  /* NVIC Configuration */
  NVIC_Configuration();

  /* Enable peripheral clocks --------------------------------------------------*/
  /* GPIOA, GPIOB and SPI1 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE);

  /* Enable USARTx clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  /* Configure PC.06, PC.07, PC.08 and PC.09 as output push-pull */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);


  /* Configure USARTx_Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_TxPin;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOx, &GPIO_InitStructure);

  /* Configure USARTx_Rx as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_RxPin;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOx, &GPIO_InitStructure);


  vs_init_io();
  
  
  /* init SPI1 */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_Init(SPI1, &SPI_InitStructure);  
  
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No ;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  //USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_InitStructure.USART_Mode = USART_Mode_Tx;
    
    /* Configure the USARTx */ 
  USART_Init(USART3, &USART_InitStructure);
  /* Enable the USARTx */
  USART_Cmd(USART3, ENABLE);
  
    /* Enable SPI1 */
  SPI_Cmd(SPI1, ENABLE);


  printf("\n\rHyper terminal is configured properly!\n\r");  
  
  
  Delay(0xAFFFF);
  

  
  /* SEND VS RESET */
  printf("hard reset\n\r");  
  vs_reset(HARD_RESET);
  Delay(0xFFFF);
  printf("done\n\r");  
   
 
  vs_SCI_write(0x00, 0x0c00);  
  Delay(0xFFFFF);
  
  printf("read: ");
  printInt(vs_SCI_read(0x00));
  Delay(0xFFFFF);
  
  
  //vs_SCI_write(0x03, 0x9000);  
  vs_SCI_write(0x03, 0x9800);  
  Delay(0xFFFFF);

  printf("read: ");
  printInt(vs_SCI_read(0x03));
  Delay(0xFFFFF);


  vs_send_null_32();
  
  
  printf("Start EFSL_Test\n\r");  
  //EFSL_Test();
  EFSL_play_test();

  while(1)
  {
  
    
    /* Turn on leds connected to PC.08 pin */
    //GPIO_Write(GPIOB, GPIO_Pin_8);  
    //sendCh('+');
  
    /* Insert delay */
    //Delay(0x7FFFF);
    
    /* Turn on leds connected to PC.08 pin */
    //GPIO_Write(GPIOB, GPIO_Pin_9);  
    //sendCh('-');
    
    /* Insert delay */
    // Delay(0x7FFFF);
  }
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
   {
   /* RCC system reset(for debug purpose) */
   RCC_DeInit();

   /* Enable HSE */
   RCC_HSEConfig(RCC_HSE_ON);

   /* Wait till HSE is ready */
   while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
      {;}  

   /* Enable Prefetch Buffer */
   FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

   /* Flash 2 wait state */
   FLASH_SetLatency(FLASH_Latency_2);

   /* HCLK = SYSCLK */
   RCC_HCLKConfig(RCC_SYSCLK_Div1); 

   /* PCLK2 = HCLK */
   RCC_PCLK2Config(RCC_HCLK_Div1); 

   /* PCLK1 = HCLK */
   RCC_PCLK1Config(RCC_HCLK_Div1);

   /* Select HSE as system clock source */
   RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);

   /* Wait till HSE is used as system clock source */
   while(RCC_GetSYSCLKSource() != 0x04)
      {;}  
   }


void RCC_Configuration2(void)
{
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
 
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_2);

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
}
/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures Vector Table base location.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void NVIC_Configuration(void)
{
#ifdef  VECT_TAB_RAM  
  /* Set the Vector Table base location at 0x20000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif
}

#ifdef  DEBUG
/*******************************************************************************
* Function Name  : assert_failed
* Description    : Reports the name of the source file and the source line number
*                  where the assert error has occurred.
* Input          : - file: pointer to the source file name
*                  - line: assert error line source number
* Output         : None
* Return         : None
*******************************************************************************/
void assert_failed(u8* file, u32 line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/*******************************************************************************
* Function Name  : Delay
* Description    : Inserts a delay time.
* Input          : nCount: specifies the delay time length.
* Output         : None
* Return         : None
*******************************************************************************/
void Delay(vu32 nCount)
{
  for(; nCount!= 0;nCount--);
}


void sendCh(u8 ch)
{
  /* Write a character to the USART */
  USART_SendData(USART3, ch);

  /* Loop until the end of transmission */
  while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
  {
  }
}

/*******************************************************************************
* Function Name  : PUTCHAR_PROTOTYPE
* Description    : Retargets the C library printf function to the USART.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
PUTCHAR_PROTOTYPE
{
  /* Write a character to the USART */
  USART_SendData(USARTx, (u8) ch);

  /* Loop until the end of transmission */
  while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
  {
  }

  return ch;
}


void printInt(u16 val) 
{
    char buf[10] = {0};
    itoa(val, 10, buf);  
    printf(buf);
    printf("\n\r");
}

void itoa(u16 val, u8 base, char* buf){
	
	u8 i = 10;	    
    char temp[10] = {0};
	for(; val && i ; --i, val /= base) {
        temp[i-1] = "0123456789abcdef"[val % base];
    }
    for (i = 0; i < 10; i++) {
        if (temp[i] != 0) {
            *buf++ = temp[i];
        }
    }
}

void EFSL_play_test(void) 
{

    printf("Read SD card\n\r");
    if(efs_init(&efs,0)!=0){
        printf("\n\rSD card not detected!\n\r");
        return;
    }
    printf("Opening file\n\r");
    if(file_fopen(&file, &efs.myFs, "test5.mp3",'r') != 0) {
        printf("Error opening file\n\r");
        return;
    }
    u8 buffer[512] = {0};
    u8 a;
    u16 e;        
    u16 z[16] = {0x00, 0x20, 0x40, 0x60, 0x80,0xA0,0xC0,0xE0,0x100,0x120,0x140,0x160,0x180,0x1A0,0x1C0,0x1E0};
    int i=0;
    
    while(e=file_read(&file,512,buffer)) {
        GPIO_ResetBits(GPIOB, GPIO_Pin_8);
        //printf("loop: ");
        //printInt(i++);        
        //sendCh('o');
        /*
        for(i=0;i<512;i++){				
            sendCh(buffer[i]);
        } 
        */
        
        
        
        for(a=0;a<16;a++){
            
            GPIO_SetBits(GPIOB, GPIO_Pin_9);
			WAIT_BUSY;
            GPIO_ResetBits(GPIOB, GPIO_Pin_9);
			vs_send_32(&buffer[z[a]]);					
		}
        if (i++ > 500) {
            break;
        }
        
        GPIO_SetBits(GPIOB, GPIO_Pin_8);
    }
    /*
    e = file_read(&file,512,buffer);
    int i;
    for(i=0;i<512;i++){				
        sendCh(buffer[i]);
    } 
    */

    printf("Done playing\n\r");
}

void EFSL_Test(void){
static u8 Buffer[20];
static int i=0;

if(efs_init(&efs,0)!=0){
  printf("\n\rSD card not detected!\n\r");
}else{
    ls_openDir(&list ,&(efs.myFs ),"/" ) ;   
    printf("\n\rSD card content:\n\r");  
    while(ls_getNext(&list)==0){
        FILE_FormatFATName(list.currentEntry.FileName,Buffer);
        printf("%3d : %s\n\r" ,i++,Buffer);               
    }
    fs_umount(&efs.myFs);
}
}

void FILE_FormatFATName(u8 * pcSkad,u8 * pcDokond){
int i,k;
int j=0;
char BylaKropka=1;

    for (i=0; i<8; i++){
        if(pcSkad[i] != 0x20){
            pcDokond[j++]=pcSkad[i];      
        }else{
            if((pcSkad[8]<'0')||(pcSkad[9]<'0')||(pcSkad[10]<'0')){
                pcDokond[j++]=' ';   
                BylaKropka=0;            
            }else{
                BylaKropka=0;
                pcDokond[j++]='.';           
            }
            break;
        }
    }
    if(BylaKropka){
        pcDokond[j++]='.';     
    }
    for (k=8; k<11; k++){   
        if(((pcSkad[k] >= 'A') && (pcSkad[k] <= 'Z'))){ 
            pcDokond[j++]=pcSkad[k];            
        }else if(((pcSkad[k] >= 'a') && (pcSkad[k] <= 'z'))){
            pcDokond[j++]=pcSkad[k];         
        }else if(((pcSkad[k] >= '0') && (pcSkad[k] <= '9'))){
            pcDokond[j++]=pcSkad[k]; 
        }else{
            pcDokond[j++]=' ';                  
        }      
    }
    pcDokond[j++]='\0';    
}
 
 
technical/vs1033_stmprimer.txt · Last modified: 2011/01/20 12:16 by adminuser
Recent changes RSS feed Creative Commons License Valid XHTML 1.0 Valid CSS Driven by DokuWiki
Drupal Garland Theme for Dokuwiki