Julia wrapper for the FTDIchip FTD2XX driver.
Install LibFTD2XX using the package manager:
]add LibFTD2XX
Platform | Architecture | Notes |
---|---|---|
Linux (x86) | 32-bit and 64-bit | 64-bit tested locally (No CI) |
Linux (ARM) | ARMv7 HF and AArch64 (ARMv8) | Tested locally (No CI) |
MacOS | 64-bit | CI active (without hardware) |
Windows | 64-bit | CI active (without hardware) |
It is likely that the kernel will automatically load VCP drivers when running on linux, which will prevent the D2XX drivers from accessing the device. Follow the guidance in the FTDI Linux driver README to unload the ftdio_sio
and usbserial
kernel modules before use. These can optionally be blacklisted if appropriate. If your device has an alternate product name you may prefer to use an alternative approach detailed here.
The D2XX drivers use raw USB access through libusb
which may not be available to non-root users. A udev file is required to enable access to a specified group. A script to create the appropriate file and user group is available, e.g., here.
LibFTD2XX provides a high-level wrapper of the underlying library functionality, detailed below.
To access the library directly, the submodule Wrapper
provides access to the functions detailed in the D2XX Programmer's Guide (FT_000071).
The demonstration considers a port running at 2MBaud which echos what it receives.
julia> using LibFTD2XX
julia> devices = D2XXDevices()
4-element Array{D2XXDevice,1}:
D2XXDevice(0, 2, 7, 67330065, 0, "FT3V1RFFA", "USB <-> Serial Converter A", Base.RefValue{FT_HANDLE}(FT_HANDLE(Ptr{Nothing} @0x0000000000000000)))
D2XXDevice(1, 2, 7, 67330065, 0, "FT3V1RFFB", "USB <-> Serial Converter B", Base.RefValue{FT_HANDLE}(FT_HANDLE(Ptr{Nothing} @0x0000000000000000)))
D2XXDevice(2, 2, 7, 67330065, 0, "FT3V1RFFC", "USB <-> Serial Converter C", Base.RefValue{FT_HANDLE}(FT_HANDLE(Ptr{Nothing} @0x0000000000000000)))
D2XXDevice(3, 2, 7, 67330065, 0, "FT3V1RFFD", "USB <-> Serial Converter D", Base.RefValue{FT_HANDLE}(FT_HANDLE(Ptr{Nothing} @0x0000000000000000)))
julia> isopen.(devices)
4-element BitArray{1}:
false
false
false
false
julia> device = devices[1]
D2XXDevice(0, 2, 7, 67330065, 0, "FT3V1RFFA", "USB <-> Serial Converter A", Base.RefValue{FT_HANDLE}(FT_HANDLE(Ptr{Nothing} @0x0000000000000000)))
julia> open(device)
julia> isopen(device)
true
julia> datacharacteristics(device, wordlength = BITS_8, stopbits = STOP_BITS_1, parity = PARITY_NONE)
julia> baudrate(device,2000000)
julia> timeout_read, timeout_wr = 200, 10; # milliseconds
julia> timeouts(device, timeout_read, timeout_wr)
julia> supertype(typeof(device))
IO
julia> write(device, Vector{UInt8}(codeunits("Hello")))
0x00000005
julia> bytesavailable(device)
0x00000005
julia> String(read(device, 5)) # read 5 bytes
"Hello"
julia> write(device, Vector{UInt8}(codeunits("World")))
0x00000005
julia> String(readavailable(device)) # read all available bytes
"World"
julia> write(device, Vector{UInt8}(codeunits("I will be deleted.")))
0x00000012
julia> bytesavailable(device)
0x00000012
julia> flush(device)
julia> bytesavailable(device)
0x00000000
julia> # Read Timeout behaviour
julia> tread = 1000 * @elapsed read(device, 5000) # nothing to read! Will timeout...
203.20976900000002
julia> timeout_read < 1.5*tread # 1.5*tread to allow for extra compile/run time.
true
julia> buffer = zeros(UInt8, 5000);
julia> twr = 1000 * @elapsed nb = write(device, buffer) # Will timeout before finishing write!
22.997304
julia> timeout_wr < 1.5*twr
true
julia> nb # doesn't correctly report number written
0x00000000
julia> Int(bytesavailable(device))
3584
julia> timeout_wr < 1.5*twr
true
julia> flush(device)
julia> timeout_wr = 1000; # increase write timeout
julia> timeouts(device, timeout_read, timeout_wr)
julia> twr = 1000 * @elapsed nb = write(device, buffer) # Won't timeout before finishing write!
15.960230999999999
julia> nb # correctly reports number written
0x00001388
julia> Int(bytesavailable(device))
5000
julia> timeout_wr < 1.5*twr
false
julia> close(device)
julia> isopen(device)
false