⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codec.c

📁 Cirrus Logic EP7312处理器部分控制程序。
💻 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 + -