📄 drv_vs1002.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2006
*
* File name : drv_vs1002.c
* Description : VS1002 driver
*
* History :
* 1. Date : October 10, 2006
* Author : Stanimir Bonev
* Description : Create
*
* $Revision: 16170 $
**************************************************************************/
#include "drv_vs1002.h"
#define MP3_VER(var) ((var)?var:MP3_Pass)
#define MP3_SHORT(var) ((var)?MP3_Fault:MP3_Pass)
#define MP3_RET(var) return((MP3_STATUS_VERBOSE?MP3_VER(var):MP3_SHORT(var)))
#define MP3_BOOT_SEL GPIO_Pin_1
#define MP3_RST GPIO_Pin_1
#define MP3_DATA_RQ GPIO_Pin_0
#define MP3_CS GPIO_Pin_0
#define MP3_MOSI GPIO_Pin_6
#define MP3_MISO GPIO_Pin_5
#define MP3_SCLK GPIO_Pin_4
#define TMR_PERIOD(Val) (8000000UL*MP3_STREAM_SIZE*8/(Val*1000UL))
const Int32U ISO11172_Bitrate[] = {
0,
TMR_PERIOD( 32),TMR_PERIOD( 40),TMR_PERIOD( 48),TMR_PERIOD( 56),TMR_PERIOD( 64),
TMR_PERIOD( 80),TMR_PERIOD( 96),TMR_PERIOD(112),TMR_PERIOD(128),TMR_PERIOD(160),
TMR_PERIOD(192),TMR_PERIOD(224),TMR_PERIOD(256),TMR_PERIOD(320),
0
};
const Int32U MPG2_Bitrate[] = {
0,
TMR_PERIOD( 8),TMR_PERIOD( 16),TMR_PERIOD( 24),TMR_PERIOD( 32),TMR_PERIOD( 40),
TMR_PERIOD( 48),TMR_PERIOD( 56),TMR_PERIOD( 64),TMR_PERIOD( 80),TMR_PERIOD( 96),
TMR_PERIOD(112),TMR_PERIOD(128),TMR_PERIOD(144),TMR_PERIOD(160),
0
};
volatile Mp3TransferStatus_t Mp3TransferStatus; // data transfer state
Boolean PlayFile = 0; // Play in progress
Int32U Mp2DmaTmp; // local buffer for transfer without incitement
Int32U DmaPeriodHold; // Sample period of a steam transfer
volatile pInt8U pMp3Data; // Stream transfer buffer
volatile Int32S Mp3Size; // Stream transfer remaining bytes
Boolean AddInc = 0; // disable/enable address increment
/*************************************************************************
* Function Name: MP3_Reset
* Parameters: Boolean Select
* Return: none
*
* Description: MP3 reset and disable booting from external EEPROM
* Select = true - Reset the VS1002
* Select = false - Release reset of the VS1002
*
*************************************************************************/
static inline
void MP3_Reset (Boolean Select)
{
// Set the Boot select low
GPIO_WriteBit(GPIO2,MP3_BOOT_SEL,Bit_RESET);
GPIO_WriteBit(GPIO3,MP3_RST,Select?Bit_RESET:Bit_SET);
}
/*************************************************************************
* Function Name: MP3_DReq
* Parameters: none
* Return: Boolean
*
* Description: Return state of the DREQ line
*
*************************************************************************/
static inline
Boolean MP3_DReq (void)
{
return(GPIO_ReadBit(GPIO3,MP3_DATA_RQ) == Bit_SET);
}
/*************************************************************************
* Function Name: MP3_ChipSelect
* Parameters: Boolean Select
* Return: none
*
* Description: MP3 chip select control
* Select = true - Chip is enable - command
* Select = false - Chip is disable - data
*
*************************************************************************/
static inline
void MP3_ChipSelect (Boolean Select)
{
GPIO_WriteBit(GPIO2,MP3_CS,Select?Bit_RESET:Bit_SET);
}
/*************************************************************************
* Function Name: MP3_SetClockFreq
* Parameters: Int32U Frequency
* Return: Int32U
*
* Description: Set SPI ckl frequency
*
*************************************************************************/
static inline
Int32U MP3_SetClockFreq (Int32U Frequency)
{
Int32U Div = 2;
Int32U Pclk;
Pclk = SCU_GetMCLKFreqValue()*1000;
if(!(SCU->CLKCNTR & 1UL << 9))
{
Pclk >>= 1; // /2
}
while((Frequency * Div) <= Pclk)
{
Div += 2;
}
if (Div > 254)
{
Div = 254;
}
SSP1->PR = Div;
// Return real frequency
return(Pclk/Div);
}
/*************************************************************************
* Function Name: MP3_TranserByte
* Parameters: Int8U ch
* Return: Int16U
*
* Description: Read 8 bits from SPI
*
*************************************************************************/
static
Int16U MP3_TranserByte (Int8U ch)
{
SSP_SendData(SSP1, ch);
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_RxFifoNotEmpty) == RESET);
return(SSP_ReceiveData(SSP1));
}
/*************************************************************************
* Function Name: MP3_RxFifoDrain
* Parameters: void
*
* Return: void
*
* Description: Drain the RX FIFO
*
*************************************************************************/
static inline
void MP3_RxFifoDrain (void)
{
while (SSP_GetFlagStatus(SSP1, SSP_FLAG_RxFifoNotEmpty) == SET)
{
Int32U Dummy = SSP_ReceiveData(SSP1);
}
}
/*************************************************************************
* Function Name: MP3_WaitTxFifoEmptying
* Parameters: void
*
* Return: void
*
* Description: Wait emptying of the TX FIFO
*
*************************************************************************/
static inline
void MP3_WaitTxFifoEmptying (void)
{
while (SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoEmpty) == RESET);
}
/*************************************************************************
* Function Name: Mp3ModuleInit
* Parameters: Int32U DmaIntrPriority, Int32U DmaTimerIntrPriority
* Return: MP3_Status_t
* MP3_Pass, MP3_Fault or MP3_WrongRev, MP3_NotComm
*
* Description: Initialize MP3 module (VS1002)
*
*************************************************************************/
static inline
MP3_Status_t Mp3ModuleInit (Int32U DmaIntrPriority, Int32U DmaTimerIntrPriority)
{
SSP_InitTypeDef SSP_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
Int32U i;
// Initialize DMA
// Enable DMA clock
SCU_AHBPeriphClockConfig(__DMA , ENABLE);
// Reinitializes the DMA
SCU_AHBPeriphReset(__DMA, ENABLE);
// Release DMA reset
SCU_AHBPeriphReset(__DMA, DISABLE);
// Enable DMA module
DMA_Cmd(ENABLE);
DMA_SyncConfig(DMA_SSP1_RX_Mask | DMA_SSP1_TX_Mask, DISABLE);
// Clear pending interrupt
DMA_ClearIT(Channel6,DMA_TCC);
DMA_ClearIT(Channel6,DMA_EC);
// VIC configuration
VIC_Config(DMA_ITLine, VIC_IRQ, DmaIntrPriority);
VIC_ITCmd(DMA_ITLine, ENABLE);
Mp3TransferStatus = Mp3NotDataTransfer;
// Initialize SPI1 and IO
// Enable GPIO, SPI1 and Timer0/1 clock
SCU_APBPeriphClockConfig(__GPIO2 | __GPIO3 | __SSP1 | __TIM01, ENABLE);
// Reinitialize the SPI1
SCU_APBPeriphReset(__SSP1, ENABLE);
// Release GPIO, SPI1 and Timer 0/1 reset
SCU_APBPeriphReset(__GPIO2 | __GPIO3 | __SSP1 | __TIM01, DISABLE);
// APB peripheral clock disabled during ARM debug state
SCU_APBPeriphDebugConfig(__TIM01,DISABLE);
// Configure Boot select pin
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = MP3_BOOT_SEL;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
GPIO_Init (GPIO2, &GPIO_InitStructure);
// Configure MP3 Reset pin
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = MP3_RST;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
GPIO_Init (GPIO3, &GPIO_InitStructure);
// Configure MP3 CS pin
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = MP3_CS;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
GPIO_Init (GPIO2, &GPIO_InitStructure);
// Configure data request pin
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = MP3_DATA_RQ;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init (GPIO3, &GPIO_InitStructure);
// Configure SSP1_CLK, SSP1_MOSI pins
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = MP3_MOSI | MP3_SCLK;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2;
GPIO_Init (GPIO3, &GPIO_InitStructure);
// Configure SSP1_nSS pin
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
GPIO_Init (GPIO3, &GPIO_InitStructure);
GPIO_WriteBit(GPIO3,GPIO_Pin_7,Bit_SET);
// Configure SSP1_MISO pin
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = MP3_MISO;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init (GPIO3, &GPIO_InitStructure);
// Spi init
SSP_StructInit(&SSP_InitStructure);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low;
SSP_InitStructure.SSP_CPHA = SSP_CPHA_1Edge;
SSP_InitStructure.SSP_DataSize = SSP_DataSize_8b;
SSP_InitStructure.SSP_ClockRate = 0;
SSP_InitStructure.SSP_ClockPrescaler = 2;
SSP_Init(SSP1, &SSP_InitStructure);
// Disable DMA
SSP_DMACmd(SSP1,SSP_DMA_Transmit | SSP_DMA_Receive,DISABLE);
// Clock Freq <= 2MHz
MP3_SetClockFreq(MP3_CLK_FREQ);
// SSP1 enable
SSP_Cmd(SSP1, ENABLE);
// Deselect chip
MP3_ChipSelect(0);
// Timer 0
// VIC configuration
VIC_Config(TIM0_ITLine, VIC_IRQ, DmaTimerIntrPriority);
VIC_ITCmd(TIM0_ITLine, ENABLE);
// Deinitialization MP3 module (VS1002)
MP3_Reset(1);
Dly100us((void *)1);
MP3_Reset(0);
// Wait XRESET inactive to DREQ low (<= 400us)
for(i = 8;i;--i)
{
if (!MP3_DReq())
{
break;
}
Dly100us((void *)1);
}
if (!i)
{
MP3_RET(MP3_NotComm);
}
// Wait XRESET inactive to software ready (<= 4ms)
for(i = 80;i;--i)
{
if (MP3_DReq())
{
break;
}
Dly100us((void *)1);
}
if (!i)
{
MP3_RET(MP3_NotComm);
}
// Wait 100ms
Dly100us((void *)1000);
// Get the chip ID
Mp3SendCmd(Mp3CmdGetRevision,&i);
if (i != MP3_VS1002_REV)
{
MP3_RET(MP3_WrongRev);
}
// Init Clk
i = 0x9800; // 12.288MHz * 2
Mp3SendCmd(Mp3CmdSetClkReg,&i);
// Init Mode
// VS1002 native SPI modes, Share SPI chip select
i = 0x0C00 |
(MP3_STREAM_MODE_ENA?1UL<<6:0) | // Stream mode mode
(MP3_PLUS_V_ENA?1UL<<7:0); // +V mode
Mp3SendCmd(Mp3CmdSetModeReg,&i);
PlayFile = 0;
MP3_RET(MP3_Pass);
}
/*************************************************************************
* Function Name: Mp3InitDmaTransmit
* Parameters: pInt32U pData , Int32U Size, Boolean StreamMode,
* Boolean SrcAddInc, pDmaLli_t DmaLli
* Return: none
*
* Description: Init DMA transmit by SPI1
*
*************************************************************************/
static
void Mp3InitDmaTransmit(pInt32U pData , Int32U Size, Boolean StreamMode,
Boolean SrcAddInc, pDmaLli_t DmaLli)
{
#if MP3_STREAM_MODE_ENA > 0
DMA_InitTypeDef DMA_InitStructure;
MP3_ChipSelect(0);
if (StreamMode)
{
AddInc = SrcAddInc;
pMp3Data = (pInt8U)pData;
Mp3Size = Size;
Mp3TransferStatus = Mp3DataTransferProgress;
}
else
{
// set the flag DMA Transfer in progress
Mp3TransferStatus = Mp3DataTransferProgress;
// Enable SPI1 DMA transfer
SSP_DMACmd(SSP1,SSP_DMA_Transmit,ENABLE);
// Initialize DMA
DMA_InitStructure.DMA_Channel_SrcAdd = (Int32U)pData;
DMA_InitStructure.DMA_Channel_DesAdd = (Int32U)&SSP1->DR;
DMA_InitStructure.DMA_Channel_LLstItm = (Int32U)DmaLli;
DMA_InitStructure.DMA_Channel_DesWidth = DMA_DesWidth_Byte;
DMA_InitStructure.DMA_Channel_SrcWidth = DMA_SrcWidth_Byte;
DMA_InitStructure.DMA_Channel_DesBstSize = DMA_DesBst_4Data;
DMA_InitStructure.DMA_Channel_SrcBstSize = DMA_SrcBst_1Data;
// Transferred_byte = DMA_Channel_TrsfSize * SrcWidth [bytes],
// when DMA controlling data flow
DMA_InitStructure.DMA_Channel_TrsfSize = Size;
DMA_InitStructure.DMA_Channel_FlowCntrl = DMA_FlowCntrl1_DMA;
DMA_InitStructure.DMA_Channel_Src = 0x0;
DMA_InitStructure.DMA_Channel_Des = DMA_DES_SSP1_TX;
// the DMA Terminal Count interrupt enable
DMA_ITConfig(DMA_Channel6,ENABLE);
// Disable destination adders increment
DMA_ChannelDESIncConfig(DMA_Channel6,DISABLE);
// Disable/Enable source adders increment
DMA_ChannelSRCIncConfig(DMA_Channel6,(SrcAddInc?ENABLE:DISABLE));
// Unmask all interrupts
DMA_ITMaskConfig(DMA_Channel6,DMA_ITMask_ALL,ENABLE);
// Init channel
DMA_Init(DMA_Channel6,&DMA_InitStructure);
// Enable channel
DMA_ChannelCmd(DMA_Channel6,ENABLE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -