This is an old version of the documentation. View the latest version here.
Control Surface  1.0.0
MIDI Control Surface library for Arduino
VPotRing.hpp
Go to the documentation of this file.
1 #pragma once
2 
5 
7 
8 namespace MCU {
9 
10 constexpr static uint8_t VPotRingAddress = 0x30;
11 
12 inline int8_t minimum(int8_t a, int8_t b) { return a > b ? b : a; }
13 inline int8_t maximum(int8_t a, int8_t b) { return a < b ? b : a; }
14 
16  VPotEmptyCallback() = default;
17  template <class T>
18  void begin(const T &) {}
19  template <class T>
20  void update(const T &) {}
21 };
22 
26 class IVPotRing {
27  protected:
28  IVPotRing() = default;
29 
30  public:
32  uint8_t getPosition() const { return getPosition(getValue()); }
34  bool getCenterLed() const { return getCenterLed(getValue()); }
37  uint8_t getMode() const { return getMode(getValue()); }
38 
40  uint8_t getStartOn() const {
41  int8_t position = getPosition();
42  if (position == 0)
43  return 0;
44  int8_t value = position - 1;
45  switch (getMode()) {
46  case 0: return value;
47  case 1: return minimum(value, 5);
48  case 2: return 0;
49  case 3: return maximum(5 - value, 0);
50  // Shouldn't happen, just keeps the compiler happy:
51  default: return 0;
52  }
53  }
54 
56  uint8_t getStartOff() const {
57  uint8_t value = getPosition();
58  switch (getMode()) {
59  case 0: return value;
60  case 1: return maximum(value, 6);
61  case 2: return value;
62  case 3: return minimum(5 + value, 11);
63  // Shouldn't happen, just keeps the compiler happy:
64  default: return 0;
65  }
66  }
67 
68  private:
69  virtual uint8_t getValue() const = 0;
70 
72  static uint8_t getPosition(uint8_t value) {
73  uint8_t position = value & 0x0F;
74  return position < 0x0C ? position : 0x0B;
75  }
77  static bool getCenterLed(uint8_t value) { return value & 0x40; }
79  static uint8_t getMode(uint8_t value) { return (value & 0x30) >> 4; }
80 };
81 
82 template <uint8_t NumValues, class Callback>
83 class VPotRing_Base : public MIDIInputElementCC, public IVPotRing {
84  protected:
85  VPotRing_Base(uint8_t track, const MIDICNChannel &channelCN,
86  const Callback &callback)
87  : MIDIInputElementCC{{track + VPotRingAddress - 1, channelCN}},
88  callback{callback} {}
89 
90  public:
92  void begin() override { callback.begin(*this); }
93 
95  void reset() override {
96 #ifdef VPOTRING_RESET
97  values = {};
98  callback.update(*this);
99 #endif
100  }
101 
102  protected:
105  static uint8_t sanitizeValue(uint8_t value) {
106  return (value & 0x0F) < 0x0C ? value : ((value & 0xF0) | 0xB);
107  }
108 
109  private:
110  bool updateImpl(const ChannelMessageMatcher &midimsg,
111  const MIDICNChannelAddress &target) override {
112  uint8_t index = getBankIndex(target);
113  uint8_t value = sanitizeValue(midimsg.data2);
114  values[index] = value;
115  return true;
116  }
117 
118  uint8_t getValue() const override { return values[getSelection()]; }
119 
121  virtual uint8_t getSelection() const { return 0; }
122 
124  virtual setting_t getBankIndex(const MIDICNChannelAddress &target) const {
125  (void)target;
126  return 0;
127  }
128 
130 
131  public:
132  Callback callback;
133 };
134 
135 // -------------------------------------------------------------------------- //
136 
143 template <class Callback = VPotEmptyCallback>
144 class GenericVPotRing : public VPotRing_Base<1, Callback> {
145  public:
146  GenericVPotRing(uint8_t track, const MIDICNChannel &channelCN,
147  const Callback &callback)
148  : VPotRing_Base<1, Callback>{track, channelCN, callback} {}
149 };
150 
157 class VPotRing : public GenericVPotRing<> {
158  public:
159  VPotRing(uint8_t track, const MIDICNChannel &channelCN = CHANNEL_1)
160  : GenericVPotRing{track, channelCN, {}} {}
161 };
162 
163 // -------------------------------------------------------------------------- //
164 
165 namespace Bankable {
166 
176 template <uint8_t NumBanks, class Callback = VPotEmptyCallback>
177 class GenericVPotRing : public VPotRing_Base<NumBanks, Callback>,
178  public BankableMIDIInput<NumBanks> {
179  public:
180  GenericVPotRing(const BankConfig<NumBanks> &config, uint8_t track,
181  const MIDICNChannel &channelCN, const Callback &callback)
182  : VPotRing_Base<NumBanks, Callback>{track, channelCN, callback},
183  BankableMIDIInput<NumBanks>{config} {}
184 
185  private:
186  setting_t getSelection() const override {
188  };
189 
190  uint8_t getBankIndex(const MIDICNChannelAddress &target) const override {
192  }
193 
196  bool match(const MIDICNChannelAddress &target) const override {
198  this->address);
199  }
200 
201  void onBankSettingChange() override { this->callback.update(*this); }
202 };
203 
212 template <uint8_t NumBanks>
213 class VPotRing : public GenericVPotRing<NumBanks> {
214  public:
215  VPotRing(BankConfig<NumBanks> config, uint8_t track,
216  MIDICNChannel channelCN = CHANNEL_1)
217  : GenericVPotRing<NumBanks>{config, track, channelCN, {}} {}
218 };
219 
220 } // namespace Bankable
221 
222 } // namespace MCU
223 
MCU::IVPotRing::getPosition
static uint8_t getPosition(uint8_t value)
Extract the position from the raw value.
Definition: VPotRing.hpp:72
MCU::Bankable::VPotRing
A class for MIDI input elements that represent Mackie Control Universal V-Pots.
Definition: VPotRing.hpp:213
MCU::IVPotRing::IVPotRing
IVPotRing()=default
MCU::IVPotRing
Definition: VPotRing.hpp:26
MCU::VPotRing_Base::sanitizeValue
static uint8_t sanitizeValue(uint8_t value)
Make sure that the received value is valid and will not result in array out of bounds conditions.
Definition: VPotRing.hpp:105
MCU::maximum
int8_t maximum(int8_t a, int8_t b)
Definition: VPotRing.hpp:13
MCU::Bankable::GenericVPotRing::getBankIndex
uint8_t getBankIndex(const MIDICNChannelAddress &target) const override
Get the bank index from a MIDI address.
Definition: VPotRing.hpp:190
MCU::Bankable::GenericVPotRing
A class for MIDI input elements that represent Mackie Control Universal V-Pots.
Definition: VPotRing.hpp:177
Bankable
A namespace for MIDI elements that can be added to a Bank, to change their address or channel.
Definition: BankAddresses.hpp:7
MCU::VPotRing_Base::begin
void begin() override
Initialize.
Definition: VPotRing.hpp:92
MCU
Names and note and controller numbers for the Mackie Control Universal (MCU) protocol.
Definition: LCDDisplay.hpp:10
MCU::VPotRing::VPotRing
VPotRing(uint8_t track, const MIDICNChannel &channelCN=CHANNEL_1)
Definition: VPotRing.hpp:159
MIDIInputElementCC
Class for objects that listen for incoming MIDI Controller Change events.
Definition: MIDIInputElementCC.hpp:23
Array< uint8_t, NumValues >
MCU::VPotRing_Base
Definition: VPotRing.hpp:83
MCU::VPotRing_Base::values
Array< uint8_t, NumValues > values
Definition: VPotRing.hpp:129
MCU::Bankable::VPotRing::VPotRing
VPotRing(BankConfig< NumBanks > config, uint8_t track, MIDICNChannel channelCN=CHANNEL_1)
Definition: VPotRing.hpp:215
ChannelMessageMatcher
Struct for easily matching MIDI messages.
Definition: ChannelMessageMatcher.hpp:10
BankableMIDIInput::getBankIndex
uint8_t getBankIndex(const MIDICNChannelAddress &target, const MIDICNChannelAddress &base) const
Calculate the bank setting of a given MIDI address, relative to a base address.
Definition: BankableMIDIInput.hpp:71
MCU::VPotRing_Base::updateImpl
bool updateImpl(const ChannelMessageMatcher &midimsg, const MIDICNChannelAddress &target) override
Update the internal state with the new MIDI message.
Definition: VPotRing.hpp:110
MCU::Bankable::GenericVPotRing::GenericVPotRing
GenericVPotRing(const BankConfig< NumBanks > &config, uint8_t track, const MIDICNChannel &channelCN, const Callback &callback)
Definition: VPotRing.hpp:180
MCU::IVPotRing::getStartOn
uint8_t getStartOn() const
Get the first segment that should be on.
Definition: VPotRing.hpp:40
MCU::IVPotRing::getValue
virtual uint8_t getValue() const =0
MCU::VPotRing
A class for MIDI input elements that represent Mackie Control Universal V-Pots.
Definition: VPotRing.hpp:157
MCU::VPotRing_Base::getSelection
virtual uint8_t getSelection() const
Get the active bank selection.
Definition: VPotRing.hpp:121
BEGIN_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
Definition: NamespaceSettings.hpp:9
MCU::VPotRing_Base::getBankIndex
virtual setting_t getBankIndex(const MIDICNChannelAddress &target) const
Get the bank index from a MIDI address.
Definition: VPotRing.hpp:124
MIDICNChannelAddress
A type-safe utility class for saving a MIDI address consisting of a 7-bit address,...
Definition: MIDICNChannelAddress.hpp:82
MCU::IVPotRing::getCenterLed
bool getCenterLed() const
Return the status of the center LED of the V-Pot ring.
Definition: VPotRing.hpp:34
BankableMIDIInput::matchBankable
bool matchBankable(uint8_t toMatch, uint8_t base) const
Check if the given address is part of the bank relative to the base address.
Definition: BankableMIDIInput.hpp:113
MCU::GenericVPotRing::GenericVPotRing
GenericVPotRing(uint8_t track, const MIDICNChannel &channelCN, const Callback &callback)
Definition: VPotRing.hpp:146
MCU::IVPotRing::getMode
uint8_t getMode() const
Return the mode of the V-Pot ring: 0 = single dot, 1 = boost/cut, 2 = wrap, 3 = spread.
Definition: VPotRing.hpp:37
MCU::IVPotRing::getCenterLed
static bool getCenterLed(uint8_t value)
Extract the center LED state from the raw value.
Definition: VPotRing.hpp:77
MCU::GenericVPotRing
A class for MIDI input elements that represent Mackie Control Universal V-Pots.
Definition: VPotRing.hpp:144
MCU::VPotEmptyCallback::update
void update(const T &)
Definition: VPotRing.hpp:20
MCU::VPotRingAddress
constexpr static uint8_t VPotRingAddress
Definition: VPotRing.hpp:10
MCU::IVPotRing::getMode
static uint8_t getMode(uint8_t value)
Extract the mode from the raw value.
Definition: VPotRing.hpp:79
MIDIInputElementCC.hpp
MIDICNChannel
A class for saving a MIDI channel and cable number.
Definition: MIDICNChannelAddress.hpp:19
MCU::IVPotRing::getPosition
uint8_t getPosition() const
Return the position of the V-Pot ring. [0, 11].
Definition: VPotRing.hpp:32
END_CS_NAMESPACE
#define END_CS_NAMESPACE
Definition: NamespaceSettings.hpp:10
MCU::VPotRing_Base::callback
Callback callback
Definition: VPotRing.hpp:132
MCU::VPotRing_Base::reset
void reset() override
Reset all values to zero.
Definition: VPotRing.hpp:95
MCU::Bankable::GenericVPotRing::match
bool match(const MIDICNChannelAddress &target) const override
Check if the address of the incoming MIDI message is in one of the banks of this element.
Definition: VPotRing.hpp:196
BankableMIDIInput::getSelection
setting_t getSelection() const
Get the current bank setting.
Definition: BankableMIDIInput.hpp:59
setting_t
uint8_t setting_t
The type used for Selectors.
Definition: Def.hpp:63
MCU::Bankable::GenericVPotRing::onBankSettingChange
void onBankSettingChange() override
A function to be executed each time the bank setting changes.
Definition: VPotRing.hpp:201
MCU::VPotEmptyCallback
Definition: VPotRing.hpp:15
BankableMIDIInput
A base class for all MIDIInputElements that can be banked.
Definition: Bank.hpp:13
MCU::VPotEmptyCallback::VPotEmptyCallback
VPotEmptyCallback()=default
MCU::VPotRing_Base::getValue
uint8_t getValue() const override
Definition: VPotRing.hpp:118
MCU::VPotRing_Base::VPotRing_Base
VPotRing_Base(uint8_t track, const MIDICNChannel &channelCN, const Callback &callback)
Definition: VPotRing.hpp:85
BankConfig
A struct for selecting the bank of BankableMIDIInputs and the bank type.
Definition: BankConfig.hpp:39
MIDIInputElement::address
const MIDICNChannelAddress address
Definition: MIDIInputElement.hpp:80
MCU::IVPotRing::getStartOff
uint8_t getStartOff() const
Get the first segment that should be off.
Definition: VPotRing.hpp:56
CHANNEL_1
constexpr Channel CHANNEL_1
Definition: Channel.hpp:111
BankableMIDIInput.hpp
MCU::minimum
int8_t minimum(int8_t a, int8_t b)
Definition: VPotRing.hpp:12
ChannelMessageMatcher::data2
uint8_t data2
Definition: ChannelMessageMatcher.hpp:21
MCU::Bankable::GenericVPotRing::getSelection
setting_t getSelection() const override
Get the active bank selection.
Definition: VPotRing.hpp:186
MCU::VPotEmptyCallback::begin
void begin(const T &)
Definition: VPotRing.hpp:18