1#define CS_MIDI_USB_ASSERT(a) \
4 Serial.println("USB Host MIDI: Assertion failed: " #a); \
13constexpr static auto mo_rel = std::memory_order_release;
14constexpr static auto mo_acq = std::memory_order_acquire;
15constexpr static auto mo_rlx = std::memory_order_relaxed;
16constexpr static auto mo_acq_rel = std::memory_order_acq_rel;
20template <u
int16_t MaxPacketSize>
22 contribute_Pipes(mypipes,
len(mypipes));
23 contribute_Transfers(mytransfers,
len(mytransfers));
27 driver_ready_for_device(
this);
30template <u
int16_t MaxPacketSize>
32 const uint8_t *descriptors,
39 USBHost::println_(
"This interface is not MIDI");
42 USBHost::println_(
"claimed");
82template <u
int16_t MaxPacketSize>
90template <u
int16_t MaxPacketSize>
96template <u
int16_t MaxPacketSize>
103template <u
int16_t MaxPacketSize>
111template <u
int16_t MaxPacketSize>
117 queue_Data_Transfer(
txpipe, buffer, size,
this);
120template <u
int16_t MaxPacketSize>
125 queue_Data_Transfer(
txpipe, buffer, size,
this);
127template <u
int16_t MaxPacketSize>
132 return transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
135template <u
int16_t MaxPacketSize>
139 queue_Data_Transfer(
rxpipe, buffer, size,
this);
142template <u
int16_t MaxPacketSize>
146 queue_Data_Transfer(
rxpipe, buffer, size,
this);
148template <u
int16_t MaxPacketSize>
151 return transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
156template <u
int16_t MaxPacketSize>
161template <u
int16_t MaxPacketSize>
164 const uint32_t *end = msgs + num_msgs;
169template <u
int16_t MaxPacketSize>
172 uint32_t total_sent = 0, sent = 1;
173 while (total_sent < num_msgs && sent != 0) {
174 sent =
write_impl(msgs + total_sent, num_msgs - total_sent,
true);
180template <u
int16_t MaxPacketSize>
182 uint32_t active_idx, size;
240template <u
int16_t MaxPacketSize>
254 uint32_t old_idx = active_idx;
256 if (old_idx != active_idx) {
262 return std::make_tuple(active_idx, writebuffer, size);
265template <u
int16_t MaxPacketSize>
287 auto old_idx = active_idx;
301 memcpy(&writebuf->buffer[size], msgs, free_size);
302 uint32_t newsize = size + free_size;
305 while (!writebuf->size.compare_exchange_weak(size, newsize,
mo_rel)) {
316 memcpy(&writebuf->buffer[size], msgs, free_size);
317 newsize = size + free_size;
326 else if (size == 0) {
329 std::atomic_signal_fence(
mo_rel);
335 return free_size / 4u;
338template <u
int16_t MaxPacketSize>
340 uint32_t active_idx) {
343 if (old_timeout !=
nullptr)
374 std::atomic_signal_fence(
mo_rel);
381template <u
int16_t MaxPacketSize>
383 std::atomic_signal_fence(
mo_acq);
392 bool old_ready = sendbuffer->ready_to_send.exchange(
true,
mo_rlx);
416 std::atomic_signal_fence(
mo_rel);
421template <u
int16_t MaxPacketSize>
423 std::atomic_signal_fence(
mo_acq);
431 uint32_t next_idx = !sent_idx;
448 sent->ready_to_send.store(
false,
mo_rlx);
449 uint32_t oldsize = sent->size.exchange(0,
mo_rel);
461 std::atomic_signal_fence(
mo_rel);
467 sent->ready_to_send.store(
false,
mo_rlx);
468 uint32_t oldsize = sent->size.exchange(0,
mo_rel);
475template <u
int16_t MaxPacketSize>
488 memcpy(&data, &readbuffer.buffer[readbuffer.index], 4);
490 readbuffer.index += 4;
492 if (readbuffer.index == readbuffer.size) {
509template <u
int16_t MaxPacketSize>
518 if (num_bytes_read == 0) {
525 writebuffer.
index = 0;
526 writebuffer.size = num_bytes_read;
541template <u
int16_t MaxPacketSize>
543template <u
int16_t MaxPacketSize>
#define BEGIN_CS_NAMESPACE
static constexpr auto mo_rel
#define CS_MIDI_USB_ASSERT(a)
static constexpr auto mo_rlx
static constexpr auto mo_acq_rel
static constexpr auto mo_acq
Teensy USB Host MIDI driver.
uint8_t buffer[PacketSize]
void disconnect() override
uint32_t read_finish(const Transfer_t *transfer)
void read_start(uint8_t *buffer, uint32_t size)
static constexpr uint32_t PacketSize
USB packet size. Must be a power of two.
std::atomic< uint32_t > size
uint32_t write_finish(const Transfer_t *transfer)
uint32_t write_nonblock(const uint32_t *msgs, uint32_t num_msgs)
Send multiple MIDI USB messages without blocking.
bool claim_if_midi(Device_t *device, int type, const uint8_t *descriptors, uint32_t len)
void timer_event(USBDriverTimer *whichtimer) override
static constexpr uint32_t SizeReserved
uint32_t read()
Try reading a 4-byte MIDI USB message.
bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len) override
struct TeensyHostMIDI::Reading::Buffer buffers[NumRxPackets]
void send_now()
Try sending the buffered data now.
USBDriverTimer write_timeout
std::atomic< uint32_t > write_idx
std::atomic< uint32_t > active_writebuffer
void in_callback(const Transfer_t *transfer)
std::atomic< uint32_t > available
writebuf_size_tup read_writebuf_size()
void read_start_isr(uint8_t *buffer, uint32_t size)
struct TeensyHostMIDI::Reading reading
typename Reading::Buffer rbuffer_t
microseconds timeout_duration
static constexpr size_t len(T(&)[N])
std::atomic< Buffer * > sending
uint32_t write_impl(const uint32_t *msgs, uint32_t num_msgs, bool nonblocking)
void write_start(uint8_t *buffer, uint32_t size)
typename Writing::Buffer wbuffer_t
static void tx_callback(const Transfer_t *transfer)
std::atomic< uint32_t > read_idx
std::atomic< bool > reading
bool send_now_impl_nonblock(uint32_t activebuf_idx)
std::atomic< bool > ready_to_send
void out_callback(const Transfer_t *transfer)
std::atomic< Buffer * > send_timeout
static constexpr uint32_t NumRxPackets
static void rx_callback(const Transfer_t *transfer)
struct TeensyHostMIDI::Writing::Buffer buffers[2]
void write(uint32_t msg)
Send a MIDI USB message.
strbuf_t mystring_bufs[1]
void write_start_isr(uint8_t *buffer, uint32_t size)
struct TeensyHostMIDI::Writing writing
constexpr auto min(const T &a, const U &b) -> decltype(b< a ? b :a)
Return the smaller of two numbers/objects.