Control Surface main
MIDI Control Surface library for Arduino
VU.hpp
Go to the documentation of this file.
1#pragma once
2
6
8
9namespace MCU {
10
13struct VUState {
22 VUState(uint8_t value = 0, bool overload = false)
24
25 uint8_t value : 4;
26 bool overload : 1;
27
28 enum Changed {
32 };
33
47 Changed update(uint8_t data) {
48 switch (data) {
49 case 0xF: { // clear overload
51 overload = false;
52 return changed;
53 }
54 case 0xE: { // set overload
56 overload = true;
57 return changed;
58 }
59 case 0xD: { // no meaning
60 return NothingChanged;
61 }
62 default: { // set value
63 Changed changed = value != data ? ValueChanged : NothingChanged;
64 value = data;
65 return changed;
66 }
67 }
68 }
69
72 bool decay() {
73 if (value == 0)
74 return false;
75 value--;
76 return true;
77 }
78};
79
80// -------------------------------------------------------------------------- //
81
107struct VUMatcher {
110
112 struct Result {
113 bool match;
114 uint8_t data;
115 };
116
119 uint8_t track = m.data1 >> 4;
121 return {false, 0};
122 uint8_t data = m.data1 & 0x0F;
123 return {true, data};
124 }
125
127};
128
132template <uint8_t BankSize>
137
139 struct Result {
140 bool match;
141 uint8_t data;
142 uint8_t bankIndex;
143 };
144
149 uint8_t track = m.data1 >> 4;
150 MIDIAddress midiaddr = {track, m.getChannelCable()};
151 if (!matchBankable(midiaddr, address, config))
152 return {false, 0, 0};
153 uint8_t data = m.data1 & 0x0F;
154 uint8_t bankIndex = getBankIndex(midiaddr, address, config);
155 return {true, data, bankIndex};
156 }
157
160 const Bank<BankSize> &getBank() const { return config.bank; }
161 BankType getBankType() const { return config.type; }
162 static constexpr setting_t getBankSize() { return BankSize; }
163
166 setting_t getSelection() const { return getBank().getSelection(); }
167
170};
171
172// -------------------------------------------------------------------------- //
173
175namespace VUDecay {
177constexpr unsigned int Hold = 0;
179constexpr unsigned int Default = 150;
180} // namespace VUDecay
181
188class VU : public MatchingMIDIInputElement<MIDIMessageType::CHANNEL_PRESSURE,
189 VUMatcher>,
190 public Interfaces::MCU::IVU {
191 public:
194 Matcher>;
213 VU(uint8_t track, MIDIChannelCable channelCN,
214 unsigned int decayTime = VUDecay::Default)
215 : Parent({{track - 1, channelCN}}),
216 IVU(12), decayTimer(decayTime) {}
217
233 VU(uint8_t track, unsigned int decayTime = VUDecay::Default)
234 : VU(track, CHANNEL_1, decayTime) {}
235
236 protected:
237 bool handleUpdateImpl(typename Matcher::Result match) {
238 auto changed = state.update(match.data);
239 if (changed == VUState::ValueChanged)
240 // reset the timer and fire after one interval
242 return changed;
243 }
244
245 void handleUpdate(typename Matcher::Result match) override {
246 dirty |= handleUpdateImpl(match);
247 }
248
249 bool decay() {
250 return decayTimer.getInterval() != VUDecay::Hold &&
251 decayTimer &&
252 state.decay();
253 }
254
255 public:
257 void reset() override { state = {}; }
258
260 void update() override {
261 dirty |= decay();
262 }
263
264 public:
267
269 uint8_t getValue() override { return state.value; }
271 bool getOverload() override { return state.overload; }
272
274
275 private:
278};
279
280// -------------------------------------------------------------------------- //
281
282namespace Bankable {
283
293template <uint8_t BankSize>
294class VU
295 : public BankableMatchingMIDIInputElement<MIDIMessageType::CHANNEL_PRESSURE,
296 BankableVUMatcher<BankSize>>,
297 public Interfaces::MCU::IVU {
298 public:
300 using Parent
302 Matcher>;
303
324 VU(BankConfig<BankSize> config, uint8_t track, MIDIChannelCable channelCN,
325 unsigned int decayTime = VUDecay::Default)
326 : Parent({config, {track - 1, channelCN}}),
327 IVU(12), decayTimer(decayTime) {}
328
346 VU(BankConfig<BankSize> config, uint8_t track,
347 unsigned int decayTime = VUDecay::Default)
348 : VU(config, track, CHANNEL_1, decayTime) {}
349
350 protected:
351 bool handleUpdateImpl(typename Matcher::Result match) {
352 auto changed = states[match.bankIndex].update(match.data);
353 if (changed == VUState::ValueChanged &&
354 match.bankIndex == this->getActiveBank())
355 // Only care about active bank's decay.
356 // Other banks will decay as well, but not as precisely.
357 // They aren't visible anyway, so it's a good compromise.
359 return changed && match.bankIndex == this->getActiveBank();
360 // Only mark dirty if the value of the active bank changed
361 }
362
363 void handleUpdate(typename Matcher::Result match) override {
364 dirty |= handleUpdateImpl(match);
365 }
366
367 bool decay() {
368 bool newdirty = false;
370 for (uint8_t i = 0; i < BankSize; ++i)
371 newdirty |= states[i].decay() && i == this->getActiveBank();
372 // Only mark dirty if the value of the active bank decayed
373 return newdirty;
374 }
375
376 public:
378 void reset() override {
379 states = {{}};
380 dirty = true;
381 }
382
384 void update() override {
385 dirty |= decay();
386 }
387
388 protected:
389 void onBankSettingChange() override { dirty = true; }
390
391 public:
394
396 uint8_t getValue(uint8_t bank) const { return states[bank].value; }
398 bool getOverload(uint8_t bank) const { return states[bank].overload; }
401 float getFloatValue(uint8_t bank) const { return getValue(bank) / 12.f; }
402
404 uint8_t getValue() override { return getValue(this->getActiveBank()); }
406 bool getOverload() override { return getOverload(this->getActiveBank()); }
409 float getFloatValue() override { return getValue() / 12.f; }
410
412
413 private:
416};
417
418} // namespace Bankable
419
420} // namespace MCU
421
BankType
An enumeration of the different bank types.
Definition: BankConfig.hpp:12
constexpr Channel CHANNEL_1
Definition: Channel.hpp:118
uint8_t setting_t
The type used for Selectors.
Definition: Def.hpp:51
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
unsigned long getInterval() const
Get the interval of the timer.
void beginNextPeriod()
Initialize or reset the timer. The timer will fire after one period.
A class that groups Bankable MIDI Output Elements and Bankable MIDI Input Elements,...
Definition: Bank.hpp:91
Similar to MatchingMIDIInputElement, but for Bankable MIDI Input Elements.
const BankType type
Definition: BankConfig.hpp:46
Bank< N > & bank
Definition: BankConfig.hpp:45
An abstract interface for VU meters.
IVU(uint8_t max, bool alwaysDirty=false)
A MIDI input element that represents a Mackie Control Universal VU meter.
Definition: VU.hpp:297
void update() override
Decay the VU meter.
Definition: VU.hpp:384
uint8_t getValue() override
Get the most recent VU position that was received for the active bank.
Definition: VU.hpp:404
bool getOverload(uint8_t bank) const
Get the status of the overload indicator for the given bank.
Definition: VU.hpp:398
AH::Timer< millis > decayTimer
Definition: VU.hpp:415
void onBankSettingChange() override
A function to be executed each time the bank setting changes.
Definition: VU.hpp:389
bool handleUpdateImpl(typename Matcher::Result match)
Definition: VU.hpp:351
VU(BankConfig< BankSize > config, uint8_t track, unsigned int decayTime=VUDecay::Default)
Constructor.
Definition: VU.hpp:346
bool getOverload() override
Get the status of the overload indicator for the active bank.
Definition: VU.hpp:406
void handleUpdate(typename Matcher::Result match) override
Definition: VU.hpp:363
float getFloatValue() override
Get the most recent VU position for the active bank as a value between 0 and 1.
Definition: VU.hpp:409
VU(BankConfig< BankSize > config, uint8_t track, MIDIChannelCable channelCN, unsigned int decayTime=VUDecay::Default)
Constructor.
Definition: VU.hpp:324
float getFloatValue(uint8_t bank) const
Get the most recent VU position for the given bank as a value between 0 and 1.
Definition: VU.hpp:401
void reset() override
Reset all values to zero.
Definition: VU.hpp:378
uint8_t getValue(uint8_t bank) const
Get the most recent VU position that was received for the given bank.
Definition: VU.hpp:396
AH::Array< VUState, BankSize > states
Definition: VU.hpp:414
bool decay()
Definition: VU.hpp:367
A MIDI input element that represents a Mackie Control Universal VU meter.
Definition: VU.hpp:190
VU(uint8_t track, unsigned int decayTime=VUDecay::Default)
Constructor.
Definition: VU.hpp:233
void update() override
Decay the VU meter.
Definition: VU.hpp:260
uint8_t getValue() override
Get the most recent VU position that was received.
Definition: VU.hpp:269
VUState state
Definition: VU.hpp:276
AH::Timer< millis > decayTimer
Definition: VU.hpp:277
bool handleUpdateImpl(typename Matcher::Result match)
Definition: VU.hpp:237
VU(uint8_t track, MIDIChannelCable channelCN, unsigned int decayTime=VUDecay::Default)
Constructor.
Definition: VU.hpp:213
bool getOverload() override
Get the status of the overload indicator.
Definition: VU.hpp:271
void handleUpdate(typename Matcher::Result match) override
Definition: VU.hpp:245
void reset() override
Reset all values to zero.
Definition: VU.hpp:257
bool decay()
Definition: VU.hpp:249
A type-safe utility class for saving a MIDI address consisting of a 7-bit address,...
static bool matchSingle(MIDIAddress toMatch, MIDIAddress base)
Check if two addresses match (are equal).
A class for saving a MIDI channel and cable number.
Definition: MIDIAddress.hpp:24
The MIDIInputElement base class is very general: you give it a MIDI message, and it calls the updateW...
uint8_t getBankIndex(uint8_t tgt, uint8_t base, const Bank< BankSize > &bank)
bool matchBankable(uint8_t tgt, uint8_t base, const Bank< BankSize > &bank)
Check if the given address is part of the bank relative to the base address.
A namespace for MIDI elements that can be added to a Bank, to change their address or channel.
constexpr unsigned int Default
Decay one segment/block every 150 ms if no new values are received.
Definition: VU.hpp:179
constexpr unsigned int Hold
Don't decay automatically, hold the latest value until a new one is received.
Definition: VU.hpp:177
An array wrapper for easy copying, comparing, and iterating.
Definition: Array.hpp:36
MIDIChannelCable getChannelCable() const
Get the MIDI channel and cable number.
MIDI Input matcher for Mackie Control Universal VU meters with bank support.
Definition: VU.hpp:133
MIDIAddress address
MIDI address to compare incoming messages with.
Definition: VU.hpp:169
setting_t getSelection() const
Get the current bank setting.
Definition: VU.hpp:166
static constexpr setting_t getBankSize()
Definition: VU.hpp:162
uint8_t bankIndex
The bank index of the message [0, BankSize-1].
Definition: VU.hpp:142
uint8_t data
The data to update the VU meter with [0x0, 0xF].
Definition: VU.hpp:141
BankableVUMatcher(BankConfig< BankSize > config, MIDIAddress address)
Constructor.
Definition: VU.hpp:135
bool match
Whether the address of the message matched our address.
Definition: VU.hpp:140
BaseBankConfig< BankSize > config
Bank configuration.
Definition: VU.hpp:168
const Bank< BankSize > & getBank() const
Definition: VU.hpp:160
BankType getBankType() const
Definition: VU.hpp:161
Result operator()(ChannelMessage m)
Parse and try to match the incoming MIDI message.
Definition: VU.hpp:146
Bank< BankSize > & getBank()
Definition: VU.hpp:159
Output data of the matcher/parser.
Definition: VU.hpp:139
MIDI Input matcher for Mackie Control Universal VU meters.
Definition: VU.hpp:107
MIDIAddress address
MIDI address to compare incoming messages with.
Definition: VU.hpp:126
VUMatcher(MIDIAddress address)
Constructor.
Definition: VU.hpp:109
uint8_t data
The data to update the VU meter with [0x0, 0xF].
Definition: VU.hpp:114
bool match
Whether the address of the message matched our address.
Definition: VU.hpp:113
Result operator()(ChannelMessage m)
Parse and try to match the incoming MIDI message.
Definition: VU.hpp:118
Output data of the matcher/parser.
Definition: VU.hpp:112
Struct that keeps track of the value and overload indicator of a Mackie Control Universal VU meter.
Definition: VU.hpp:13
bool overload
The state of the overload indicator.
Definition: VU.hpp:26
uint8_t value
The value of the VU meter [0, 12].
Definition: VU.hpp:25
@ OverloadChanged
Definition: VU.hpp:31
@ ValueChanged
Definition: VU.hpp:30
@ NothingChanged
Definition: VU.hpp:29
Changed update(uint8_t data)
Update the value or overload status with a new raw MIDI value.
Definition: VU.hpp:47
VUState(uint8_t value=0, bool overload=false)
Constructor.
Definition: VU.hpp:22
bool decay()
Decay the VU value: subtract one from the position if it is not zero.
Definition: VU.hpp:72
uint8_t data1
First MIDI data byte.