MCU Control Surface Question

Hello, I built a 4 channel control surface with faders, Pan, Mute, Solo, Select and Record Ready and it woks beautifully. Now, I'm wanting to implement the MCU protocol but it's giving an error. Here's my code:

#include <Control_Surface.h>
#include <AH/Hardware/ExtendedInputOutput/SPIShiftRegisterOut.hpp> 

using namespace ExtIO; // Bring the ExtIO pin functions into your sketch

USBMIDI_Interface usbmidi;

template <class T, size_t N> constexpr size_t len(const T (&)[N]) { return N; }

const int speedMultiplier = 1;

//Instantiate 2 Shift Registers
SPIShiftRegisterOut<16> sreg {
  SPI,      // SPI interface to use
  10,      // Latch pin (ST_CP)
  MSBFIRST, // Bit order
};

//*** MUX 1 ***
//Instantiate 74HC4067 Digital multiplexer
CD74HC4067 mux1 ={4, {0,1,2,3} };
NoteButton buttons1 [] = {
{ mux1.pin(15), {82, MCU::SELECT_4 } },  // SEL 4
{ mux1.pin(14), {83, MCU::REC_RDY_4 } },  // REC 4 
{ mux1.pin(13), {84, MCU::SOLO_4 } },  // SOLO 4
{ mux1.pin(12), {85, MCU::MUTE_4 } },  // MUTE 4
{ mux1.pin(11), {86, MCU::SELECT_3 } },  // SEL 3
{ mux1.pin(10), {87, MCU::REC_RDY_3 } },  // REC 3
{ mux1.pin(9), {88, MCU::SOLO_3 } },  // SOLO 3
{ mux1.pin(8), {89, MCU::MUTE_3 } },  // MUTE 3
{ mux1.pin(7), {92, MCU::SELECT_2 },  // SEL 2
{ mux1.pin(6), {93, MCU::REC_RDY_2 } },  // REC 2 
{ mux1.pin(5), {94, MCU::SOLO_2 },  // SOLO 2
{ mux1.pin(4), {95, MCU::MUTE_2 } },  // MUTE 2
{ mux1.pin(3), {96, MCU::SELECT_1 } },  // SEL 1
{ mux1.pin(2), {97, MCU::REC_RDY_1 } },  // REC 1
{ mux1.pin(1), {98, MCU::SOLO_1 } },  // SOLO 1
{ mux1.pin(0), {99, MCU::MUTE_1 } },  // MUTE 1
};

pin_t leds1 [] {
  sreg.pin(0),
  sreg.pin(4),
  sreg.pin(8),
  sreg.pin(12),
  sreg.pin(1),
  sreg.pin(5),
  sreg.pin(9),
  sreg.pin(13),

  sreg.pin(2),
  sreg.pin(6),
  sreg.pin(10),
  sreg.pin(14),
  sreg.pin(3),
  sreg.pin(7),
  sreg.pin(11),
  sreg.pin(15),
};

//*** FADERS & POTS ***
CCPotentiometer knobsTop [] {
  {A2, {0x28, CHANNEL_1}}, // PAN 1 
  {A3, {0x29, CHANNEL_2}}, // PAN 2 
  {A4, {0x30, CHANNEL_3}}, // PAN 3 
  {A5, {0x31, CHANNEL_4}}, // PAN 4
  {A6, {0x24, CHANNEL_1}}, // FADER 1
  {A7, {0x25, CHANNEL_2}}, // FADER 2
  {A8, {0x26, CHANNEL_3}}, // FADER 3
  {A9, {0x27, CHANNEL_4}}, // FADER 4
};

BitArray<len(leds1)> led_states1;

static_assert(len(leds1) == len(buttons1), "");

void setup() {
  Control_Surface.begin();
for (auto led1 : leds1)
    pinMode(led1, OUTPUT);
}

void loop() { // Refresh all inputs
  Control_Surface.loop();
  for (size_t i = 0; i < len(buttons1); ++i) {
    if (buttons1[i].getButtonState() == Button::Falling) {
      bool new_state1 = !led_states1.get(i);
      digitalWrite(leds1[i], new_state1 ? HIGH : LOW);
      led_states1.set(i, new_state1);
    }
   }
}

The error is:

"Compilation error: could not convert '{mux1.AH::AnalogMultiplex<4>::.AH::StaticSizeExtendedIOElement<16>::.AH::ExtendedIOElement::pin(3), {96, CS::MCU::SELECT_1}}' from '' to 'CS::NoteButton'

Does this have to do the analog multiplexer? How do I set up MCU with the 2 shift register since the variable is pin_t and not NoteLed?

Thank you.

I apologize...it's now working. Here's my updated code:

#include <Control_Surface.h>
#include <AH/Hardware/ExtendedInputOutput/SPIShiftRegisterOut.hpp> 

using namespace ExtIO; // Bring the ExtIO pin functions into your sketch

USBMIDI_Interface usbmidi;

template <class T, size_t N> constexpr size_t len(const T (&)[N]) { return N; }

const int speedMultiplier = 1;

//Instantiate 2 Shift Registers
SPIShiftRegisterOut<16> sreg {
  SPI,      // SPI interface to use
  10,      // Latch pin (ST_CP)
  MSBFIRST, // Bit order
};

//*** MUX 1 ***
//Instantiate 74HC4067 Digital multiplexer
CD74HC4067 mux1 ={4, {0,1,2,3} };
NoteButton buttons1 [] = {
{ mux1.pin(15), {MCU::MUTE_1} },  // SEL 4
{ mux1.pin(14), {MCU::SOLO_1} },  // REC 4 
{ mux1.pin(13), {MCU::SELECT_1} },  // SOLO 4
{ mux1.pin(12), {MCU::REC_RDY_1} },  // MUTE 4
{ mux1.pin(11), {MCU::MUTE_2} },  // SEL 3
{ mux1.pin(10), {MCU::SOLO_2} },  // REC 3
{ mux1.pin(9), {MCU::SELECT_2} },  // SOLO 3
{ mux1.pin(8), {MCU::REC_RDY_2} },  // MUTE 3
{ mux1.pin(7), {MCU::MUTE_3} },  // SEL 2
{ mux1.pin(6), {MCU::SOLO_3} },  // REC 2 
{ mux1.pin(5), {MCU::SELECT_3} },  // SOLO 2
{ mux1.pin(4), {MCU::REC_RDY_3} },  // MUTE 2
{ mux1.pin(3), {MCU::MUTE_4} },  // SEL 1
{ mux1.pin(2), {MCU::SOLO_4} },  // REC 1
{ mux1.pin(1), {MCU::SELECT_4} },  // SOLO 1
{ mux1.pin(0), {MCU::REC_RDY_4} },  // MUTE 1
};

pin_t leds1 [] {
  sreg.pin(0),
  sreg.pin(4),
  sreg.pin(8),
  sreg.pin(12),
  sreg.pin(1),
  sreg.pin(5),
  sreg.pin(9),
  sreg.pin(13),

  sreg.pin(2),
  sreg.pin(6),
  sreg.pin(10),
  sreg.pin(14),
  sreg.pin(3),
  sreg.pin(7),
  sreg.pin(11),
  sreg.pin(15),
};

//*** FADERS & POTS ***
CCPotentiometer knobsTop [] {
  {A2, {0x28, CHANNEL_1}}, // PAN 1 
  {A3, {0x29, CHANNEL_2}}, // PAN 2 
  {A4, {0x30, CHANNEL_3}}, // PAN 3 
  {A5, {0x31, CHANNEL_4}}, // PAN 4
  {A6, {0x24, CHANNEL_1}}, // FADER 1
  {A7, {0x25, CHANNEL_2}}, // FADER 2
  {A8, {0x26, CHANNEL_3}}, // FADER 3
  {A9, {0x27, CHANNEL_4}}, // FADER 4
};

BitArray<len(leds1)> led_states1;

static_assert(len(leds1) == len(buttons1), "");

void setup() {
  Control_Surface.begin();
for (auto led1 : leds1)
    pinMode(led1, OUTPUT);
}

void loop() { // Refresh all inputs
  Control_Surface.loop();
  for (size_t i = 0; i < len(buttons1); ++i) {
    if (buttons1[i].getButtonState() == Button::Falling) {
      bool new_state1 = !led_states1.get(i);
      digitalWrite(leds1[i], new_state1 ? HIGH : LOW);
      led_states1.set(i, new_state1);
    }
   }
}

When select SOLO, all the Mute buttons are flashing in Logic.  How can I have also the LEDs flashing on my control  surface? How can I modify the shift register to do that?







2 Likes

Ok, I changed the code of the LED as follows:

#include <Control_Surface.h>
#include <AH/Hardware/ExtendedInputOutput/SPIShiftRegisterOut.hpp> 

using namespace ExtIO; // Bring the ExtIO pin functions into your sketch

USBMIDI_Interface usbmidi;

template <class T, size_t N> constexpr size_t len(const T (&)[N]) { return N; }

const int speedMultiplier = 1;

//Instantiate 2 Shift Registers
SPIShiftRegisterOut<16> sreg {
  SPI,      // SPI interface to use
  10,      // Latch pin (ST_CP)
  MSBFIRST, // Bit order
};

//*** MUX 1 ***
//Instantiate 74HC4067 Digital multiplexer
CD74HC4067 mux1 ={4, {0,1,2,3} };
NoteButton buttons1 [] = {
{ mux1.pin(15), {MCU::MUTE_1} },  // SEL 4
{ mux1.pin(14), {MCU::SOLO_1} },  // REC 4 
{ mux1.pin(13), {MCU::SELECT_1} },  // SOLO 4
{ mux1.pin(12), {MCU::REC_RDY_1} },  // MUTE 4
{ mux1.pin(11), {MCU::MUTE_2} },  // SEL 3
{ mux1.pin(10), {MCU::SOLO_2} },  // REC 3
{ mux1.pin(9), {MCU::SELECT_2} },  // SOLO 3
{ mux1.pin(8), {MCU::REC_RDY_2} },  // MUTE 3
{ mux1.pin(7), {MCU::MUTE_3} },  // SEL 2
{ mux1.pin(6), {MCU::SOLO_3} },  // REC 2 
{ mux1.pin(5), {MCU::SELECT_3} },  // SOLO 2
{ mux1.pin(4), {MCU::REC_RDY_3} },  // MUTE 2
{ mux1.pin(3), {MCU::MUTE_4} },  // SEL 1
{ mux1.pin(2), {MCU::SOLO_4} },  // REC 1
{ mux1.pin(1), {MCU::SELECT_4} },  // SOLO 1
{ mux1.pin(0), {MCU::REC_RDY_4} },  // MUTE 1
};

NoteLED leds1 [] {
{ sreg.pin(15), {MCU::MUTE_1} },  // SEL 4
{ sreg.pin(14), {MCU::SOLO_1} },  // REC 4 
{ sreg.pin(13), {MCU::SELECT_1} },  // SOLO 4
{ sreg.pin(12), {MCU::REC_RDY_1} },  // MUTE 4
{ sreg.pin(11), {MCU::MUTE_2} },  // SEL 3
{ sreg.pin(10), {MCU::SOLO_2} },  // REC 3
{ sreg.pin(9), {MCU::SELECT_2} },  // SOLO 3
{ sreg.pin(8), {MCU::REC_RDY_2} },  // MUTE 3
{ sreg.pin(7), {MCU::MUTE_3} },  // SEL 2
{ sreg.pin(6), {MCU::SOLO_3} },  // REC 2 
{ sreg.pin(5), {MCU::SELECT_3} },  // SOLO 2
{ sreg.pin(4), {MCU::REC_RDY_3} },  // MUTE 2
{ sreg.pin(3), {MCU::MUTE_4} },  // SEL 1
{ sreg.pin(2), {MCU::SOLO_4} },  // REC 1
{ sreg.pin(1), {MCU::SELECT_4} },  // SOLO 1
{ sreg.pin(0), {MCU::REC_RDY_4} },  // MUTE 1
};

//*** FADERS & POTS ***
CCPotentiometer knobsTop [] {
  {A2, {0x28, CHANNEL_1}}, // PAN 1 
  {A3, {0x29, CHANNEL_2}}, // PAN 2 
  {A4, {0x30, CHANNEL_3}}, // PAN 3 
  {A5, {0x31, CHANNEL_4}}, // PAN 4
  {A6, {0x24, CHANNEL_1}}, // FADER 1
  {A7, {0x25, CHANNEL_2}}, // FADER 2
  {A8, {0x26, CHANNEL_3}}, // FADER 3
  {A9, {0x27, CHANNEL_4}}, // FADER 4
};

BitArray<len(leds1)> led_states1;

static_assert(len(leds1) == len(buttons1), "");

void setup() {
  Control_Surface.begin();
for (auto led1 : leds1)
    pinMode(led1, OUTPUT);
}

void loop() { // Refresh all inputs
  Control_Surface.loop();
  for (size_t i = 0; i < len(buttons1); ++i) {
    if (buttons1[i].getButtonState() == Button::Falling) {
      bool new_state1 = !led_states1.get(i);
      digitalWrite(leds1[i], new_state1 ? HIGH : LOW);
      led_states1.set(i, new_state1);
    }
   }
}

But it's giving an error:

Compilation error: no matching function for call to 'pinMode(CS::NoteCCKPLEDCS::MIDIMessageType::NOTE_ON&, const PinMode_t&)'

How can fix that?

Also, MCU variables are for 8 channels, what if I want to build a 24 channels console? Is there a way to make extension units?

Turned out, I didn't need the array and the For loop:

#include <Control_Surface.h>
#include <AH/Hardware/ExtendedInputOutput/SPIShiftRegisterOut.hpp>

using namespace ExtIO; // Bring the ExtIO pin functions into your sketch

USBMIDI_Interface usbmidi;

template <class T, size_t N> constexpr size_t len(const T (&)[N]) { return N; }

const int speedMultiplier = 1;

//Instantiate 2 Shift Registers
SPIShiftRegisterOut<16> sreg {
  SPI,      // SPI interface to use
  10,      // Latch pin (ST_CP)
  MSBFIRST, // Bit order
};

//*** MUX 1 ***
//Instantiate 74HC4067 Digital multiplexer
CD74HC4067 mux1 ={4, {0,1,2,3} };
NoteButton buttons1 [] = {
{ mux1.pin(15), {MCU::MUTE_1} },  
{ mux1.pin(14), {MCU::SOLO_1} },  
{ mux1.pin(13), {MCU::SELECT_1} },  
{ mux1.pin(12), {MCU::REC_RDY_1} },  
{ mux1.pin(11), {MCU::MUTE_2} },  
{ mux1.pin(10), {MCU::SOLO_2} },  
{ mux1.pin(9), {MCU::SELECT_2} },  
{ mux1.pin(8), {MCU::REC_RDY_2} },  
{ mux1.pin(7), {MCU::MUTE_3} },  
{ mux1.pin(6), {MCU::SOLO_3} },  
{ mux1.pin(5), {MCU::SELECT_3} },  
{ mux1.pin(4), {MCU::REC_RDY_3} },  
{ mux1.pin(3), {MCU::MUTE_4} },  
{ mux1.pin(2), {MCU::SOLO_4} },  
{ mux1.pin(1), {MCU::SELECT_4} },  
{ mux1.pin(0), {MCU::REC_RDY_4} },  
};

NoteLED leds1 [] {
{ sreg.pin(15), {MCU::REC_RDY_4} },  
{ sreg.pin(14), {MCU::REC_RDY_3} },  
{ sreg.pin(13), {MCU::REC_RDY_2} },  
{ sreg.pin(12), {MCU::REC_RDY_1} },  
{ sreg.pin(11), {MCU::SELECT_4} },  
{ sreg.pin(10), {MCU::SELECT_3} },
{ sreg.pin(9), {MCU::SELECT_2} },  
{ sreg.pin(8), {MCU::SELECT_1} },  
{ sreg.pin(7), {MCU::SOLO_4} },  
{ sreg.pin(6), {MCU::SOLO_3} },  
{ sreg.pin(5), {MCU::SOLO_2} },  
{ sreg.pin(4), {MCU::SOLO_1} },  
{ sreg.pin(3), {MCU::MUTE_4} },  
{ sreg.pin(2), {MCU::MUTE_3} },  
{ sreg.pin(1), {MCU::MUTE_2} },
{ sreg.pin(0), {MCU::MUTE_1} },  
};

//*** FADERS & POTS ***
CCPotentiometer knobsTop [] {
  {A2, {0x28, CHANNEL_1}}, // PAN 1
  {A3, {0x29, CHANNEL_2}}, // PAN 2
  {A4, {0x30, CHANNEL_3}}, // PAN 3
  {A5, {0x31, CHANNEL_4}}, // PAN 4
  {A6, {0x24, CHANNEL_1}}, // FADER 1
  {A7, {0x25, CHANNEL_2}}, // FADER 2
  {A8, {0x26, CHANNEL_3}}, // FADER 3
  {A9, {0x27, CHANNEL_4}}, // FADER 4
};

// BitArray<len(leds1)> led_states1;
//
// static_assert(len(leds1) == len(buttons1), "");

void setup() {
  Control_Surface.begin();
//for (auto led1 : leds1)
//    pinMode(led1, OUTPUT);
}

void loop() {
  // Refresh all inputs
  Control_Surface.loop();
//   for (size_t i = 0; i < len(buttons1); ++i) {
//     if (buttons1[i].getButtonState() == Button::Falling) {
//       bool new_state1 = !led_states1.get(i);
//       digitalWrite(leds1[i], new_state1 ? HIGH : LOW);
//       led_states1.set(i, new_state1);
//     }
//   }
}

The MCU variables are incredibly simple to use. I was able to program the MCU::F1 to toggle on/off the EQ view per selected track. I will try it with a rotary encoder.

Thanks.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.