Control Surface  1.1.1
MIDI Control Surface library for Arduino
MIDI_Interface.cpp
Go to the documentation of this file.
1 #include "MIDI_Interface.hpp"
2 
4 
6  setAsDefault(); // Make this the default MIDI Interface
7 }
8 
10  if (getDefault() == this)
11  DefaultMIDI_Interface = nullptr;
12 }
13 
15 
17 
19 
20 // -------------------------------- SENDING --------------------------------- //
21 
22 void MIDI_Interface::send(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2) {
23  sendOnCable(m, c, d1, d2, 0);
24 }
25 
26 void MIDI_Interface::send(uint8_t m, uint8_t c, uint8_t d1) {
27  sendOnCable(m, c, d1, 0);
28 }
29 
30 void MIDI_Interface::sendOnCable(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2,
31  uint8_t cn) {
32  c--; // Channels are zero-based
33  m &= 0xF0; // bitmask high nibble
34  m |= 0b10000000; // set msb
35  c &= 0x0F; // bitmask low nibble
36  d1 &= 0x7F; // clear msb
37  d2 &= 0x7F; // clear msb
38  cn &= 0x0F; // bitmask low nibble
39  sendImpl(m, c, d1, d2, cn);
40 }
41 
42 void MIDI_Interface::sendOnCable(uint8_t m, uint8_t c, uint8_t d1, uint8_t cn) {
43  c--; // Channels are zero-based
44  m &= 0xF0; // bitmask high nibble
45  m |= 0b10000000; // set msb
46  c &= 0x0F; // bitmask low nibble
47  d1 &= 0x7F; // clear msb
48  cn &= 0x0F; // bitmask low nibble
49  sendImpl(m, c, d1, cn);
50 }
51 
52 void MIDI_Interface::sendOnCable(uint8_t r, uint8_t cn) {
53  r |= 0b10000000; // set msb
54  cn &= 0x0F; // bitmask low nibble
55  sendImpl(r, cn);
56 }
57 
59  uint8_t velocity) {
60  if (address)
61  sendImpl(NOTE_ON, address.getRawChannel(), address.getAddress(),
62  velocity, address.getCableNumber());
63 }
65  uint8_t velocity) {
66  if (address)
67  sendImpl(NOTE_OFF, address.getRawChannel(), address.getAddress(),
68  velocity, address.getCableNumber());
69 }
70 void MIDI_Interface::sendKP(MIDICNChannelAddress address, uint8_t pressure) {
71  if (address)
72  sendImpl(KEY_PRESSURE, address.getRawChannel(), address.getAddress(),
73  pressure, address.getCableNumber());
74 }
75 void MIDI_Interface::sendCC(MIDICNChannelAddress address, uint8_t value) {
76  if (address)
77  sendImpl(CC, address.getRawChannel(), address.getAddress(), value,
78  address.getCableNumber());
79 }
80 void MIDI_Interface::sendPC(MIDICNChannel address, uint8_t value) {
81  if (address)
82  sendImpl(PROGRAM_CHANGE, address.getRawChannel(), value,
83  address.getCableNumber());
84 }
86  if (address)
87  sendImpl(PROGRAM_CHANGE, address.getRawChannel(), address.getAddress(),
88  address.getCableNumber());
89 }
90 void MIDI_Interface::sendCP(MIDICNChannel address, uint8_t pressure) {
91  if (address)
92  sendImpl(CHANNEL_PRESSURE, address.getRawChannel(), pressure,
93  address.getCableNumber());
94 }
95 void MIDI_Interface::sendPB(MIDICNChannel address, uint16_t value) {
96  if (address)
97  sendImpl(PITCH_BEND, address.getRawChannel(), value & 0x7F, value >> 7,
98  address.getCableNumber());
99 }
101  if (message.length) {
102  if (message.length < 2) {
103  ERROR(F("Error: invalid SysEx length"), 0x7F7F);
104  return;
105  }
106  sendImpl(message.data, message.length, message.CN);
107  }
108 }
109 void MIDI_Interface::send(uint8_t rt, uint8_t cn) {
110  if (rt) {
111  sendImpl(rt, cn);
112  }
113 }
114 
115 // -------------------------------- PARSING --------------------------------- //
116 
118  : parser(parser) {}
119 
121  return parser.getChannelMessage();
122 }
123 
125  return parser.getSysEx();
126 }
127 
128 uint8_t Parsing_MIDI_Interface::getCN() const { return parser.getCN(); }
129 
130 // -------------------------------- READING --------------------------------- //
131 
133  bool repeat = true;
134  while (repeat) {
135  MIDI_read_t event = read();
136  repeat = dispatchMIDIEvent(event);
137  }
138 }
139 
140 #pragma GCC diagnostic push
141 #pragma GCC diagnostic ignored "-Wswitch-enum"
142 
144  switch (event) {
145  case NO_MESSAGE: return false;
146  case CHANNEL_MESSAGE: onChannelMessage(); return true;
147  case SYSEX_MESSAGE: onSysExMessage(); return true;
148  default: onRealtimeMessage(static_cast<uint8_t>(event)); return true;
149  }
150 }
151 
152 #pragma GCC diagnostic pop
153 
155  if (callbacks)
156  callbacks->onRealtimeMessage(*this, message);
157 }
158 
160  if (callbacks)
161  callbacks->onChannelMessage(*this);
162 }
163 
165  if (callbacks)
166  callbacks->onSysExMessage(*this);
167 }
168 
MIDI_Parser::getChannelMessage
ChannelMessage getChannelMessage()
Get the latest MIDI channel message.
Definition: MIDI_Parser.cpp:17
MIDI_Interface::DefaultMIDI_Interface
static MIDI_Interface * DefaultMIDI_Interface
Definition: MIDI_Interface.hpp:182
CHANNEL_PRESSURE
const uint8_t CHANNEL_PRESSURE
Definition: MIDI_Parser.hpp:21
MIDI_Interface::getDefault
static MIDI_Interface * getDefault()
Return the default MIDI interface.
Definition: MIDI_Interface.cpp:18
SysExMessage
Definition: MIDI_Parser.hpp:64
Parsing_MIDI_Interface::getCN
uint8_t getCN() const
Return the cable number of the received message.
Definition: MIDI_Interface.cpp:128
MIDI_Interface::send
void send(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2)
Send a 3-byte MIDI packet.
Definition: MIDI_Interface.cpp:22
Parsing_MIDI_Interface::parser
MIDI_Parser & parser
Definition: MIDI_Interface.hpp:239
SysExMessage::data
const uint8_t * data
Definition: MIDI_Parser.hpp:72
Parsing_MIDI_Interface::read
virtual MIDI_read_t read()=0
Parsing_MIDI_Interface::getSysExMessage
SysExMessage getSysExMessage() const
Return the received system exclusive message.
Definition: MIDI_Interface.cpp:124
MIDI_Interface::MIDI_Interface
MIDI_Interface()
Constructor.
Definition: MIDI_Interface.cpp:5
Parsing_MIDI_Interface::dispatchMIDIEvent
bool dispatchMIDIEvent(MIDI_read_t event)
Definition: MIDI_Interface.cpp:143
MIDI_read_t
MIDI_read_t
Definition: MIDI_Parser.hpp:29
MIDI_Parser
Definition: MIDI_Parser.hpp:84
MIDICNChannelAddress::getRawChannel
constexpr uint8_t getRawChannel() const
Get the channel [0, 15].
Definition: MIDICNChannelAddress.hpp:148
CHANNEL_MESSAGE
Definition: MIDI_Parser.hpp:31
BEGIN_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
Definition: Settings/NamespaceSettings.hpp:9
Parsing_MIDI_Interface::onChannelMessage
void onChannelMessage()
Definition: MIDI_Interface.cpp:159
MIDI_Interface::sendCP
void sendCP(MIDICNChannel address, uint8_t pressure)
Send a MIDI Channel Pressure event.
Definition: MIDI_Interface.cpp:90
MIDICNChannelAddress::getCableNumber
constexpr uint8_t getCableNumber() const
Get the cable number [0, 15].
Definition: MIDICNChannelAddress.hpp:151
MIDI_Interface::sendKP
void sendKP(MIDICNChannelAddress address, uint8_t pressure)
Send a MIDI Key Pressure event.
Definition: MIDI_Interface.cpp:70
MIDI_Interface::sendNoteOn
void sendNoteOn(MIDICNChannelAddress address, uint8_t velocity)
Send a MIDI Note On event.
Definition: MIDI_Interface.cpp:58
MIDI_Callbacks::onSysExMessage
virtual void onSysExMessage(Parsing_MIDI_Interface &midi)
Definition: MIDI_Interface.hpp:250
END_CS_NAMESPACE
#define END_CS_NAMESPACE
Definition: Settings/NamespaceSettings.hpp:10
MIDI_Callbacks::onRealtimeMessage
virtual void onRealtimeMessage(Parsing_MIDI_Interface &midi, uint8_t message)
Definition: MIDI_Interface.hpp:251
Parsing_MIDI_Interface::update
void update() override
Read the MIDI interface and call the callback if a message is received.
Definition: MIDI_Interface.cpp:132
ERROR
#define ERROR(msg, errc)
Print the error message and error code, and stop the execution if FATAL_ERRORS are enabled.
Definition: Error.hpp:42
Parsing_MIDI_Interface::Parsing_MIDI_Interface
Parsing_MIDI_Interface(MIDI_Parser &parser)
Construct a MIDI interface with the given parser.
Definition: MIDI_Interface.cpp:117
MIDICNChannelAddress
A type-safe utility class for saving a MIDI address consisting of a 7-bit address,...
Definition: MIDICNChannelAddress.hpp:82
Parsing_MIDI_Interface::getChannelMessage
ChannelMessage getChannelMessage()
Return the received channel message.
Definition: MIDI_Interface.cpp:120
MIDICNChannelAddress::getAddress
constexpr uint8_t getAddress() const
Get the address [0, 127].
Definition: MIDICNChannelAddress.hpp:141
MIDI_Callbacks::onChannelMessage
virtual void onChannelMessage(Parsing_MIDI_Interface &midi)
Definition: MIDI_Interface.hpp:249
MIDI_Interface::sendImpl
virtual void sendImpl(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2, uint8_t cn)=0
Low-level function for sending a 3-byte MIDI message.
MIDI_Interface::sendPB
void sendPB(MIDICNChannel address, uint16_t value)
Send a MIDI Pitch Bend event.
Definition: MIDI_Interface.cpp:95
NO_MESSAGE
Definition: MIDI_Parser.hpp:30
NOTE_ON
const uint8_t NOTE_ON
Definition: MIDI_Parser.hpp:17
Parsing_MIDI_Interface::callbacks
MIDI_Callbacks * callbacks
Definition: MIDI_Interface.hpp:240
PROGRAM_CHANGE
const uint8_t PROGRAM_CHANGE
Definition: MIDI_Parser.hpp:20
PITCH_BEND
const uint8_t PITCH_BEND
Definition: MIDI_Parser.hpp:22
SysExMessage::CN
uint8_t CN
Definition: MIDI_Parser.hpp:74
MIDICNChannel
A class for saving a MIDI channel and cable number.
Definition: MIDICNChannelAddress.hpp:19
NOTE_OFF
const uint8_t NOTE_OFF
Definition: MIDI_Parser.hpp:16
MIDI_Interface::sendNoteOff
void sendNoteOff(MIDICNChannelAddress address, uint8_t velocity)
Send a MIDI Note Off event.
Definition: MIDI_Interface.cpp:64
MIDI_Parser::getCN
virtual uint8_t getCN() const
Get the cable number of the latests MIDI message.
Definition: MIDI_Parser.hpp:99
SYSEX_MESSAGE
Definition: MIDI_Parser.hpp:32
MIDI_Interface::sendOnCable
void sendOnCable(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2, uint8_t cn)
Send a 3-byte MIDI packet with cable number.
Definition: MIDI_Interface.cpp:30
Parsing_MIDI_Interface::onSysExMessage
void onSysExMessage()
Definition: MIDI_Interface.cpp:164
MIDI_Notes::F
constexpr int8_t F
Definition: Notes.hpp:23
CC
const uint8_t CC
Definition: MIDI_Parser.hpp:19
MIDI_Interface::setAsDefault
void setAsDefault()
Set this MIDI interface as the default interface.
Definition: MIDI_Interface.cpp:16
ChannelMessage
Definition: MIDI_Parser.hpp:47
MIDI_Parser::getSysEx
virtual SysExMessage getSysEx() const =0
Get the latest SysEx message.
MIDICNChannel::getRawChannel
constexpr uint8_t getRawChannel() const
Get the channel as an integer [0, 15].
Definition: MIDICNChannelAddress.hpp:38
MIDI_Interface
An abstract class for MIDI interfaces.
Definition: MIDI_Interface.hpp:16
SysExMessage::length
uint8_t length
Definition: MIDI_Parser.hpp:73
MIDI_Interface::sendCC
void sendCC(MIDICNChannelAddress address, uint8_t value)
Send a MIDI Control Change event.
Definition: MIDI_Interface.cpp:75
MIDI_Interface.hpp
MIDI_Interface::~MIDI_Interface
virtual ~MIDI_Interface()
Destructor.
Definition: MIDI_Interface.cpp:9
MIDI_Interface::sendPC
void sendPC(MIDICNChannelAddress address)
Send a MIDI Program Change event.
Definition: MIDI_Interface.cpp:85
Parsing_MIDI_Interface::onRealtimeMessage
void onRealtimeMessage(uint8_t message)
Definition: MIDI_Interface.cpp:154
MIDICNChannel::getCableNumber
constexpr uint8_t getCableNumber() const
Get the cable number [0, 15].
Definition: MIDICNChannelAddress.hpp:41
KEY_PRESSURE
const uint8_t KEY_PRESSURE
Definition: MIDI_Parser.hpp:18