LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces/USBMIDI/LowLevel - BulkTX.hpp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 3 3 100.0 %
Date: 2024-11-09 15:32:27 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <cstddef>
       4             : 
       5             : #include <MIDI_Interfaces/USBMIDI/util/Atomic.hpp>
       6             : #include <Settings/NamespaceSettings.hpp>
       7             : 
       8             : BEGIN_CS_NAMESPACE
       9             : 
      10             : /// Sends Bulk packets (IN for device mode, OUT for host mode)
      11             : template <class Derived, class MessageTypeT, uint16_t MaxPacketSizeV>
      12             : struct BulkTX {
      13             :   public:
      14             :     using MessageType = MessageTypeT;
      15             : 
      16             :     /// Send a MIDI USB message. May block.
      17             :     ///
      18             :     /// @param  msg
      19             :     ///         The 4-byte MIDI USB message to send.
      20             :     void write(MessageType msg);
      21             : 
      22             :     /// Send multiple MIDI USB messages. May block.
      23             :     ///
      24             :     /// @param  msgs
      25             :     ///         An array of 4-byte MIDI USB messages to send.
      26             :     /// @param  num_msgs
      27             :     ///         The number of messages in the array.
      28             :     void write(const MessageType *msgs, uint32_t num_msgs);
      29             : 
      30             :     /// Send multiple MIDI USB messages. May block.
      31             :     template <size_t N>
      32             :     void write(const MessageType (&msgs)[N]) {
      33             :         write(msgs, N);
      34             :     }
      35             : 
      36             :     /// Send multiple MIDI USB messages without blocking.
      37             :     ///
      38             :     /// @param  msgs
      39             :     ///         An array of 4-byte MIDI USB messages to send.
      40             :     /// @param  num_msgs
      41             :     ///         The number of messages in the array.
      42             :     /// @return The number of messages that were actually sent.
      43             :     uint32_t write_nonblock(const MessageType *msgs, uint32_t num_msgs);
      44             : 
      45             :     /// Try sending the buffered data now.
      46             :     /// Start transmitting the latest packet if possible, even if it isn't full
      47             :     /// yet. If the latest packet is empty, this function has no effect.
      48             :     void send_now();
      49             : 
      50             :     /// Check if all transfers have completed.
      51             :     bool is_done() const;
      52             : 
      53             :     /// Get the number messages that failed to send.
      54             :     uint32_t getWriteError() const { return writing.error.load(mo_rlx); }
      55             :     /// Get and clear the number messages that failed to send.
      56             :     uint32_t clearWriteError() { return writing.error.exchange(0, mo_rlx); }
      57             : 
      58             :   protected:
      59             :     void reset(uint16_t packet_size = MaxPacketSize);
      60             :     bool wait_connect();
      61             : 
      62             :   private:
      63             :     static constexpr uint16_t MaxPacketSize = MaxPacketSizeV;
      64             :     static constexpr uint16_t SizeReserved = MaxPacketSize + 1;
      65             : 
      66             :   protected:
      67             :     // Derived should implement the following methods:
      68             : 
      69             :     /// Start a timeout (e.g. using a timer interrupt) that later calls
      70             :     /// @ref timeout_callback().
      71             :     void start_timeout() = delete;
      72             :     /// Cancel the timeout started by @ref timeout_callback().
      73             :     void cancel_timeout() = delete;
      74             :     /// Start a USB transfer (from the main program).
      75             :     void tx_start(const void *data, uint32_t size) = delete;
      76             :     /// Start a USB transfer (from the timeout callback).
      77             :     void tx_start_timeout(const void *data, uint32_t size) = delete;
      78             :     /// Start a USB transfer (from the USB interrupt handler).
      79             :     void tx_start_isr(const void *data, uint32_t size) = delete;
      80             : 
      81             :   private:
      82             :     constexpr static std::memory_order mo_seq = std::memory_order_seq_cst;
      83             :     constexpr static std::memory_order mo_rel = std::memory_order_release;
      84             :     constexpr static std::memory_order mo_acq = std::memory_order_acquire;
      85             :     constexpr static std::memory_order mo_rlx = std::memory_order_relaxed;
      86             :     constexpr static std::memory_order mo_acq_rel = std::memory_order_acq_rel;
      87             : 
      88             :     /// State for writing outgoing USB-MIDI data.
      89             :     struct Writing {
      90             :         struct Buffer {
      91             :             uint16_t size {0};
      92             :             alignas(MessageType) uint8_t buffer[MaxPacketSize];
      93             :         } buffers[2];
      94             :         interrupt_atomic<Buffer *> active_writebuffer {&buffers[0]};
      95             :         interrupt_atomic<Buffer *> sending {nullptr};
      96             :         interrupt_atomic<Buffer *> send_later {nullptr};
      97             :         interrupt_atomic<Buffer *> send_now {nullptr};
      98             :         interrupt_atomic<uint32_t> error {0};
      99             :         uint16_t packet_size = MaxPacketSize;
     100             :     } writing;
     101             :     using wbuffer_t = typename Writing::Buffer;
     102             :     bool disconnected = false;
     103             : 
     104       94934 :     uint32_t index_of(wbuffer_t *p) const { return p - writing.buffers; }
     105       94934 :     wbuffer_t *other_buf(wbuffer_t *p) {
     106       94934 :         return &writing.buffers[!index_of(p)];
     107             :     }
     108             :     uint32_t write_impl(const MessageType *msgs, uint32_t num_msgs);
     109             : 
     110             :   protected:
     111             :     void timeout_callback();
     112             :     void tx_callback();
     113             : };
     114             : 
     115             : END_CS_NAMESPACE
     116             : 
     117             : #include "BulkTX.ipp"

Generated by: LCOV version 1.15