tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.
GNU General Public License v3.0
1.23k stars 139 forks source link

ssd1306 and teensy 4.0 #286

Open benwadub opened 4 years ago

benwadub commented 4 years ago

hi, again me, I d like to add the ssd 1306 display I just received to my controller but can t find how to adapt the exemple code to my teensy 4.0, no problem to wire and and vcc but how to wire the scl sda res and dc pins of the screen and how to write it in the code, I can t find in your exemple code the screen pins, I just see dc pin reset and cs that I don t have on my screen

/**
 /**
 * An example demonstrating the use of DisplayElement%s to display information
 * from the DAW on a small OLED display.
 *
 * @boards  Teensy 3.x
 * 
 * Connections
 * -----------
 * 
 * - 5:  Push button (to ground)
 * - 6:  Push button (to ground)
 * - 7:  OLED Data/D1 (SPI MOSI)
 * - 13: OLED Clock/D0 (SPI SCK)
 * - 17: OLED Data/Command
 * - 10: OLED Cable Select
 * 
 * Add a capacitor between the reset pin of the display and 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 display, without it, it won't work.  
 * Alternatively, you could use an IO pin from the Teensy to reset the 
 * display, but this just "wastes" a pin.
 * 
 * Behavior
 * --------
 * 
 * - The time (bars, beats, fraction), play and record status are shown at the 
 *   top of the display.
 * - For each of the 8 first tracks, a VU level meter with peak indicator and
 *   a V-Pot ring showing the pan are displayed, as well as the the mute, solo 
 *   and record arm status.
 * - Two tracks are displayed at once. By pressing the push buttons connected
 *   to pins 5 and 6, you can cycle through four banks to display all 8 tracks.
 * 
 * Mapping
 * -------
 * 
 * Map "Control Surface" as a Mackie Control Universal unit in your DAW.
 * 
 * @note    There seem to be some differences in the way some applications 
 *          handle VU meters: some expect the hardware to decay automatically,
 *          some don't.  
 *          If you notice that the meters behave strangely, try both 
 *          MCU::VUDecay::Hold and MCU::VUDecay::Default, or try a different 
 *          decay time.
 * 
 * Written by PieterP, 2019-11-12  
 * https://github.com/tttapa/Control-Surface
 */

#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library.
#include <Control_Surface.h> // Include the Control Surface library
// Include the display interface you'd like to use
#include <Display/DisplayInterfaces/DisplayInterfaceSSD1306.hpp>

// ----------------------------- MIDI Interface ----------------------------- //
// ========================================================================== //

/*
   Instantiate a MIDI interface to use for the Control Surface.
*/

USBMIDI_Interface midi;
// USBDebugMIDI_Interface midi(115200);

// ----------------------------- Display setup ------------------------------ //
// ========================================================================== //

/*
   Instantiate and initialize the SSD1306 OLED display
*/

constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;

constexpr int8_t OLED_DC = 17;    // Data/Command pin of the display
constexpr int8_t OLED_reset = -1; // Use the external RC circuit for reset
constexpr int8_t OLED_CS = 10;    // Chip Select pin of the display

constexpr uint32_t SPI_Frequency = SPI_MAX_SPEED;

// Instantiate the displays
Adafruit_SSD1306 ssd1306Display = {
  SCREEN_WIDTH, SCREEN_HEIGHT, &SPI,          OLED_DC,
  OLED_reset,   OLED_CS,       SPI_Frequency,
};

// --------------------------- Display interface ---------------------------- //
// ========================================================================== //

// Implement the display interface, specifically, the begin and drawBackground
// methods.
class MySSD1306_DisplayInterface : public SSD1306_DisplayInterface {
 public:
  MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
    : SSD1306_DisplayInterface(display) {}

  void begin() override {
    // Initialize the Adafruit_SSD1306 display
    if (!disp.begin())
      FATAL_ERROR(F("SSD1306 allocation failed."), 0x1306);

    // If you override the begin method, remember to call the super class method
    SSD1306_DisplayInterface::begin();
  }

  void drawBackground() override { disp.drawLine(1, 8, 126, 8, WHITE); }

} display = ssd1306Display;

// ------------------------------- Bank setup ------------------------------- //
// ========================================================================== //

/*
   Create a bank and a bank selector to change its setting.
*/

Bank<4> bank(2); // Create a new bank with two tracks per bank

// Create a new bank selector to control the bank using two push buttons
IncrementDecrementSelector<4> bankselector = {bank, {5, 6}, Wrap::Wrap};

// -------------------------- MIDI Input Elements --------------------------- //
// ========================================================================== //

/*
   Define all elements that listen for MIDI messages.
*/

// Time display keeps track of the bar counter
MCU::TimeDisplay timedisplay = {};

// Play / Record
NoteValue play = {MCU::PLAY};
NoteValue record = {MCU::RECORD};

// Mute
Bankable::NoteValue<4> mute[] = {
  {bank, MCU::MUTE_1},
  {bank, MCU::MUTE_2},
};

// Solo
Bankable::NoteValue<4> solo[] = {
  {bank, MCU::SOLO_1},
  {bank, MCU::SOLO_2},
};

NoteValue rudeSolo = {MCU::RUDE_SOLO};

// Record arm / ready
Bankable::NoteValue<4> recrdy[] = {
  {bank, MCU::REC_RDY_1},
  {bank, MCU::REC_RDY_2},
};

// VU meters
MCU::Bankable::VU<4> vu[] = {
  {bank, 1, MCU::VUDecay::Hold},
  {bank, 2, MCU::VUDecay::Hold},
};

// VPot rings
MCU::Bankable::VPotRing<4> vpot[] = {
  {bank, 1},
  {bank, 2},
};

// ---------------------------- Display Elements ---------------------------- //
// ========================================================================== //

/*
   Define all display elements that display the state of the input elements.
*/

// Time display
MCU::TimeDisplayDisplay timedisplaydisplay = {
  // position (0, 0), font size (1)
  display, timedisplay, {0, 0}, 1, WHITE,
};

// Play / Record
NoteBitmapDisplay playDisp = {
  display, play, XBM::play_7, {16 + 64, 0}, WHITE,
};
NoteBitmapDisplay recordDisp = {
  display, record, XBM::record_7, {26 + 64, 0}, WHITE,
};

// Mute
NoteBitmapDisplay muteDisp[] = {
  {display, mute[0], XBM::mute_10B, {14, 50}, WHITE},
  {display, mute[1], XBM::mute_10B, {14 + 64, 50}, WHITE},
};

// Solo
NoteBitmapDisplay soloDisp[] = {
  {display, solo[0], XBM::solo_10B, {14, 50}, WHITE},
  {display, solo[1], XBM::solo_10B, {14 + 64, 50}, WHITE},
};

NoteBitmapDisplay rudeSoloDisp = {
  display, rudeSolo, XBM::solo_7, {36 + 64, 0}, WHITE};

// Record arm / ready
NoteBitmapDisplay recrdyDisp[] = {
  {display, recrdy[0], XBM::rec_rdy_10B, {14 + 14, 50}, WHITE},
  {display, recrdy[1], XBM::rec_rdy_10B, {14 + 14 + 64, 50}, WHITE},
};

// VU meters
MCU::VUDisplay vuDisp[] = {
  // position (32+11, 60), width (16), bar height (3) px, bar spacing (1) px
  {display, vu[0], {32 + 11, 60}, 16, 3, 1, WHITE},
  {display, vu[1], {32 + 11 + 64, 60}, 16, 3, 1, WHITE},
};

// VPot rings
MCU::VPotDisplay vpotDisp[] = {
  // position (0, 10), outer radius (16) px, inner radius (13) px
  {display, vpot[0], {0, 10}, 16, 13, WHITE},
  {display, vpot[1], {64, 10}, 16, 13, WHITE},
};

// Bank seting
BankDisplay bankDisp[] = {
  // first track of the bank (1), position (0, 50), font size (2)
  {display, bank, 1, {0, 50}, 2, WHITE},
  {display, bank, 2, {64, 50}, 2, WHITE},
};

// --------------------------------- Setup ---------------------------------- //
// ========================================================================== //

void setup() {
  // The default SPI MOSI pin (11) is used for I²S, so we need to use the
  // alternative MOSI pin (7)
  SPI.setMOSI(7);
  // Correct relative mode for MCU rotary encoders
  RelativeCCSender::setMode(MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

// ---------------------------------- Loop ---------------------------------- //
// ========================================================================== //

void loop() {
  Control_Surface.loop(); // Refresh all elements
}
tttapa commented 4 years ago

These are questions about the Adafruit_SSD1306 library. Please see the examples that come with that library, as well as the pinout diagram of the Teensy board you're using.

benwadub commented 4 years ago

I already tried this but as a total noob I don t understand everything don t know where to put data connection by exemple :-( and the reset

tttapa commented 4 years ago

Did you get the examples of the Adafruit_SSD1306 library to work? If that doesn't work, you won't get this example to work either.

benwadub commented 4 years ago

I m totally confusing between all these things!! 😅 I ll have to find clear documentation on spi protocol and find what correspond to what sck dc cs... all made a big head hake to my brain this evening 😅 I don’t know at all where my screens pins have to go on the teensy and don t understand for the moment how the code work for spi!

benwadub commented 4 years ago

It seems that the labeling on my screen is not like the standard spi did you already saw that? I don t have pin labeled mosi or midi or dc, ![Uploading 228E0333-93BF-4CE5-973D-48DA97416005.jpeg…]()

benwadub commented 4 years ago

![Uploading 6EE67709-783D-4EF3-BD6A-7CB639878EE2.jpeg…]()

tttapa commented 4 years ago

The images you posted don't work. You have to wait for them to upload before posting.

benwadub commented 4 years ago

Sorry! 297C5D65-34EB-48B8-B974-FE4EDAAAC07A ![Uploading EB0DC1AA-C7F1-43D4-8961-5DF7DB7E97AA.jpeg…]()

tttapa commented 4 years ago

I've never come across an SSD1306 display with 6 pins. The DC pin suggests that it's an SPI variant, but the lack of a CS pin and the SCL/SDA labels suggest I²C.

Since this is not strictly related to the Control Surface library, I'd suggest using the Arduino forum instead.

benwadub commented 4 years ago

I asked on the teensy Facebook group, hope I ll have an answer! It s a display that can be used with i2c and spi, it could be better for me to find a nirmal spi display

Le 28 sept. 2020 à 20:48, Pieter P notifications@github.com a écrit :

 I've never come across an SSD1306 display with 6 pins. The DC pin suggests that it's an SPI variant, but the lack of a CS pin and the SCL/SDA labels suggest I²C.

Since this is not strictly related to the Control Surface library, I'd suggest using the Arduino forum instead.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

benwadub commented 4 years ago

ok so I got it working! with the Adafruit library now! I ll be able to start with your library!

benwadub commented 4 years ago

ok so my display work with these pins assignment in the Adafruit exemple

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   11//sda pin on my display
#define OLED_CLK   13//scl pin on my display
#define OLED_DC    18//dc pin on my display
#define OLED_CS    10//not wired
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

but can t make it work with your exemple: mcu OLED display I can t find where you use the clk pin in your code?

tttapa commented 4 years ago

The code you posted uses software SPI, which is much slower than hardware SPI. Also try to avoid preprocessor macros, use constants instead.

Try this

constexpr uint8_t SCREEN_WIDTH = 128; // OLED display width, in pixels
constexpr uint8_t SCREEN_HEIGHT = 64; // OLED display height, in pixels

// Declaration for SSD1306 display connected using software SPI (default case):
constexpr uint8_t OLED_DC = 18; // DC pin on my display
constexpr uint8_t OLED_CS = 10; // not wired
constexpr uint8_t OLED_RESET = -1;

Adafruit_SSD1306 ssd1306Display = {
  SCREEN_WIDTH, SCREEN_HEIGHT,
  &SPI,
  OLED_DC, OLED_RESET, OLED_CS,
};
benwadub commented 4 years ago

I ll try tomorrow thanks! I think i didn’t show you the finished controler here it is! Thanks again for this I m glad to achieved this with your help! 10CC0C35-1E54-4918-A54B-8649E165EBA1

tttapa commented 4 years ago

Looks great! Thanks for sharing.

benwadub commented 4 years ago

hi, that doesn't work, is it normal that you don t declare the clk pin that is on pin 13 ?

benwadub commented 4 years ago

hi, I found that spa has to be in mode 3 for ssd1306 and teensy 4.0

include

include

class Adafruit_SSD1309_SPI : public Adafruit_SSD1306 { public: Adafruit_SSD1309_SPI(uint8_t w, uint8_t h, SPIClass *spi, int8_t dc_pin, int8_t rst_pin, int8_t cs_pin, uint32_t bitrate=8000000UL) : Adafruit_SSD1306(w, h, spi, dc_pin, rst_pin, cs_pin, bitrate) {

ifdef SPI_HAS_TRANSACTION

spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE3);

endif

I add this lines at the top of the code like in the Adafruit exemple and that works fine now! thanks for the help!

tttapa commented 4 years ago

I didn't know that, the SSD1306 SPI displays I have lying around all use the default SPI mode. Are you using an SSD1309 or SSD1306?

benwadub commented 4 years ago

Have a look at this page it s where I found the solution! https://github.com/adafruit/Adafruit_SSD1306/issues/167

benwadub commented 4 years ago

It s a 1306 here

benwadub commented 4 years ago

hi i m relie not enough experienced to use theses screens I got, do you have link where you buy yours to be sure they will work with the library please?

tttapa commented 4 years ago

I got mine on eBay long ago, I doubt the same listing will still be available. Just make sure it has 7 pins: Gnd, Vcc, D0, D1, Res, DC, CS

If you made your display work with the Adafruit library, why can't you get it to work with Control Surface? It uses the same library, you just have to wrap your display in the MySSD1306_DisplayInterface class of the example.

// You should already have this from the Adafruit library, it is identical.
Adafruit_SSD1309_SPI ssd1306Display( /* options */);

// This is a wrapper to pass your display to the Control Surface library
class MySSD1306_DisplayInterface : public SSD1306_DisplayInterface {
 public:
  MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
    : SSD1306_DisplayInterface(display) {}

  void begin() override {
    // Initialize the Adafruit_SSD1306 display
    if (!disp.begin())
      FATAL_ERROR(F("SSD1306 allocation failed."), 0x1306);

    // If you override the begin method, remember to call the super class method
    SSD1306_DisplayInterface::begin();
  }

  void drawBackground() override { disp.drawLine(1, 8, 126, 8, WHITE); }

} display = ssd1306Display; // Pass the Adafruit display to the wrapper.

You'll have to post your code and explain exactly what the problem is, otherwise I can't help you.

benwadub commented 4 years ago

Wouah thanks, I didn’t want to be insistant with my problem that is not really related to your library! I forgot to save the code when that worked and can t make it working again! I ll try again with that!

benwadub commented 4 years ago

I got it but with my code the screen is scrolling, see the vidéo any idea of what can do it? image post in the next comment

benwadub commented 4 years ago

#include <Encoder.h> // Include the Encoder library.
#include "Control_Surface.h"
#include <Display/DisplayInterfaces/DisplayInterfaceSSD1306.hpp>

//#include <name.c>
// celà doit etre écrit avant la library control surface
 //USBDebugMIDI_Interface midi = 115200; // enlever les // en début de ligne pour entrer en mode debug usb et voir dans le panneau de control si vos controler envoient bien les infos

//auto &serial = Serial1;// Selectionne le port série à utiliser remplacer par serial pour une arduino
//SerialMIDI_Interface<decltype(serial)> midi = {serial, MIDI_BAUD};// démarre une interface midi serial au midi baud rate par defaut
USBMIDI_Interface usbmidi;// enlever les / en debut de ligne pour activer l'interface usb, penser à désactiver l'interface série(din)
HardwareSerialMIDI_Interface midiser = Serial1;

MIDI_PipeFactory<8> pipes;
// ----------------------------- Display setup ------------------------------ //
// ========================================================================== //

/*
   Instantiate and initialize the SSD1306 OLED display
*/

constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;

constexpr int8_t OLED_DC = 19;    // Data/Command pin of the display
constexpr int8_t OLED_reset = -1; // Use the external RC circuit for reset
constexpr int8_t OLED_CS = 10;   //wired on 13

constexpr uint32_t SPI_Frequency = SPI_MAX_SPEED;

// Instantiate the displays
Adafruit_SSD1306 ssd1306Display = {
  SCREEN_WIDTH, SCREEN_HEIGHT, &SPI,          OLED_DC,
  OLED_reset,   OLED_CS,       SPI_Frequency,
};

// --------------------------- Display interface ---------------------------- //
// ========================================================================== //

// Implement the display interface, specifically, the begin and drawBackground
// methods.
class MySSD1306_DisplayInterface : public SSD1306_DisplayInterface {
 public:
  MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
    : SSD1306_DisplayInterface(display) {}

  void begin() override {
    // Initialize the Adafruit_SSD1306 display
    if (!disp.begin())
      FATAL_ERROR(F("SSD1306 allocation failed."), 0x1306);

    // If you override the begin method, remember to call the super class method
    SSD1306_DisplayInterface::begin();
  }

  void drawBackground() override { disp.drawLine(1, 8, 126, 8, WHITE); }

} display = ssd1306Display;

CD74HC4067 mux1 = {
  14,       // numéro de broche de l'arduino
  {9, 3, 4, 5} // numéro de pins de l'arduino sur lesquels sont branchés tous les multiplexeurs apellés mux S0, S1, S2
};

CD74HC4067 mux2 = {
  15,              
  {9, 3, 4, 5}, 
};

CD74HC4067 mux3 = {
  16,       
  {9, 3, 4, 5} 
};
CD74HC4067 mux4 = {
  17,       
  {9, 3, 4, 5} 
};
CD74HC4067 mux5 = {
  18,      
  {9, 3, 4, 5} 
};

Bank<2> bank = {8}; // active 2 bank avec 8 adresses par bank
IncrementDecrementSelector<2> selector = {
    bank,       // Bank to manage
    {5, 6},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

CCPotentiometer fxparameter [] = {
  {mux1.pin(0), {85, CHANNEL_16}},//delay time
  {mux1.pin(1), {86, CHANNEL_16}},//pingpong
  {mux1.pin(2), {87, CHANNEL_16}},//stereo width
  {mux1.pin(3), {88, CHANNEL_16}},//feedback
  {mux1.pin(4), {89, CHANNEL_16}},//hph
  {mux1.pin(5), {90, CHANNEL_16}},//lpf
  {mux1.pin(6), {91, CHANNEL_16}},//reverb send
  {mux1.pin(7), {92, CHANNEL_16}},//mix volume
  {mux1.pin(15), {24, CHANNEL_16}},//pre delay
  {mux1.pin(14), {25, CHANNEL_16}},//reverb decay
  {mux1.pin(13), {26, CHANNEL_16}},//reverb filter
  {mux1.pin(12), {27, CHANNEL_16}},//shelving gain
  {mux1.pin(11), {28, CHANNEL_16}},//hpf
  {mux1.pin(10), {29, CHANNEL_16}},//lpf
  {mux1.pin(9), {31, CHANNEL_16}},//mux volume
  {mux1.pin(8), {119, CHANNEL_16}},//pattern volume
};

Bankable::CCPotentiometer ODPAN [] = {
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(0), {81, CHANNEL_1}},//overdrive
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(1), {81, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(2), {81, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(3), {81, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(4), {81, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(5), {81, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(6), {81, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(7), {81, CHANNEL_8}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(15), {10, CHANNEL_1}},//pan
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(14), {10, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(13), {10, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(12), {10, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(11), {10, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(10), {10, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(9), {10, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(8), {10, CHANNEL_8}},
};
Bankable::CCPotentiometer fx [] = {
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(0), {83, CHANNEL_1}},//reverb send
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(1), {83, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(2), {83, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(3), {83, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(4), {83, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(5), {83, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(6), {83, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(7), {83, CHANNEL_8}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(15), {82, CHANNEL_1}},//delay send
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(14), {82, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(13), {82, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(12), {82, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(11), {82, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(10), {82, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(9), {82, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(8), {82, CHANNEL_8}},
};

Bankable::CCPotentiometer filtre [] = {
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(0), {74, CHANNEL_1}},//filtre freq
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(1), {74, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(2), {74, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(3), {74, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(4), {74, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(5), {74, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(6), {74, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(7), {74, CHANNEL_8}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(15), {75, CHANNEL_1}},//filtre reso
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(14), {75, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(13), {75, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(12), {75, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(11), {75, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(10), {75, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(9), {75, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(8), {75, CHANNEL_8}},
};

Bankable::CCPotentiometer fader [] = { //ici on déclare les faders avec comme vu plus haut le numéro de CC et le canal
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(15), {7, CHANNEL_1}},//volume
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(14), {7, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(13), {7, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(12), {7, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(11), {7, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(10), {7, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(9), {7, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(8), {7, CHANNEL_8}},
};
 Bankable::CCButtonLatched<2> buttonmute[] = { 
  {{bank,BankType::CHANGE_CHANNEL}, mux5.pin(0), {94, CHANNEL_1}},//numéro de bank correspondant/indique que le changement de bank change le canal midi (+8 car on a 8 adresses par bank)/pin sur laquelle le controleur est branché/numéro de cc/numéro de canal midi
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(1), {94, CHANNEL_2}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(2), {94, CHANNEL_3}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(3), {94, CHANNEL_4}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(4), {94, CHANNEL_5}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(5), {94, CHANNEL_6}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(6), {94, CHANNEL_7}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(7), {94, CHANNEL_8}},
};
CCButtonLatched button1 = {19, {120, CHANNEL_16}};
CCButtonLatched button2 = {20, {121, CHANNEL_16}};

/*CCButton button2 = {
  // Push button on pin 20:
  20,
  // General Purpose Controller #1 on MIDI channel 1:
  {121, CHANNEL_16},
};*/

  // -------------------------- MIDI Input Elements --------------------------- //
// ========================================================================== //

/*
   Define all elements that listen for MIDI messages.
*/

// Time display keeps track of the bar counter
MCU::TimeDisplay timedisplay = {};

// Play / Record
NoteValue play = {MCU::PLAY};
NoteValue record = {MCU::RECORD};

// Mute
Bankable::NoteValue<2> mute[] = {
  {bank, MCU::MUTE_1},
  {bank, MCU::MUTE_2},
};

// Solo
Bankable::NoteValue<2> solo[] = {
  {bank, MCU::SOLO_1},
  {bank, MCU::SOLO_2},
};

NoteValue rudeSolo = {MCU::RUDE_SOLO};

// Record arm / ready
Bankable::NoteValue<2> recrdy[] = {
  {bank, MCU::REC_RDY_1},
  {bank, MCU::REC_RDY_2},
};

// VU meters
MCU::Bankable::VU<2> vu[] = {
  {bank, 1, MCU::VUDecay::Hold},
  {bank, 2, MCU::VUDecay::Hold},
};

// VPot rings
MCU::Bankable::VPotRing<2> vpot[] = {
  {bank, 1},
  {bank, 2},
};

// ---------------------------- Display Elements ---------------------------- //
// ========================================================================== //

/*
   Define all display elements that display the state of the input elements.
*/

// Time display
MCU::TimeDisplayDisplay timedisplaydisplay = {
  // position (0, 0), font size (1)
  display, timedisplay, {0, 0}, 1, WHITE,
};

// Play / Record
NoteBitmapDisplay playDisp = {
  display, play, XBM::play_7, {16 + 64, 0}, WHITE,
};
NoteBitmapDisplay recordDisp = {
  display, record, XBM::record_7, {26 + 64, 0}, WHITE,
};

// Mute
NoteBitmapDisplay muteDisp[] = {
  {display, mute[0], XBM::mute_10B, {14, 50}, WHITE},
  {display, mute[1], XBM::mute_10B, {14 + 64, 50}, WHITE},
};

// Solo
NoteBitmapDisplay soloDisp[] = {
  {display, solo[0], XBM::solo_10B, {14, 50}, WHITE},
  {display, solo[1], XBM::solo_10B, {14 + 64, 50}, WHITE},
};

NoteBitmapDisplay rudeSoloDisp = {
  display, rudeSolo, XBM::solo_7, {36 + 64, 0}, WHITE};

// Record arm / ready
NoteBitmapDisplay recrdyDisp[] = {
  {display, recrdy[0], XBM::rec_rdy_10B, {14 + 14, 50}, WHITE},
  {display, recrdy[1], XBM::rec_rdy_10B, {14 + 14 + 64, 50}, WHITE},
};

// VU meters
MCU::VUDisplay vuDisp[] = {
  // position (32+11, 60), width (16), bar height (3) px, bar spacing (1) px
  {display, vu[0], {32 + 11, 60}, 16, 3, 1, WHITE},
  {display, vu[1], {32 + 11 + 64, 60}, 16, 3, 1, WHITE},
};

// VPot rings
MCU::VPotDisplay vpotDisp[] = {
  // position (0, 10), outer radius (16) px, inner radius (13) px
  {display, vpot[0], {0, 10}, 16, 13, WHITE},
  {display, vpot[1], {64, 10}, 16, 13, WHITE},
};

// Bank seting
BankDisplay bankDisp[] = {
  // first track of the bank (1), position (0, 50), font size (2)
  {display, bank, 1, {0, 50}, 2, WHITE},
  {display, bank, 2, {64, 50}, 2, WHITE},
};

void setup() {
    SPI.setMOSI(11);
  // Correct relative mode for MCU rotary encoders
  RelativeCCSender::setMode(MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface

  Control_Surface.begin(); // initialise la library surface de control
  usbmidi >> pipes >> midiser; // all incoming midi from USB is sent to serial
  usbmidi << pipes << midiser; // all incoming midi from Serial is sent to USB
  usbmidi >> pipes >> usbmidi; // all incoming midi from USB is looped back
  midiser << pipes << midiser;
  Control_Surface >> pipes >> usbmidi;
  Control_Surface << pipes << usbmidi;
  Control_Surface >> pipes >> midiser;
  Control_Surface << pipes << midiser;
  usbmidi.begin();
  midiser.begin();
 // The default SPI MOSI pin (11) is used for I²S, so we need to use the
  // alternative MOSI pin (7)
  SPI.setMOSI(11);
  // Correct relative mode for MCU rotary encoders
  RelativeCCSender::setMode(MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface

}                           
void loop() {

  Control_Surface.loop(); // Update the Control Surface
  usbmidi.update();
  midiser.update();
}```
tttapa commented 4 years ago

Your code is way too complicated, start with a shorter example when debugging. Remove 90% of it, leaving a single MIDI interface, a single MIDI input element, and a single display element, without all the mux stuff or MIDI routing. Don't start integrating until your separate components work correctly.

constexpr int8_t OLED_CS = 10;   //wired on 13

What do you mean "wired on 13"? Pin 13 is the SCK pin, you shouldn't be using it for other purposes. I can't see whether pin 13 is connected from your image. Pin 13 (SCK) should be connected to the clock pin of the display. Please see the Teensy pinout: Teensy 4.0 pinout

Why are you calling Control_Surface.begin() multiple times? Please see https://tttapa.github.io/Control-Surface-doc/Doxygen/d5/da5/Dual-MIDI-Interface_8ino-example.html, you have to connect the pipes before initializing Control_Surface.

Do you really want to loop back all MIDI data to the same interface? I just tried it, and it simply crashed my DAW, because the DAW also loops back some messages, creating an infinite loop.

If you are using Control_Surface to handle the MIDI interfaces, you don't have to call usbmidi.begin() or update() yourself.

SPI.setMOSI(11); is redundant, pin 11 is the default SPI MOSI pin.

I cannot see any videos, so I'm not sure what you mean by flickering. If the problem persists, try shorter cables or a lower SPI clock speed.

tttapa commented 4 years ago

Also, what's the value of the capacitor on your reset line? It looks way too small. I'm using 0.1 µF. If it's too small, the display won't reset properly. Also try disconnecting the Teensy entirely to reset the display.

benwadub commented 4 years ago

So my code is working fine without the display settings, I loop the midi to be able to use my contrôler over usb for a part of it and midi din for the other part and this work nicely! For the control surface begin it s a mistake I just done by copy/paste from your exemple sorry! I removed the spi pin didn’t t know it was not useful! By screen scrolling I mean my vpots and vu meter... are turning from left to right infinitely, and my capacitor is a 104z that is normaly 0,1 µF i m right?

benwadub commented 4 years ago

I tried removing the pots and all I got on mux and this work fine! I think the problem is because my mux are not connected while I try the display screen! Could you just write me a line of code for this line

{{bank,BankType::CHANGE_CHANNEL}, mux5.pin(0), {94, CHANNEL_1}},

display the mute icon on the display to this location I had with the mcu

{display, mute[0], XBM::mute_10B, {10, 13}, WHITE},
tttapa commented 4 years ago

Could you just write me a line of code for this line

What do you mean?

benwadub commented 4 years ago

when I push my cc button that send the cc94 on channel that is mapped to my daw mute, I d like that my daw send back this information to my controller screen this way I could know just looking my controller what track is muted or not

tttapa commented 4 years ago

Use the NoteValue class, you already have it in your code, just replace MCU::MUTE_1 with 94. Then pass that NoteValue object to a NoteBitmapDisplay (you already have this in your code as well).

Again, I highly recommend using a much smaller sketch to start with, especially if you're going to post them here. Isolate the relevant parts, and make sure each component works separately before combining everything.

benwadub commented 4 years ago

ok so I reduced the code to the minimum for my mute button only but I can t compile


#include <Control_Surface.h>

#include <Encoder.h> // Include the Encoder library.
#include "Control_Surface.h"
#include <Display/DisplayInterfaces/DisplayInterfaceSSD1306.hpp>

//#include <name.c>
// celà doit etre écrit avant la library control surface
 //USBDebugMIDI_Interface midi = 115200; // enlever les // en début de ligne pour entrer en mode debug usb et voir dans le panneau de control si vos controler envoient bien les infos

//auto &serial = Serial1;// Selectionne le port série à utiliser remplacer par serial pour une arduino
//SerialMIDI_Interface<decltype(serial)> midi = {serial, MIDI_BAUD};// démarre une interface midi serial au midi baud rate par defaut
USBMIDI_Interface usbmidi;// enlever les / en debut de ligne pour activer l'interface usb, penser à désactiver l'interface série(din)
// ----------------------------- Display setup ------------------------------ //
// ========================================================================== //

/*
   Instantiate and initialize the SSD1306 OLED display
*/

constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;

constexpr int8_t OLED_DC = 19;    // Data/Command pin of the display
constexpr int8_t OLED_reset = -1; // Use the external RC circuit for reset
constexpr int8_t OLED_CS = 10;   //wired on 13

constexpr uint32_t SPI_Frequency = SPI_MAX_SPEED;

// Instantiate the displays
Adafruit_SSD1306 ssd1306Display = {
  SCREEN_WIDTH, SCREEN_HEIGHT, &SPI,          OLED_DC,
  OLED_reset,   OLED_CS,       SPI_Frequency,
};

// --------------------------- Display interface ---------------------------- //
// ========================================================================== //

// Implement the display interface, specifically, the begin and drawBackground
// methods.
class MySSD1306_DisplayInterface : public SSD1306_DisplayInterface {
 public:
  MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
    : SSD1306_DisplayInterface(display) {}

  void begin() override {
    // Initialize the Adafruit_SSD1306 display
    if (!disp.begin())
      FATAL_ERROR(F("SSD1306 allocation failed."), 0x1306);

    // If you override the begin method, remember to call the super class method
    SSD1306_DisplayInterface::begin();
  }

  void drawBackground() override { disp.drawLine(1, 8, 126, 8, WHITE); }

} display = ssd1306Display;
Bank<2> bank = {8}; // active 2 bank avec 8 adresses par bank
IncrementDecrementSelector<2> selector = {
    bank,       // Bank to manage
    {5, 6},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};
CD74HC4067 mux5 = {
  18,      
  {9, 3, 4, 5} 
};
 Bankable::CCButtonLatched<2> buttonmute[] = { 
  {{bank,BankType::CHANGE_CHANNEL}, mux5.pin(0), {94, CHANNEL_1}},//numéro de bank correspondant/indique que le changement de bank change le canal midi (+8 car on a 8 adresses par bank)/pin sur laquelle le controleur est branché/numéro de cc/numéro de canal midi
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(1), {94, CHANNEL_2}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(2), {94, CHANNEL_3}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(3), {94, CHANNEL_4}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(4), {94, CHANNEL_5}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(5), {94, CHANNEL_6}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(6), {94, CHANNEL_7}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(7), {94, CHANNEL_8}},
};
// Mute
Bankable::NoteValue<2> mute[] = {
  {bank, {94, CHANNEL_1}},
  {bank, {94, CHANNEL_2}},
  {bank, {94, CHANNEL_3}},
  {bank, {94, CHANNEL_4}},
  {bank, {94, CHANNEL_5}},
  {bank, {94, CHANNEL_6}},
  {bank, {94, CHANNEL_7}},
  {bank, {94, CHANNEL_8}},

};
// Mute
NoteBitmapDisplay muteDisp[] = {
  display, 94, CHANNEL_1, XBM::mute_10B, {10, 13}, WHITE,
  display, 94, CHANNEL_2, XBM::mute_10B, {42, 13}, WHITE,
  display, 94, CHANNEL_3, XBM::mute_10B, {74, 13}, WHITE,
  display, 94, CHANNEL_4, XBM::mute_10B, {106, 13}, WHITE,
  display, 94, CHANNEL_5, XBM::mute_10B, {10, 38}, WHITE,
  display, 94, CHANNEL_6, XBM::mute_10B, {42, 38}, WHITE,
  display, 94, CHANNEL_7, XBM::mute_10B, {74, 38}, WHITE,
  display, 94, CHANNEL_8, XBM::mute_10B, {106, 38}, WHITE,

};
void setup() {
  RelativeCCSender::setMode(MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface

}

void loop() {
 Control_Surface.loop(); // Update the Control Surface

}``
I get lot of error could not convert...
tttapa commented 4 years ago

The NoteBitmapDisplay doesn't do any MIDI related things, so 94, CHANNEL_1 is meaningless in that context.

You need two things: 1. a NoteValue object that listens for MIDI messages on the given address, and 2. a NoteBitmapDisplay to display the values that are stored by the NoteValue object.

// Mute
Bankable::NoteValue<2> mute[] = {
  {bank, {94, CHANNEL_1}},
  {bank, {94, CHANNEL_2}},
  // ...
};
NoteBitmapDisplay muteDisp[] = {
  {display, mute[0], XBM::mute_10B, {10, 13}, WHITE},
  {display, mute[1], XBM::mute_10B, {10, 13}, WHITE},
  // ...
};

Please see the C++ syntax rules, and the arguments in the Control Surface documentation. Your curly braces were incorrect as well. Just passing random arguments to the constructors until it compiles will never work, please use the documentation.

benwadub commented 4 years ago

thanks! but impossible for me to know what note Ableton send for mute :-( I think I ll have to use the mcu protocol! is this the right way to implement the mcu bank? NoteButton noteButton[]={ { 5, // Push button on pin 14 MCU::BANK_LEFT, }, { 6, // Push button on pin 15 MCU::BANK_RIGHT },

MCU::Bankable::NoteValue<8> mute[] = { {bank, MCU::MUTE_1}, {bank, MCU::MUTE_2}, {bank, MCU::MUTE_3}, {bank, MCU::MUTE_4}, {bank, MCU::MUTE_5}, {bank, MCU::MUTE_6}, {bank, MCU::MUTE_7}, {bank, MCU::MUTE_8},

tttapa commented 4 years ago

but impossible for me to know what note Ableton send for mute

You can use the Mackie-Control-Universal-Reverse-Engineering example to see what Ableton is sending. Or you can use a MIDI monitor, or pipe the messages from the USBMIDI_Interface to a USBDebugMIDI_Interface.

is this the right way to implement the mcu bank?

No, your braces don't match, and if you use the MCU banks, there's no point in using the Control Surface Bankable classes. Also, there is no MCU::Bankable::NoteValue<8>, you just need NoteValue.

benwadub commented 4 years ago

I can t find the documentation on the mcu note value, where can I find how I have to write it, when I try with only notes values I get CS::NoteValue' is not a template

tttapa commented 4 years ago

I can t find the documentation on the mcu note value, where can I find how I have to write it

There is no MCU::NoteValue, only NoteValue

when I try with only notes values I get CS::NoteValue' is not a template

The compiler is right: CS::NoteValue is not a template, so don't try to pass any template arguments to it (arguments in angled brackets <...>).

benwadub commented 4 years ago

oh my god this mcu totally confuse all I thought I learnt with you!!!

// Mute
NoteValue mute = {
  {MCU::MUTE_1},
  {MCU::MUTE_2},
  {MCU::MUTE_3},
  {MCU::MUTE_4},
  {MCU::MUTE_5},
  {MCU::MUTE_6},
  {MCU::MUTE_7},
  {MCU::MUTE_8},

I thought that could work but not

tttapa commented 4 years ago

What doesn't work?

benwadub commented 4 years ago

this way that didn't t want to compile now I wrote it like this


NoteButton noteButton[]={
  {
    14,                       // Push button on pin 14
    MCU::BANK_LEFT,
  },
  {
    15,                       // Push button on pin 15
    MCU::BANK_RIGHT
  },
};
// Mute
NoteValue mute []= {
  {{MCU::MUTE_1}},
  {{MCU::MUTE_2}},
  {{MCU::MUTE_3}},
  {{MCU::MUTE_4}},
  {{MCU::MUTE_5}},
  {{MCU::MUTE_6}},
  {{MCU::MUTE_7}},
  {{MCU::MUTE_8}},

};
// Mute
NoteBitmapDisplay muteDisp[] = {
  {display, mute[0], XBM::mute_10B, {10, 13}, WHITE},
  {display, mute[1], XBM::mute_10B, {42, 13}, WHITE},
  {display, mute[2], XBM::mute_10B, {74, 13}, WHITE},
  {display, mute[3], XBM::mute_10B, {106, 13}, WHITE},
  {display, mute[4], XBM::mute_10B, {10, 38}, WHITE},
  {display, mute[5], XBM::mute_10B, {42, 38}, WHITE},
  {display, mute[6], XBM::mute_10B, {74, 38}, WHITE},
  {display, mute[7], XBM::mute_10B, {106, 38}, WHITE},

};```
the code compile but now I have no tracks that send the mute icon for Ableton, before that worked for the 8 first tracks and now no tracks work :-(
tttapa commented 4 years ago

Post your complete code. Did you select the Mackie Control Universal in the Ableton settings?

benwadub commented 4 years ago

i i selected the Mackie control as output on my daw, rectification tracks 2 3 4 5 6 7 8 work but the 1 9 10...16 doesn't t


#include <Control_Surface.h>

#include <Encoder.h> // Include the Encoder library.
#include "Control_Surface.h"
#include <Display/DisplayInterfaces/DisplayInterfaceSSD1306.hpp>

//#include <name.c>
// celà doit etre écrit avant la library control surface
 //USBDebugMIDI_Interface midi = 115200; // enlever les // en début de ligne pour entrer en mode debug usb et voir dans le panneau de control si vos controler envoient bien les infos

//auto &serial = Serial1;// Selectionne le port série à utiliser remplacer par serial pour une arduino
//SerialMIDI_Interface<decltype(serial)> midi = {serial, MIDI_BAUD};// démarre une interface midi serial au midi baud rate par defaut
USBMIDI_Interface usbmidi;// enlever les / en debut de ligne pour activer l'interface usb, penser à désactiver l'interface série(din)
HardwareSerialMIDI_Interface midiser = Serial1;

MIDI_PipeFactory<8> pipes;
// ----------------------------- Display setup ------------------------------ //
// ========================================================================== //

/*
   Instantiate and initialize the SSD1306 OLED display
*/

constexpr uint8_t SCREEN_WIDTH = 128;
constexpr uint8_t SCREEN_HEIGHT = 64;

constexpr int8_t OLED_DC = 19;    // Data/Command pin of the display
constexpr int8_t OLED_reset = -1; // Use the external RC circuit for reset
constexpr int8_t OLED_CS = 10;   //wired on 13

constexpr uint32_t SPI_Frequency = SPI_MAX_SPEED;

// Instantiate the displays
Adafruit_SSD1306 ssd1306Display = {
  SCREEN_WIDTH, SCREEN_HEIGHT, &SPI,          OLED_DC,
  OLED_reset,   OLED_CS,       SPI_Frequency,
};

// --------------------------- Display interface ---------------------------- //
// ========================================================================== //

// Implement the display interface, specifically, the begin and drawBackground
// methods.
class MySSD1306_DisplayInterface : public SSD1306_DisplayInterface {
 public:
  MySSD1306_DisplayInterface(Adafruit_SSD1306 &display)
    : SSD1306_DisplayInterface(display) {}

  void begin() override {
    // Initialize the Adafruit_SSD1306 display
    if (!disp.begin())
      FATAL_ERROR(F("SSD1306 allocation failed."), 0x1306);

    // If you override the begin method, remember to call the super class method
    SSD1306_DisplayInterface::begin();
  }

  void drawBackground() override { disp.drawLine(1, 8, 126, 8, WHITE); }

} display = ssd1306Display;

/*
CD74HC4067 mux1 = {
  14,       // numéro de broche de l'arduino
  {9, 3, 4, 5} // numéro de pins de l'arduino sur lesquels sont branchés tous les multiplexeurs apellés mux S0, S1, S2
};

CD74HC4067 mux2 = {
  15,              
  {9, 3, 4, 5}, 
};

CD74HC4067 mux3 = {
  16,       
  {9, 3, 4, 5} 
};
CD74HC4067 mux4 = {
  17,       
  {9, 3, 4, 5} 
};
CD74HC4067 mux5 = {
  18,      
  {9, 3, 4, 5} 
};
*/
Bank<2> bank = {8}; // active 2 bank avec 8 adresses par bank
IncrementDecrementSelector<2> selector = {
    bank,       // Bank to manage
    {5, 6},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};
NoteButton noteButton[]={
  {
    5,                       // Push button on pin 14
    MCU::BANK_LEFT,
  },
  {
    6,                       // Push button on pin 15
    MCU::BANK_RIGHT
  },
};
/*
CCPotentiometer fxparameter [] = {
  {mux1.pin(0), {85, CHANNEL_16}},//delay time
  {mux1.pin(1), {86, CHANNEL_16}},//pingpong
  {mux1.pin(2), {87, CHANNEL_16}},//stereo width
  {mux1.pin(3), {88, CHANNEL_16}},//feedback
  {mux1.pin(4), {89, CHANNEL_16}},//hph
  {mux1.pin(5), {90, CHANNEL_16}},//lpf
  {mux1.pin(6), {91, CHANNEL_16}},//reverb send
  {mux1.pin(7), {92, CHANNEL_16}},//mix volume
  {mux1.pin(15), {24, CHANNEL_16}},//pre delay
  {mux1.pin(14), {25, CHANNEL_16}},//reverb decay
  {mux1.pin(13), {26, CHANNEL_16}},//reverb filter
  {mux1.pin(12), {27, CHANNEL_16}},//shelving gain
  {mux1.pin(11), {28, CHANNEL_16}},//hpf
  {mux1.pin(10), {29, CHANNEL_16}},//lpf
  {mux1.pin(9), {31, CHANNEL_16}},//mux volume
  {mux1.pin(8), {119, CHANNEL_16}},//pattern volume
};

Bankable::CCPotentiometer ODPAN [] = {
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(0), {81, CHANNEL_1}},//overdrive
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(1), {81, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(2), {81, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(3), {81, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(4), {81, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(5), {81, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(6), {81, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(7), {81, CHANNEL_8}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(15), {10, CHANNEL_1}},//pan
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(14), {10, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(13), {10, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(12), {10, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(11), {10, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(10), {10, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(9), {10, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux2.pin(8), {10, CHANNEL_8}},
};
Bankable::CCPotentiometer fx [] = {
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(0), {83, CHANNEL_1}},//reverb send
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(1), {83, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(2), {83, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(3), {83, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(4), {83, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(5), {83, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(6), {83, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(7), {83, CHANNEL_8}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(15), {82, CHANNEL_1}},//delay send
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(14), {82, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(13), {82, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(12), {82, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(11), {82, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(10), {82, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(9), {82, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux4.pin(8), {82, CHANNEL_8}},
};

Bankable::CCPotentiometer filtre [] = {
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(0), {74, CHANNEL_1}},//filtre freq
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(1), {74, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(2), {74, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(3), {74, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(4), {74, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(5), {74, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(6), {74, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(7), {74, CHANNEL_8}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(15), {75, CHANNEL_1}},//filtre reso
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(14), {75, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(13), {75, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(12), {75, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(11), {75, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(10), {75, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(9), {75, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux3.pin(8), {75, CHANNEL_8}},
};

Bankable::CCPotentiometer fader [] = { //ici on déclare les faders avec comme vu plus haut le numéro de CC et le canal
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(15), {7, CHANNEL_1}},//volume
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(14), {7, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(13), {7, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(12), {7, CHANNEL_4}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(11), {7, CHANNEL_5}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(10), {7, CHANNEL_6}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(9), {7, CHANNEL_7}},
  {{bank, BankType::CHANGE_CHANNEL},mux5.pin(8), {7, CHANNEL_8}},
};
 Bankable::CCButtonLatched<2> buttonmute[] = { 
  {{bank,BankType::CHANGE_CHANNEL}, mux5.pin(0), {94, CHANNEL_1}},//numéro de bank correspondant/indique que le changement de bank change le canal midi (+8 car on a 8 adresses par bank)/pin sur laquelle le controleur est branché/numéro de cc/numéro de canal midi
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(1), {94, CHANNEL_2}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(2), {94, CHANNEL_3}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(3), {94, CHANNEL_4}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(4), {94, CHANNEL_5}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(5), {94, CHANNEL_6}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(6), {94, CHANNEL_7}},
  {{bank,BankType::CHANGE_CHANNEL},mux5.pin(7), {94, CHANNEL_8}},
};
CCButtonLatched button1 = {19, {120, CHANNEL_16}};
CCButtonLatched button2 = {20, {121, CHANNEL_16}};
*/
/*CCButton button2 = {
  // Push button on pin 20:
  20,
  // General Purpose Controller #1 on MIDI channel 1:
  {121, CHANNEL_16},
};*/

  // -------------------------- MIDI Input Elements --------------------------- //
// ========================================================================== //

/*
   Define all elements that listen for MIDI messages.
*/

MCU::TimeDisplay timedisplay = {};
// Play / Record
NoteValue play = {MCU::PLAY};
NoteValue record = {MCU::RECORD};

// Mute
NoteValue mute []= {
  {{MCU::MUTE_1}},
  {{MCU::MUTE_2}},
  {{MCU::MUTE_3}},
  {{MCU::MUTE_4}},
  {{MCU::MUTE_5}},
  {{MCU::MUTE_6}},
  {{MCU::MUTE_7}},
  {{MCU::MUTE_8}},

};

// Solo
Bankable::NoteValue<2> solo[] = {
  {bank, MCU::SOLO_1},
  {bank, MCU::SOLO_2},
};

NoteValue rudeSolo = {MCU::RUDE_SOLO};

// Record arm / ready
Bankable::NoteValue<2> recrdy[] = {
  {bank, MCU::REC_RDY_1},
  {bank, MCU::REC_RDY_2},
};

// VU meters
MCU::Bankable::VU<2> vu[] = {
  {bank, 1, MCU::VUDecay::Hold},
  {bank, 2, MCU::VUDecay::Hold},
};

// ---------------------------- Display Elements ---------------------------- //
// ========================================================================== //

/*
   Define all display elements that display the state of the input elements.
*/

// Time display
MCU::TimeDisplayDisplay timedisplaydisplay = {
  // position (0, 0), font size (1)
  display, timedisplay, {0, 0}, 1, WHITE,
};

// Play / Record
NoteBitmapDisplay playDisp = {
  display, play, XBM::play_7, {16 + 64, 0}, WHITE,
};
NoteBitmapDisplay recordDisp = {
  display, record, XBM::record_7, {26 + 64, 0}, WHITE,
};

// Mute
NoteBitmapDisplay muteDisp[] = {
  {display, mute[0], XBM::mute_10B, {10, 13}, WHITE},
  {display, mute[1], XBM::mute_10B, {42, 13}, WHITE},
  {display, mute[2], XBM::mute_10B, {74, 13}, WHITE},
  {display, mute[3], XBM::mute_10B, {106, 13}, WHITE},
  {display, mute[4], XBM::mute_10B, {10, 38}, WHITE},
  {display, mute[5], XBM::mute_10B, {42, 38}, WHITE},
  {display, mute[6], XBM::mute_10B, {74, 38}, WHITE},
  {display, mute[7], XBM::mute_10B, {106, 38}, WHITE},

};
/*
// Solo
NoteBitmapDisplay soloDisp[] = {
  {display, solo[0], XBM::solo_10B, {14, 50}, WHITE},
  {display, solo[1], XBM::solo_10B, {14 + 64, 50}, WHITE},
};

NoteBitmapDisplay rudeSoloDisp = {
  display, rudeSolo, XBM::solo_7, {36 + 64, 0}, WHITE};

// Record arm / ready
NoteBitmapDisplay recrdyDisp[] = {
  {display, recrdy[0], XBM::rec_rdy_10B, {14 + 14, 50}, WHITE},
  {display, recrdy[1], XBM::rec_rdy_10B, {14 + 14 + 64, 50}, WHITE},
};

// VU meters
MCU::VUDisplay vuDisp[] = {
  // position (32+11, 60), width (16), bar height (3) px, bar spacing (1) px
  {display, vu[0], {32 + 11, 60}, 16, 3, 1, WHITE},
  {display, vu[1], {32 + 11 + 64, 60}, 16, 3, 1, WHITE},
};

// VPot rings
MCU::VPotDisplay vpotDisp[] = {
  // position (0, 10), outer radius (16) px, inner radius (13) px
  {display, vpot[0], {0, 10}, 4, 2, WHITE},
  {display, vpot[1], {32, 10}, 4, 2, WHITE},

};
*/
// Bank seting
BankDisplay bankDisp[] = {
  // first track of the bank (1), position (0, 50), font size (2)
  {display, bank, 1, {3, 10}, 1, WHITE},
  {display, bank, 2, {35, 10}, 1, WHITE},
  {display, bank, 3, {67, 10}, 1, WHITE},
  {display, bank, 4, {99, 10}, 1, WHITE},
  {display, bank, 5, {3, 35}, 1, WHITE},
  {display, bank, 6, {35, 35}, 1, WHITE},
  {display, bank, 7, {67, 35}, 1, WHITE},
  {display, bank, 8, {99, 35}, 1, WHITE},

};

void setup() {
    SPI.setMOSI(11);
  // Correct relative mode for MCU rotary encoders
  RelativeCCSender::setMode(MACKIE_CONTROL_RELATIVE);

  Control_Surface.begin(); // initialise la library surface de control
  usbmidi >> pipes >> midiser; // all incoming midi from USB is sent to serial
  usbmidi << pipes << midiser; // all incoming midi from Serial is sent to USB
  //usbmidi >> pipes >> usbmidi; // all incoming midi from USB is looped back
  midiser << pipes << midiser;
  Control_Surface >> pipes >> usbmidi;
  Control_Surface << pipes << usbmidi;
  Control_Surface >> pipes >> midiser;
  Control_Surface << pipes << midiser;
  usbmidi.begin();
  midiser.begin();
 // The default SPI MOSI pin (11) is used for I²S, so we need to use the
  // alternative MOSI pin (7)
  SPI.setMOSI(11);
  // Correct relative mode for MCU rotary encoders
  RelativeCCSender::setMode(MACKIE_CONTROL_RELATIVE);

}                           
void loop() {

  Control_Surface.loop(); // Update the Control Surface
  usbmidi.update();
  midiser.update();
}```
benwadub commented 4 years ago

https://forum.ableton.com/viewtopic.php?t=190422 hmmm it seems that the Ableton mcu script has problem with mute buttons for others people too! maybe the problem has to be solved there and not in my code!

tttapa commented 4 years ago

Please see the remarks I made earlier:

Why are you calling Control_Surface.begin() multiple times? Please see https://tttapa.github.io/Control-Surface-doc/Doxygen/d5/da5/Dual-MIDI-Interface_8ino-example.html, you have to connect the pipes before initializing Control_Surface.

If you are using Control_Surface to handle the MIDI interfaces, you don't have to call usbmidi.begin() or update() yourself.

SPI.setMOSI(11); is redundant, pin 11 is the default SPI MOSI pin.

Try removing all things that are not related to the buttons/mute bitmaps from your code.

Try using a USBDebugMIDI_Interface to trigger the display from the Serial Monitor. 90 10 7F should enable the first mute bitmap, and 80 10 7F should disable it.

benwadub commented 4 years ago

oops sorry I made the modification you mentioned on the original code! I copy pasted it to be sure to not make a terrible thing on it! yes that work for triggering via monitor in debug midi interface mode, that s for the tracks 9 to 16 that I can t have it working.

benwadub commented 4 years ago

woh damn that work also on track 9 if I use the bank button, the problem is so as I mentioned just before withe the mcu script for Ableton! i m in parallel making the script for my controller, I ll use the same note number as the mcu and that could work! again a big thanks for your help and patience!

tttapa commented 4 years ago

The MCU banks are handled in the DAW, so it's normal that only tracks 1-8 work when using the debug MIDI interface.

benwadub commented 4 years ago

they don t work with the normal usb interface too, I have a small led indicator in Ableton. that blink when a midi message is output, it blink blue when I switch mute with my mouse on track 1 to 8 but doesn't t blink with the tracks 9 to 16, now I m sure the Ableton script is buggy and my code works fine!

tttapa commented 4 years ago

They'll only send MIDI when you've selected the second bank (using the BANK_LEFT/BANK_RIGHT buttons), but of course, your DAW/script has to support these MCU banks.