mirror of
https://github.com/Architeuthis-Flux/Jumperless.git
synced 2024-11-23 23:00:57 +01:00
Add custom class driver, instead of using HID
This commit is contained in:
parent
b54e4fa695
commit
aab83ac20f
@ -70,9 +70,13 @@ extern "C" {
|
|||||||
#define CFG_TUD_CDC 2
|
#define CFG_TUD_CDC 2
|
||||||
|
|
||||||
#define CFG_TUD_MSC 0
|
#define CFG_TUD_MSC 0
|
||||||
#define CFG_TUD_HID 1
|
#define CFG_TUD_HID 0
|
||||||
#define CFG_TUD_MIDI 0
|
#define CFG_TUD_MIDI 0
|
||||||
#define CFG_TUD_VENDOR 0
|
#define CFG_TUD_VENDOR 0
|
||||||
|
#define CFG_TUD_JUMPERLESS 1
|
||||||
|
|
||||||
|
// max is 64
|
||||||
|
#define CFG_TUD_JUMPERLESS_EP_BUFSIZE 8
|
||||||
|
|
||||||
// CDC FIFO size of TX and RX
|
// CDC FIFO size of TX and RX
|
||||||
#define CFG_TUD_CDC_RX_BUFSIZE 256
|
#define CFG_TUD_CDC_RX_BUFSIZE 256
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
#include "tusb_option.h"
|
||||||
|
|
||||||
|
#if CFG_TUD_JUMPERLESS
|
||||||
|
|
||||||
|
#if CFG_TUD_JUMPERLESS > 1
|
||||||
|
#error "Only one jumperless interface can be used"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "device/usbd.h"
|
||||||
|
#include "device/usbd_pvt.h"
|
||||||
|
#include "jumperless_device.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t itf_num;
|
||||||
|
uint8_t ep_in;
|
||||||
|
uint8_t ep_out;
|
||||||
|
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_JUMPERLESS_EP_BUFSIZE];
|
||||||
|
} jl_interface_t;
|
||||||
|
|
||||||
|
CFG_TUSB_MEM_SECTION tu_static jl_interface_t _jl_itf[CFG_TUD_JUMPERLESS];
|
||||||
|
|
||||||
|
bool tud_jumperless_ready() {
|
||||||
|
uint8_t const rhport = 0;
|
||||||
|
uint8_t const ep_in = _jl_itf[0].ep_in;
|
||||||
|
return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tud_jumperless_send_measurements(void const *data, uint16_t len) {
|
||||||
|
uint8_t const rhport = 0;
|
||||||
|
jl_interface_t *iface = &_jl_itf[0];
|
||||||
|
TU_VERIFY(usbd_edpt_claim(rhport, iface->ep_in));
|
||||||
|
TU_VERIFY(0 == tu_memcpy_s(iface->epin_buf, CFG_TUD_JUMPERLESS_EP_BUFSIZE, data, len));
|
||||||
|
return usbd_edpt_xfer(rhport, iface->ep_in, iface->epin_buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tud_jumperless_init(void) {
|
||||||
|
tud_jumperless_reset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tud_jumperless_reset(uint8_t rhport) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t tud_jumperless_open(uint8_t rhport,
|
||||||
|
tusb_desc_interface_t const *desc_itf,
|
||||||
|
uint16_t max_len) {
|
||||||
|
TU_VERIFY(0xFF == desc_itf->bInterfaceClass, 0);
|
||||||
|
|
||||||
|
uint16_t const drv_len = (uint16_t) sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t);
|
||||||
|
|
||||||
|
TU_ASSERT(max_len >= drv_len, 0);
|
||||||
|
|
||||||
|
jl_interface_t *iface = &_jl_itf[0];
|
||||||
|
|
||||||
|
uint8_t const *p_desc = (uint8_t const*) desc_itf;
|
||||||
|
|
||||||
|
p_desc = tu_desc_next(p_desc);
|
||||||
|
|
||||||
|
TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_INTERRUPT, &iface->ep_out, &iface->ep_in), 0);
|
||||||
|
|
||||||
|
iface->itf_num = desc_itf->bInterfaceNumber;
|
||||||
|
|
||||||
|
return drv_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tud_jumperless_control_xfer_cb(uint8_t rhport, uint8_t stage,
|
||||||
|
tusb_control_request_t const *request) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tud_jumperless_xfer_cb(uint8_t rhport, uint8_t ep_addr,
|
||||||
|
xfer_result_t event, uint32_t xferred_bytes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _TUSB_JUMPERLESS_DEVICE_H_
|
||||||
|
#define _TUSB_JUMPERLESS_DEVICE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Application API
|
||||||
|
bool tud_jumperless_ready();
|
||||||
|
bool tud_jumperless_send_measurements(void const* data, uint16_t len);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Internal Class Driver API
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
void tud_jumperless_init (void);
|
||||||
|
void tud_jumperless_reset (uint8_t rhport);
|
||||||
|
uint16_t tud_jumperless_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len);
|
||||||
|
bool tud_jumperless_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
|
||||||
|
bool tud_jumperless_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -233,6 +233,18 @@ tu_static usbd_class_driver_t const _usbd_driver[] =
|
|||||||
.sof = NULL
|
.sof = NULL
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_JUMPERLESS
|
||||||
|
{
|
||||||
|
DRIVER_NAME("JUMPERLESS")
|
||||||
|
.init = tud_jumperless_init,
|
||||||
|
.reset = tud_jumperless_reset,
|
||||||
|
.open = tud_jumperless_open,
|
||||||
|
.control_xfer_cb = tud_jumperless_control_xfer_cb,
|
||||||
|
.xfer_cb = tud_jumperless_xfer_cb,
|
||||||
|
.sof = NULL
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
|
enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
|
||||||
|
@ -113,6 +113,10 @@
|
|||||||
#if CFG_TUD_BTH
|
#if CFG_TUD_BTH
|
||||||
#include "class/bth/bth_device.h"
|
#include "class/bth/bth_device.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CFG_TUD_JUMPERLESS
|
||||||
|
#include "class/jumperless/jumperless_device.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#ifdef USE_TINYUSB
|
|
||||||
#include <Adafruit_TinyUSB.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CFG_TUSB_CONFIG_FILE
|
|
||||||
#include CFG_TUSB_CONFIG_FILE
|
|
||||||
#else
|
|
||||||
#include "tusb_config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ADCInput.h>
|
|
||||||
|
|
||||||
// Other parts of the code can just read from here instead of using `analogRead`
|
|
||||||
volatile uint16_t adcReadings[4] = { 0, 0, 0, 0 };
|
|
||||||
|
|
||||||
Adafruit_USBD_HID USBHID;
|
|
||||||
|
|
||||||
uint8_t desc_hid_report[] = {
|
|
||||||
TUD_HID_REPORT_DESC_GENERIC_INOUT(sizeof(adcReadings))
|
|
||||||
};
|
|
||||||
|
|
||||||
// samples all four pins, round-robin
|
|
||||||
ADCInput adc(A0, A1, A2, A3);
|
|
||||||
|
|
||||||
static uint16_t getReportCallback(uint8_t report_id, hid_report_type_t report_type,
|
|
||||||
uint8_t *buffer, uint16_t reqlen) {
|
|
||||||
// ignore this.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setReportCallback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
|
||||||
{
|
|
||||||
// ignore this as well.
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when the ADC buffer has data
|
|
||||||
static void adcCallback() {
|
|
||||||
if (adc.available() < 4) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// need a separate buffer here, since `sendReport` can't accept a volatile buffer.
|
|
||||||
uint16_t buf[4];
|
|
||||||
buf[0] = adcReadings[0] = adc.read();
|
|
||||||
buf[1] = adcReadings[1] = adc.read();
|
|
||||||
buf[2] = adcReadings[2] = adc.read();
|
|
||||||
buf[3] = adcReadings[3] = adc.read();
|
|
||||||
|
|
||||||
// only send readings if HID is "ready". Otherwise `sendReport` just hangs.
|
|
||||||
if (tud_hid_n_ready(0)) {
|
|
||||||
USBHID.sendReport(0, buf, sizeof(buf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupAdcHidStuff() {
|
|
||||||
USBHID.setPollInterval(1);
|
|
||||||
USBHID.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
|
||||||
USBHID.setStringDescriptor("Jumperless USB Analog");
|
|
||||||
USBHID.setReportCallback(getReportCallback, setReportCallback);
|
|
||||||
USBHID.begin();
|
|
||||||
|
|
||||||
adc.setBuffers(4, 32);
|
|
||||||
adc.onReceive(adcCallback);
|
|
||||||
// the sample rate passed here is already adjusted for the number of pins.
|
|
||||||
// in other words: passing 1000 actually samples at a rate of 4000, such that
|
|
||||||
// values for all 4 pins are available every millisecond.
|
|
||||||
adc.begin(1000);
|
|
||||||
}
|
|
86
JumperlessNano/src/AdcUsb.cpp
Normal file
86
JumperlessNano/src/AdcUsb.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifdef USE_TINYUSB
|
||||||
|
#include <Adafruit_TinyUSB.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_TUSB_CONFIG_FILE
|
||||||
|
#include CFG_TUSB_CONFIG_FILE
|
||||||
|
#else
|
||||||
|
#include "tusb_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ADCInput.h>
|
||||||
|
|
||||||
|
// Other parts of the code can just read from here instead of using `analogRead`
|
||||||
|
volatile uint16_t adcReadings[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
// samples all four pins, round-robin
|
||||||
|
ADCInput adc(A0, A1, A2, A3);
|
||||||
|
|
||||||
|
// called when the ADC buffer has data
|
||||||
|
static void adcCallback() {
|
||||||
|
if (adc.available() < 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// need a separate buffer here, since `sendReport` can't accept a volatile buffer.
|
||||||
|
uint16_t buf[4];
|
||||||
|
buf[0] = adcReadings[0] = adc.read();
|
||||||
|
buf[1] = adcReadings[1] = adc.read();
|
||||||
|
buf[2] = adcReadings[2] = adc.read();
|
||||||
|
buf[3] = adcReadings[3] = adc.read();
|
||||||
|
|
||||||
|
if (tud_jumperless_ready()) {
|
||||||
|
tud_jumperless_send_measurements(buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This class is needed to feed the custom interface descriptor to the Adafruit USB library.
|
||||||
|
// The actual functionality for allocating endpoints, handling transfers etc. is implemented
|
||||||
|
// within `class/jumperless/jumperless_device.c` in the tinyusb tree.
|
||||||
|
class JumperlessUsbInterface : public Adafruit_USBD_Interface {
|
||||||
|
public:
|
||||||
|
JumperlessUsbInterface();
|
||||||
|
|
||||||
|
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
|
||||||
|
uint16_t bufsize);
|
||||||
|
};
|
||||||
|
|
||||||
|
JumperlessUsbInterface::JumperlessUsbInterface() {
|
||||||
|
this->setStringDescriptor("Jumperless Analog");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t JumperlessUsbInterface::getInterfaceDescriptor(uint8_t itfnum,
|
||||||
|
uint8_t *buf,
|
||||||
|
uint16_t bufsize) {
|
||||||
|
uint16_t epsize = CFG_TUD_JUMPERLESS_EP_BUFSIZE;
|
||||||
|
uint8_t ep_interval = 1;
|
||||||
|
uint8_t desc[] = {
|
||||||
|
9, TUSB_DESC_INTERFACE, itfnum, 0, 2, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, 0,
|
||||||
|
7, TUSB_DESC_ENDPOINT, 0x80, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(epsize), ep_interval,
|
||||||
|
7, TUSB_DESC_ENDPOINT, 0x00, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(epsize), ep_interval
|
||||||
|
};
|
||||||
|
uint16_t const len = sizeof(desc);
|
||||||
|
if (bufsize < len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != NULL) {
|
||||||
|
memcpy(buf, desc, len);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
JumperlessUsbInterface jlUsbInterface;
|
||||||
|
|
||||||
|
void setupAdcUsbStuff() {
|
||||||
|
TinyUSBDevice.addInterface(jlUsbInterface);
|
||||||
|
|
||||||
|
adc.setBuffers(4, 32);
|
||||||
|
adc.onReceive(adcCallback);
|
||||||
|
// the sample rate passed here is already adjusted for the number of pins.
|
||||||
|
// in other words: passing 1000 actually samples at a rate of 4000, such that
|
||||||
|
// values for all 4 pins are available every millisecond.
|
||||||
|
adc.begin(1000);
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#ifndef JUMPERLESS_HID_H
|
#ifndef JUMPERLESS_ADC_USB_H
|
||||||
#define JUMPERLESS_HID_H
|
#define JUMPERLESS_ADC_USB_H
|
||||||
|
|
||||||
// if `setupAdcHidStuff` was called, this always contains somewhat up-to-date ADC readings
|
// if `setupAdcHidStuff` was called, this always contains somewhat up-to-date ADC readings
|
||||||
extern uint16_t adcReadings[4];
|
extern uint16_t adcReadings[4];
|
||||||
|
|
||||||
void setupAdcHidStuff();
|
void setupAdcUsbStuff();
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "AdcHid.h"
|
#include "AdcUsb.h"
|
||||||
|
|
||||||
Adafruit_USBD_CDC USBSer1;
|
Adafruit_USBD_CDC USBSer1;
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ void setup()
|
|||||||
|
|
||||||
USBSer1.begin(115200);
|
USBSer1.begin(115200);
|
||||||
|
|
||||||
setupAdcHidStuff();
|
setupAdcUsbStuff();
|
||||||
|
|
||||||
#ifdef EEPROMSTUFF
|
#ifdef EEPROMSTUFF
|
||||||
EEPROM.begin(256);
|
EEPROM.begin(256);
|
||||||
|
Loading…
Reference in New Issue
Block a user