This is an example on how to use multiple displays to display the VU meters of many tracks, by using the Arduino as a Mackie Control Universal with extenders.
This is an example on how to use multiple displays to display the VU meters of many tracks, by using the Arduino as a Mackie Control Universal with extenders.
This example is currenty only supported on boards that support multiple virtual MIDI USB cables (e.g. Teensy).
Connect the reset pins of the two displays together, connect a capacitor from reset to ground, and a resistor from reset to 3.3V. The values are not critical, 0.1µF and 10kΩ work fine.
You do need some way to reset the displays, without it, they won't work.
Alternatively, you could use an IO pin from the Teensy to reset the displays, but this just "wastes" a pin.
Select "MIDIx4" from the Tools > USB Type menu.
Map "Control Surface (1)" as a Mackie Control Universal unit in your DAW, and map "Control Surface (2)" as a Mackie Control Universal Extender (XT).
If you have to manually set the track offset of the extender, choose 8.
The first display should now display the level meters and mute/solo states of the first 8 tracks, and the second display should display the ones of tracks 9-16.
constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;
constexpr int8_t OLED_DC = 19;
constexpr int8_t OLED_reset = -1;
constexpr int8_t OLED_CSA = 17;
constexpr int8_t OLED_CSB = 18;
constexpr uint32_t SPI_Frequency = SPI_MAX_SPEED;
Adafruit_SSD1306 ssd1306DisplayA = {
SCREEN_WIDTH, SCREEN_HEIGHT,
&SPI, OLED_DC, OLED_reset, OLED_CSA, SPI_Frequency
};
Adafruit_SSD1306 ssd1306DisplayB = {
SCREEN_WIDTH, SCREEN_HEIGHT,
&SPI, OLED_DC, OLED_reset, OLED_CSB, SPI_Frequency
};
public:
MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
if(!disp.begin())
}
disp.drawFastHLine(0, 52, 128, WHITE);
disp.drawRect(0, 0, 128, 64, WHITE);
}
} displayA = ssd1306DisplayA, displayB = ssd1306DisplayB;
};
};
};
};
};
};
{ displayA, VUMeters[0], { 2 + 16 * 0, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[1], { 2 + 16 * 1, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[2], { 2 + 16 * 2, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[3], { 2 + 16 * 3, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[4], { 2 + 16 * 4, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[5], { 2 + 16 * 5, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[6], { 2 + 16 * 6, 50 }, 12, 3, 1, WHITE },
{ displayA, VUMeters[7], { 2 + 16 * 7, 50 }, 12, 3, 1, WHITE },
};
{ displayB, VUMetersXT[0], { 2 + 16 * 0, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[1], { 2 + 16 * 1, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[2], { 2 + 16 * 2, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[3], { 2 + 16 * 3, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[4], { 2 + 16 * 4, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[5], { 2 + 16 * 5, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[6], { 2 + 16 * 6, 50 }, 12, 3, 1, WHITE },
{ displayB, VUMetersXT[7], { 2 + 16 * 7, 50 }, 12, 3, 1, WHITE },
};
{ displayA, mute[0],
XBM::mute_7, { 4 + 16 * 0, 54 }, WHITE },
{ displayA, mute[1],
XBM::mute_7, { 4 + 16 * 1, 54 }, WHITE },
{ displayA, mute[2],
XBM::mute_7, { 4 + 16 * 2, 54 }, WHITE },
{ displayA, mute[3],
XBM::mute_7, { 4 + 16 * 3, 54 }, WHITE },
{ displayA, mute[4],
XBM::mute_7, { 4 + 16 * 4, 54 }, WHITE },
{ displayA, mute[5],
XBM::mute_7, { 4 + 16 * 5, 54 }, WHITE },
{ displayA, mute[6],
XBM::mute_7, { 4 + 16 * 6, 54 }, WHITE },
{ displayA, mute[7],
XBM::mute_7, { 4 + 16 * 7, 54 }, WHITE },
};
{ displayB, muteXT[0],
XBM::mute_7, { 4 + 16 * 0, 54 }, WHITE },
{ displayB, muteXT[1],
XBM::mute_7, { 4 + 16 * 1, 54 }, WHITE },
{ displayB, muteXT[2],
XBM::mute_7, { 4 + 16 * 2, 54 }, WHITE },
{ displayB, muteXT[3],
XBM::mute_7, { 4 + 16 * 3, 54 }, WHITE },
{ displayB, muteXT[4],
XBM::mute_7, { 4 + 16 * 4, 54 }, WHITE },
{ displayB, muteXT[5],
XBM::mute_7, { 4 + 16 * 5, 54 }, WHITE },
{ displayB, muteXT[6],
XBM::mute_7, { 4 + 16 * 6, 54 }, WHITE },
{ displayB, muteXT[7],
XBM::mute_7, { 4 + 16 * 7, 54 }, WHITE },
};
{ displayA, solo[0],
XBM::solo_7, { 4 + 16 * 0, 54 }, WHITE },
{ displayA, solo[1],
XBM::solo_7, { 4 + 16 * 1, 54 }, WHITE },
{ displayA, solo[2],
XBM::solo_7, { 4 + 16 * 2, 54 }, WHITE },
{ displayA, solo[3],
XBM::solo_7, { 4 + 16 * 3, 54 }, WHITE },
{ displayA, solo[4],
XBM::solo_7, { 4 + 16 * 4, 54 }, WHITE },
{ displayA, solo[5],
XBM::solo_7, { 4 + 16 * 5, 54 }, WHITE },
{ displayA, solo[6],
XBM::solo_7, { 4 + 16 * 6, 54 }, WHITE },
{ displayA, solo[7],
XBM::solo_7, { 4 + 16 * 7, 54 }, WHITE },
};
{ displayB, soloXT[0],
XBM::solo_7, { 4 + 16 * 0, 54 }, WHITE },
{ displayB, soloXT[1],
XBM::solo_7, { 4 + 16 * 1, 54 }, WHITE },
{ displayB, soloXT[2],
XBM::solo_7, { 4 + 16 * 2, 54 }, WHITE },
{ displayB, soloXT[3],
XBM::solo_7, { 4 + 16 * 3, 54 }, WHITE },
{ displayB, soloXT[4],
XBM::solo_7, { 4 + 16 * 4, 54 }, WHITE },
{ displayB, soloXT[5],
XBM::solo_7, { 4 + 16 * 5, 54 }, WHITE },
{ displayB, soloXT[6],
XBM::solo_7, { 4 + 16 * 6, 54 }, WHITE },
{ displayB, soloXT[7],
XBM::solo_7, { 4 + 16 * 7, 54 }, WHITE },
};
void setup() {
}
void loop() {
}
constexpr Channel Channel_1
The main header file that includes all Control-Surface header files.
Control_Surface_ & Control_Surface
A predefined instance of the Control Surface to use in the Arduino sketches.
A class that displays a bitmap depending on the state of a MIDINote or any other object that has a ge...
void begin()
Initialize the Control_Surface.
void loop()
Update all MIDI elements, send MIDI events and read MIDI input.
virtual void begin()
Initialize the display.
Displays a MCU level meter.
A MIDI input element that represents a Mackie Control Universal VU meter.
Generic base class for classes that listen for MIDI Note, Control Change and Key Pressure events on a...
This class creates a mapping between the Adafruit_SSD1306 display driver and the general display inte...
void drawBackground() override=0
Draw a custom background.
A class for MIDI interfaces sending MIDI messages over a USB MIDI connection.
#define FATAL_ERROR(msg, errc)
Print the error message and error code, and stop the execution.
constexpr uint8_t MUTE_1
Mute 1 (In/Out)
constexpr uint8_t SOLO_6
Solo 6 (In/Out)
constexpr uint8_t MUTE_5
Mute 5 (In/Out)
constexpr uint8_t MUTE_6
Mute 6 (In/Out)
constexpr uint8_t SOLO_2
Solo 2 (In/Out)
constexpr uint8_t SOLO_1
Solo 1 (In/Out)
constexpr uint8_t SOLO_8
Solo 8 (In/Out)
constexpr uint8_t MUTE_8
Mute 8 (In/Out)
constexpr uint8_t SOLO_4
Solo 4 (In/Out)
constexpr uint8_t SOLO_5
Solo 5 (In/Out)
constexpr uint8_t MUTE_7
Mute 7 (In/Out)
constexpr uint8_t MUTE_4
Mute 4 (In/Out)
constexpr uint8_t SOLO_7
Solo 7 (In/Out)
constexpr uint8_t SOLO_3
Solo 3 (In/Out)
constexpr uint8_t MUTE_2
Mute 2 (In/Out)
constexpr uint8_t MUTE_3
Mute 3 (In/Out)
constexpr unsigned int Default
Decay one segment/block every 150 ms if no new values are received.
const XBitmap solo_7
XBitmap solo_7 (7px × 7px)
const XBitmap mute_7
XBitmap mute_7 (7px × 7px)