LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - USBMIDI_Interface.hpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 41 43 95.3 %
Date: 2020-09-08 17:44:46 Functions: 12 13 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "MIDI_Interface.hpp"
       4             : #include "USBMIDI/USBMIDI.hpp"
       5             : #include <AH/Error/Error.hpp>
       6             : #include <AH/Teensy/TeensyUSBTypes.hpp>
       7             : #include <MIDI_Parsers/USBMIDI_Parser.hpp>
       8             : 
       9             : AH_DIAGNOSTIC_WERROR()
      10             : 
      11             : #if defined(TEENSYDUINO) && !defined(TEENSY_MIDIUSB_ENABLED)
      12             : #warning                                                                       \
      13             :     "Teensy: USB MIDI not enabled. Enable it from the Tools > USB Type menu."
      14             : #endif
      15             : 
      16             : #ifndef ARDUINO
      17             : #include <gmock-wrapper.h>
      18             : #endif
      19             : 
      20             : // If the main MCU has a USB connection or is a Teensy with MIDI USB type
      21             : #if defined(USBCON) || defined(TEENSY_MIDIUSB_ENABLED) || !defined(ARDUINO)
      22             : 
      23             : BEGIN_CS_NAMESPACE
      24             : 
      25             : /**
      26             :  * @brief   A class for MIDI interfaces sending MIDI messages over a USB MIDI
      27             :  *          connection.
      28             :  * 
      29             :  * On boards that support it, this will create a native MIDI over USB interface
      30             :  * using the platform-specific libraries (e.g. MIDIUSB for Arduino Leonardo, or 
      31             :  * the Core usbMIDI library for Teensy).  
      32             :  * On boards without native USB support, it'll fall back to a serial MIDI 
      33             :  * interface at the default @ref MIDI_BAUD "MIDI baud rate" on the UART 
      34             :  * connected to the Serial to USB chip. This can be used with custom 
      35             :  * MIDI over USB firmware for the Serial to USB chip.
      36             :  * 
      37             :  * @note    See @ref md_pages_MIDI-over-USB for more information.
      38             :  * 
      39             :  * @ingroup MIDIInterfaces
      40             :  */
      41          25 : class USBMIDI_Interface : public Parsing_MIDI_Interface {
      42             :   public:
      43             :     /**
      44             :      * @brief   Construct a new USBMIDI_Interface.
      45             :      */
      46          25 :     USBMIDI_Interface() : Parsing_MIDI_Interface(parser) {}
      47             : 
      48             :     using MIDIUSBPacket_t = USBMIDI::MIDIUSBPacket_t;
      49             : 
      50             :   private:
      51             :     USBMIDI_Parser parser;
      52             : 
      53             : #ifndef ARDUINO
      54             :   public:
      55          42 :     MOCK_METHOD(void, writeUSBPacket,
      56             :                 (uint8_t, uint8_t, uint8_t, uint8_t, uint8_t));
      57          33 :     MOCK_METHOD(MIDIUSBPacket_t, readUSBPacket, ());
      58          12 :     void flushUSB() {}
      59             : 
      60             :   private:
      61             : #else
      62             :     void writeUSBPacket(uint8_t cn, uint8_t cin, uint8_t d0, uint8_t d1,
      63             :                         uint8_t d2) {
      64             :         USBMIDI::write(cn, cin, d0, d1, d2);
      65             :     }
      66             :     MIDIUSBPacket_t readUSBPacket() { return USBMIDI::read(); }
      67             :     void flushUSB() { USBMIDI::flush(); }
      68             : #endif
      69             : 
      70           3 :     void sendImpl(uint8_t header, uint8_t d1, uint8_t d2, uint8_t cn) override {
      71           6 :         writeUSBPacket(cn, header >> 4, // CN|CIN
      72           3 :                        header,          // status
      73           3 :                        d1,              // data 1
      74           3 :                        d2);             // data 2
      75           3 :         flushUSB();
      76           3 :     }
      77             : 
      78           1 :     void sendImpl(uint8_t header, uint8_t d1, uint8_t cn) override {
      79           1 :         sendImpl(header, d1, 0, cn);
      80           1 :     }
      81             : 
      82           8 :     void sendImpl(const uint8_t *data, size_t length, uint8_t cn) override {
      83          17 :         while (length > 3) {
      84           9 :             writeUSBPacket(cn, 0x4, data[0], data[1], data[2]);
      85           9 :             data += 3;
      86           9 :             length -= 3;
      87             :         }
      88           8 :         switch (length) {
      89           3 :             case 3: writeUSBPacket(cn, 0x7, data[0], data[1], data[2]); break;
      90           3 :             case 2: writeUSBPacket(cn, 0x6, data[0], data[1], 0); break;
      91           2 :             case 1: writeUSBPacket(cn, 0x5, data[0], 0, 0); break;
      92           0 :             default: break;
      93             :         }
      94           8 :         flushUSB();
      95           8 :     }
      96             : 
      97           1 :     void sendImpl(uint8_t rt, uint8_t cn) override {
      98           2 :         writeUSBPacket(cn, 0xF, // CN|CIN
      99           1 :                        rt,      // single byte
     100             :                        0,       // no data
     101             :                        0);      // no data
     102           1 :         flushUSB();
     103           1 :     }
     104             : 
     105             :   public:
     106          16 :     MIDIReadEvent read() override {
     107          40 :         for (uint8_t i = 0; i < (SYSEX_BUFFER_SIZE + 2) / 3; ++i) {
     108          24 :             MIDIUSBPacket_t midi_packet = readUSBPacket();
     109          24 :             if (midi_packet.data[0] == 0)
     110           7 :                 return MIDIReadEvent::NO_MESSAGE;
     111             : 
     112          17 :             MIDIReadEvent parseResult = parser.parse(midi_packet.data);
     113             : 
     114          17 :             if (parseResult != MIDIReadEvent::NO_MESSAGE)
     115           9 :                 return parseResult;
     116          24 :         }
     117           0 :         return MIDIReadEvent::NO_MESSAGE;
     118          16 :     }
     119             : };
     120             : 
     121             : END_CS_NAMESPACE
     122             : 
     123             : // If the main MCU doesn't have a USB connection:
     124             : // Fall back on Serial connection at the hardware MIDI baud rate.
     125             : // (Can be used with HIDUINO or USBMidiKliK.)
     126             : #else
     127             : 
     128             : #include "SerialMIDI_Interface.hpp"
     129             : 
     130             : BEGIN_CS_NAMESPACE
     131             : 
     132             : /**
     133             :  * @brief   A class for MIDI interfaces sending MIDI messages over a USB MIDI
     134             :  *          connection.
     135             :  * 
     136             :  * @note    See @ref md_pages_MIDI-over-USB for more information.
     137             :  * 
     138             :  * @ingroup MIDIInterfaces
     139             :  */
     140             : class USBMIDI_Interface : public USBSerialMIDI_Interface {
     141             :   public:
     142             :     /**
     143             :      * @brief   Construct a new USBMIDI_Interface.
     144             :      */
     145             :     USBMIDI_Interface() : USBSerialMIDI_Interface(MIDI_BAUD) {}
     146             : };
     147             : 
     148             : END_CS_NAMESPACE
     149             : 
     150             : #endif
     151             : 
     152             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.14-6-g40580cd