I'm using a Teensy 4.1 to connect to a Steel Battalion Controller:
I have experience with this controller and have already written a driver for it. I was actually able to get it working as a normal joystick fairly easily using the teensy to read the info over usb and emulate a joystick.
My problem comes from writing out commands to control the LEDs using the joystick's only out endpoint.
I reduced my program to the bare minimum needed to run. Currently it turns on LEDs on and off a few times and then stops responding. I'm sending the exact same 32 byte packet in my Windows C# program and it controls the LEDs just fine.
SBCLight.ino
SBCController.cpp
SBController.h
Here is an example of the current output with USB Debugging enabled:
Is there anything obvious I'm missing. I've tried playing around with the tx_size variable. The values for tx_size, tx_interval and txep were determined using the Joystick example by parsing the descriptor. I removed that section of code to make things more concise.
I have experience with this controller and have already written a driver for it. I was actually able to get it working as a normal joystick fairly easily using the teensy to read the info over usb and emulate a joystick.
My problem comes from writing out commands to control the LEDs using the joystick's only out endpoint.
I reduced my program to the bare minimum needed to run. Currently it turns on LEDs on and off a few times and then stops responding. I'm sending the exact same 32 byte packet in my Windows C# program and it controls the LEDs just fine.
SBCLight.ino
Code:
#include <USBHost_t36.h>
#include "SBCController.h"
USBHost myusb;
USBHub hub1(myusb);
SBCController SBC(myusb);
long changeTime = 100;//milliseconds
long currentMillis;
long lastMillis;
bool flipLight = false;
void setup()
{
Serial1.begin(2000000);
while (!Serial) ; // wait for Arduino Serial Monitor
myusb.begin();
}
void loop()
{
currentMillis = millis();
if(currentMillis - lastMillis > changeTime)
{
if(flipLight)
{
SBC.txbuf_[5] = 255;
flipLight = false;
}
else
{
SBC.txbuf_[5] = 0;
flipLight = true;
}
SBC.sendLightDataPacket();
lastMillis = currentMillis;
}
myusb.Task();
delay(50);
}
SBCController.cpp
Code:
#include "SBCController.h"
void SBCController::init()
{
driver_ready_for_device(this);
}
// Again this class is solely to display as much information about a device as we can...
// This all comes from the information passed to it through the claim method.
bool SBCController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len) {
uint32_t txep = 1;
uint8_t tx_interval = 4;
tx_size_ = 32;
txpipe_ = new_Pipe(dev, 3, txep, 0, tx_size_, tx_interval);
if (!txpipe_) {
return false;
}
txpipe_->callback_function = tx_callback;
return true;
}
void SBCController::tx_callback(const Transfer_t *transfer)
{
if (!transfer->driver) return;
((SBCController *)(transfer->driver))->tx_data(transfer);
}
void SBCController::sendLightDataPacket()
{
Serial.println("trying to send light");
queue_Data_Transfer(txpipe_, txbuf_, tx_size_, this);
}
void SBCController::tx_data(const Transfer_t *transfer)
{
Serial.println("Light Sent");
}
SBController.h
Code:
#ifndef __SBCController_h_
#define __SBCController_h_
#include <Arduino.h>
#include <USBHost_t36.h>
class SBCController : public USBDriver {
public:
SBCController(USBHost &host) { init();}
Device_t *currentDevice;
void sendLightDataPacket();
bool firstSent = false;
uint8_t txbuf_[64]; // buffer to use to send commands to joystick
void (*data_received)(const Transfer_t *);
protected:
virtual bool claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len);
virtual void disconnect() {};
void init();
uint16_t tx_size_ = 0;
Pipe_t *txpipe_;
static void tx_callback(const Transfer_t *transfer);
void tx_data(const Transfer_t *transfer);
Device_t *mydevice = NULL;
};
#endif
Here is an example of the current output with USB Debugging enabled:
Code:
USB2 PLL running
reset waited 6
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 20003000
periodictable = 20003000
port change: 10001803
connect
trying to send light
begin reset
trying to send light
port change: 10001005
port enabled
end recovery
new_Device: 12 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
12 01 10 01 00 00 00 08 7B 0A 00 D0 00 01 00 00 00 01
VendorID = 0A7B, ProductID = D000, Version = 0100
Class/Subclass/Protocol = 0 / 0 / 0
Number of Configurations = 1
enumeration:
Config data length = 32
enumeration:
Configuration Descriptor:
09 02 20 00 01 01 00 80 FA
NumInterfaces = 1
ConfigurationValue = 1
09 04 00 00 02 58 42 00 00
Interface = 0
Number of endpoints = 2
Class/Subclass/Protocol = 88 / 66 / 0
07 05 82 03 20 00 04
Endpoint = 2 IN
Type = Interrupt
Max Size = 32
Polling Interval = 4
07 05 01 03 20 00 04
Endpoint = 1 OUT
Type = Interrupt
Max Size = 32
Polling Interval = 4
enumeration:
USBHub memory usage = 960
USBHub claim_device this=20001E80
new_Pipe
allocate_interrupt_pipe_bandwidth
best_bandwidth = 5, at offset = 0, shift= 0
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
Light Sent
trying to send light
trying to send light
trying to send light
trying to send light
Is there anything obvious I'm missing. I've tried playing around with the tx_size variable. The values for tx_size, tx_interval and txep were determined using the Joystick example by parsing the descriptor. I removed that section of code to make things more concise.