📄 i2saudio.cpp
字号:
//
// 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_GSR & GSR_TX0_FIFO_HALF_EMPTY))
{
if(ulCount2++>10000000)
{
*SAI_GSR = 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::WriteCodecReg(UCHAR ucRegAddr, UCHAR ucRegValue)
{
ULONG ulSPIStatus;
ULONG ulTimeOut;
#ifdef CS4288_TWO_READ_MODE
if( m_bTwoWire )
{
return WriteCodecRegNOSPI( ucRegAddr, ucRegValue);
}
else
#endif
{
// 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
));
}
}
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(unsigned long ulCodec)
{
#if (EP93XX_PLATFORM_TYPE== EDB9307) || (EP93XX_PLATFORM_TYPE== EDB9312) || (EP93XX_PLATFORM_TYPE== EDB9315)
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 ;
#endif
if(ulCodec == 4228)
{
//
// Configure EGPIO7 as an output and set it. This selects
// I2S codec as the device on the SSP output instead of
// the serial flash (on an EP9312).
//
HalWriteCommonReg(GPIO_PADDR,0x80,0x80);
HalWriteCommonReg(GPIO_PADR,0x80,0x80);
//
// Configure EGPIO8 as an output and set it. This selects
// I2S codec as the device on the SSP output (on an EP9315 & EP9307).
//
HalWriteCommonReg(GPIO_PBDDR,0x1,0x1);
HalWriteCommonReg(GPIO_PBDR,0x1,0x0);
}
if(ulCodec == 4271)
{
//
// Configure EGPIO6 as an output and set it. This selects
// I2S codec as the device on the SSP (on an EP9301).
//
HalWriteCommonReg(GPIO_PADDR,0x40,0x40);
HalWriteCommonReg(GPIO_PADR,0x40,0x00);
}
//
// 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(unsigned long ulCodec)
{
#if (EP93XX_PLATFORM_TYPE== EDB9307) || (EP93XX_PLATFORM_TYPE== EDB9312) || (EP93XX_PLATFORM_TYPE== EDB9315)
ULONG ulTemp;
//
// Clear GPIO pins 12 and 14.
ulTemp = *GPIO_PBDR;
*GPIO_PBDR = (~0x50) & ulTemp ;
#endif
if(ulCodec == 4228)
{
//
// Clear EGPIO7. This de-selects
// I2S codec as the device on the SSP output (on an EP9312).
//
HalWriteCommonReg (GPIO_PADDR,0x80,0x00);
HalWriteCommonReg(GPIO_PADR,0x80,0x00);
//
// Set EGPIO8. This de-selects I2S codec as the device on the SSP
// output (on an EP9315 & EP9307).
//
HalWriteCommonReg(GPIO_PBDDR,0x1,0x1);
HalWriteCommonReg(GPIO_PBDR,0x1,0x1);
}
if(ulCodec == 4271)
{
//
// Clear EGPIO6. This de-selects I2S codec as the device on the SSP
// output (on an EP9301).
//
HalWriteCommonReg(GPIO_PADDR,0x40,0x00);
HalWriteCommonReg(GPIO_PADR,0x40,0x40);
}
//
// 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;
}
void I2SReset( void )
{
HalWriteCommonReg
(
CSC_DEVCFG,
DEVCFG_I2SONSSP | DEVCFG_I2SONAC97,
DEVCFG_I2SONAC97
);
//
// Disable all transmit audio channels.
// Disable all recieve audio channels.
// Set the global configuration register to Disable PCLK to it.
//
*SAI_TX0_EN = *SAI_TX1_EN =* SAI_TX2_EN = 0;
*SAI_RX0_EN = *SAI_RX1_EN =* SAI_RX2_EN = 0;
*SAI_GCR = 0;
//
// Initialize the SAI interface.
//
*SAI_TX_CLKCFG = CLKCFG_MST | CLKCFG_TREL ; //the right-left channel is reversed if setting this bit.
// *SAI_TX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_POLARITY;
// *SAI_RX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_NBCG | CLKCFG_POLARITY;
*SAI_RX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_NBCG ;
//
// Left justified, MSB first, Repeat zero if underflow.
// Outputing zero's will cause the dac to mute.
//
// *SAI_TX_LCR = TX_LCR_UNDERFLOW_ZERO;
*SAI_TX_LCR = 0;
//
// Generate a Interrupt on Halfempty
// (Don't think this makes a difference for DMA.)
//
*SAI_TX_CR = TX_CR_TXUFIE;
//
// Transmit word length. I don't think this matters in Left Justified
// mode.
//
*SAI_TX_WL = WL_24BIT;
//
// Left justified, MSB first.
//
*SAI_RX_LCR = 0;
//
// Generate a Interrupt on Half full
// (Don't think this makes a difference for DMA.)
//
*SAI_RX_CR = RX_CR_OVERFLOW_INT;
//
// Receive word length. I don't think this matters in Left Justified
// mode.
//
*SAI_RX_WL = WL_24BIT;
//
// Set the global configuration register to enable PCLK to it.
//
*SAI_GCR = GCR_PCLK;
*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;
}
#define ZONE_MIXER 1
DWORD I2SCodec:: MixerVolumeSettings( DWORD dwCode ,DWORD dwControl, DWORD dwSetting)
{
DWORD *pdwSetting=(DWORD *)dwSetting;
DWORD dwRet= MMSYSERR_NOERROR;
if( dwCode == WPDM_GETMIXERVAL )
{
switch (dwControl) {
case WPDMX_MASTER_VOL:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MASTER_VOL\r\n")));
*pdwSetting=m_VolumeSettings.dwMasterVolume;
break;
case WPDMX_MASTER_MUTE:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MASTER_MUTE\r\n")));
*pdwSetting = m_VolumeSettings.fMasterMute;
break;
case WPDMX_LINEIN_VOL:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_LINEIN_VOL\r\n")));
*pdwSetting = m_VolumeSettings.dwLineInVolume;
break;
case WPDMX_LINEIN_MUTE:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_LINEIN_MUTE\r\n")));
*pdwSetting = m_VolumeSettings.fLineInMute;
break;
case WPDMX_MIC_VOL:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MIC_VOL\r\n")));
*pdwSetting = m_VolumeSettings.dwMicVolume;
break;
case WPDMX_MIC_MUTE:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MIC_MUTE\r\n")));
*pdwSetting = m_VolumeSettings.fMicMute;
break;
case WPDMX_INPUT_MUX:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_INPUT_MUX\r\n")));
*pdwSetting = m_VolumeSettings.dwInputSelect;
break;
default:
RETAILMSG(1, (TEXT("private_GetMixerValue: unrecognized control %d"), dwControl));
dwRet= MMSYSERR_NOTSUPPORTED;
break;
}
RETAILMSG(1, (TEXT("private_GetMixerValue(%04x, %08x)\r\n"), dwControl, *pdwSetting));
}
else if( dwCode == WPDM_SETMIXERVAL )
{
//ULONG ulRight, ulLeft;
RETAILMSG(1, (TEXT("private_SetMixerValue(%04x, %08x)\r\n"), dwControl, dwSetting));
switch (dwControl) {
// volume controls
case WPDMX_MASTER_VOL:
SetVolume( dwSetting>>16 , dwSetting&0xFFFF, 0 );
m_VolumeSettings.dwMasterVolume =dwSetting;
break;
case WPDMX_LINEIN_VOL:
m_Volum
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -