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 for serial-in/parallel-out shift registers, like the 74HC595 that are connected to the SPI bu...
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...