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

📄 i2saudio.cpp

📁 EP931X系列的WinCE声卡驱动源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    *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 + -