📄 i2saudio.cpp
字号:
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE data line low. Since the EE clock line is currently
// high, this is the repeated start condition.
//
uiVal &= ~GPIOG_EEDAT;
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE clock low.
//
uiVal &= ~GPIOG_EECLK;
*GPIO_PGDR = uiVal;
//
// Re-send the address. Loop through the 8 bits in this byte.
//
ucData = (UCHAR)(CS4228_DEV_ADDRESS | 1);
for(ucBit = 0; ucBit < 8; ucBit++)
{
//
// Set the EE data line to correspond to the most significant bit of
// the data byte.
//
if(ucData & 0x80)
{
uiVal |= GPIOG_EEDAT;
}
else
{
uiVal &= ~GPIOG_EEDAT;
}
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE clock line high.
//
*GPIO_PGDR = uiVal | GPIOG_EECLK;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE clock line low.
//
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Shift the data byte to the left by one bit.
//
ucData <<= 1;
}
//
// We've sent the eight bits in this data byte, so we need to wait for the
// acknowledge from the target. Reconfigure the EE data line as an input
// so we can read the acknowledge from the device.
//
uiDDR &= ~GPIOG_EEDAT;
*GPIO_PGDDR = uiDDR;
//
// Drive the EE clock line high.
//
*GPIO_PGDR = uiVal | GPIOG_EECLK;
//
// Wait until the EE data line is pulled low by the target device.
//
ulTimeout = 0;
while(*GPIO_PGDR & GPIOG_EEDAT)
{
DelayuS( EE_DELAY_USEC );
ulTimeout++;
if(ulTimeout > EE_READ_TIMEOUT )
{
ERRMSG
((
L"I2SCodec::ReadCodecReg Read timeout on register 0x%02x\r\n",
(ULONG)ucRegAddr
));
return (MMSYSERR_HANDLEBUSY);
}
}
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE clock line low.
//
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Now read the value from the target. Loop through the 8 bits in the
// byte.
//
ucData = 0;
for(ucBit = 0; ucBit < 8; ucBit++)
{
//
// Drive the EE clock line high.
//
*GPIO_PGDR = uiVal | GPIOG_EECLK;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Read this bit from the target.
//
if(*GPIO_PGDR & GPIOG_EEDAT)
{
ucData = (UCHAR)( ucData | (1 << (7 - ucBit)) );
}
//
// Drive the EE clock line low.
//
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
}
//
// Reconfigure the EE data line as an output.
//
uiDDR |= GPIOG_EEDAT;
*GPIO_PGDDR = uiDDR;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE data line low.
//
uiVal &= ~GPIOG_EEDAT;
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE clock line high.
//
uiVal |= GPIOG_EECLK;
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Drive the EE data line high.
//
uiVal |= GPIOG_EEDAT;
*GPIO_PGDR = uiVal;
//
// Delay to meet the EE Interface timing specification.
//
DelayuS( EE_DELAY_USEC );
//
// Return the byte that we read.
//
*pucRegValue = ucData;
FUNC_I2S
(
(
L"ReadCodecReg: Reg = 0x%02x, Value = 0x%02x\n",
(ULONG)ucRegAddr,
(ULONG)ucData
)
);
return (MMSYSERR_NOERROR);
}
static volatile ULONG ulJunk;
//****************************************************************************
// I2SCodec::ProducePIOTone
//****************************************************************************
// For Debug only.
//
// Uses I2S to produce a PIO tone.
//
//
void I2SCodec::ProducePIOTone(void)
{
ULONG ulCount;
ULONG ulCount2;
volatile ULONG ulTemp;
//volatile ULONG ulCSR;
ULONG ulMax= 0x0007Fffff, ulMin=0x00800000;
//
// Enable the I2S transmitt channel 0.
//
*SAI_TX0_EN = 1;
Sleep(1);
ulCount2 = 0;
ulTemp = 0x800000;
for(ulCount = 0; ;ulCount ++)
{
if(ulCount& 0x40)
{
ulTemp = ulMax;
}
else
{
ulTemp = ulMin;
}
ulJunk = *SAI_TX0_LEFT;
ulJunk = *SAI_TX0_RIGHT;
//while( *SAI_CSR & TX0_FIFO_FULL);
while(!( *SAI_CSR & TX0_FIFO_HALF_EMPTY))
{
if(ulCount2++>10000000)
{
*SAI_CSR = 0;
Initialize();
*SAI_TX0_EN = 1;
Sleep(1);
break;
}
};
*SAI_TX0_LEFT = ulTemp;
*SAI_TX0_RIGHT = ulTemp;
}
}
//****************************************************************************
// I2SCodec::ReadAllCodecReg
//****************************************************************************
// For Debug only.
//
// Reads all of the I2C registers.
void I2SCodec::ReadAllCodecReg(void)
{
UCHAR ucCodecReg, ucValue;
for(ucCodecReg = 1; ucCodecReg < 0xE; ucCodecReg++)
{
ReadCodecReg(ucCodecReg, &ucValue);
}
}
//****************************************************************************
// DelayuS
//****************************************************************************
// Delays a certian number of microseconds.
//
//
void DelayuS(ULONG ulMicroSec)
{
LARGE_INTEGER liStart, liCurrent;
BOOL b;
b = QueryPerformanceCounter(&liStart);
ASSERT(b);
do
{
Sleep(0);
b = QueryPerformanceCounter(&liCurrent);
ASSERT(b);
} while((liStart.QuadPart + (LONGLONG)ulMicroSec) >=liCurrent.QuadPart);
}
//****************************************************************************
// I2SCodec::WriteCodecSPI
//****************************************************************************
// Writes a codec register using SPI.
//
//
MMRESULT I2SCodec::WriteCodecRegSPI(UCHAR ucRegAddr, UCHAR ucRegValue)
{
ULONG ulSPIStatus;
ULONG ulTimeOut;
// ulADR = *GPIO_PADR;
// *GPIO_PADR = ulADR | 0x80;
//
// Wait for the the fifo to be empty.
//
for(ulTimeOut = 0;;ulTimeOut++)
{
ulSPIStatus = *SPI_SR;
if(ulSPIStatus & SPISR_TFE)
break;
Sleep(2);
if(ulTimeOut >50)
{
ERRMSG
((
L"I2SCodec::WriteCodecSSP Write timeout on register 0x%02x\r\n",
(ULONG)ucRegAddr
));
}
}
//
// Write out the chip address for the CS4228.
//
*SPI_DR = 0x20;
*SPI_DR = (ULONG)ucRegAddr;
*SPI_DR = (ULONG)ucRegValue;
//
// Wait for the the fifo to be empty.
//
for(ulTimeOut = 0;;ulTimeOut++)
{
ulSPIStatus = *SPI_SR;
Sleep(2);
if(ulSPIStatus & SPISR_TFE)
break;
if(ulTimeOut >50)
{
ERRMSG
((
L"I2SCodec::WriteCodecSSP Write timeout on register 0x%02x\r\n",
(ULONG)ucRegAddr
));
}
}
// *GPIO_PADR = ulADR & ~0x80;
//Sleep(0);
return (MMSYSERR_NOERROR);
}
//****************************************************************************
// SetSPIToI2S
//****************************************************************************
// This is currently a hack to get audio working on the Videon Central
// board. I need to fix this later.
//
//
void SetSPIToI2S(void)
{
ULONG ulTemp;
//
// Set GPIO pins 12 and 14 as outputs. They are used in the ps2 keyboard
// interface.
//
ulTemp = *GPIO_PBDDR;
*GPIO_PBDDR = 0x50 | ulTemp;
//
// Clear GPIO pins 12 and 14.
//
ulTemp = *GPIO_PBDR;
*GPIO_PBDR = 0x50 | ulTemp ;
//
// Sleep a couple Milliseconds. Hopefully the keyboard will get
// any characters in the fifo.
//
Sleep(2);
//
// SPICR0_SPO - SCLKOUT Polarity
// SPICR0_SPH - SCLKOUT Phase
// Motorola format, 10 bit, one start, 8 data, one bit for parity,
// one stop bit.
//
*SPI_CR0 = SPICR0_SPO| SPICR0_SPH |SPICR0_FRF_MOTOROLA |
(SPICR0_DSS_MASK & (8 -1));
//
// Configure the device as a slave, enable interrupts and
// reset the device.
//
*SPI_CR1 = 0;
*SPI_CR1 = SPICR1_SSE;
}
//****************************************************************************
// SetSPIToPS2
//****************************************************************************
// This is currently a hack to get audio working on the Videon Central
// board. I need to fix this later.
//
//
void SetSPIToPS2(void)
{
ULONG ulTemp;
//
// Clear GPIO pins 12 and 14.
//
ulTemp = *GPIO_PBDR;
*GPIO_PBDR = (~0x50) & ulTemp ;
//
// SPICR0_SPO - SCLKOUT Polarity
// SPICR0_SPH - SCLKOUT Phase
// Motorola format, 10 bit, one start, 8 data, one bit for parity,
// one stop bit.
//
*SPI_CR0 = SPICR0_SPO| SPICR0_SPH |SPICR0_FRF_MOTOROLA |
(SPICR0_DSS_MASK & (11 -1));
//
// Configure the device as a slave, enable interrupts and
// reset the device.
//
*SPI_CR1 = SPICR1_MS | SPICR1_RIE;
*SPI_CR1 = SPICR1_MS | SPICR1_RIE | SPICR1_SSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -