Search code examples
c#ftdid2xx

How to use BDBUS of FTDI for SPI using FTD2XX_NET


I am trying to use FT4232 ports for SPI communication. For this, I am using the ADBUS for SPI using the usual SPI configuration (AD0 -> SCK, AD1 -> MOSI, AD2 -> MISO, AD3 -> CS).

Now I have to use SPI available in BDBUS. As I understand, the FT4232 allows SPI in BDBUS. So far, I am stuck about using BDBUS.

The code using ADBUS is as follow

    /*********  SPI INIT AND CONFIG **********/
    void SPI_Init()
    {
        
        Console.WriteLine("Scanning Device");
        ftStatus = SPI_Device.GetNumberOfDevices(ref ftdiDeviceCount);
        if (ftStatus != FTDI.FT_STATUS.FT_OK)
        {
            Console.WriteLine("ftStatus NOT OK");
        }
        Console.WriteLine("Number of device = " + ftdiDeviceCount);
        if (ftdiDeviceCount == 0)
        {
            return;
        }
        FTDI.FT_DEVICE_INFO_NODE[] ftdiDeviceList = new FTDI.FT_DEVICE_INFO_NODE[ftdiDeviceCount];
        ftStatus = SPI_Device.GetDeviceList(ftdiDeviceList);

        if (ftStatus != FTDI.FT_STATUS.FT_OK)
            return;
        
        string serialnumber = "FTKI02A";
        ftStatus = SPI_Device.OpenBySerialNumber(serialnumber);
        Console.WriteLine("FTKI02B open status: {0}", ftStatus);
        if (ftStatus != FTDI.FT_STATUS.FT_OK)
        {
            Console.WriteLine(serialnumber + " port open failed");
        }
        ftStatus = SPI_Config();

        Console.WriteLine("\nConfig status: {0}", ftStatus);

        if (ftStatus == FTDI.FT_STATUS.FT_OK)
            spi_initialized = true;
    }

    FTDI.FT_STATUS SPI_Config()
    {

        FTDI.FT_STATUS stat = FTDI.FT_STATUS.FT_OK;
        stat = SPI_Device.ResetDevice();

        //Purge USB receive buffer first by reading out all old data from FT2232H receive buffer
        //stat |= SPI_Device.Purge(FTDI.FT_PURGE.FT_PURGE_RX);
        stat |= SPI_Device.GetRxBytesAvailable(ref numBytesRead);
        Console.WriteLine("Input buffer size: {0}", numBytesRead);
        if (stat == FTDI.FT_STATUS.FT_OK && numBytesRead > 0)
        {
            numBytesToRead = numBytesRead;
            stat |= SPI_Device.Read(inputBuffer, numBytesToRead, ref numBytesRead);
        }
        stat |= SPI_Device.SetCharacters(0, false, 0, false);
        stat |= SPI_Device.SetTimeouts(5000, 5000);
        stat |= SPI_Device.SetLatency(16);
        //stat |= SPI_Device.SetFlowControl(FTDI.FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x00, 0x00);      // This is not done in SPI pdf
        stat |= SPI_Device.SetBitMode(0x00, 0x00);
        stat |= SPI_Device.SetBitMode(0x00, 0x02);         // MPSSE mode

        if (stat != FTDI.FT_STATUS.FT_OK)
        {
            Console.WriteLine("Failed to initialize SPI");
            return stat;
        }
        Delay(50);

        // SYNCHRONIZATION WITH BAD COMMAND IS OMITTED HERE

        uint dwClockDivisor = 29;
        // Configure MPSSE for SPI communication with EEPROM
        numBytesToSend = numBytesSent = 0;
        outputBuffer[numBytesToSend++] = 0x8A;    // disable clock divide by 5 for 60MHz master clock
        outputBuffer[numBytesToSend++] = 0x97;    // turn off adaptive clocking
        outputBuffer[numBytesToSend++] = 0x8D;    //  3 phase data clock disable

        outputBuffer[numBytesToSend++] = 0x80;    // Command to set directions of lower 8 pins and force value on bits set as output on ADBUS
        outputBuffer[numBytesToSend++] = 0x00;    // Initial state = 0            
        outputBuffer[numBytesToSend++] = 0x0B;    // Set SCK,DO,CS -> output, DI-> input
                                                // The SK clock frequency can be worked out by below algorithm with divide by 5 set as off
                                                // SK frequency = 60MHz /((1 + [(1 + 0xValueH*256) OR 0xValueL])*2)
        outputBuffer[numBytesToSend++] = 0x86;  // command to set clock divisor
        outputBuffer[numBytesToSend++] = (byte) (dwClockDivisor & 0xFF);  //Set 0xValue L of clock divisor
        outputBuffer[numBytesToSend++] = (byte) (dwClockDivisor >> 8);  // Set 0xValue H of clock divisor            
        stat |= SPI_Device.Write(outputBuffer, numBytesToSend, ref numBytesSent);

        Delay(20);

        // Turn Off loop back in case
        numBytesToSend = 0;
        outputBuffer[numBytesToSend++] = 0x85;
        stat |= SPI_Device.Write(outputBuffer, numBytesToSend, ref numBytesSent);

        if (stat == FTDI.FT_STATUS.FT_OK)
            Console.WriteLine("\nSPI INITIALIZATION SUCCESSFUL.");

        return stat;
    }

    /*********  SEND DATA **********/
    void WREN_Command()
    {
        // This command writes WREN command
        numBytesToSend = numBytesSent = 0;
        // Chip select enable
        outputBuffer[numBytesToSend++] = 0x80;  // GPIO command ADBUS
        outputBuffer[numBytesToSend++] = 0x00;  // set values -> CS High, MOSI and SCL low
        outputBuffer[numBytesToSend++] = 0x0B;  // set directions -> bit3: CS, bit2: MISO, bit1: MOSI, bit0: SCK

        outputBuffer[numBytesToSend++] = MSB_FALLING_EDGE_CLOCK_BIT_OUT;
        outputBuffer[numBytesToSend++] = 7;
        outputBuffer[numBytesToSend++] = FLASH_CMD_WREN;   // Write WREN command to SPI FLASH

        //SPI_CS_Disable
        outputBuffer[numBytesToSend++] = 0x80;  // GPIO command ADBUS
        outputBuffer[numBytesToSend++] = 0x08;  // set values -> CS, MOSI and SCL low
        outputBuffer[numBytesToSend++] = 0x0B;  // set directions -> bit3: CS, bit2: MISO, bit1: MOSI, bit0: SCK
        
        ftStatus = SPI_Device.Write(outputBuffer, numBytesToSend, ref numBytesSent);
    }

Which command do we send to use BDBUS, first I modified string serialnumber = "FTKI02B"; // "FTKI02A"; ftStatus = SPI_Device.OpenBySerialNumber(serialnumber);

To send and receive data through BDBUS which in the following line ?

        // Chip select enable
        outputBuffer[numBytesToSend++] = 0x80;  // GPIO command ADBUS

Solution

  • I was not able to communicate in SPI may be because of capacitance. When I connected oscilloscope probe to the SPI lines, the communication worked perfectly.

    I completed the communication using BDBUS in the following way during initialization.

    "FTKI02B" is the serial number of the FT4232 that I am using.
    ftStatus = SPI_Device_B.OpenBySerialNumber("FTKI02B");
    

    To send data to Port B, I changed nothing.

    outputBuffer[numBytesToSend++] = 0x80;  //Command to set data bits.