Comments (18)
Thanks for all the help :-)
from control-surface.
I have figured it out and is clearly a very noob mistake.
switchOctave.set(map(controlPots[2].getValue(), 0, 124, 15, 0));
I have only defined 9 banks, 0 to 8. Mapping a value even if it wasn't greater than 8 seemed to cause quite a crash. That's why this worked: switchOctave.set(3); for eg.
So I guess my next question is, what should I be using as a selector for changing banks if I am using a potentiometer as my physical selector ? So that I don't programatically make these simple mistakes of setting out of bounds values :-)
from control-surface.
Also, is there a way to have the change of channel banks affect both the midi notes channel and the effect channel ? So when changing the midi channel the midi notes travel with the midi cc to the next channel ?
from control-surface.
When you try to select a non-existent setting, you get an error. The on-board LED should start blinking in that case, and if you enable debugging in src/Settings/Settings.hpp
, it'll print the error message:
[static CS::setting_t CS::Selectable<N>::validateSetting(CS::setting_t) [with unsigned char N = 9; CS::setting_t = unsigned char] @ line 24]: Error: Setting 9 is not less than the number of settings (9) (0xFFFE)
So I guess my next question is, what should I be using as a selector for changing banks if I am using a potentiometer as my physical selector ? So that I don't programatically make these simple mistakes of setting out of bounds values :-)
Compile-time checking is done by specifying the number of settings as a template parameter (between the <>
). You could create your own class for potentiometer selectors, and make it a template, so it can only be combined with a bank with the same number of settings.
This is the code I used for testing your code, by the way:
#include <Control_Surface.h> // Include the Control Surface library
USBMIDI_Interface midi; // Instantiate a MIDI Interface to use
Bank<9> channelBank(1);
FilteredAnalog<7> controlPot = A2;
void setup() {
Control_Surface.begin(); // Setup the Control Surface
Serial.begin(115200); // Setup Serial output
}
void loop() {
if (controlPot.update()) {
uint8_t setting = map(controlPot.getValue(), 0, 124, 0, 15);
Serial.println(setting);
channelBank.select(setting);
}
Control_Surface.loop();
}
Also, is there a way to have the change of channel banks affect both the midi notes channel and the effect channel ? So when changing the midi channel the midi notes travel with the midi cc to the next channel ?
No, this is not supported at the moment.
from control-surface.
Thanks so much for the help, I do appreciate it. I will attempt to create a potentiometer selector class using one of the existing classes as a basis to work from. I'm not overly confident at this point but I'm willing to give it a go. Thanks for the pointers.
Is it possible to create another bank selector to change channels on the midi notes so that there is a bank to change the octave and a bank to change the midi channel ?
from control-surface.
I think something like this would work:
#define protected public // Forgive me, Father :(
#include <Control_Surface.h>
BEGIN_CS_NAMESPACE
namespace Bankable {
class TwoBanks {
public:
TwoBanks(OutputBankConfig config1, OutputBankConfig config2,
MIDICNChannelAddress address)
: bankable1{config1}, bankable2{config2}, address(address) {}
void lock() {
bankable1.lock();
bankable2.lock();
}
void unlock() {
bankable1.unlock();
bankable2.unlock();
}
MIDICNChannelAddress getBaseAddress() const { return address; }
MIDICNChannelAddress getActiveAddress() const {
return getBaseAddress()
+ bankable1.getAddressOffset()
+ bankable2.getAddressOffset();
}
private:
BankableMIDIOutput bankable1;
BankableMIDIOutput bankable2;
MIDICNChannelAddress address;
};
class TwoBanksNoteButton : public MIDIButton<TwoBanks, DigitalNoteSender> {
public:
TwoBanksNoteButton(const OutputBankConfig &config1,
const OutputBankConfig &config2,
pin_t pin,
const MIDICNChannelAddress &address,
const DigitalNoteSender &sender = {})
: MIDIButton<TwoBanks, DigitalNoteSender>{
{config1, config2, address}, pin, sender} {}
};
} // namespace Bankable
END_CS_NAMESPACE
USBDebugMIDI_Interface midi;
Bank<16> channelBank(1);
Bank<9> pitchBank(12);
using namespace MIDI_Notes;
Bankable::TwoBanksNoteButton button = {
{channelBank, CHANGE_CHANNEL},
{pitchBank, CHANGE_ADDRESS},
2, // pin
note(C, 0), // address
};
void setup() {
Control_Surface.begin();
channelBank.select(CHANNEL_10.getRaw());
pitchBank.select(4);
}
void loop() {
Control_Surface.loop();
}
from control-surface.
Wow, that was quick. You have really given me a lot to go through and use. Again I really do appreciate your time and help.
I will be looking into attempting to create the potentiometer selector class.
Great work on this library it really has saved me a lot of work and time in trying to figure things out myself :-)
from control-surface.
This seems to work:
#include <Control_Surface.h>
USBMIDI_Interface midi;
MAX7219SevenSegmentDisplay display = {10}; // MAX7219 connected to SPI bus, load pin to pin 10
template <setting_t N>
class PotSelector : public Updatable<> {
public:
PotSelector(Selectable<N> &selectable, pin_t analogPin, uint8_t displayPosition = 0)
: selectable(selectable), pot{analogPin}, displayPosition(displayPosition) {}
void begin() override {}
void update() override {
if (pot.update()) {
setting_t setting = map(pot.getValue(), 0, 64, 0, N);
selectable.select(setting);
static_assert(N <= 16, "Can only display 0-15");
display.printHex(displayPosition, setting);
}
}
private:
Selectable<N> &selectable;
FilteredAnalog<6, 3, 3> pot; // tweak filter and bit depth if necessary
uint8_t displayPosition;
};
Bank<9> pitchBank(12);
Bank<16> channelBank(1);
PotSelector<9> pitchSel = {
pitchBank, A2, 0,
};
PotSelector<16> channelSel = {
channelBank, A3, 7,
};
void setup() {
display.begin();
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
}
I added the printHex method in the latest commit: d8471ba, so you might have to update.
from control-surface.
Pieter, you are a scholar and a gentleman ... thank you :-) You have helped immensely. I will try this out today. I am a few steps closer to having everything that I need working.
Your code for the TwoBanksNoteButton works perfectly and for now I can manipulate the banks using an Increment selector setting the banks manually reading from the pots. I started looking into the potSelector code and seeing how I can use that.
My last thing to figure out is to create banks of effects that I can apply to a group of slide potentiometers. eg.
Bank 1 = Reverb, Chorus, Tremelo, Phaser
Bank 2 = Pitchbend, Modulation, Breath, Portamento
Bank 3 = Release, Attack, Cutoff, Variation
etc ...
from control-surface.
I'm not sure I understand what you mean. Does each effect have a certain CC number?
from control-surface.
Yes they would have their own Midi CC number except for Pitch Bend which seems to be on it's own. So the banks would look like this with midi cc:
Bank 1 = 91, 93, 92, 95
Bank 2 = ??, 1, 2, 5
Bank 3 = 72, 73, 74, 70
I'm not sure how many banks I could come up with, but grouping together certain effects that are related to each other in some way could give me a few more.
So for eg. when bank 1 is selected the 4 slide potentiometers are assigned Reverb, Chorus, Tremolo and Phaser. Bank 2 they get assigned Modulation, Breath, Portamento ... etc.
from control-surface.
Okay, I see. For the normal CC numbers, you can use Bankable::ManyAddresses:CCPotentiometer
. I didn't add any examples yet, but maybe you can figure it out from the documentation: https://tttapa.github.io/Control-Surface/Doc/Doxygen/d5/d71/classBankable_1_1ManyAddresses_1_1CCPotentiometer.html
If I have time tonight, I'll try to add an example.
For the pitch bend, you'll have to check the bank setting, disable the CCPotentiometer, and enable the PBPotentiometer when appropriate. They have enable()
and disable()
methods, and you can call getSelection()
on the Bank, IIRC.
If you get stuck, just let me know, and I'll try to look into it tonight.
from control-surface.
Turns out you don't even need enable
and disable
, you can just specify an invalid address, so that it won't send anything.
See the example I added in 4bddc91.
from control-surface.
Pieter, your code works perfectly. Exactly what I needed to get done. Using the bankable ManyAddresses works exactly like you described and a simple copy/paste of your example code is doing the job.
Thank you again for your time and effort in helping out with this. I really do appreciate it. I now need to put everything into a box so I can bash the buttons proper, as a friend said to me today. :-)
from control-surface.
Glad I could help :-)
from control-surface.
Created an include file to take your class definition for TwoBanks out of the main code. I don't have my project with me at work today so can't test if it works correctly however it seems to compile ok after adding the files to my Project directory. Not sure if I've done it correctly, but when I added the include #include "TwoBanks.h" while the original code was there the compiler did complain about a redeclaration, so I assume it had included it correctly.
TwoBanks.cpp
#ifdef TEST_COMPILE_ALL_HEADERS_SEPARATELY
#include "TwoBanks.h"
#endif
TwoBanks.h
#pragma once
#include <MIDI_Outputs/Abstract/MIDIButton.hpp>
#include <MIDI_Senders/DigitalNoteSender.hpp>
BEGIN_CS_NAMESPACE
namespace Bankable {
class TwoBanks {
public:
TwoBanks(OutputBankConfig config1, OutputBankConfig config2,
MIDICNChannelAddress address)
: bankable1{config1}, bankable2{config2}, address(address) {}
void lock() {
bankable1.lock();
bankable2.lock();
}
void unlock() {
bankable1.unlock();
bankable2.unlock();
}
MIDICNChannelAddress getBaseAddress() const { return address; }
MIDICNChannelAddress getActiveAddress() const {
return getBaseAddress()
+ bankable1.getAddressOffset()
+ bankable2.getAddressOffset();
}
private:
BankableMIDIOutput bankable1;
BankableMIDIOutput bankable2;
MIDICNChannelAddress address;
};
class TwoBanksNoteButton : public MIDIButton<TwoBanks, DigitalNoteSender> {
public:
TwoBanksNoteButton(const OutputBankConfig &config1,
const OutputBankConfig &config2,
pin_t pin,
const MIDICNChannelAddress &address,
const DigitalNoteSender &sender = {})
: MIDIButton<TwoBanks, DigitalNoteSender>{
{config1, config2, address}, pin, sender} {}
};
} // namespace Bankable
END_CS_NAMESPACE
from control-surface.
Managed to test it all this evening, and it works perfectly just including the .h file in my project directory :-)
from control-surface.
Great, glad to hear!
from control-surface.
Related Issues (20)
- Bankable::ManyAddresses::CCAbsoluteEncoder HOT 2
- FastLed VU and VPotRing ( ws2812 ) HOT 3
- Arduino UNO HOT 3
- Control Change Potentiometer Example doesn't compile for Teensy 4.1 HOT 1
- Compilation error: expected template-name before '<' token HOT 2
- Arduino UNO R4 support and testing HOT 3
- Arduino Yun HOT 2
- Trying to setVelocity for all notebutton values in mux with piezo device HOT 1
- External app/webpage to change CC and Channel values HOT 1
- Hi, I would like to see the USBMIDI_Interface adapted so that you can specify the fixed cablenumber. This would it make possible to use pipes and filters connecting serial ports with virtual usb ports
- Support for MCP23S17 SPI
- error: 'SelectorPC' does not name a type HOT 2
- Switching presets Roland FP-30X HOT 2
- TYPO IN DOCUMENTATION HOT 1
- Error running on M1 Mac Sonoma with Teensy 4.0 HOT 4
- Arduino Nano 33 BLE Support? HOT 3
- Пример CCIncrementDecrementButtons.ino HOT 10
- Select bank HOT 2
- MIDI-монитор-OLED HOT 3
- Arduino Giga R1 Wifi support HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from control-surface.