UsbSerial SPI support

UsbSerial already supports most of the common USB to serial chips out there but these chips are pretty “serial standard” and as you probably know there are a lot of different serial architectures.

SPI is one of them. Developed by Motorola in the 80’s allows synchronous communication between one master devices and nth number of slaves devices.

A typical SPI configuration with one SPI master and three SPI slaves.

Someone requested support for CP2130 Usb to SPI bridge and, as always I like to emphasize I am always open to support new devices but this one is not as “serial generic” as the others (Windows even doesn’t see it as serial port). It is specifically designed to bridge USB to SPI. SPI interfaces presents different capabilities compared to a simple UART. Clock signal is provided by the master so greater speeds than using simple UARTS are possible and there are nth SSX lines to select different slaves.

Because of these characteristics a new interface specific for SPI was necessary for UsbSerial but I’ve tried to preserve the same philosophy of use that governs UsbSerial. Keep in mind that SPI support is still in beta state and this interface could change due to adding new devices.

  //Common SPI operations
  boolean connectSPI(); // connect SPI device
  void writeMOSI(byte[] buffer); // send data to the selected slave via MOSI. Asynchronous call
  void readMISO(int lengthBuffer); // read data sent from the selected slave via MISO.  Asynchronous call
  void writeRead(byte[] buffer, int lenghtRead); // write and read at the same time. Asynchronous call
  void setClock(int clockDivider); // set clock speed
  void selectSlave(int nSlave); // select slave
  void setMISOCallback(UsbMISOCallback misoCallback); // set MISO callback
  void closeSPI(); // close SPI device

  // Status information
  int getClockDivider(); // get clock divider
  int getSelectedSlave(); // get selected slave
  
  // Miso callback for received data
  interface UsbMISOCallback
  {
      int onReceivedData(byte[] data);
  }

  // CP2130 speed values
  CP2130SpiDevice.CLOCK_12MHz
  CP2130SpiDevice.CLOCK_6MHz
  CP2130SpiDevice.CLOCK_3MHz;
  CP2130SpiDevice.CLOCK_1_5MHz;
  CP2130SpiDevice.CLOCK_750KHz;
  CP2130SpiDevice.CLOCK_375KHz;
  CP2130SpiDevice.CLOCK_187_5KHz;
  CP2130SpiDevice.CLOCK_93_75KHz;

Previous examples of UsbSerial provides a good start keeping in mind the minor changes.

// Define MISO callback
private UsbSpiInterface.UsbMISOCallback misoCallback = new UsbSpiInterface.UsbMISOCallback()
{

  @Override
  public int onReceivedData(byte[] data) {
     // Your code here
  }
};

//...

// Setup SPI communication
UsbSpiDevice spi = UsbSpiDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
  boolean ret = spi.connectSPI();
  if(ret){
    spi.selectSlave(0); //select slave 0
    spi.setClock(CP2130SpiDevice.CLOCK_3MHz);
    spi.setMISOCallback(misoCallback);
  }
}

// Write and read operations
spi.writeMOSI("Hola!".getBytes()); // Write "Hola!" to the selected slave through MOSI (MASTER OUTPUT SLAVE INPUT)
spi.readMISO(5); // Read 5 bytes from the MISO (MASTER INPUT SLAVE OUTPUT) line. Data will be received through UsbMISOCallback
spi.writeRead("Hola!".getBytes(), 15); // Write "Hola!" and read 15 bytes synchronously

//Close spi device
spi.closeSPI();

As I previously said, it is still in beta state and only CP2103 chipset is supported. I would really appreciate any feedback you could give me about this feature to further improvements.

Happy hacking!