?? hssi.c
字號:
SSICR_TX.bits.DEL = 1; // Serial Data no Delay
SSICR_TX.bits.BREN = 0; // Burst Mode Disable
SSICR_TX.bits.CKDV = 3; // Serial Oversample Clock Divide Ratio
SSICR_TX.bits.MUEN = 0; // Mute disable
SSICR_TX.bits.CPEN = 0; // Compress mode disable
SSICR_TX.bits.TRMD = 1; // Transmit mode
SSICR_TX.bits.EN = 0; // SSI Disable
RegValue = SSICR_TX.AsDWORD;
WRITE_REGISTER_ULONG(pSSI_CR_TX, RegValue);
}
data_count = 0;
FUNC_WPDD("-hssi_txstart");
return;
}
/*****************************************************************************
* FUNCTION : module_rxstart
* DESCRIPTION : HSSI Rx Start
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
VOID
module_rxstart(
VOID
)
{
ULONG RegValue;
unsigned char DSPmaster[5][2] = {
//{Register Pointer, Value}
{CODEC_CMB, 0x00}, //*0:(01h)Clock Mode Byte(CO1乣CO0,CI1乣CI0)
// if 11.025kHz then ch0:0x52,ch1:0x50,ch2/3:0x40
{CODEC_DSP_PMB, 0xe8}, //*1:(0Eh)DSP Port Mode Byte(DCK1乣DCK0,DSCK)
// slave:0xc8,master:0xe8
{CODEC_APMB, 0xe8}, //*2:(0Fh)Auxiliary Port Mode Byte(ACK1乣ACK0,AMS1乣AMS0,ASCK)
// slave:0x00,master:0xe8
{CODEC_DAC_CB, 0x3f}, //*3:(03h)DAC Control Byte(ZCD,MUTC)
{CODEC_NONE, 0x00}}; // 4:delimiter
FUNC_WPDD("+hssi_rxstart");
DSPmaster[0][1] = CS4226_REC_CMB;
DSPmaster[1][1] = CS4226_REC_DSP_PMB;
DSPmaster[2][1] = CS4226_REC_APMB;
if(PlayOpenFlag == 0){
DSPmaster[3][1] = CS4226_DACCB_MUTE;
}
else{
DSPmaster[3][1] = CS4226_DACCB_NORMAL;
}
//Stop SSI
WRITE_REGISTER_ULONG((PULONG)pSSI_CR_RX, (ULONG)(SSICR_RX.AsDWORD & SSI_DISABLE_MASK) ); // Disable SSI
if(CS4226_ReadADDR == SSI1_CS4226_ReadADDR){
// stop playback only ch1
WRITE_REGISTER_ULONG((PULONG)pSSI_CR_TX, (ULONG)(0x00000000) ); // Disable SSI for TX
}
if ( ulDSPMode != DSPmaster[1][1] || ulDACControl != DSPmaster[3][1] ){
if(I2C_SetCODEC(DSPmaster)){
ulDSPMode = DSPmaster[1][1];
ulDACControl = DSPmaster[3][1];
}
}
// Set SSI Control Register
if(CS4226_ReadADDR == SSI2_CS4226_ReadADDR){
if(PlayOpenFlag == 0){
// ch3 need ch2's clock
SSICR_TX.bits.Reserved = 0;
SSICR_TX.bits.DMEN = 0; // DMA Disable
SSICR_TX.bits.UIEN = 0; // Underflow IRQ disable
SSICR_TX.bits.OIEN = 0; // Overflow IRQ disable
SSICR_TX.bits.IIEN = 0; // Idle Mode IRQ disable
SSICR_TX.bits.DIEN = 0; // Data IRQ disable
SSICR_TX.bits.CHNL = 0; // Channels
SSICR_TX.bits.DWL = 3; // Data Word Length 20 bit
SSICR_TX.bits.SWL = 3; // System Word Length 32 bit
SSICR_TX.bits.SCKD = SSI_PLAY_MODE; // Serial Clock Output(Master)
SSICR_TX.bits.SWSD = SSI_PLAY_MODE; // Serial WS Output(Master)
SSICR_TX.bits.SCKP = 1; // Serial Clock Polarity falling edge
SSICR_TX.bits.SWSP = 1; // Serial WS Polarity High for Left
SSICR_TX.bits.SPDP = 0; // Serial Padding Polarity Low
SSICR_TX.bits.SDTA = 1; // Serial Data Alignment Right
SSICR_TX.bits.PDTA = 1; // Parallel Data Alignment Right
SSICR_TX.bits.DEL = 1; // Serial Data no Delay
SSICR_TX.bits.BREN = 0; // Burst Mode Disable
SSICR_TX.bits.CKDV = 3; // Serial Oversample Clock Divide Ratio
SSICR_TX.bits.MUEN = 0; // Mute disable
SSICR_TX.bits.CPEN = 0; // Compress mode disable
SSICR_TX.bits.TRMD = 1; // Transmit mode
SSICR_TX.bits.EN = 0; // SSI Disable
RegValue = SSICR_TX.AsDWORD;
WRITE_REGISTER_ULONG(pSSI_CR_TX, RegValue);
}
}
SSICR_RX.bits.Reserved = 0;
SSICR_RX.bits.DMEN = 0; // DMA Disable
SSICR_RX.bits.UIEN = 0; // Underflow IRQ disable
SSICR_RX.bits.OIEN = 0; // Overflow IRQ disable
SSICR_RX.bits.IIEN = 0; // Idle Mode IRQ disable
SSICR_RX.bits.DIEN = 0; // Data IRQ disable
SSICR_RX.bits.CHNL = 0; // Channels
SSICR_RX.bits.DWL = 3; // Data Word Length 20 bit
SSICR_RX.bits.SWL = 3; // System Word Length 32 bit
SSICR_RX.bits.SCKD = SSI_REC_MODE; // Serial Clock Output
SSICR_RX.bits.SWSD = SSI_REC_MODE; // Serial WS Output
SSICR_RX.bits.SCKP = 1; // Serial Clock Polarity falling edge
SSICR_RX.bits.SWSP = 1; // Serial WS Polarity High for Left
SSICR_RX.bits.SPDP = 0; // Serial Padding Polarity Low
SSICR_RX.bits.SDTA = 1; // Serial Data Alignment Right
SSICR_RX.bits.PDTA = 1; // Parallel Data Alignment Right
SSICR_RX.bits.DEL = 1; // Serial Data no Delay
SSICR_RX.bits.BREN = 0; // Burst Mode Disable
SSICR_RX.bits.CKDV = 3; // Serial Oversample Clock Divide Ratio
SSICR_RX.bits.MUEN = 0; // Mute disable
SSICR_RX.bits.CPEN = 0; // Compress mode disable
SSICR_RX.bits.TRMD = 0; // Receive mode
SSICR_RX.bits.EN = 0; // SSI Disable
RegValue = SSICR_RX.AsDWORD;
WRITE_REGISTER_ULONG(pSSI_CR_RX, RegValue);
FUNC_WPDD("-hssi_rxstart");
return;
}
/*****************************************************************************
* FUNCTION : private_ChangeSampleRate
* DESCRIPTION : Change sampling rate for DAC
* INPUTS : SampleRate - Sampling Rate
* OUTPUTS : Return TRUE for success, FALSE for failure
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
BOOL private_ChangeSampleRate(
ULONG SampleRate
)
{
// do nothing
return TRUE;
}
/*****************************************************************************
* FUNCTION : private_ChangeRecSampleRate
* DESCRIPTION : Change sampling rate for ADC
* INPUTS : SampleRate - Sampling Rate
* OUTPUTS : Return TRUE for success, FALSE for failure
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
BOOL private_ChangeRecSampleRate(
ULONG SampleRate
)
{
// do nothing
return TRUE;
}
/*****************************************************************************
* FUNCTION : AudioFillBuffer_M8
* DESCRIPTION : convert sample and fill audio DMA buffer(8bit Mono)
* INPUTS : pSrcPtr - wave audio data Address
* pDstPtr - Audio Buffer Address
* ulSrcSampleCount - Sampling count
* nIncreasing - The coefficient for increasing data
* OUTPUTS : None
* DESIGN NOTES : Soft-ware Sampling Rate Convert
* (11.025kHz and 22.05kHz to 44.1kHz)
* convert 8bit to 20bit and mono to stereo
* CAUTIONS :
*****************************************************************************/
VOID
AudioFillBuffer_M8 (
PBYTE pSrcPtr,
PULONG pDstPtr,
ULONG ulSrcSampleCount,
ULONG nIncreasing
)
{
ULONG sample;
ULONG n;
while (ulSrcSampleCount > 0) {
sample = *pSrcPtr++;
sample -= 128;
sample <<= 12;
for(n=0; n<nIncreasing; n++){
*pDstPtr++ = sample;
*pDstPtr++ = sample;
}
ulSrcSampleCount--;
}
}
/*****************************************************************************
* FUNCTION : AudioFillBuffer_S8
* DESCRIPTION : convert sample and fill audio DMA buffer(8bit Stereo)
* INPUTS : pSrcPtr - wave audio data Address
* pDstPtr - Audio Buffer Address
* ulSrcSampleCount - Sampling count
* nIncreasing - The coefficient for increasing data
* OUTPUTS : None
* DESIGN NOTES : Soft-ware Sampling Rate Convert
* (11.025kHz and 22.05kHz to 44.1kHz)
* convert 8bit to 20bit
* CAUTIONS :
*****************************************************************************/
VOID
AudioFillBuffer_S8 (
PBYTE pSrcPtr,
PULONG pDstPtr,
ULONG ulSrcSampleCount,
ULONG nIncreasing
)
{
ULONG l_sample, r_sample;
ULONG n;
while (ulSrcSampleCount > 0) {
l_sample = *pSrcPtr++;
l_sample -= 128;
l_sample <<= 12;
r_sample = *pSrcPtr++;
r_sample -= 128;
r_sample <<= 12;
for(n=0; n<nIncreasing; n++){
*pDstPtr++ = l_sample;
*pDstPtr++ = r_sample;
}
ulSrcSampleCount--;
}
}
/*****************************************************************************
* FUNCTION : AudioFillBuffer_M16
* DESCRIPTION : convert sample and fill audio DMA buffer(16bit Mono)
* INPUTS : pSrcPtr - wave audio data Address
* pDstPtr - Audio Buffer Address
* ulSrcSampleCount - Sampling count
* nIncreasing - The coefficient for increasing data
* OUTPUTS : None
* DESIGN NOTES : Soft-ware Sampling Rate Convert
* (11.025kHz and 22.05kHz to 44.1kHz)
* convert 16bit to 20bit and mono to stereo
* CAUTIONS :
*****************************************************************************/
VOID
AudioFillBuffer_M16 (
PUSHORT pSrcPtr,
PULONG pDstPtr,
ULONG ulSrcSampleCount,
ULONG nIncreasing
)
{
ULONG n;
ULONG sample;
while (ulSrcSampleCount > 0) {
sample = *pSrcPtr++;
sample <<= 4;
for(n=0; n<nIncreasing; n++){
*pDstPtr++ = sample;
*pDstPtr++ = sample;
}
ulSrcSampleCount--;
}
}
/*****************************************************************************
* FUNCTION : AudioFillBuffer_S16
* DESCRIPTION : convert sample and fill audio DMA buffer(16bit Stereo)
* INPUTS : pSrcPtr - wave audio data Address
* pDstPtr - Audio Buffer Address
* ulSrcSampleCount - Sampling count
* nIncreasing - The coefficient for increasing data
* OUTPUTS : None
* DESIGN NOTES : Soft-ware Sampling Rate Convert
* (11.025kHz and 22.05kHz to 44.1kHz)
* convert 16bit to 20bit
* CAUTIONS :
*****************************************************************************/
VOID
AudioFillBuffer_S16 (
PUSHORT pSrcPtr,
PULONG pDstPtr,
ULONG ulSrcSampleCount,
ULONG nIncreasing
)
{
ULONG n;
ULONG l_sample, r_sample;
while (ulSrcSampleCount > 0) {
l_sample = *pSrcPtr++;
l_sample = l_sample<<4;
r_sample = *pSrcPtr++;
r_sample = r_sample<<4;
for(n=0; n<nIncreasing; n++){
*pDstPtr++ = l_sample;
*pDstPtr++ = r_sample;
}
ulSrcSampleCount--;
}
}
/*****************************************************************************
* FUNCTION : private_AudioFillBuffer
* DESCRIPTION : fills next buffer from given wave
* toggles ready/empty pointers to double buffer
* INPUTS : wave
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
VOID
private_AudioFillBuffer (
PWAVEHDR pwh
)
{
const PPCMWAVEFORMAT pFormat = (PPCMWAVEFORMAT) g_pwfx[WAPI_OUT];
ULONG samplingRate;
ULONG *lpAudioBuffer;
LONG nDstLen, nSrcLen;
ULONG nSampleCount,nSampleUnit;
LONG nIncreasing = 1;
ULONG CODEC_SAMPLING_RATE;
volatile DWORD dwDummy; // used to synchronize data fill and DMA
FUNC_VERBOSE("+PDD_AudioFillBuffer");
//Set terminal condition for double-buffer and exit if no data remains
if (pwh == NULL)
{
pDriverGlobals->aud[AUDIO_NO].play_address = (ULONG)NULL;
return;
}
//
// For this line, the number of bytes from this audio stream
// depends on the dma_buffer_size and the sample rate of the stream
//
// What's the maximum number of samples from this stream are needed
// to fill the DMA buffer?
//
switch (g_pcmtype[WAPI_OUT])
{
case PCM_TYPE_S16:
nSampleUnit = 4; // 2 words per sample unit
break;
case PCM_TYPE_M16:
nSampleUnit = 2; // 1 word per sample unit
break;
case PCM_TYPE_S8:
nSampleUnit = 2; // 2 bytes per sample unit
break;
case PCM_TYPE_M8:
nSampleUnit = 1; // 1 byte per sample unit
break;
} // end switch
samplingRate = pFormat->wf.nSamplesPerSec;
CODEC_SAMPLING_RATE = get_CODEC_SAMPLING_RATE(pDriverGlobals->aud[AUDIO_NO].PLAY_CH);
nIncreasing = CODEC_SAMPLING_RATE / samplingRate; // The coefficient for increasing data
lpAudioBuffer = (ULONG *)(pAudioBufferBase + v_nNextPage * AUDIO_DMA_PAGE_SIZE);
nDstLen = AUDIO_DMA_PAGE_SIZE / (sizeof(ULONG) * 2 * nIncreasing);
//
// For each sample in the buffer...
//
while (nDstLen > 0) {
nSrcLen = pwh->dwBufferLength - pwh->dwBytesRecorded;
if (nSrcLen <= 0)
{
pwh = pwh->lpNext;
if (pwh == NULL)
break; // The rest of the buffer will be cleared later.
}
else
{
nSampleCount = nSrcLen / nSampleUnit;
if (nDstLen < (LONG)nSampleCount) nSampleCount = nDstLen;
switch (g_pcmtype[WAPI_OUT])
{
case PCM_TYPE_S16:
AudioFillBuffer_S16((PUSHORT)(pwh->lpData + pwh->dwBytesRecorded), (PULONG)lpAudioBuffer,
nSampleCount, nIncreasing);
break;
case PCM_TYPE_M16:
AudioFillBuffer_M16((PUSHORT)(pwh->lpData + pwh->dwBytesRecorded), (PULONG)lpAudioBuffer,
nSampleCount, nIncreasing);
break;
case PCM_TYPE_S8:
AudioFillBuffer_S8((PBYTE)(pwh->lpData + pwh->dwBytesRecorded), (PULONG)lpAudioBuffer,
nSampleCount, nIncreasing);
break;
case PCM_TYPE_M8:
AudioFillBuffer_M8((PBYTE)(pwh->lpData + pwh->dwBytesRecorded), (PULONG)lpAudioBuffer,
nSampleCount, nIncreasing);
break;
} // end switch
pwh->dwBytesRecorded += (nSampleCount * nSampleUnit) ;
nDstLen -= nSampleCount;
lpAudioBuffer += (2 * nSampleCount * nIncreasing);
}
}
// pad with silence if necessary
memset(lpAudioBuffer, 0, nDstLen * sizeof(ULONG) * 2 * nIncreasing);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -