Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
PluggableUSBMIDI.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <cstdint>
6#include <utility>
7
8#include <USB/PluggableUSBDevice.h>
9#include <drivers/Timeout.h>
10#include <platform/Callback.h>
11
14#include <Settings/NamespaceSettings.hpp>
15
17
18class PluggableUSBMIDI : protected arduino::internal::PluggableUSBModule,
19 protected BulkRX<PluggableUSBMIDI, uint32_t, 64>,
20 protected BulkTX<PluggableUSBMIDI, uint32_t, 64> {
21 public:
24
25 public:
26 using setup_packet_t = USBDevice::setup_packet_t;
27 using DeviceState = USBDevice::DeviceState;
28 using microseconds = std::chrono::microseconds;
29
30 private:
31 // BulkTX/RX API
32 friend class BulkTX<PluggableUSBMIDI, uint32_t, 64>;
33 friend class BulkRX<PluggableUSBMIDI, uint32_t, 64>;
34 static constexpr uint32_t get_packet_size() { return 64; }
35
37 auto cb = mbed::callback(this, &PluggableUSBMIDI::timeout_callback);
38 timeout.attach(std::move(cb), timeout_duration);
39 }
40 void cancel_timeout() { timeout.detach(); }
41 void tx_start(const void *data, uint32_t size) {
42 auto data_u8 = reinterpret_cast<uint8_t *>(const_cast<void *>(data));
43 write_start(bulk_in_ep, data_u8, size);
44 }
45 void tx_start_timeout(const void *data, uint32_t size) {
46 tx_start(data, size);
47 }
48 void tx_start_isr(const void *data, uint32_t size) { tx_start(data, size); }
49 void rx_start(void *data, uint32_t size) {
50 read_start(bulk_out_ep, reinterpret_cast<uint8_t *>(data), size);
51 }
52 void rx_start_isr(void *data, uint32_t size) { rx_start(data, size); }
53
54 public:
56 bool connected() const;
57
61 uint32_t read() {
62 uint32_t data = 0;
63 read(data);
64 return data;
65 }
66
67 using BulkRX<PluggableUSBMIDI, uint32_t, 64>::read;
68 using BulkTX<PluggableUSBMIDI, uint32_t, 64>::write;
69 using BulkTX<PluggableUSBMIDI, uint32_t, 64>::write_nonblock;
70 using BulkTX<PluggableUSBMIDI, uint32_t, 64>::send_now;
71
80
82 uint32_t getWriteError() const { return write_errors; }
84 uint32_t clearWriteError() { return std::exchange(write_errors, 0); }
85
86 protected:
87 void init(EndpointResolver &resolver) override;
88 void callback_state_change(DeviceState new_state) override;
89 uint32_t callback_request(const setup_packet_t *setup,
90 USBDevice::RequestResult *result,
91 uint8_t **data) override;
93 bool aborted) override;
94 bool callback_set_configuration(uint8_t configuration) override;
95 void callback_set_interface(uint16_t interface, uint8_t alternate) override;
96
97 const uint8_t *string_iinterface_desc() override;
98 const uint8_t *configuration_desc(uint8_t index) override;
99 uint8_t getProductVersion() override { return 16; }
100
101 protected:
105 mbed::Timeout timeout;
106 uint32_t write_errors {0};
107
108 usb_ep_t bulk_in_ep;
109 usb_ep_t bulk_out_ep;
110 uint8_t config_descriptor[0x65];
111
112 // Interrupt handlers
116 void in_callback() {
117 assert_locked();
118 write_finish(bulk_in_ep);
120 }
122 assert_locked();
123 uint32_t num_bytes_read = read_finish(bulk_out_ep);
124 BulkRX::rx_callback(num_bytes_read);
125 }
126};
127
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
void setErrorTimeout(microseconds timeout)
USBDevice::setup_packet_t setup_packet_t
uint8_t getProductVersion() override
microseconds error_timeout_duration
void rx_start(void *data, uint32_t size)
void rx_start_isr(void *data, uint32_t size)
USBDevice::DeviceState DeviceState
uint32_t read()
Try reading a 4-byte MIDI USB message.
void callback_state_change(DeviceState new_state) override
uint32_t getWriteError() const
Count how many USB packets were dropped.
const uint8_t * configuration_desc(uint8_t index) override
microseconds timeout_duration
void callback_set_interface(uint16_t interface, uint8_t alternate) override
interrupt_atomic< bool > usb_connected
void setTimeout(microseconds timeout)
Set the timeout, the number of microseconds to buffer the outgoing MIDI messages.
bool callback_set_configuration(uint8_t configuration) override
bool connected() const
Check if this class is connected and ready.
void init(EndpointResolver &resolver) override
uint32_t callback_request(const setup_packet_t *setup, USBDevice::RequestResult *result, uint8_t **data) override
void tx_start_isr(const void *data, uint32_t size)
bool callback_request_xfer_done(const setup_packet_t *setup, bool aborted) override
void tx_start_timeout(const void *data, uint32_t size)
uint8_t config_descriptor[0x65]
const uint8_t * string_iinterface_desc() override
std::chrono::microseconds microseconds
static constexpr uint32_t get_packet_size()
void tx_start(const void *data, uint32_t size)
uint32_t clearWriteError()
Clear the counter of how many USB packets were dropped.
Wrapper that provides atomic access to variables shared between the main program and interrupt handle...
Definition Atomic.hpp:81
Receives Bulk packets (OUT for device mode, IN for host mode)
Definition BulkRX.hpp:12
void rx_callback(uint32_t num_bytes_read)
Sends Bulk packets (IN for device mode, OUT for host mode)
Definition BulkTX.hpp:12
void tx_callback()
uint32_t write_nonblock(const MessageType *msgs, uint32_t num_msgs)
Send multiple MIDI USB messages without blocking.
void timeout_callback()
void send_now()
Try sending the buffered data now.
void write(MessageType msg)
Send a MIDI USB message.