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

📄 hwctxt.cpp

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    DEBUGMSG(ZONE_FUNCTION,(TEXT("+++StartOutputDMA\n")));

    if (!m_OutputDMARunning)
    {
        //----- 1. Initialize our buffer counters -----
        m_OutputDMARunning=TRUE;
        m_OutputDMABuffer = OUT_BUFFER_A;
        m_OutBytes[OUT_BUFFER_A]=m_OutBytes[OUT_BUFFER_B]=0;

        //----- 2. Prime both output buffer with as much sound data as possible -----
        ULONG OutputTransferred = TransferOutputBuffer(OUT_BUFFER_A);
        OutputTransferred += TransferOutputBuffer(OUT_BUFFER_B);

        //----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----
        if (OutputTransferred)
        {
            //----- 4. Configure the DMA channel for playback -----
            if (!InitOutputDMA())
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("HardwareContext::StartOutputDMA() - Unable to initialize output DMA channel!\r\n")));
                goto Exit;
            }


            ////////////////////////////////////////////////////////////////////////////////
            // To correct left/right channel on ouput stream,
            // You should reset IISCON[0] bit.

            // Disable interface. This reset forces L/R bit to be reset
            g_pIISregs->IISCON &= ~IIS_INTERFACE_ENABLE;
            g_pIISregs->IISCON |= TRANSMIT_DMA_REQUEST_ENABLE;
            g_pIISregs->IISCON &= ~TRANSMIT_IDLE_CMD;

            g_pIISregs->IISFCON |= (  TRANSMIT_FIFO_ACCESS_DMA | TRANSMIT_FIFO_ENABLE  );
            g_pIISregs->IISMOD  |= IIS_TRANSMIT_MODE;

            //----- 5. Make sure the audio isn't muted -----
            AudioMute(DMA_CH_OUT, FALSE);

            //----- 6. Start the DMA controller -----
            // Set DMA to start on buffer A
            g_pDMAregs->DISRC2 = (g_PhysDMABufferAddr.LowPart);

            Codec_channel();    // Turn ON output channel

            // Start the DMA!
            g_pDMAregs->DMASKTRIG2 &= ~STOP_DMA_TRANSFER;
            g_pDMAregs->DMASKTRIG2 |= ENABLE_DMA_CHANNEL;

            // wait for DMA to start so we can set the start address of buffer B.
            while ((g_pDMAregs->DSTAT2&0xfffff)==0);

            // Wait for some data to appear in the IIS transmit FIFO
            while ( !(g_pIISregs->IISCON & TRANSMIT_FIFO_READY) ) ;

            // Now reenable the IIS interface
            g_pIISregs->IISCON |= IIS_INTERFACE_ENABLE;

            // change the buffer pointer so the DMA autoswitches to buffer B once it's finished with A
            g_pDMAregs->DISRC2 = (g_PhysDMABufferAddr.LowPart + AUDIO_DMA_PAGE_SIZE);
        }
        else    // We didn't transfer any data, so DMA wasn't enabled
        {
            m_OutputDMARunning=FALSE;
        }
    }

    DEBUGMSG(ZONE_FUNCTION,(TEXT("---StartOutputDMA\n")));
    bRet = TRUE;

Exit:
    return bRet;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:               StopOutputDMA()

Description:    Stops any DMA activity on the output channel.

Returns:                Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopOutputDMA()
{
    //----- 1. If the output DMA is running, stop it -----
    if (m_OutputDMARunning)
    {
        // Disable DMA
        g_pDMAregs->DMASKTRIG2 |= STOP_DMA_TRANSFER;
        g_pDMAregs->DMASKTRIG2 &= ~ENABLE_DMA_CHANNEL;

        // Clear output interrupt
        g_pDMAregs->DCON2 = g_pDMAregs->DCON2;

        g_pIISregs->IISCON &= ~TRANSMIT_DMA_REQUEST_ENABLE;
        g_pIISregs->IISCON |= TRANSMIT_IDLE_CMD;

        g_pIISregs->IISFCON &= ~(  TRANSMIT_FIFO_ACCESS_DMA | TRANSMIT_FIFO_ENABLE  );
        g_pIISregs->IISMOD  &= ~IIS_TRANSMIT_MODE;

        AudioMute(DMA_CH_OUT, TRUE);

        m_OutputDMARunning = FALSE;
        Codec_channel();
    }
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:               InitInputDMA()

Description:    Initializes the DMA channel for input.

Notes:                  ***** NOT IMPLEMENTED *****

                                The following routine is not implemented due to a
                                hardware bug in the revision of the Samsung SC2410
                                CPU this driver was developed on.  See the header
                                at the top of this file for details.

Returns:                Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitInputDMA()
{

    DEBUGMSG(ZONE_FUNCTION,(TEXT("+++InitInputDMA\n")));

    if (!g_PhysDMABufferAddr.LowPart)
    {
        DEBUGMSG(TRUE, (TEXT("ERROR:HardwareContext::InitInputDMA: Invalid DMA buffer physical address.\r\n")));
        return(FALSE);
    }

    //============================ Configure DMA Channel 1 ===========================
    //------ On platforms with the revsion of the Samsung SC2410 CPU with the IIS SLAVE bug fix, this -----
    //               code can be used to configure DMA channel 1 for input.

    //----- 1. Initialize the DMA channel for input mode and use the first input DMA buffer -----
    g_pDMAregs->DISRC1      = (int)(S3C2410X_BASE_REG_PA_IISBUS+0x10);
    g_pDMAregs->DISRCC1 = (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);                           // Source is periperal bus, fixed addr

    //----- 2. Initialize the DMA channel to receive data over the I2S bus -----
    g_pDMAregs->DIDSTC1 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);   // Destination is system bus, increment addr

    //----- 3. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
    //                 single tx, single service, I2SSDI, I2S request, no auto-reload, half-word, tx count
    g_pDMAregs->DCON1       = (  HANDSHAKE_MODE | GENERATE_INTERRUPT | I2SSDI_DMA1 | DMA_TRIGGERED_BY_HARDWARE
                                 | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2)
                              );
    return(TRUE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:               StartInputDMA()

Description:    Starts inputting the recorded sound data from the
                                audio codec chip via DMA.

Notes:                  ***** NOT IMPLEMENTED *****

                                The following routine is not implemented due to a
                                hardware bug in the revision of the Samsung SC2410
                                CPU this driver was developed on.  See the header
                                at the top of this file for details.

Returns:                Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::StartInputDMA()
{
    BOOL bRet=FALSE;

    //------ On platforms with the revsion of the Samsung SC2410 CPU with the IIS SLAVE bug fix, this -----
    //               code can be used to configure DMA channel 1 for input.

    DEBUGMSG(ZONE_FUNCTION,(TEXT("+++StartInputDMA\n")));

    if (!m_InputDMARunning)
    {
        //----- 1. Initialize our buffer counters -----
        m_InputDMARunning=TRUE;
        Codec_channel();        // Turn On Input channel

        //----- 2. Prime the output buffer with sound data -----
        m_InputDMABuffer = IN_BUFFER_A;

        //----- 3. Configure the DMA channel for record -----
        if (!InitInputDMA())
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("HardwareContext::StartInputDMA() - Unable to initialize input DMA channel!\r\n")));
            goto Exit;
        }

        g_pIISregs->IISCON  |= RECEIVE_DMA_REQUEST_ENABLE;
        g_pIISregs->IISCON  &= ~RECEIVE_IDLE_CMD;
        g_pIISregs->IISFCON |= ( RECEIVE_FIFO_ACCESS_DMA  | RECEIVE_FIFO_ENABLE);
        g_pIISregs->IISMOD  |= IIS_RECEIVE_MODE;

        //----- 4. Make sure the audio isn't muted -----
        AudioMute(DMA_CH_MIC, FALSE);

        //----- 5. Start the input DMA -----
        g_pDMAregs->DIDST1 = g_PhysDMABufferAddr.LowPart + (2 * AUDIO_DMA_PAGE_SIZE);

        Codec_channel();        // Turn On Input channel
        g_pDMAregs->DMASKTRIG1 = ENABLE_DMA_CHANNEL;

        // wait for DMA to start.
        while ((g_pDMAregs->DSTAT1&0xfffff)==0);

        // change the buffer pointer
        g_pDMAregs->DIDST1 = g_PhysDMABufferAddr.LowPart + (3 * AUDIO_DMA_PAGE_SIZE);

    }

    DEBUGMSG(ZONE_FUNCTION,(TEXT("---StartInputDMA\n")));
    bRet=TRUE;

Exit:
    return bRet;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:               StopInputDMA()

Description:    Stops any DMA activity on the input channel.

Notes:                  ***** NOT IMPLEMENTED *****

                                The following routine is not implemented due to a
                                hardware bug in the revision of the Samsung SC2410
                                CPU this driver was developed on.  See the header
                                at the top of this file for details.

Returns:                Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopInputDMA()
{

    //------ On platforms with the revsion of the Samsung SC2410 CPU with the IIS SLAVE bug fix, this -----
    //               code can be used to configure DMA channel 1 for input.

    //----- 1. If the output DMA is running, stop it -----
    if (m_InputDMARunning)
    {
        g_pIISregs->IISCON &= ~RECEIVE_DMA_REQUEST_ENABLE;
        g_pIISregs->IISCON |= RECEIVE_IDLE_CMD;
        g_pIISregs->IISFCON &= ~( RECEIVE_FIFO_ACCESS_DMA  | RECEIVE_FIFO_ENABLE);
        g_pIISregs->IISMOD  &= ~IIS_RECEIVE_MODE;

        // Disable DMA
        g_pDMAregs->DMASKTRIG1 |= STOP_DMA_TRANSFER;
        g_pDMAregs->DMASKTRIG1 &= ~ENABLE_DMA_CHANNEL;

        // Clear input interrupt
        g_pDMAregs->DCON1 = g_pDMAregs->DCON1;

        AudioMute(DMA_CH_MIC, TRUE);

        m_InputDMARunning = FALSE;
        Codec_channel();
    }
}


DWORD HardwareContext::GetInterruptThreadPriority()
{
    HKEY hDevKey;
    DWORD dwValType;
    DWORD dwValLen;
    DWORD dwPrio = 249; // Default priority

    hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
    if (hDevKey)
    {
        dwValLen = sizeof(DWORD);
        RegQueryValueEx(
                       hDevKey,
                       TEXT("Priority256"),
                       NULL,
                       &dwValType,
                       (PUCHAR)&dwPrio,
                       &dwValLen);
        RegCloseKey(hDevKey);
    }

    return dwPrio;
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:               InitInterruptThread()

Description:    Initializes the IST for handling DMA interrupts.

Returns:                Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitInterruptThread()
{
    m_hAudioInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!m_hAudioInterrupt)
    {
        ERRMSG("Unable to create interrupt event");
        return(FALSE);
    }

    if (! InterruptInitialize(m_dwSysintrOutput, m_hAudioInterrupt, NULL, 0))
    {
        ERRMSG("Unable to initialize output interrupt");
        return FALSE;
    }
    if (! InterruptInitialize(m_dwSysintrInput, m_hAudioInterrupt, NULL, 0))
    {
        ERRMSG("Unable to initialize input interrupt");
        return FALSE;
    }

    m_hAudioInterruptThread  = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                                            0,
                                            (LPTHREAD_START_ROUTINE)CallInterruptThread,
                                            this,
                                            0,
                                            NULL);
    if (!m_hAudioInterruptThread)
    {
        ERRMSG("Unable to create interrupt thread");
        return FALSE;
    }

    // Bump up the priority since the interrupt must be serviced immediately.
    CeSetThreadPriority(m_hAudioInterruptThread, GetInterruptThreadPriority());

    return(TRUE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:               PowerUp()

Description:            Powers up the audio codec chip.

Returns:                Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::PowerUp()
{
    // Init SPI interface;
    I2S_Init();

    // Init codec registers
    InitCodec();

    // Reload current gain settings

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -