static bool SPIMaster_TransferGlobAppend()

in IndustrialDeviceController/Software/MT3620_IDC_RTApp/lib/SPIMaster.c [465:541]


static bool SPIMaster_TransferGlobAppend(
    const SPITransfer      *transfer,
    uint32_t                count,
    SPIMaster_TransferGlob *glob)
{
    // If next transfer is a write but the one after involves a read, we don't glob it
    // as we need to glob a read onto a write due to hardware limitations.
    if (transfer[0].writeData && !transfer[0].readData && (count >= 2)) {
        if (transfer[1].writeData && transfer[1].readData) {
            return false;
        }
    }

    // We can't append a write/duplex to a half-duplex read.
    if ((glob->type == SPI_MASTER_TRANSFER_READ) && transfer->writeData) {
        return false;
    }

#ifdef SPI_ALLOW_TRANSFER_WRITE
    // We can't append a read/duplex to a half-duplex write.
    if ((glob->type == SPI_MASTER_TRANSFER_WRITE) && transfer->readData) {
        return false;
    }
#endif // #ifdef SPI_ALLOW_TRANSFER_WRITE

    unsigned payloadLimit;
    switch (glob->type) {
    case SPI_MASTER_TRANSFER_FULL_DUPLEX:
        payloadLimit = MT3620_SPI_BUFFER_SIZE_FULL_DUPLEX;
        break;

    case SPI_MASTER_TRANSFER_READ:
        payloadLimit = MT3620_SPI_BUFFER_SIZE_HALF_DUPLEX;
        break;

    case SPI_MASTER_TRANSFER_WRITE:
        // We must reserve the last byte to set the MOSI idle level high.
        // This is due to a bug in the MT3620 SPI interface.
        payloadLimit = MT3620_SPI_BUFFER_SIZE_HALF_DUPLEX - 1;
        break;

    default:
        return false;
    }

    if ((glob->payloadLen + transfer->length) > payloadLimit) {
#ifdef SPI_ALLOW_TRANSFER_WRITE
        if ((glob->type == SPI_MASTER_TRANSFER_FULL_DUPLEX) && !transfer->readData) {
            // Check if this transfer would overflow half-duplex glob.
            if ((glob->payloadLen + glob->opcodeLen + transfer->length) > (
                MT3620_SPI_BUFFER_SIZE_HALF_DUPLEX - 1)) {
                return false;
            }

            // Check if full-duplex glob contains reads.
            unsigned t;
            for (t = 0; t < glob->transferCount; t++) {
                if (glob->transfer[t].readData) {
                    return false;
                }
            }

            // If a full-duplex glob only contains writes, make it a write glob.
            glob->type = SPI_MASTER_TRANSFER_WRITE;
            glob->payloadLen += glob->opcodeLen;
            glob->opcodeLen = 0;
        } else
#endif //#ifdef SPI_ALLOW_TRANSFER_WRITE
        {
            return false;
        }
    }

    glob->transferCount++;
    glob->payloadLen += transfer->length;
    return true;
}