📄 codec.c
字号:
//****************************************************************************
//
// CODEC.C - Routines to enable the serial codec interface and use it to
// playback and record waveform data
//
// Copyright (c) 1998-2001 Cirrus Logic, Inc.
//
//****************************************************************************
#include "ep7312.h"
#include "lib7312.h"
//****************************************************************************
//
// The following variables describe the buffer of PCM data that is currently
// being played back.
//
//****************************************************************************
static char * volatile pcCurPlayBuffer = 0;
static char * volatile pcNextPlayBuffer = 0;
static long lCurPlayPos;
static long lCurPlayLength;
static long lNextPlayLength;
//****************************************************************************
//
// The following variables describe the buffer of PCM data that is currently
// being recorded.
//
//****************************************************************************
static char * volatile pcCurRecordBuffer = 0;
static char * volatile pcNextRecordBuffer = 0;
static long lCurRecordPos;
static long lCurRecordLength;
static long lNextRecordLength;
//****************************************************************************
//
// CodecISR is the interrupt handler for the codec interrupt. It will write
// samples into the codec FIFO until it is full. If there are no samples
// available, it will write silence instead.
//
//****************************************************************************
static void
CodecISR(void)
{
unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
volatile char cTemp;
//
// Loop until the output FIFO is full.
//
while(!(pulPtr[HwStatus >> 2] & HwStatusCodecTxFifoFull))
{
//
// If there is not a buffer of samples waiting to be played, then
// simply fill the FIFO with silence.
//
if(!pcCurPlayBuffer && !pcNextPlayBuffer)
{
pulPtr[HwCodecData >> 2] = 0xFF;
continue;
}
//
// See if we need to move to the next buffer.
//
if(!pcCurPlayBuffer)
{
//
// Move the next buffer to the current buffer.
//
pcCurPlayBuffer = pcNextPlayBuffer;
lCurPlayLength = lNextPlayLength;
lCurPlayPos = 0;
//
// Clear out the next buffer.
//
pcNextPlayBuffer = 0;
lNextPlayLength = 0;
}
//
// Write another sample into the FIFO.
//
pulPtr[HwCodecData >> 2] = pcCurPlayBuffer[lCurPlayPos++];
//
// See if we've reached the end of the play buffer.
//
if(lCurPlayPos == lCurPlayLength)
{
pcCurPlayBuffer = 0;
}
}
//
// Loop until the input FIFO is empty.
//
while(!(pulPtr[HwStatus >> 2] & HwStatusCodecRxFifoEmpty))
{
//
// If there is not a buffer to record into, then simply throw away the
// sample from the FIFO.
//
if(!pcCurRecordBuffer && !pcNextRecordBuffer)
{
cTemp = pulPtr[HwCodecData >> 2];
continue;
}
//
// See if we need to move to the next buffer.
//
if(!pcCurRecordBuffer)
{
//
// Move the next buffer to the current buffer.
//
pcCurRecordBuffer = pcNextRecordBuffer;
lCurRecordLength = lNextRecordLength;
lCurRecordPos = 0;
//
// Clear out the next buffer.
//
pcNextRecordBuffer = 0;
lNextRecordLength = 0;
}
//
// Read another sample from the FIFO.
//
pcCurRecordBuffer[lCurRecordPos++] = (pulPtr[HwCodecData >> 2] & 0xff);
//
// See if we've reached the end of the record buffer.
//
if(lCurRecordPos == lCurRecordLength)
{
pcCurRecordBuffer = 0;
}
}
}
//****************************************************************************
//
// CodecEnable configures the codec for playback and recording of u-law PCM
// data.
//
//****************************************************************************
void
CodecEnable(void)
{
unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
//
// Select CODEC/SSI mode instead of DAI mode.
//
pulPtr[HwControl3 >> 2] &= ~HwControl3DAISelect;
//
// The codec enable bit must always be set for the codec interface to work.
//
pulPtr[HwControl2 >> 2] |= HwControl2CodecEnable;
//
// Enable the codec transmit and receive buffers. They can not be
// individually controlled (even they have separate control bits).
//
pulPtr[HwControl >> 2] |= HwControlCodecTxEnable | HwControlCodecRxEnable;
//
// Turn on the codec and external speaker on the EP7209 eval board.
//
((unsigned char *)pulPtr)[HwPortE] |= HwPortECodecPower;
//
// Install the ISR so that we can process the codec interrupt.
//
InterruptInstallIRQ();
//
// Install the codec interrupt handler.
//
InterruptSetCodecHandler(CodecISR);
//
// Enable the codec interrupt.
//
pulPtr[HwIntMask >> 2] |= HwIrqCodec;
}
//****************************************************************************
//
// CodecDisable powers down the codec.
//
//****************************************************************************
void
CodecDisable(void)
{
unsigned long * volatile pulPtr = (unsigned long *)HwBaseAddress;
//
// Disable the codec interrupt.
//
pulPtr[HwIntMask >> 2] &= ~HwIrqCodec;
//
// Remove the codec interrupt handler.
//
InterruptSetCodecHandler(0);
//
// Remove the interrupt handler.
//
InterruptRemoveIRQ();
//
// Disable the codec transmit and receive buffers.
//
pulPtr[HwControl >> 2] &= ~(HwControlCodecTxEnable |
HwControlCodecRxEnable);
//
// Turn off the codec and external speaker on the EP7209 eval board.
//
((unsigned char *)pulPtr)[HwPortE] &= ~HwPortECodecPower;
//
// Mark both playback and record buffers as completed.
//
pcCurPlayBuffer = 0;
pcNextPlayBuffer = 0;
pcCurRecordBuffer = 0;
pcNextRecordBuffer = 0;
}
//****************************************************************************
//
// CodecPlay plays the specified buffer of u-law PCM data out via the codec.
//
//****************************************************************************
void
CodecPlay(char *pcBuffer, long lLength)
{
//
// Wait until there is space in the play queue.
//
while(pcNextPlayBuffer)
{
}
//
// Setup the buffer to be played in the background.
//
lNextPlayLength = lLength;
pcNextPlayBuffer = pcBuffer;
//
// Wait until the entire buffer has been consumed.
//
while(pcNextPlayBuffer || pcCurPlayBuffer)
{
}
}
//****************************************************************************
//
// CodecPlayBg plays the specified buffer of u-law PCM data out via the codec
// in the background (i.e. it returns before the data has been played,
// allowing other processing to occur).
//
//****************************************************************************
void
CodecPlayBg(char *pcBuffer, long lLength)
{
//
// Wait until there is space in the play queue.
//
while(pcNextPlayBuffer)
{
}
//
// Setup the buffer to be played in the background.
//
lNextPlayLength = lLength;
pcNextPlayBuffer = pcBuffer;
}
//****************************************************************************
//
// CodecPlaySpaceAvailable determines if there is space available in the
// playback data queue.
//
//****************************************************************************
int
CodecPlaySpaceAvailable(void)
{
//
// If the next buffer pointer is currently set, then there is not space in
// the playback data queue.
//
if(pcNextPlayBuffer)
{
return(0);
}
//
// There is room in the playback data queue.
//
return(1);
}
//****************************************************************************
//
// CodecPlayIsDone determines whether or not the current data buffer has
// completed playing.
//
//****************************************************************************
int
CodecPlayIsDone(void)
{
//
// See if the either buffer is still playing.
//
if(pcNextPlayBuffer || pcCurPlayBuffer)
{
//
// It is, so indicate that the playback is not done.
//
return(0);
}
//
// The playback is done.
//
return(1);
}
//****************************************************************************
//
// CodecPlayWaitTilDone does not return until the current data buffer has
// completed playing.
//
//****************************************************************************
void
CodecPlayWaitTilDone(void)
{
//
// Loop until the buffers are marked as being done.
//
while(pcNextPlayBuffer || pcCurPlayBuffer)
{
}
}
//****************************************************************************
//
// CodecRecord fills the specified buffer with u-law PCM data recorded via the
// codec.
//
//****************************************************************************
void
CodecRecord(char *pcBuffer, long lLength)
{
//
// Wait until there is space in the record queue.
//
while(pcNextRecordBuffer)
{
}
//
// Setup the buffer to be recorded in the background.
//
lNextRecordLength = lLength;
pcNextRecordBuffer = pcBuffer;
//
// Wait until the entire buffer has been recorded.
//
while(pcNextRecordBuffer || pcCurRecordBuffer)
{
}
}
//****************************************************************************
//
// CodecRecordBg fills the specified buffer with u-law PCM data recorded via
// the codec in the background (i.e. it returns before the data has been
// recorded, allowing other processing to occur).
//
//****************************************************************************
void
CodecRecordBg(char *pcBuffer, long lLength)
{
//
// Wait until there is space in the record queue.
//
while(pcNextRecordBuffer)
{
}
//
// Setup the buffer to be recorded in the background.
//
lNextRecordLength = lLength;
pcNextRecordBuffer = pcBuffer;
}
//****************************************************************************
//
// CodecRecordSpaceAvailable determines if there is space available in the
// record data queue.
//
//****************************************************************************
int
CodecRecordSpaceAvailable(void)
{
//
// If the next buffer pointer is current set, then there is not space in
// the record data queue.
//
if(pcNextRecordBuffer)
{
return(0);
}
//
// There is room in the record data queue.
//
return(1);
}
//****************************************************************************
//
// CodecRecordIsDone determines whether or not the current data buffer has
// completed recording.
//
//****************************************************************************
int
CodecRecordIsDone(void)
{
//
// See if the either buffer is still recording.
//
if(pcNextRecordBuffer || pcCurRecordBuffer)
{
//
// It is, so indicate that the record is not done.
//
return(0);
}
//
// The record is done.
//
return(1);
}
//****************************************************************************
//
// CodecRecordWaitTilDone does not return until the current data buffer has
// completed recording.
//
//****************************************************************************
void
CodecRecordWaitTilDone(void)
{
//
// Loop until the buffers are marked as being done.
//
while(pcNextRecordBuffer || pcCurRecordBuffer)
{
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -