Skip to content

Latest commit

 

History

53 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

libMPSSE i2c/spi Janet binding

Janet language bindings to FTDI's libMPSSE library for I2C and Serial communications on Windows & Linux.

LibMPSSE is a library written by FTDI to simplify I2C, SPI development, as configuring the underlying MPSSE hardware is fairly complex.

The Multi-Protocol Synchronous Serial Engine (MPSSE) is a piece of hardware available in some FTDI chips and cables that allows for configurable serial communication with devices, such as I2C, SPI, and JTAG, through their D2XX driver. Commands are sent to the MPSSE to execute, such as sending data, setting the clock, protocol features, or setting GPIO lines. While the chip will also appear as a Virtual COM port, that feature is not used here.

This module is an alpha-phase project written by a hobbyist -- all comments and nitpicks encouraged.

API is documented in api.md and is in flux. Function naming and usage generally follows libMPSSE, though some changes were made for ergonomics, e.g, I2C_GetChannelInfo -> (i2c/info)

Usage

A demo driver for an MPU6050 gyro is in the /examples folder

The module can be imported in a script or the REPL:

(use libmpsse)

which loads two submodules, i2c/ and spi/ which are generally the same, except the I2C functions take a 7-bit I2C address. Many functions can also be called as methods on an opened channel, such as (i2c/err) or (:err chan) and (:close chan)

Getting a channel's information:

(use libmpsse)
(i2c/channels)                                     # Number of hardware channels; some devices have multiple
# => 1

(i2c/info 1)
# => {:description "C232HM-EDHSL-0"
#     :flags 2
#     :id 67330068
#     :locid 28
#     :serial "00000000"
#     :type 8}

This is an example flow for opening a new I2C channel:

(if (> (i2c/channels) 0)
  (with [chan (i2c/open 1)]         # Open the first channel
    (-> chan
      (:write-opt :start :stop)		  # Transfer settings can be changed prior to each read/write call
      (:read-opt  :start :stop :nak-last-byte) 
      (:init :fast)                 # Initialize to 400kbs
      (:write 0x3C @"\x40\x00" 2))  # Write 2 bytes to address 0x3C

    (def buf @"some data: ")
    (:read chan 0x3C buf 2)         # Append 2 bytes from address 0x3C to buffer
    (:close chan))                  # Currently a closed channel object cannot be reopened; use (i2c/open) to create a new one
  (print "no channel found"))

The various transfer and config options are lightly documented in api-i2c.md and api-spi.md, but for a full description see the FTDI libMPSSE Application Notes 177 (i2c) and 178 (spi) as some options are only available on specific devices.

The /read and /write functions are blocking, and /channels and /info are not thread-safe

Installation

This module has been primarily written and tested on:

  • Windows 10 x64
  • lighly tested on Debian 12.11/Proxmox VM with usb passthru.
  • Fedora 44 amd64

Documentation is generated using documentarian.

Requirements:

Windows

Instructions for building jpm and Janet on Windows can be found on the Janet Docs page.

libMPSSE can be installed via jpm in a Windows Native Tools Command Prompt:

jpm install https://github.com/strangepete/janet-libMPSSE.git

or built manually:

jpm build
jpm test
jpm install

Enable debug with set "INFRA_DEBUG=1" or, optionally set INFRA_DEBUG_LEVEL=7 to a range of 0-7, with 7 being the most verbose. The ASan DLL needs to be found in PATH, or Janet will return a generic "The Specified Module Cannot Be Found." This path should be setup by using the Developer Console.

Linux

The underlying d2xx library uses libusb and requires kernel level access to the device, which means any use of the library, including jpm test needs to be run with sudo or as root. There are work-arounds but they are beyond the scope of this document.

Build with jpm as shown above, then install the D2XX linux driver as root or using sudo:

# FOLLOW THE README
cp libftd2xx.* /usr/local/lib
chmod 0755 /usr/local/lib/libftd2xx.*
ln -sf /usr/local/lib/libftd2xx.so.1.4.33 /usr/local/lib/libftd2xx.so

cp ftd2xx.h /usr/local/include
cp WinTypes.h /usr/local/include

ldconfig -v

On many distributions, an ftdi_sio module is enabled (responsible for creating a serial device) but prevents d2xx use and must be disabled:

# Check if enabled
sudo lsmod | grep ftdi_sio

# Unload temporarily
# The readme demonstrates alternate options to disable permanently 
sudo rmmod ftdi_sio
sudo rmmod usbserial

Notes

  • libMPSSE can only operate as an I2C/SPI bus master. Many GPS devices also talk as master, and as such cannot be used to get nema messages :(
  • JTAG is no longer planned, the library is no longer developed by FTDI.
  • On linux, libftdi is not d2xx; I think it would be worth targeting next, being open source and easily cross-platform.

Known issues

  • LibMPSSE reports misleading invalid index 0 (valid range: 0 to 4294967295) when no channels found
  • Underlying libusb or USB device presence/permission issues may show as functions returning :other-error
  • Rapid hot-plugging can result in an :insufficient-resources error, and possible communications issues with SPI. MPSSE is not properly reset, in addition to uninitialized memory use in ftd2xx channel list.

Tested Devices

  • C232HM-EDHSL 5v cable

About

Janet language bindings to FTDI libMPSSE for I2C / SPI communications

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages