Example #1
0
extern bool Nrf24l::dataReady() 
// Checks if data is available for reading
{
    // See note in getData() function - just checking RX_DR isn't good enough
	uint8_t status = getStatus();

    // We can short circuit on RX_DR, but if it's not set, we still need
    // to check the FIFO for any pending packets
    if ( status & (1 << RX_DR) ) return 1;
    return !rxFifoEmpty();
}
Example #2
0
extern bool Nrf24l::dataReady() 
// Checks if data is available for reading
// 检测是否有可读的数据
{
    // See note in getData() function - just checking RX_DR isn't good enough
	// 查看 getData() 函数说明,
	// 只检查 RX_DR(接收数据中断,当接收到有效数据后置一) 并不是好办法。
	uint8_t status = getStatus();

    // We can short circuit on RX_DR, but if it's not set, we still need
    // to check the FIFO for any pending packets
	// 可以快速的检测 RX_DR ,但是如果没有检测到,还得检测FIFO是否空。
    if ( status & (1 << RX_DR) ) return 1;
    return !rxFifoEmpty();
}
HRESULT BtI2cControllerClass::_performContiguousTransfers(I2cTransferClass* & pXfr)
{
    ULONGLONG startWaitTicks = 0;
    ULONGLONG currentTicks = 0;
    I2cTransferClass* cmdXfr = nullptr;
    I2cTransferClass* readXfr = nullptr;
    PUCHAR readPtr = nullptr;
    HRESULT hr = S_OK;
    BOOL restart = FALSE;
    ULONG cmdDat;
    LONG cmdsOutstanding = 0;
    LONG readsOutstanding = 0;
    UCHAR outByte;
    UCHAR inByte;


    if (pXfr == nullptr)
    {
        hr = DMAP_E_DMAP_INTERNAL_ERROR;
    }

    if (SUCCEEDED(hr))
    {
        // Calculate the command and read counts for the current sequence of 
        // contiguous transfers in this transaction.
        hr = calculateCurrentCounts(pXfr, cmdsOutstanding, readsOutstanding);
    }

    // For each transfer in this section of the transaction:
    cmdXfr = pXfr;
    while (SUCCEEDED(hr) && (cmdsOutstanding > 0) && (cmdXfr != nullptr))
    {
        // If this is the first read transfer in this sequence of transfers:
        if ((readXfr == nullptr) && cmdXfr->transferIsRead())
        {
            // Indicate this is the transfer to read into.
            readXfr = cmdXfr;
            readXfr->resetRead();
            readPtr = readXfr->getNextReadLocation();
        }

        // Prepare to access the cmd buffer.
        cmdXfr->resetCmd();

        // Signal a pre-restart if this transfer is marked for one.
        if (cmdXfr->preResart())
        {
            restart = TRUE;
        }

        // For each byte in the transfer:
        while (SUCCEEDED(hr) && (cmdXfr->getNextCmd(outByte)))
        {
            // Wait for at least one empty space in the TX FIFO.
            while (txFifoFull());

            // Issue the command.
            if (cmdXfr->transferIsRead())
            {
                cmdDat = 0x100;             // Build read command (data is ignored)
            }
            else
            {
                cmdDat = outByte;           // Build write command with data byte
            }

            // If restart has been requested, signal a pre-RESTART.
            if (restart)
            {
                cmdDat = cmdDat | (1 << 10);
                restart = FALSE;            // Only want to RESTART on first command of transfer
            }

            // If this is the last command before the end of the transaction or
            // before a callback, signal a STOP.
            if (cmdsOutstanding == 1)
            {
                cmdDat = cmdDat | (1 << 9);
            }

            // Issue the command.
            m_registers->IC_DATA_CMD.ALL_BITS = cmdDat;
            cmdsOutstanding--;

            hr = _handleErrors();

            // Pull any available bytes out of the receive FIFO.
            while (SUCCEEDED(hr) && rxFifoNotEmtpy())
            {
                // Read a byte from the I2C Controller.
                inByte = readByte();
                readsOutstanding--;

                // Store the byte if we have a place for it.
                if (readPtr != nullptr)
                {
                    *readPtr = inByte;

                    // Figure out where the next byte should go.
                    readPtr = readXfr->getNextReadLocation();
                    while ((readPtr == nullptr) && (readXfr->getNextTransfer() != nullptr))
                    {
                        readXfr = readXfr->getNextTransfer();
                        readXfr->resetRead();
                        readPtr = readXfr->getNextReadLocation();
                    }
                }
            }
        }

        if (SUCCEEDED(hr))
        {
            cmdXfr = cmdXfr->getNextTransfer();
        }
    }

    // Complete any outstanding reads and wait for the TX FIFO to empty.
    startWaitTicks = GetTickCount64();
    currentTicks = startWaitTicks;
    while (SUCCEEDED(hr) && ((readsOutstanding > 0) || !txFifoEmpty()) && !errorOccurred())
    {
        // Pull any available bytes out of the receive FIFO.
        while (rxFifoNotEmtpy())
        {
            // Read a byte from the I2C Controller.
            inByte = readByte();
            readsOutstanding--;

            // Store the byte if we have a place for it.
            if (readPtr != nullptr)
            {
                *readPtr = inByte;

                // Figure out where the next byte should go.
                readPtr = readXfr->getNextReadLocation();
                while ((readPtr == nullptr) && (readXfr->getNextTransfer() != nullptr))
                {
                    readXfr = readXfr->getNextTransfer();
                    readXfr->resetRead();
                    readPtr = readXfr->getNextReadLocation();
                }
            }
        }

        // Wait up to to 100 milliseconds for transfers to happen.
        if (readsOutstanding > 0)
        {
            currentTicks = GetTickCount64();
            if (((currentTicks - startWaitTicks) > 100) && rxFifoEmpty())
            {
                hr = DMAP_E_I2C_READ_INCOMPLETE;
            }
        }
    }

    // Determine if an error occured on this transaction.
    if (SUCCEEDED(hr))
    {
        hr = _handleErrors();
    }

    // Pass the next transfer pointer back to the caller.
    pXfr = cmdXfr;

    // Record the read wait count for debugging purposes.
    if ((currentTicks - startWaitTicks) > m_maxWaitTicks)
    {
        m_maxWaitTicks = (ULONG)(currentTicks - startWaitTicks);
    }

    if (SUCCEEDED(hr))
    {
        // Check for some catch-all errors.
        if (cmdsOutstanding > 0)
        {
            hr = DMAP_E_I2C_OPERATION_INCOMPLETE;
        }
        else if (readsOutstanding < 0)
        {
            hr = DMAP_E_I2C_EXTRA_DATA_RECEIVED;
        }
        else if (cmdsOutstanding < 0)
        {
            hr = DMAP_E_DMAP_INTERNAL_ERROR;
        }
    }

    return hr;
}