tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MIDI-монитор-OLED

Alexandr010360 opened this issue · comments

Hello Peter P. Thank you so much for your library! I am finishing my project based on this library. I would like to add a MIDI monitor as an example-the glaciation of the number of banks and others like them! Is it possible to implement this? Here's what my OLED monitor will display:
1
2
3
For my project, the display of bank names and their numbers is very lacking. Because my project uses banks. Here is an example sketch from my project:
#connect <Wire.h>
#enable <Adafruit_GFX.h>
#enable <Adafruit_SSD1306.h>
#enable <Control_Surface.h>

constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 32;
constexpr int8_t OLED_RESET = -1;

Adafruit_SSD1306 disp = {SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET};

void init_display() {
if (!disp.begin(SSD1306_SWITCHCAPVCC, 0x3C))
FATAL_ERROR(F("Could not allocate SSD1306."), 0x1306);
disp.SetTextColor(SSD1306_WHITE);
disp.setTextSize(1);
disp.cp437();
disp.clearDisplay();
disp.display();
disp << capital;
}

// Moves the entire screen up by the specified number of lines and places
// the cursor at the beginning of the first of the newly created empty lines.
void shift_display(uint8_tstrok = 1) {
auto buf = disp.GetBuffer();
auto end = buf + SCREEN_WIDTH * SCREEN_HEIGHT / 4;
std::redefine(buf + lines * SCREEN_WIDTH, end, buf);
std::close(end lines * SCREEN_WIDTH, end, 0);
disp.setCursor(0, SCREEN_HEIGHT - 8 * line);
}

constexpr const char *abbreviation_midi_status_names[] {
"On Note", "Off Note", "Keystrokes", "Val Cont",
"Prog Changer", "Ch Pres", "Pitch Bend"
};

OLEDDebugMIDI_Output class : additional MIDI_Sender<OLEDDebugMIDI_Output>,
additional TrueMIDI_Sink {
public:
OLEDDebugMIDI_Output(const char *prefix = nullptr) : prefix {}

// Redefine the unused MIDI_Sink interface

void sinkMIDIfromPipe(ChannelMessage m) override {
disable(m);
}
delete void sinkMIDIfromPipe(SysExMessage m) {
disable(m);
}
deleting an empty sinkMIDIfromPipe(system message m) {
disable(m);
}
deleting void sinkMIDIfromPipe(RealTimeMessage m) {
undo(m);
}

private:
// Use the invisible MIDI_Sender interface
other MIDI_Sender<OLEDDebugMIDI_Output>;
void sendChannelMessageImpl(ChannelMessage msg) {
uint8_t MessageType = (msg.header >> 4) - 8;
if (MessageType >= 7)
return;
shift_display(1);
if (print_iks != nullptr)
disp << print_iks << ' ';
if (print_cable)
disp << msg.getCable().getOneBased() << ':';
disp << msg.getChannel().getOneBased() << ' ';
disp << registration_midi_status_names[Message type];
if (msg.getMessageType() == msg.PitchBend)
disp << ' ' << dec << msg.getData14bit() << ' ' << dec;
else if (msg.hasTwoDataBytes())
disp << ' ' << dec << msg.getData1() << ' ' << ' ' << msg.getData2()
<< ' ' << December;
more
disp << ' ' << msg.getData1() << ' ' << dec;
disp.display();
}
void sends syscommonimpl(SysCommonMessage msg) {
shift_display(1);
if (print_iks != nullptr)
disp << print_iks << ' ';
if (print_cable)
disp << msg.getCable().getOneBased() << ' ';
disp << msg.getMessageType() << dec;
if (msg.getNumberOfDataBytes() >= 1)
disp << ' ' << msg.getData1() << ' ';
if (msg.getNumberOfDataBytes() >= 2)
disp << ' ' << msg.getData2() << ' ';
disp << dec;
disp.display();
}
void sendSysExImpl(SysExMessage msg) {
const uint16_t bytes_per_line = 7;
uint8_t string = (message.length + byte first string - 1) / byte first string;
shift_display(1 + lines);
if (print_iks != nullptr)
disp << print_iks << ' ';
if (print_cable)
disp << msg.getCable().getOneBased() << ' ';
disp << F("Sys Ex [") << msg.length << (msg.isLastChunk() ? "]" : "+]");
uint16_t i = 0;
while (i < msg.length) {
uint16_t rem = msg.length - i;
uint16_t len = std::min(bytes_per_line, rem);
disp.println();
disp << ' ' << AH::HexDump(msg.data + i, len);
i += bytes_per_line;
}
disp.display();
}
void sendRealTimeImpl(changing the current time) {
shift_display(1);
if (ifics != nullptr)
disp << refics << ' ';
if (print_cable)
disp << msg.getCable().getOneBased() << ' ';
disp << msg.getMessageType();
disp.display();
}
void sendNowImpl() {}

//The prefix is printed before each message
constant character *precision;

// Enter the number of the USB cable
bool print_cable = false;
};

// The usual MIDI interface used by the user to control
USBMIDI_The midi interface;
// Displays incoming messages
OLEDDebugMIDI_Output midi_disp_in {"\x1a"}; // preview="→"
// Prints messages sent to the display
OLEDDebugMIDI_Output midi_disp_out {"\x1b"}; // preview="←"
// Two channels for MIDI marking
MIDI_PipeFactory<2> pipes;

// A bank consisting of six addresses for selecting sontrollers and channels linked to CC controllers.
Bank<10> bank;

// Selector for selecting a bank of controllers and channels.
Incremental selector<10> bank selector {
bank,
6,
};
// Encoder for adjusting the value of the volume, reverb and rurus control parameters.
Available for payments::ManyAddresses::CCAbsoluteEncoder<10> enc = {
bank, // The bank that controls the totem.
{4, 5}, // Encoder connection pins.
{
{
{07, Channel_1}, // Bank address 1.
{07, Channel_2}, // Bank address 2.
{07, Channel_3}, // Bank address 3.
{07, Channel_10},// Bank address 4.
{91, Channel_1}, // Bank address 5.
{91, Channel_2}, // Bank address 6.
{91, Channel_3}, // Bank address 7.
{93, Channel_1}, // Bank address 8.
{93, Channel_2}, // Bank address 9.
{93, Channel_3}, // Bank address 10.
}
},
};

void setup() {
init_display();
midi.setAsDefault();
Control_Surface.begin();
// Redirect the MIDI connection to the diskley
midi >> pipes >> midi_disp_in;
Control_Surface >> channels >> midi_disp_out;

Serial.begin(57600);
}

void loop() {
Control_Surface.loop();
}

This is not exactly what I need! In my accordion project, the parameters of the volume level, reverb, chorus, and percussion for three keyboards will be displayed on the display. This is a melody, bass, chord on channels 1, 2, 3. And a separate 10 channel for the drum and cymbal. On all three keyboards, separately and independently, there are banks of sounds combined into groups of keyboards, strings, wind instruments, bows and synthesizer sounds. There are five tools in each group that are switched by hotkeys separately. So that you can quickly switch the timbres during the game. Turn the drums on and off. Turn effects on and off. I need to display in static mode the name of the bank and its parameters (number, channel, level) with the possibility of changing the settings. The bank with the encoder for setting levels should be displayed separately when the encoder button is pressed. Banks of sounds that are turned on separately with an increment of one button are also separate. When pressing the hotkey, the previous display should be replaced with the name of the instrument that is currently playing. And so it is with the replacement of the display when pressing the listed functions. Pressing and releasing notes does not need to be displayed. The pressure sensor for volume control by the bellows may not be displayed. It will be turned on all the time. And the relative volume and effects levels will be adjusted in each channel with one encoder. Please give an example of how to attach the display readings to these functions. And the previous issue with the monitor disappears by itself!

I'm not entirely sure what you mean, but I'm afraid that discussing specific display behavior and layout is beyond the scope of this issue tracker.

If you need help with your project, I'd recommend opening an issue on e.g. https://forum.arduino.cc/.
It will help if you post your code as is, without translating it, and you should post your code between code fences:

```cpp
// place your code between these triple backticks
```

I'd recommend also posting a link to the example you based your code on.

Thank you for taking the time to respond to my request! Indeed, my project goes far beyond the discussions and capabilities of your library. Everything that could be useful from the library documentation has already been done. As for connecting the display and displaying the system parameters, I began to study. And I've already figured out a lot of things. But so far only in a continuous loop Control_Surface.loop (); using the CCPotentiometer::getValue() and CCButton::getButtonState() methods. It remains to figure out the callback function and the binding of output variables via the adapter to the control panel elements for display on the display screen. I close the topic as going beyond the problems related directly to the library. The main purpose of this library is to communicate and control the DAW and DJ using a remote control of buttons, encoders, potentiometers. I need to transform all this into controlling the midi system built into the accordion. For playing live and not controlling the soundtrack as it happens in DAW. I wish you all the best and good health!