Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/led-drivers/spi/ProviderSpiFtdi.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <led-drivers/LedDevice.h>
#include <led-drivers/spi/ProviderSpiInterface.h>

#include <vector>
#include <Windows.h>
#include <led-drivers/spi/ftdi/ftd2xx.h>

Expand All @@ -23,6 +25,7 @@ class ProviderSpiFtdi : public QObject, public ProviderSpiInterface
{
HMODULE _dllHandle;
FT_HANDLE _deviceHandle;
std::vector<uint8_t> _writeCommand;

PTR_FT_ListDevices _fun_FT_ListDevices;
PTR_FT_OpenEx _fun_FT_OpenEx;
Expand Down
7 changes: 7 additions & 0 deletions include/led-drivers/spi/ProviderSpiLibFtdi.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
#include <led-drivers/LedDevice.h>
#include <led-drivers/spi/ProviderSpiInterface.h>

#include <vector>

#include <led-drivers/spi/ftdi/ftdi.h>
#include <led-drivers/spi/ftdi/libusb.h>

typedef struct ftdi_context* (*PTR_ftdi_new)(void);
typedef int (*PTR_ftdi_usb_open_bus_addr)(struct ftdi_context* ftdi, uint8_t bus, uint8_t addr);
typedef int (*PTR_ftdi_usb_open_string)(struct ftdi_context* ftdi, const char* description);
typedef int (*PTR_ftdi_usb_get_strings)(struct ftdi_context* ftdi, struct libusb_device* dev, char* manufacturer, int mnf_len, char* description, int desc_len, char* serial, int serial_len);
typedef void (*PTR_ftdi_free)(struct ftdi_context* ftdi);
typedef int (*PTR_ftdi_usb_reset)(struct ftdi_context* ftdi);
typedef int (*PTR_ftdi_set_baudrate)(struct ftdi_context* ftdi, int baudrate);
Expand All @@ -28,9 +32,12 @@ class ProviderSpiLibFtdi final : public QObject, public ProviderSpiInterface
{
void* _dllHandle;
struct ftdi_context* _deviceHandle;
std::vector<uint8_t> _writeCommand;

PTR_ftdi_new _fun_ftdi_new;
PTR_ftdi_usb_open_bus_addr _fun_ftdi_usb_open_bus_addr;
PTR_ftdi_usb_open_string _fun_ftdi_usb_open_string;
PTR_ftdi_usb_get_strings _fun_ftdi_usb_get_strings;
PTR_ftdi_free _fun_ftdi_free;
PTR_ftdi_usb_reset _fun_ftdi_usb_reset;
PTR_ftdi_set_baudrate _fun_ftdi_set_baudrate;
Expand Down
17 changes: 12 additions & 5 deletions sources/led-drivers/spi/ProviderSpi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,28 @@ bool ProviderSpi::init(QJsonObject deviceConfig)
// Initialise sub-class
if (LedDevice::init(deviceConfig))
{
bool isInt = false;
#ifdef ENABLE_SPI_FTDI
deviceConfig["output"].toString().toLong(&isInt, 10);
if (isInt)
bool isFtdi = false;
#ifdef ENABLE_SPI_FTDI
{
QString output = deviceConfig["output"].toString();
bool isInt = false;
output.toLong(&isInt, 10);
// Use FTDI provider for numeric bus:addr locations or ftdi_usb_open_string identifiers
// (e.g. "s:0x0403:0x6014:serial", "i:0x0403:0x6014", "d:/dev/...")
isFtdi = isInt || output.startsWith("s:") || output.startsWith("i:") || output.startsWith("d:");
if (isFtdi)
{
#ifdef WIN32
_provider = std::make_unique<ProviderSpiFtdi>(_log);
#else
_provider = std::make_unique<ProviderSpiLibFtdi>(_log);
#endif
}
}
#endif

#if !defined(WIN32) && !defined(__APPLE__)
if (!isInt)
if (!isFtdi)
{
_provider = std::make_unique<ProviderSpiGeneric>(_log);
}
Expand Down
57 changes: 33 additions & 24 deletions sources/led-drivers/spi/ProviderSpiFtdi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
* SOFTWARE.
*/

#include <algorithm>
#include <cstring>
#include <iterator>
#include <led-drivers/spi/ProviderSpiFtdi.h>
#include <utils/Logger.h>

Expand Down Expand Up @@ -220,7 +222,7 @@ QString ProviderSpiFtdi::open()

if (_fun_FT_Write(_deviceHandle, command.data(), static_cast<DWORD>(command.size()), &dwNumBytesSent) != FT_OK)
{
error = "Cannot initilize SPI interface";
error = "Cannot initialize SPI interface";
}
}

Expand All @@ -246,34 +248,43 @@ int ProviderSpiFtdi::close()

int ProviderSpiFtdi::writeBytes(unsigned size, const uint8_t* data)
{
if (size == 0 || size > 65536)
{
return -1;
}

DWORD dwNumBytesSent = 0;
std::vector<uint8_t> command;
_writeCommand.clear();
if (_writeCommand.capacity() < 3 + 3 + size + 3)
{
_writeCommand.reserve(3 + 3 + size + 3);
}

// cs & clock low
command.push_back(0x80);
command.push_back(0);
command.push_back(0x08 | 0x02 | 0x01);
_fun_FT_Write(_deviceHandle, command.data(), static_cast<DWORD>(command.size()), &dwNumBytesSent);

command.push_back(0x11);
command.push_back((size - 1) & 0xFF);
command.push_back(((size - 1) >> 8) & 0xFF);
_fun_FT_Write(_deviceHandle, command.data(), static_cast<DWORD>(command.size()), &dwNumBytesSent);
if (_fun_FT_Write(_deviceHandle, const_cast<uint8_t*>(data), size, &dwNumBytesSent) != FT_OK)
_writeCommand.push_back(0x80);
_writeCommand.push_back(0);
_writeCommand.push_back(0x08 | 0x02 | 0x01);

// MPSSE DO_WRITE command + length
_writeCommand.push_back(0x11);
_writeCommand.push_back((size - 1) & 0xFF);
_writeCommand.push_back(((size - 1) >> 8) & 0xFF);

// data payload
_writeCommand.insert(_writeCommand.end(), data, data + size);

// cs high
_writeCommand.push_back(0x80);
_writeCommand.push_back(0x08);
_writeCommand.push_back(0x08 | 0x02 | 0x01);

if (_fun_FT_Write(_deviceHandle, _writeCommand.data(), static_cast<DWORD>(_writeCommand.size()), &dwNumBytesSent) != FT_OK)
{
Error(_log, "The FTDI device reports error while writing");
return -1;
}

// cs high
command.clear();
command.push_back(0x80);
command.push_back(0x08);
command.push_back(0x08 | 0x02 | 0x01);
_fun_FT_Write(_deviceHandle, command.data(), static_cast<DWORD>(command.size()), &dwNumBytesSent);


return dwNumBytesSent;
return size;
}

int ProviderSpiFtdi::getRate()
Expand Down Expand Up @@ -308,13 +319,11 @@ QJsonObject ProviderSpiFtdi::discover(const QJsonObject& /*params*/)
QJsonArray deviceList;
QStringList files;

for (DWORD i = 0, count = std::min(numDevs, DWORD(std::size(deviceIds))); i < count; ++i)
{
for (DWORD i = 0, count = std::min(numDevs, DWORD(std::size(deviceIds))); i < count; i++)
deviceList.push_back(QJsonObject{
{"value", QJsonValue(static_cast<qint64>(deviceIds[i]))},
{"name", QString("FTDI SPI device location: %1").arg(QString::number(deviceIds[i]))}
});
}

devicesDiscovered.insert("devices", deviceList);

Expand Down
Loading