📄 ac97.c
字号:
}
/*------------------------------------------------------------
* InitSPORT0
*
* Parameters:
* None
*
* Globals Used:
* None
*
* Description:
* Initializes SPORT0 for AC-Link
*
* Returns:
* Nothing.
*
*------------------------------------------------------------*/
void InitSPORT0 (void)
{
SPORT0_TX_CONFIG_REG = 0;
asm("ssync;");
SPORT0_RX_CONFIG_REG = 0;
asm("ssync;");
SPORT0_MCMC1_REG = 0;
asm("ssync;");
SPORT0_IRQSTAT_RX_REG = kIRQSTAT_RX; //bits are cleared by writing 1s to this register
asm("ssync;");
SPORT0_IRQSTAT_TX_REG = kIRQSTAT_TX; //bits are cleared by writing 1s to this register
asm("ssync;");
// Set SPORT0 frame sync divisor rx
SPORT0_RFSDIV_REG = 0x00ff;// AC'97 48Khz Frame Sync with 12.288Mhz Input Clock
asm("ssync;");
// Set SPORT0 frame sync divisor tx
SPORT0_TFSDIV_REG = 0x00ff;// AC'97 48Khz Frame Sync with 12.288Mhz Input Clock
asm("ssync;");
SPORT0_RSCLKDIV_REG = 0x0005; // AC'97 48Khz Frame Sync with 12.288Mhz Input Clock???
asm("ssync;");
SPORT0_RX_CONFIG_REG = kRX_CFG;
asm("ssync;");
SPORT0_TX_CONFIG_REG = kTX_CFG;
asm("ssync;");
// Enable MCM Transmit and Receive Channels
SPORT0_MTCS0_REG = 0xFFFF; // Select 16 Channels for TX out of possibly 128
asm("ssync;");
SPORT0_MTCS1_REG = 0;
asm("ssync;");
SPORT0_MTCS2_REG = 0;
asm("ssync;");
SPORT0_MTCS3_REG = 0;
asm("ssync;");
SPORT0_MTCS4_REG = 0;
asm("ssync;");
SPORT0_MTCS5_REG = 0;
asm("ssync;");
SPORT0_MTCS6_REG = 0;
asm("ssync;");
SPORT0_MTCS7_REG = 0;
asm("ssync;");
SPORT0_MRCS0_REG = 0xFFFF; // Select 16 Channels for RX out of possibly 128
asm("ssync;");
SPORT0_MRCS1_REG = 0;
asm("ssync;");
SPORT0_MRCS2_REG = 0;
asm("ssync;");
SPORT0_MRCS3_REG = 0;
asm("ssync;");
SPORT0_MRCS4_REG = 0;
asm("ssync;");
SPORT0_MRCS5_REG = 0;
asm("ssync;");
SPORT0_MRCS6_REG = 0;
asm("ssync;");
SPORT0_MRCS7_REG = 0;
asm("ssync;");
// Set MCM Configuration Reg 1
SPORT0_MCMC1_REG = kMCMC1;
asm("ssync;");
// Set MCM Configuration Reg 2
SPORT0_MCMC2_REG = kMCMC2;
asm("ssync;");
}
/*------------------------------------------------------------
* InitSPORT0DMA
*
* Parameters:
* pTxBuffer - pointer to a 16byte buffer to hold transmit frame
* pRxBuffer - pointer to a 16bite buffer to hold the receive frame
*
* Globals Used:
* None
*
* Description:
* Sets up the SPORT0 DMA to use AC-Link
*
* Returns:
* Nothing
*
*------------------------------------------------------------*/
void InitSPORT0DMA (void *pTxBuffer, void *pRxBuffer)
{
// set autobuffer mode
SPORT0_CONFIG_DMA_TX_REG = kTxDAUTO;
asm("ssync;");
SPORT0_START_ADDR_LO_TX_REG = LOWORD ((ULONG)pTxBuffer);
asm("ssync;");
SPORT0_START_ADDR_HI_TX_REG = HIWORD ((ULONG)pTxBuffer);
asm("ssync;");
SPORT0_COUNT_TX_REG = FRAME_BUFFER_LEN >> 1;
asm("ssync;");
// SPORT0 DMA AUTOBUFFER RX
// set autobuffer mode
SPORT0_CONFIG_DMA_RX_REG = ZET(bRxDAUTO,1);
asm("ssync;");
SPORT0_START_ADDR_LO_RX_REG = LOWORD ((ULONG)pRxBuffer);
asm("ssync;");
SPORT0_START_ADDR_HI_RX_REG = HIWORD ((ULONG)pRxBuffer);
asm("ssync;");
SPORT0_COUNT_RX_REG = FRAME_BUFFER_LEN >> 1;
asm("ssync;");
// ENABLE SPORT0 DMA and DIRECTION IN DMA CONFIGURATION REGISTER
// Enable and configure TX DMA
SPORT0_CONFIG_DMA_TX_REG = kTX_DMA_CFG;
asm("ssync;");
// Enable and configure RX DMA
SPORT0_CONFIG_DMA_RX_REG = kRX_DMA_CFG;
asm("ssync;");
}
/*------------------------------------------------------------
* InitCodec
*
* Parameters:
*
* Globals Used:
* gpTxBuffer, gpRxBuffer, gInitCodecRegs, gCodecInitResults
*
* Description:
* This routine initializes the AC97 codec from the gInitCodecRegs
* array, and stores the register values read back in gCodecInitResults
*
* Returns:
* Nothing
*
*------------------------------------------------------------*/
void InitCodec (void)
{
USHORT regVal, currentReg, interruptCount;
//Enable SPORT0 RX
SPORT0_RX_CONFIG_REG |= ZET (bRxRSPEN, 1);
asm ("ssync;");
//Enable SPORT0 TX
SPORT0_TX_CONFIG_REG |= ZET (bTxTSPEN, 1); // Enable SPORT0 TX
asm ("ssync;");
// idle and ssync will put the processor
// in "idle state". The processor remains here until a peripheral or
// external device such as a SPORT or the RTC generates an interrupt
// that requires servicing.
asm ("idle;"); // Wait a few RX interrupts to ensure
asm ("ssync;"); // SPORT is up and running
asm ("idle;"); // Wait a few RX interrupts to ensure
asm ("ssync;"); // SPORT is up and running
//Wait for the codec to be ready
while (!(gpRxBuffer[0] & ZET(bCodecRdy, 1)))
{
asm ("idle;");
asm ("ssync;");
}
//Now initialize all the registers
gpTxBuffer[oTagPhase >> 1] = kVldFrm; //Don't say we've got anything until we've placed the data
for (currentReg = 0; currentReg < CODEC_REG_INIT_COUNT; currentReg++)
{
gpTxBuffer[oCmdAddrSlot >> 1] = gInitCodecRegs[currentReg * 2];
asm ("ssync;");
gpTxBuffer[oCmdDataSlot >> 1] = gInitCodecRegs[(currentReg * 2)+1];
asm ("ssync;");
//Now it's safe to say we've got address and data
gpTxBuffer[oTagPhase >> 1] = kVldFrm|kVldCmd|kVldAddr; //we've got commands coming in
asm ("ssync;");
asm ("idle;");
asm ("ssync;");
asm ("idle;");
asm ("ssync;");
asm ("idle;");
asm ("ssync;");
asm ("idle;");
asm ("ssync;");
interruptCount = gInterruptCount;
//Wait for at least one interrupt to be received
while (interruptCount == gInterruptCount)
{
asm ("idle;");
asm ("ssync;");
}
gpTxBuffer[oTagPhase >> 1] = kVldFrm; //Don't say we've got anything until we've placed the data
}
//Now read the values back...
gpTxBuffer[oTagPhase >> 1] = kVldFrm; //Don't say we've got anything until we've placed the data
for (currentReg = 0; currentReg < CODEC_REG_INIT_COUNT; currentReg++)
{
gpTxBuffer[oCmdAddrSlot >> 1] = gInitCodecRegs[currentReg * 2] | kAddrRead; //signal read request
asm ("ssync;");
//Now it's safe to say we've got address
gpTxBuffer[oTagPhase >> 1] = kVldFrm|kVldCmd; //we've got commands coming in
asm ("ssync;");
interruptCount = gInterruptCount;
//Wait for at least one interrupt to be received
while (interruptCount == gInterruptCount)
{
asm ("idle;");
asm ("ssync;");
}
//Now wait for the data
while ((!gpRxBuffer[0] & ZET(bCodecRdy, 1)) || (gpRxBuffer[oStatusAddrSlot>>1] != gInitCodecRegs[currentReg * 2]))
{
asm ("idle;");
asm ("ssync;");
}
//It's here
gCodecInitResults[currentReg] = gpRxBuffer[oStatusDataSlot >> 1];
gpTxBuffer[oTagPhase >> 1] = kVldFrm; //Don't say we've got anything until we've placed the data
}
//That's all folks!
return;
}
/*------------------------------------------------------------
* AC97_ISR
*
* Parameters:
* r0x, r1x, r2x
*
* Globals Used:
*
*
* Description:
* The ISR to handle SPORT0 DMA Tx and Rx interrupts.
*
* Returns:
* Nothing
*
*
*------------------------------------------------------------*/
EX_INTERRUPT_HANDLER (AC97_ISR)
{
//USHORT rxStat;
//rxStat = SPORT0_IRQSTAT_RX_REG;
//asm ("ssync;");
//txStat = SPORT0_IRQSTAT_TX_REG;
//asm ("ssync;");
// Clear RX and TX Interrupts
// (cleared by writing 1s to them)
//rxStat = SPORT0_IRQSTAT_RX_REG;
SPORT0_IRQSTAT_RX_REG = kIRQSTAT_RX;
asm ("ssync;");
//SPORT0_IRQSTAT_TX_REG = txStat;
//asm ("ssync;");
//if (((FRAME_BUFFER_LEN >> 1) - SPORT0_COUNT_RX_REG) == 0)
if ((FRAME_BUFFER_LEN >> 1) == SPORT0_COUNT_RX_REG)
//if (rxStat & ZET(bRxCOMPL,1))
{
gInterruptCount++;
if (gCurrentAC97State == AC97_STATE_PLAY_DATA)
{
//ToDo: Fetch data from the supplier,
//and put it into the TxBuffer
//
//gpTxBuffer[oTagPhase >> 1] = kVldFrm; //Don't say we've got anything until we've placed the data
gpTxBuffer[oLeft >> 1] = *(PUSHORT)(&gDataBuffer[gDataBufferTail]);
gDataBufferTail += 2;
//if (gDataBufferTail >= MAX_DATA_BUFFER_SIZE)
// gDataBufferTail = (gDataBufferTail - MAX_DATA_BUFFER_SIZE);
gpTxBuffer[oRght >> 1] = *(PUSHORT)(&gDataBuffer[gDataBufferTail]);
//gpTxBuffer[oTagPhase >> 1] = kVldFrm | kVldLeft | kVldRight;
gDataBufferTail += 2;
if (gDataBufferTail >= MAX_DATA_BUFFER_SIZE)
gDataBufferTail = (gDataBufferTail - MAX_DATA_BUFFER_SIZE);
}
}
}
/*----------------------------------------------------------------------------------
* $Log: ac97.c,v $
* Revision 1.5 2003/01/16 23:54:39 Devendra
* - The volume registers were not being set properly.
*
* Revision 1.4 2003/01/16 19:01:09 Devendra
* Changed "exported" function names to include AC97 prefix.
* Added routine to set volume and mute registers.
* Change the code af SPORT0 ISR to make it consume lesser DSP cycles.
*
* Revision 1.3 2003/01/15 01:33:20 Devendra
* - Changed code reset sequence to light all the LEDs on Eagle-35 after the codec has been reset.
*
* Revision 1.2 2003/01/13 19:57:53 Devendra
* Changed the priorities of interrupts - now SPORT0 is ivg7, USB is ivg8
* Other fixes with interrupt handling.
* Removed divides (used for modulo add) from the ISR
*
*
*---------------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -