📄 vs1003b.c
字号:
/*******************************************************************/
/* VS1003 diriver for Mega8 MP3 Player */
/* */
/* Platform : AVRStudio4.13 b528 + WinAVR20070122 */
/* optimize -0s */
/* Author : bozai(Zhang Qibo) */
/* E-mail : sudazqb@163.com */
/* MSN : zhangqibo_1985@hotmail.com */
/* Date : 2006-05-09 */
/*******************************************************************/
/* 20080928: modify codes for ARM platform (NXP LPC2132) */
/* 20071208: modify codes for ARM platform (AT91SAM7S256) */
/*2007-11-22: add bass tremble control */
/*2007-10-21: add new functions, */
/*2007-10-19: use new delay function */
/*2007-05-04: add slow start up code, and add enough delay */
/*2007-04-21: */
#include "VS1003B.h"
#define uchar unsigned char
#define uint unsigned short
void VS1003B_SPI_Low(void);//low spi clk
void VS1003B_SPI_High(void);//high spi clk
unsigned char VS1003B_WriteByte(unsigned char CH);//spi write a byte
void VS1003B_WriteCMD(unsigned char addr, unsigned short dat);//write register
unsigned short VS1003B_ReadCMD(unsigned char addr);//read register
/* Run at the loweset spi speed, clk should below 12.288M/6 */
void VS1003B_SPI_Low(void)
{
S0PCCR = 100; /* 设置SPI0时钟分频值为8 Set the value of dividing frequency to 8 */
S0PCR = (0 << 3) | // CPHA = 0, 数据 在SCK 的第一个时钟沿采样
(1 << 4) | // CPOL = 1, SCK 为低有效
(1 << 5) | // MSTR = 1, SPI 处于主模式
(0 << 6) | // LSBF = 0, SPI 数据传输MSB (位7)在先
(0 << 7); // SPIE = 0, SPI 中断被禁止
#if 0
AT91PS_SPI pSPI = AT91C_BASE_SPI;
unsigned long reg;
unsigned char speed = MCK/200000; /* 200KHz, below 400KHz */
reg = pSPI->SPI_CSR[0]; /* we control the CS but not SPI , so just use default SPI_CSR0 */
reg = ( reg & ~(AT91C_SPI_SCBR) ) | ( (unsigned long)speed << 8 ); /* recaulate */
pSPI->SPI_CSR[0] = reg; /* set the value */
#endif
}
/* High speed, should not exceed 49.512MHz/6 */
void VS1003B_SPI_High(void)
{
S0PCCR = 6; /* 设置SPI0时钟分频值为8 Set the value of dividing frequency to 8 */
S0PCR = (0 << 3) | // CPHA = 0, 数据 在SCK 的第一个时钟沿采样
(1 << 4) | // CPOL = 1, SCK 为低有效
(1 << 5) | // MSTR = 1, SPI 处于主模式
(0 << 6) | // LSBF = 0, SPI 数据传输MSB (位7)在先
(0 << 7); // SPIE = 0, SPI 中断被禁止
#if 0
AT91PS_SPI pSPI = AT91C_BASE_SPI;
unsigned long reg;
unsigned char speed = MCK/12000000; /* 8MHz */
reg = pSPI->SPI_CSR[0]; /* we control the CS but not SPI , so just use default SPI_CSR0 */
reg = ( reg & ~(AT91C_SPI_SCBR) ) | ( (unsigned long)speed << 8 ); /* recaulate */
pSPI->SPI_CSR[0] = reg; /* set the value */
#endif
}
/* write one byte to vs1003 */
unsigned char VS1003B_WriteByte(unsigned char val)
{
S0PDR = val;
while(0 == (S0PSR & 0x80)); /* wait for SPI0F being set, that is, wait for finishing of data being send */
return(S0PDR);
#if 0
AT91PS_SPI pSPI = AT91C_BASE_SPI;
while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); /* transfer compl. wait */
pSPI->SPI_TDR = val;
while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); /* wait for char */
return (unsigned char)( pSPI->SPI_RDR ); /* it's important to read RDR here! */
#endif
}
/* read one byte from vs1003 */
unsigned char VS1003B_ReadByte()
{
S0PDR = 0xff;
while(0 == (S0PSR & 0x80)); /* wait for SPI0F being set, that is, wait for finishing of data being send */
return(S0PDR);
#if 0
AT91PS_SPI pSPI = AT91C_BASE_SPI;
while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); /* transfer compl. wait */
pSPI->SPI_TDR = 0xff;
while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); /* wait for char */
return (unsigned char)( pSPI->SPI_RDR ); /* it's important to read RDR here! */
#endif
}
/*写寄存器,参数,地址和数据 config register */
void VS1003B_WriteCMD(unsigned char addr, unsigned short dat)
{
VS1003B_XDCS_H();
VS1003B_XCS_L();
VS1003B_WriteByte(0x02);
VS1003B_WriteByte(addr);
VS1003B_WriteByte(dat>>8);
VS1003B_WriteByte(dat);
VS1003B_XCS_H();
}
/* 读寄存器,参数 地址 返回内容 read register */
unsigned short VS1003B_ReadCMD(unsigned char addr)
{
unsigned short temp;
VS1003B_XDCS_H();
VS1003B_XCS_L();
VS1003B_WriteByte(0x03);
VS1003B_WriteByte(addr);
temp = VS1003B_ReadByte();
temp <<= 8;
temp += VS1003B_ReadByte();
VS1003B_XCS_H();
return temp;
}
/* fill 2048 zero */
void VS1003B_Fill2048Zero()
{
unsigned char i,j;
VS1003B_SPI_High();
for(i=0;i<64;i++)
{
VS1003B_XDCS_L();
while(VS1003B_NeedData()==0);
for(j=0;j<32;j++)
{
VS1003B_WriteByte(0x00);
}
VS1003B_XDCS_H();
}
}
/* Write 32bytes data */
void VS1003B_Write32B(unsigned char * buf)
{
unsigned char n = 32;
VS1003B_SPI_High();
VS1003B_XDCS_L();
while(n--)
{
VS1003B_WriteByte(*buf++);
}
VS1003B_XDCS_H();
}
/********** Initialization, 1 means fail, 0 OK ***************/
unsigned char VS1003B_Init(void)
{
unsigned char retry;
#if 0
AT91PS_SPI pSPI = AT91C_BASE_SPI;
AT91PS_PMC pPMC = AT91C_BASE_PMC;
#endif
PORT_INI(); /* Prot Initialize */
#if 0
/* disable PIO from controlling MOSI, MISO, SCK (=hand over to SPI) */
pPIO->PIO_PDR = AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK;
/* set pin-functions in PIO Controller */
pPIO->PIO_ASR = AT91C_PA12_MISO | AT91C_PA13_MOSI | AT91C_PA14_SPCK;
/* enable peripheral clock for SPI ( PID Bit 5 ) */
pPMC->PMC_PCER = ( 1 << AT91C_ID_SPI ); /* n.b. IDs are just bit-numbers */
/* SPI enable and reset */
pSPI->SPI_CR = AT91C_SPI_SPIEN | AT91C_SPI_SWRST;
/* SPI mode: master, fixed periph. sel., FDIV=0, fault detection disabled */
pSPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_PS_FIXED | AT91C_SPI_MODFDIS;
/* set PCS for fixed select, in this program we do not use select of the SPI */
/* We control the select ourself, so the default cs is 0, but we never use it */
pSPI->SPI_MR &= 0xFFF0FFFF; /* clear old PCS - redundant (AT91lib) */
pSPI->SPI_MR |= ( (0<<16) & AT91C_SPI_PCS ); /* set PCS */
pSPI->SPI_CSR[0] = AT91C_SPI_NCPHA | AT91C_SPI_BITS_8;
#endif
/* set SPI clock speed */
VS1003B_SPI_Low(); /* Low initialize spi clock */
#if 0
/* Enable SPI interface */
pSPI->SPI_CR = AT91C_SPI_SPIEN;
#endif
VS1003B_XRESET_L(); /* A hardware reset */
_delay_ms(20);
VS1003B_XRESET_H();
VS1003B_SPI_Low(); /* Low initialize spi clock */
_delay_ms(20);
retry=0;
while(VS1003B_ReadCMD(0x03) != CLOCK_REG) /* set PLL register */
{
VS1003B_WriteCMD(0x03,CLOCK_REG);
if(retry++ >10 )return 1;
}
_delay_ms(20);
VS1003B_WriteCMD(0x05,0x000a);
retry=0;
while(VS1003B_ReadCMD(0x0b) != 0xfefe) /* set Volume to minimum */
{
VS1003B_WriteCMD(0x0b,0xfefe);
if(retry++ >10 )return 1;
}
VS1003B_WriteCMD(0x05,0xac45); /* Soft start */
retry=0;
while(VS1003B_ReadCMD(0x0b) != DEFAULT_VOLUME) /* Set volume to default value */
{
VS1003B_WriteCMD(0x0b,DEFAULT_VOLUME);
if(retry++ >10 )return 1;
}
retry=0;
while(VS1003B_ReadCMD(0x00) != 0x0800) /* set mode register */
{
VS1003B_WriteCMD(0x00,0x0800);
if(retry++ >10 )return 1;
}
_delay_ms(1);
retry=0;
while(VS1003B_ReadCMD(0x02) != DEFAULT_BASS_TREMBLE) /* set bass/tremble register */
{
VS1003B_WriteCMD(0x02,DEFAULT_BASS_TREMBLE);
if(retry++ >10 )return 1;
}
_delay_ms(20);
VS1003B_SoftReset(); /* A soft reset */
_delay_ms(20);
VS1003B_SPI_High(); /* High SPI clock, for internal pll has been works now */
return 0;
}
/* VS1003B soft reset */
void VS1003B_SoftReset()
{
VS1003B_SPI_High();
VS1003B_WriteCMD(0x00,0x0804); /* reset */
_delay_ms(20);
}
/* get total decode time form last reset */
unsigned short VS1003B_ReadDecodeTime()
{
VS1003B_SPI_High();
return VS1003B_ReadCMD(0x04);
}
/* check if the chip need data, 1: need 0: don't */
unsigned char VS1003B_NeedData(void)
{
// unsigned int temp;
//temp = pPIO->PIO_PDSR;
if(VS1003_DREQ_STATE()!=0)return 1;
else return 0;
}
/* Set volume */
void VS1003B_SetVolume(unsigned short vol)
{
VS1003B_SPI_High();
VS1003B_WriteCMD(0x0b,vol);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -