📄 pcm.c
字号:
rINTMSK2|=(BIT_PCM0);
}
else
{
rPCM_CTL1 = 0;
rPCM_CLKCTL1 = 0;
rINTMSK2|=(BIT_PCM1);
}
PCM_DisableInt();
printf("\nEnd of Play!\n");
}
//memory : 16bit stereo continous expected(16bit mono left, first 16bit is available to play)
void PCM_PCMOutInt2(unsigned int uBufferAddr, unsigned int uPcmSize)
{
unsigned int uSclkDiv, uSyncDiv, uSclkSel;
unsigned int uTxMsbPos, uRxMsbPos;
bool bret;
//printf("\nListen to Sound via Speak Out Connector.\n");
//printf("Press any key to play.\n");
//getchar();
//init variable
g_PcmPlayDone =0;
g_uPcmBuffer32 = (unsigned int *) uBufferAddr;
g_uPcmEndBuffer32 = g_uPcmBuffer32 + uPcmSize/4;
//IRQ Initialization
PCM_ISRInit();
PCM_ClearInt();
PCM_SetInt(TXFIFO_ALMOST_EMPTY);
PCM_EnableInt();
//presetting
bret=PCM_GetClkValAndClkDir(&uSclkDiv, &uSyncDiv);
if(!bret)
{
printf("clock can not be made, exit");
return;
}
if(g_oPCMState.PCMClkSrc == PCM_PCLK)
uSclkSel = 1<<18;
else
uSclkSel = 0<<18;
{
double sclk;
double syncclk;
sclk = (double)PCLK /(2*( uSclkDiv+ 1) );
syncclk = sclk /( uSyncDiv+ 1 );
printf("Actural value\n\
Source_Clk : %f PCM_SCLK : %fKHz PCM_Syncclk: %fKHz\n",
(float)PCLK, sclk, syncclk);
}
if(g_oPCMState.PCMMSBPosition == AFTER_PCMSYNC_HIGH)
{
uTxMsbPos = TX_MSB_POS1;
uRxMsbPos = RX_MSB_POS1;
}
else if(g_oPCMState.PCMMSBPosition == DURING_PCMSYNC_HIGH)
{
uTxMsbPos = TX_MSB_POS0;
uRxMsbPos = RX_MSB_POS0 ;
}
//setting
if(g_oPCMState.PCMPort == PCM_PORT0)
{
rPCM_CLKCTL0 = ( PCM_SCLK_EN | uSclkSel | (uSclkDiv<<9) | (uSyncDiv<<0) ); //PCM Clock Setting
rPCM_CTL0= (TXFIFO_DIPSTICK(0x8) |uTxMsbPos |uRxMsbPos |PCM_TXFIFO_EN|PCM_PCM_ENABLE);//Transfer data enable
}
else
{
rPCM_CLKCTL1 = ( PCM_SCLK_EN | uSclkSel | (uSclkDiv<<9) | (uSyncDiv<<0) );
rPCM_CTL1= (TXFIFO_DIPSTICK(0x8) |uTxMsbPos |uRxMsbPos |PCM_TXFIFO_EN|PCM_PCM_ENABLE);
}
//playing
while(1)
{
if(g_PcmPlayDone)
break;
}
//stop
if(g_oPCMState.PCMPort == PCM_PORT0)
{
rPCM_CTL0 = 0;
rPCM_CLKCTL0 = 0;
}
else
{
rPCM_CTL1 = 0;
rPCM_CLKCTL1 = 0;
}
PCM_DisableInt();
PCM_ISRDeInit();
printf("\nEnd of Play!\n");
}
void PCM_ISRInit(void)
{
if(g_oPCMState.PCMPort == PCM_PORT0)
{
ClearPending2(BIT_PCM0);
pISR_PCM0 = (unsigned)Isr_PCM_PCMOut2;
rINTMSK2=~(BIT_PCM0);
}
else
{
ClearPending2(BIT_PCM1);
pISR_PCM1 = (unsigned)Isr_PCM_PCMOut2;
rINTMSK2=~(BIT_PCM1);
}
}
void PCM_ISRDeInit(void)
{
if(g_oPCMState.PCMPort == PCM_PORT0)
{
rINTMSK2|=(BIT_PCM0);
}
else
{
rINTMSK2|=(BIT_PCM1);
}
}
void PCM_ClearInt(void)
{
if(g_oPCMState.PCMPort == PCM_PORT0)
rPCM_CLRINT0 = CLRINT;
else
rPCM_CLRINT1 = CLRINT;
}
void PCM_EnableInt(void)
{
if(g_oPCMState.PCMPort == PCM_PORT0)
rPCM_IRQ_CTL0 |= EN_IRQ_TO_ARM;
else
rPCM_IRQ_CTL1 |= EN_IRQ_TO_ARM;
}
void PCM_DisableInt(void)
{
if(g_oPCMState.PCMPort == PCM_PORT0)
rPCM_IRQ_CTL0 &= ~EN_IRQ_TO_ARM;
else
rPCM_IRQ_CTL1 &= ~EN_IRQ_TO_ARM;
}
void PCM_SetInt(unsigned int ePcmInt)
{
if(g_oPCMState.PCMPort == PCM_PORT0)
rPCM_IRQ_CTL0 = (rPCM_IRQ_CTL0 & EN_IRQ_TO_ARM) | ePcmInt;
else
rPCM_IRQ_CTL1 = (rPCM_IRQ_CTL1 & EN_IRQ_TO_ARM) | ePcmInt;
}
//input :
// enable 1 : selected clock path open
// 0 : selected clock path close
void PCM_SelClkSrc(unsigned char ePort, unsigned char eClkSrc, bool enable)
{
//port0,1
if(eClkSrc == PCM_PCLK)
{
if(enable)
rPCLKCON |= (1<<19); // PCLK bus block of pcm(0&1) enable
else
rPCLKCON &= ~(1<<19);// PCLK bus block of pcm(0&1) disable
}
else//PCM_PCMCDCLK
{
if(enable)
{
printf("extclk clock gate open, port %d\n", ePort);
if(ePort == PCM_PORT0) rSCLKCON |= (1<<17); // bus block of pcm0 EXT Codec Clock enable
else if(ePort == PCM_PORT1) rSCLKCON |= (1<<18); // bus block of pcm0 EXT Codec Clock enable
}
else
{
printf("extclk clock gate close, port %d\n", ePort);
if(ePort == PCM_PORT0) rSCLKCON &= ~(1<<17); // bus block of pcm0 EXT Codec Clock disable
else if(ePort == PCM_PORT1) rSCLKCON &= ~(1<<18); // bus block of pcm0 EXT Codec Clock disable
}
}
}
//return : false - with current configuration impossible to make.
bool PCM_GetClkValAndClkDir(unsigned int* uSclkDiv, unsigned int* uSyncDiv)
{
#if 0
double dTmpVal, dVclkSrc;
double uTemp0,uTemp1,uTemp2,uTemp3,uTemp4,uTemp5;
if(g_oPCMState.PCMClkSrc == PCM_PCMCDCLK)
dVclkSrc = (double)g_oPCMState.EXTCDCLKFreq; //should be changed according to your system clock condition
else if(g_oPCMState.PCMClkSrc == PCM_PCLK)
dVclkSrc = (double)PCLK; //should be changed according to your system clock condition
uTemp1 = 1 / dVclkSrc;
uTemp2 = 1 /(double) g_oPCMState.PCMSClk;
uTemp3 = (18 * (double) g_oPCMState.PCMSClk) / 16;
uTemp4 = 1 / (uTemp1 + uTemp2);
// Calculate SCLK_DIV for PCMSCLK
if (g_oPCMState.PCMMSBPosition == DURING_PCMSYNC_HIGH)
dTmpVal = dVclkSrc/(double)(2*g_oPCMState.PCMSClk) - 1; //PCMSCLK = dvclksrc / (2 * usclkDiv +1)
else if (g_oPCMState.PCMMSBPosition == AFTER_PCMSYNC_HIGH)
//dTmpVal = dVclkSrc/(double)(2*(g_oPCMState.PCMSClk)) - 1; //PCMSCLK = dvclksrc / (2 * usclkDiv +1)
dTmpVal = dVclkSrc/(double)(2*(uTemp3)) - 1; //PCMSCLK = dvclksrc / (2 * usclkDiv +1)
dTmpVal = (dTmpVal+0.5)*10;
*uSclkDiv = (int)(dTmpVal/10.0);
// Calculate SYNC_DIV for PCMSYNC
if (g_oPCMState.PCMMSBPosition == DURING_PCMSYNC_HIGH)
dTmpVal = (double) g_oPCMState.PCMSClk/(double)(g_oPCMState.PCMSync) - 1; //PCMSYNC = PCMSCLK / (SYNC_DIV + 1)
else if (g_oPCMState.PCMMSBPosition == AFTER_PCMSYNC_HIGH)
//dTmpVal = (double) g_oPCMState.PCMSCLK/(double)( 128000/17) -1;
dTmpVal = (double) uTemp3/(double)( g_oPCMState.PCMSync) -1;
//dTmpVal = (double)(g_oPCMState.PCMSCLK)/(double)(g_oPCMState.PCM_FS) - 1;
dTmpVal = (dTmpVal+0.5)*10;
*uSyncDiv = (int)(dTmpVal/10.0);
#else
/* double dTmpVal, dVclkSrc;
// extern u32 g_MPLL, g_ARMCLK, g_HCLK, g_PCLK, g_MCLK;
if(g_oPCMState.PCMClkSrc == PCM_PCMCDCLK)
dVclkSrc = 512000;
else if(g_oPCMState.PCMClkSrc == PCM_PCLK)
dVclkSrc = g_PCLK; //should be changed according to your system clock condition
dTmpVal = dVclkSrc/(double)(2*g_oPCMState.PCMSCLK);
if (g_oPCMState.PCMMSBPosition == DURING_PCMSYNC_HIGH)
dTmpVal = (dTmpVal)*10;
else if (g_oPCMState.PCMMSBPosition == AFTER_PCMSYNC_HIGH)
dTmpVal = (dTmpVal + 0.5)*10;
*uSclkDiv = (int)(dTmpVal/10.0) - 1;
if (g_oPCMState.PCMMSBPosition == DURING_PCMSYNC_HIGH)
dTmpVal = g_oPCMState.PCMSCLK/(double)(g_oPCMState.PCM_FS);
else if (g_oPCMState.PCMMSBPosition == AFTER_PCMSYNC_HIGH)
dTmpVal = g_oPCMState.PCMSCLK/(double)(g_oPCMState.PCM_FS) + 1;
dTmpVal = (dTmpVal-0.5)*10;
*uSyncDiv = (int)(dTmpVal/10.0);
*/
//for after sync, 16 fs is not allowed.
double dTmpVal, dVclkSrc;
if(g_oPCMState.PCMClkSrc == PCM_PCMCDCLK)
dVclkSrc = (double)g_oPCMState.EXTCDCLKFreq; //should be changed according to your system clock condition
else if(g_oPCMState.PCMClkSrc == PCM_PCLK)
dVclkSrc = (double)PCLK; //should be changed according to your system clock condition
// Calculate SCLK_DIV for PCMSCLK
dTmpVal = dVclkSrc/(double)(2*g_oPCMState.PCMSClk) - 1; //PCMSCLK = dvclksrc / (2 * usclkDiv +1)
if(dTmpVal<0 || dTmpVal>511)return 0;
dTmpVal = (dTmpVal+0.5)*10;
*uSclkDiv = (int)(dTmpVal/10.0);
// Calculate SYNC_DIV for PCMSYNC
dTmpVal = (double) g_oPCMState.PCMSClk/(double)(g_oPCMState.PCMSync) - 1; //PCMSYNC = PCMSCLK / (SYNC_DIV + 1)
if(dTmpVal<0 || dTmpVal>511)return 0;
dTmpVal = (dTmpVal+0.5)*10;
*uSyncDiv = (int)(dTmpVal/10.0);
return 1;
#endif
}
///////////////////////////////////////////////
void __irq Isr_PCM_PCMIn_DMADone(void)
{
ClearPending(BIT_DMA);
printf("\nPCM In DMA Done.\n");
rSUBSRCPND=(BIT_SUB_DMA2);
g_PcmRecDone = 1;
}
void __irq Isr_PCM_PCMOut_DMADone(void)
{
rINTSUBMSK=~(BIT_SUB_DMA2);
rINTMSK = ~(BIT_DMA);
rSUBSRCPND=(BIT_SUB_DMA1);
ClearPending(BIT_DMA);
printf("\n~~~");
g_PcmPlayDone=1;
rINTMSK |= (BIT_DMA);
rINTSUBMSK |=(BIT_SUB_DMA2);
}
void __irq Isr_PCM_Interrupt(void)
{
unsigned int i, uPcmFifoStat;
int testreg;
if(g_oPCMState.PCMPort == PCM_PORT0)
{
rINTMSK2|=(BIT_PCM0);
g_pcmirqstat[g_interrupt_cnt].irqstat1 = rPCM_IRQ_STAT0;
if(rPCM_IRQ_CTL0 & RXFIFO_FULL) testreg = rPCM_RXFIFO0;
else if(rPCM_IRQ_CTL0 & RXFIFO_ALMOST_FULL) testreg = rPCM_RXFIFO0;
if(rPCM_IRQ_CTL0 & RXFIFO_EMPTY) rPCM_RXFIFO0=0x1111;
else if(rPCM_IRQ_CTL0 & RXFIFO_ALMOST_EMPTY) rPCM_RXFIFO0=0x1111;
// if(rPCM_IRQ_CTL0 & TXFIFO_FULL) testreg = rPCM_TXFIFO0;
// else if(rPCM_IRQ_CTL0 & TXFIFO_ALMOST_FULL) testreg = rPCM_TXFIFO0;
if(rPCM_IRQ_CTL0 & TXFIFO_EMPTY) rPCM_TXFIFO0=0x1111;
else if(rPCM_IRQ_CTL0 & TXFIFO_ALMOST_EMPTY) rPCM_TXFIFO0=0x1111;
PCM_ClearInt();
g_pcmirqstat[g_interrupt_cnt].irqstat2 = rPCM_IRQ_STAT0;
g_interrupt_cnt++;
printf("interrupt occured\n");
if(g_interrupt_cnt>=PCM_IRQ_STAT_MAX) PCM_DisableInt();
ClearPending2(BIT_PCM0);
rINTMSK2&=~(BIT_PCM0);
}
else
{
rINTMSK2|=(BIT_PCM1);
g_pcmirqstat[g_interrupt_cnt].irqstat1 = rPCM_IRQ_STAT1;
if(rPCM_IRQ_CTL1 & RXFIFO_FULL) testreg = rPCM_RXFIFO1;
else if(rPCM_IRQ_CTL1 & RXFIFO_ALMOST_FULL) testreg = rPCM_RXFIFO1;
if(rPCM_IRQ_CTL1 & RXFIFO_EMPTY) rPCM_RXFIFO1=0x1111;
else if(rPCM_IRQ_CTL1 & RXFIFO_ALMOST_EMPTY) rPCM_RXFIFO1=0x1111;
// if(rPCM_IRQ_CTL1 & TXFIFO_FULL) testreg = rPCM_TXFIFO1;
// else if(rPCM_IRQ_CTL1 & TXFIFO_ALMOST_FULL) testreg = rPCM_TXFIFO1;
if(rPCM_IRQ_CTL1 & TXFIFO_EMPTY) rPCM_TXFIFO1=0x1111;
else if(rPCM_IRQ_CTL1 & TXFIFO_ALMOST_EMPTY) rPCM_TXFIFO1=0x1111;
PCM_ClearInt();
g_pcmirqstat[g_interrupt_cnt].irqstat2 = rPCM_IRQ_STAT1;
g_interrupt_cnt++;
printf("interrupt occured\n");
if(g_interrupt_cnt>=PCM_IRQ_STAT_MAX) PCM_DisableInt();
ClearPending2(BIT_PCM1);
rINTMSK2&=~(BIT_PCM1);
}
}
void __irq Isr_PCM_InterruptTEST(void)
{
unsigned int i, uPcmFifoStat;
int testreg;
if(g_oPCMState.PCMPort == PCM_PORT0)
{
rINTMSK2|=(BIT_PCM0);
g_pcmirqstat[g_interrupt_cnt].irqstat1 = rPCM_IRQ_STAT0;
if(rPCM_IRQ_CTL0 & RXFIFO_FULL) testreg = rPCM_RXFIFO0;
else if(rPCM_IRQ_CTL0 & RXFIFO_ALMOST_FULL) testreg = rPCM_RXFIFO0;
if(rPCM_IRQ_CTL0 & RXFIFO_EMPTY) rPCM_RXFIFO0=0x1111;
else if(rPCM_IRQ_CTL0 & RXFIFO_ALMOST_EMPTY) rPCM_RXFIFO0=0x1111;
if(rPCM_IRQ_CTL0 & TXFIFO_FULL) te
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -