Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
VPotRing.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <AH/STL/algorithm>
7
9
10namespace MCU {
11
14struct VPotState {
16 VPotState(uint8_t value = 0) : value(value) {}
17
18 uint8_t value;
19
20 bool update(uint8_t data) {
21 data = sanitizeData(data);
22 bool changed = data != this->value;
23 this->value = data;
24 return changed;
25 }
26
28 enum Mode {
31 Wrap = 2,
32 Spread = 3,
33 };
34
37
39 uint8_t getPosition() const { return value & 0x0F; }
41 bool getCenterLed() const { return value & 0x40; }
43 Mode getMode() const { return static_cast<Mode>((value & 0x30) >> 4); }
44
46 uint8_t getStartOn() const {
47 int8_t position = getPosition();
48 if (position == 0)
49 return 0;
50 int8_t value = position - 1;
51 switch (getMode()) {
52 case SingleDot: return value;
53 case BoostCut: return std::min(+value, 5);
54 case Wrap: return 0;
55 case Spread: return std::max(5 - value, 0);
56 default: return 0;
57 }
58 }
59
61 uint8_t getStartOff() const {
62 uint8_t value = getPosition();
63 switch (getMode()) {
64 case SingleDot: return value;
65 case BoostCut: return std::max(+value, 6);
66 case Wrap: return value;
67 case Spread: return std::min(5 + value, 11);
68 default: return 0;
69 }
70 }
71
73
76 static uint8_t sanitizeData(uint8_t data) {
77 // Maximum valid position value is 0xB.
78 return (data & 0x0F) <= 0x0B ? data : ((data & 0xF0) | 0x0B);
79 }
80};
81
82// -------------------------------------------------------------------------- //
83
118 VPotMatcher(uint8_t track, MIDIChannelCable channelCN)
119 : TwoByteMIDIMatcher({track + 0x30 - 1, channelCN}) {}
120};
121
126template <uint8_t BankSize>
141 MIDIChannelCable channelCN)
143 {track + 0x30 - 1, channelCN}) {}
144};
145
146// -------------------------------------------------------------------------- //
147
154class VPotRing : public MatchingMIDIInputElement<MIDIMessageType::ControlChange,
155 VPotMatcher>,
157 public:
159 using Parent =
161
171 VPotRing(uint8_t track, MIDIChannelCable channelCN = Channel_1)
172 : Parent({track, channelCN}) {}
173
174 protected:
175 bool handleUpdateImpl(typename Matcher::Result match) {
176 return state.update(match.value);
177 }
178
179 void handleUpdate(typename Matcher::Result match) override {
180 dirty |= handleUpdateImpl(match);
181 }
182
183 public:
186
188 VPotState getState() const { return state; }
189
191 uint8_t getPosition() const { return state.getPosition(); }
193 bool getCenterLed() const override { return state.getCenterLed(); }
195 VPotState::Mode getMode() const { return state.getMode(); }
196
198 uint8_t getStartOn() const override { return state.getStartOn(); }
200 uint8_t getStartOff() const override { return state.getStartOff(); }
201
203
205 void reset() override {
206 if (!ignoreReset) {
207 state = {};
208 dirty = true;
209 }
210 }
211
212 private:
214
215 public:
219 bool ignoreReset = true;
220};
221
222// -------------------------------------------------------------------------- //
223
224namespace Bankable {
225
235template <uint8_t BankSize>
237 : public BankableMatchingMIDIInputElement<MIDIMessageType::ControlChange,
238 BankableVPotMatcher<BankSize>>,
240 public:
242 using Parent =
244 Matcher>;
257 VPotRing(BankConfig<BankSize> config, uint8_t track,
258 MIDIChannelCable channelCN = Channel_1)
259 : Parent({config, track, channelCN}) {}
260
261 protected:
262 bool handleUpdateImpl(typename Matcher::Result match) {
263 return states[match.bankIndex].update(match.value) &&
264 match.bankIndex == this->getActiveBank();
265 // Only mark dirty if the value of the active bank changed
266 }
267
268 void handleUpdate(typename Matcher::Result match) override {
269 dirty |= handleUpdateImpl(match);
270 }
271
272 public:
275
277 VPotState getState(uint8_t bank) const { return states[bank]; }
278
281 uint8_t getPosition(uint8_t bank) const {
282 return getState(bank).getPosition();
283 }
286 bool getCenterLed(uint8_t bank) const {
287 return getState(bank).getCenterLed();
288 }
291 VPotState::Mode getMode(uint8_t bank) const {
292 return getState(bank).getMode();
293 }
294
297 uint8_t getStartOn(uint8_t bank) const {
298 return getState(bank).getStartOn();
299 }
302 uint8_t getStartOff(uint8_t bank) const {
303 return getState(bank).getStartOff();
304 }
305
307 VPotState getState() const { return getState(this->getActiveBank()); }
308
311 uint8_t getPosition() const { return getPosition(this->getActiveBank()); }
314 bool getCenterLed() const override {
315 return getCenterLed(this->getActiveBank());
316 }
319 VPotState::Mode getMode() const { return getMode(this->getActiveBank()); }
320
323 uint8_t getStartOn() const override {
324 return getStartOn(this->getActiveBank());
325 }
328 uint8_t getStartOff() const override {
329 return getStartOff(this->getActiveBank());
330 }
331
333
335 void reset() override {
336 if (!ignoreReset) {
337 states = {{}};
338 dirty = true;
339 }
340 }
341
342 protected:
343 void onBankSettingChange() override { dirty = true; }
344
345 private:
347
348 public:
352 bool ignoreReset = true;
353};
354
355} // namespace Bankable
356
357} // namespace MCU
358
constexpr Channel Channel_1
Definition Channel.hpp:118
@ ControlChange
Control Change Channel Voice message (3B).
Wrap
An enumeration to set the behavior of selectors that are incremented (decremented) beyond their maxim...
Definition Selector.hpp:14
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
A class that reads and filters an analog input.
bool update()
Read the analog input value, apply the mapping function, and update the average.
Similar to MatchingMIDIInputElement, but for Bankable MIDI Input Elements.
A MIDI input element that represents a Mackie Control Universal VPot ring.
Definition VPotRing.hpp:239
VPotState::Mode getMode() const
Return the mode of the V-Pot ring.
Definition VPotRing.hpp:319
bool getCenterLed(uint8_t bank) const
Return the status of the center LED of the V-Pot ring.
Definition VPotRing.hpp:286
uint8_t getStartOff(uint8_t bank) const
Get the first segment that should be off.
Definition VPotRing.hpp:302
VPotState::Mode getMode(uint8_t bank) const
Return the mode of the V-Pot ring.
Definition VPotRing.hpp:291
bool ignoreReset
Don't reset the state when calling the reset method.
Definition VPotRing.hpp:352
uint8_t getStartOff() const override
Get the first segment that should be off.
Definition VPotRing.hpp:328
void onBankSettingChange() override
A function to be executed each time the bank setting changes.
Definition VPotRing.hpp:343
uint8_t getPosition() const
Return the position of the V-Pot ring. [0, 11].
Definition VPotRing.hpp:311
VPotState getState() const
Get the full state of the VPot ring. (For the active bank.)
Definition VPotRing.hpp:307
bool handleUpdateImpl(typename Matcher::Result match)
Definition VPotRing.hpp:262
uint8_t getStartOn() const override
Get the first segment that should be on.
Definition VPotRing.hpp:323
VPotRing(BankConfig< BankSize > config, uint8_t track, MIDIChannelCable channelCN=Channel_1)
Constructor.
Definition VPotRing.hpp:257
VPotState getState(uint8_t bank) const
Get the full state of the VPot ring. (For the given bank.)
Definition VPotRing.hpp:277
uint8_t getPosition(uint8_t bank) const
Return the position of the V-Pot ring. [0, 11].
Definition VPotRing.hpp:281
AH::Array< VPotState, BankSize > states
Definition VPotRing.hpp:346
void handleUpdate(typename Matcher::Result match) override
Definition VPotRing.hpp:268
void reset() override
Reset all states to zero.
Definition VPotRing.hpp:335
uint8_t getStartOn(uint8_t bank) const
Get the first segment that should be on.
Definition VPotRing.hpp:297
bool getCenterLed() const override
Return the status of the center LED of the V-Pot ring.
Definition VPotRing.hpp:314
A MIDI input element that represents a Mackie Control Universal VPot ring.
Definition VPotRing.hpp:156
VPotState::Mode getMode() const
Return the mode of the V-Pot ring.
Definition VPotRing.hpp:195
VPotRing(uint8_t track, MIDIChannelCable channelCN=Channel_1)
Constructor.
Definition VPotRing.hpp:171
bool ignoreReset
Don't reset the state when calling the reset method.
Definition VPotRing.hpp:219
uint8_t getStartOff() const override
Get the first segment that should be off.
Definition VPotRing.hpp:200
uint8_t getPosition() const
Return the position of the V-Pot ring. [0, 11].
Definition VPotRing.hpp:191
VPotState getState() const
Get the full state of the VPot ring.
Definition VPotRing.hpp:188
bool handleUpdateImpl(typename Matcher::Result match)
Definition VPotRing.hpp:175
uint8_t getStartOn() const override
Get the first segment that should be on.
Definition VPotRing.hpp:198
void handleUpdate(typename Matcher::Result match) override
Definition VPotRing.hpp:179
VPotState state
Definition VPotRing.hpp:213
void reset() override
Reset the state to zero.
Definition VPotRing.hpp:205
bool getCenterLed() const override
Return the status of the center LED of the V-Pot ring.
Definition VPotRing.hpp:193
A class for saving a MIDI channel and cable number.
The MIDIInputElement base class is very general: you give it a MIDI message, and it calls the updateW...
A namespace for MIDI elements that can be added to a Bank, to change their address or channel.
Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control Change, Key Pressure.
BaseBankConfig< BankSize > config
MIDI Input matcher for Mackie Control Universal VPot LED rings with bank support.
Definition VPotRing.hpp:127
BankableVPotMatcher(BankConfig< BankSize > config, uint8_t track, MIDIChannelCable channelCN)
Constructor.
Definition VPotRing.hpp:140
MIDI Input matcher for Mackie Control Universal VPot LED rings.
Definition VPotRing.hpp:108
VPotMatcher(uint8_t track, MIDIChannelCable channelCN)
Constructor.
Definition VPotRing.hpp:118
Struct that keeps track of the value and overload indicator of a Mackie Control Universal VPot LED ri...
Definition VPotRing.hpp:14
Mode getMode() const
Return the mode of the V-Pot ring.
Definition VPotRing.hpp:43
uint8_t getStartOff() const
Get the first segment that should be off.
Definition VPotRing.hpp:61
uint8_t getStartOn() const
Get the first segment that should be on.
Definition VPotRing.hpp:46
bool getCenterLed() const
Return the status of the center LED of the V-Pot ring.
Definition VPotRing.hpp:41
Mode
Determines how the VPot value is displayed using the LEDs.
Definition VPotRing.hpp:28
@ SingleDot
Single dot.
Definition VPotRing.hpp:29
@ BoostCut
Boost/Cut.
Definition VPotRing.hpp:30
@ Spread
Spread.
Definition VPotRing.hpp:32
uint8_t value
The value representing the VPot position, mode and LED.
Definition VPotRing.hpp:18
uint8_t getPosition() const
Return the position of the V-Pot ring. [0, 11].
Definition VPotRing.hpp:39
static uint8_t sanitizeData(uint8_t data)
Make sure that the received value is valid and will not result in array out of bounds conditions.
Definition VPotRing.hpp:76
bool update(uint8_t data)
Definition VPotRing.hpp:20
VPotState(uint8_t value=0)
Constructor.
Definition VPotRing.hpp:16
Matcher for MIDI messages with 2 data bytes, such as Note On/Off, Control Change, Key Pressure (but n...