📄 lib_audio.c
字号:
/*************************************** Copyright (c) *************************************************
*
* POLAR STAR
* 北天星国际有限公司
* http://www.po-star.com
*
*文 件 名: lib_audio.c
*
*编译环境:ADS1.2
*
********************************************************************************************************/
#include "main.h"
#include "lib_audio.h"
#define DELAY 100000
AT91PS_WaveHeaderDESC sdram_file = (AT91PS_WaveHeaderDESC)AT91C_ATMEL_WAVE;
AT91PS_SSC pSSC = AT91C_BASE_SSC0;
//*----------------------------------------------------------------------------
//* \fn AT91F_SPI_CfgSPI
//* \brief Config SPI for 1MHz on NPCS0
//*----------------------------------------------------------------------------
void AT91F_SPI1_CfgSPI(void)
{
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOB, // PIO controller base address
((unsigned int) AT91C_PB1_SPI1_MOSI) |
((unsigned int) AT91C_PB3_SPI1_NPCS0) |
((unsigned int) AT91C_PB0_SPI1_MISO) |
((unsigned int) AT91C_PB2_SPI1_SPCK), // Peripheral A
0); // Peripheral B
// Configure PMC by enabling SSC1 clock
AT91F_SPI1_CfgPMC();
// Reset the SPI
AT91F_SPI_Reset(AT91C_BASE_SPI1);
// Configure SPI in Master Mode
AT91F_SPI_CfgMode(AT91C_BASE_SPI1, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | (AT91C_SPI_PCS0_AUDIODAC << 16) );
// Configure SPI NPCS03
AT91F_SPI_CfgCs(AT91C_BASE_SPI1, 0, AT91C_SPI_BITS_16 | (AT91C_SPI_DLYBS & 0x100000) |
((AT91C_MASTER_CLOCK_FOR_I2S / AT91C_SPI_CLK_AUDIODAC) << 8));
// Enable the SPI
AT91F_SPI_Enable(AT91C_BASE_SPI1);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_SpiWrite
//* \brief Set the PDC registers for a transfer
//*----------------------------------------------------------------------------
void AT91F_SpiWrite (unsigned short *rx_buf, unsigned short *tx_buf, int size)
{
int i;
for(i=0;i<size;i++)
{
AT91C_BASE_SPI1->SPI_TDR = *tx_buf++;
while((AT91C_BASE_SPI1->SPI_SR & AT91C_SPI_RDRF) != AT91C_SPI_RDRF);
*rx_buf++ = AT91C_BASE_SPI1->SPI_RDR;
}
}
//*----------------------------------------------------------------------------
//* \fn AT91F_InitDrivers
//* \brief This function initializes AIC and SSC1 in I2S mode
//*----------------------------------------------------------------------------
void AT91F_InitDrivers()
{
int tmp;
// ======================= Init SPI and at73c213 DAC ==========================
// Init PLLA to 11.289MHz x 8 = 90.316MHz
/* AT91C_BASE_CKGR->CKGR_PLLAR = (1<<29) | AT91C_CKGR_OUTA_0 | AT91C_CKGR_PLLACOUNT |\
(AT91C_CKGR_MULA & (548<<16)) | (AT91C_CKGR_DIVA & 112); // 90.349 MHz
// Wait for PLL stabilization LOCK bit in PMC_SR
tmp = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA) && (tmp++ < DELAY) );
*/
// Init PCK0 to PLLA/8 = 11.289MHz
AT91F_PIOC_CfgPMC();
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOC, 0, AT91C_PC1_PCK0);
// AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, AT91C_PMC_PCK0);
AT91F_PMC_EnablePCK(AT91C_BASE_PMC, 0, AT91C_PMC_CSS_PLLA_CLK | AT91C_PMC_PRES_CLK_8);
// Select PLLA/2 for MCK to be synchronous with SSC
// bit clock will be 11.289MHz/8 = 1.411MHz
// FS freq will be 11.289/256 = 44.097 kHz
/* AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_PLLA_CLK | AT91C_PMC_PRES_CLK_2;
// Wait until Master Clock is established
tmp = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY) );
// Reinit SDRAM
AT91F_InitSDRAM(AT91C_MASTER_CLOCK_FOR_I2S);
// Reinit DBGU
AT91F_Configure_DBGU (AT91C_MASTER_CLOCK_FOR_I2S);
*/
// Configure SPI clock
AT91F_SPI1_CfgSPI();
// Configure DAC
// Write @0x10 => 0x00
// Write @0x10 => 0x03 (deassert the reset)
// Write @0x00 => 0x30 (precharge + master on)
// Delay 500 ms
// Write @0x0C => 0x01 (precharge off + master on)
// Write @0x00 => 0x3c (ONLNOL and ONLONOR set to 1)
// Write/read each register
{
unsigned short txbuf[18] = {0x1000,0x1003,0x0030};
unsigned short rxbuf[18];
int tempo = 10000000;
int i;
for (i=0;i<16;i++) rxbuf[i] = 0x0;
AT91F_SpiWrite(rxbuf,txbuf,3);
while(tempo--);
txbuf[0] = 0x0c01;
txbuf[1] = 0x8cff;
AT91F_SpiWrite(rxbuf,txbuf,1);
txbuf[0] = 0x003c;
txbuf[1] = 0x80ff;
AT91F_SpiWrite(rxbuf,txbuf,1);
txbuf[0] = 0x0a00;
txbuf[1] = 0x8aff;
AT91F_SpiWrite(rxbuf,txbuf,1);
// Read all regs
for (i=0;i<18;i++) rxbuf[i] = 0x0;
for (i=0;i<18;i++) txbuf[i] = 0x80ff + (i<<8);
AT91F_SpiWrite(rxbuf,txbuf,18);
rxbuf[0] = txbuf[0];
}
// ======================= Init SSC in I2S mode ==========================
// Configure SSC0 PIOs
AT91F_PIO_CfgPeriph(
AT91C_BASE_PIOB, // PIO controller base address
((unsigned int) AT91C_PB16_TK0 ) |
((unsigned int) AT91C_PB18_TD0 ) |
((unsigned int) AT91C_PB17_TF0 ), // Peripheral A
0); // Peripheral B
// AT91F_SSC0_CfgPIO();
// Configure PMC by enabling SSC0 clock
AT91F_SSC0_CfgPMC();
// Configure SSC in I2S mode
AT91F_SSC_Configure (pSSC, // \arg pointer to a SSC controller
AT91C_MASTER_CLOCK_FOR_I2S, // \arg master clock
AT91C_WAV_FILE_SAMPLING_FREQ*(AT91C_I2S_NB_BITS_BY_SLOT*AT91C_I2S_NB_SLOT_BY_FRAME), // \arg baudrate
0,
0,
AT91C_I2S_ASY_MASTER_TX_SETTING(AT91C_I2S_NB_BITS_BY_SLOT, AT91C_I2S_NB_SLOT_BY_FRAME),
AT91C_I2S_ASY_TX_FRAME_SETTING(AT91C_I2S_NB_BITS_BY_SLOT, AT91C_I2S_NB_SLOT_BY_FRAME)
); // End of SSC_Configure function
// Disable PDC Rx and Tx
AT91F_PDC_DisableTx ((AT91PS_PDC) &(pSSC->SSC_RPR));
AT91F_PDC_DisableRx ((AT91PS_PDC) &(pSSC->SSC_RPR));
// Enable Transmit
AT91F_SSC_EnableTx (pSSC);
// Disable all interrupts
AT91F_SSC_DisableIt (pSSC, 0xFFFFFFFF);
// Configure AIC controller to handle SSC interrupts
AT91F_AIC_ConfigureIt (
AT91C_BASE_AIC, // AIC base address
AT91C_ID_SSC0, // System peripheral ID
AT91C_IRQ_LEVEL_I2S, // Max priority
AT91C_AIC_SRCTYPE_EXT_HIGH_LEVEL, // Level sensitive
AT91F_ASM_I2S_Init_Handler );
// Enable SSC interrupt in AIC
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SSC0);
// Enable Interrupt
AT91F_SSC_EnableIt (pSSC, AT91C_SSC_TXSYN);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_CloseDrivers
//* \brief This function Close SSC1 in I2S mode and the AIC
//*----------------------------------------------------------------------------
void AT91F_CloseDrivers()
{
// Disable Interrupt
AT91F_SSC_DisableIt (pSSC, 0xFFFFFFFF);
// Disable SSC interrupt in AIC
AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_SSC0);
// Disable Transmit
AT91F_SSC_DisableTx (pSSC);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_TestAudio
//* \brief
//*----------------------------------------------------------------------------
int AT91F_TestAudio()
{
volatile unsigned int dummy;
char message[1];
// Wait message is displayed
for (dummy = 0; dummy < 5000000; dummy++);
// Init I2S
AT91F_InitDrivers();
AT91F_DBGU_Printk("\n\r-I- Step 11. SSC/I2S Stereo Audio DAC\n\r");
AT91F_DBGU_Printk("-I- Press a key to stop the test...\n\r");
message[0] = AT91F_Wait4KeyPressed();
AT91F_CloseDrivers();
AT91F_DBGU_Printk("\r\n");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -