tttapa / Control-Surface

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

I need help to transfer from leonardo to esp32-s3 #1078

Open DRCRecoveryData opened 3 weeks ago

DRCRecoveryData commented 3 weeks ago

Hi,

After 4 years i made button and leds working like novation launchpad now, but i need you help to transfer for me from leonardo to working esp32-s3 as Control-Surface library of:

#include <Adafruit_NeoPixel.h>
#include "MIDIUSB.h"

// LED Strip definition
const byte _NLED = 16;  // Number of LEDs
const byte _DPIN = 10;
Adafruit_NeoPixel _LED = Adafruit_NeoPixel(_NLED, _DPIN, NEO_GRB + NEO_KHZ800);

// Color Palette (example values; modify as needed)
const byte _R[128] = {0, 65, 130, 255, 255, 255, 130, 65, 255, 255, 130, 65, 255, 255, 130, 65, 134, 81, 40, 20, 73, 0, 0, 0, 73, 0, 0, 0, 73, 0, 0, 0, 73, 0, 0, 0, 73, 0, 0, 0, 73, 0, 0, 0, 45, 0, 0, 0, 105, 45, 24, 12, 255, 255, 130, 65, 255, 255, 130, 65, 255, 150, 117, 32, 0, 0, 0, 0, 0, 16, 125, 28, 255, 186, 174, 97, 12, 0, 0, 0, 24, 89, 174, 40, 255, 134, 113, 0, 57, 85, 53, 89, 49, 105, 210, 255, 255, 182, 142, 130, 57, 0, 12, 20, 20, 101, 130, 219, 215, 255, 158, 101, 20, 219, 125, 154, 142, 61, 113, 223, 158, 53, 24, 4, 182, 61, 178, 73};
const byte _G[128] = {0, 65, 130, 255, 61, 0, 0, 0, 186, 61, 32, 16, 174, 255, 130, 65, 255, 255, 130, 65, 255, 255, 130, 65, 255, 255, 130, 65, 255, 255, 130, 65, 255, 255, 130, 65, 194, 166, 85, 45, 134, 85, 45, 24, 36, 0, 0, 0, 53, 0, 0, 0, 61, 0, 0, 0, 65, 0, 0, 0, 12, 53, 81, 53, 57, 73, 20, 0, 69, 0, 125, 28, 0, 255, 235, 255, 138, 255, 166, 40, 0, 0, 24, 16, 49, 223, 255, 255, 255, 255, 255, 138, 81, 81, 28, 0, 69, 166, 255, 89, 40, 73, 77, 20, 28, 57, 0, 65, 73, 190, 223, 178, 20, 210, 235, 150, 101, 61, 113, 255, 0, 0, 206, 65, 174, 49, 81, 20};
const byte _B[128] = {0, 65, 130, 255, 61, 0, 0, 0, 105, 0, 0, 0, 45, 0, 0, 0, 49, 0, 0, 0, 73, 0, 0, 0, 93, 24, 12, 4, 89, 85, 45, 24, 182, 150, 73, 36, 255, 255, 130, 65, 255, 255, 130, 65, 255, 255, 130, 65, 251, 255, 130, 65, 255, 255, 130, 65, 109, 81, 40, 20, 0, 0, 0, 4, 0, 24, 109, 255, 77, 202, 125, 28, 0, 45, 4, 8, 0, 93, 255, 255, 255, 255, 121, 0, 0, 4, 20, 0, 36, 109, 202, 255, 194, 231, 255, 89, 0, 0, 0, 4, 0, 12, 32, 40, 89, 24, 0, 40, 16, 36, 45, 12, 45, 105, 138, 255, 255, 61, 113, 255, 0, 0, 0, 0, 0, 0, 0, 0};

// Brightness control (0 to 100)
byte brightness = 10;

// Map MIDI notes to LED indices (4x4 grid)
const byte noteToLED[4][4] = {
  {36, 37, 38, 39},
  {40, 41, 42, 43},
  {24, 25, 26, 27},
  {60, 61, 62, 63}
};

// For controlling LED updates based on time
unsigned long lastUpdate = 0;
const unsigned long updateInterval = 5;  // LED update every 5ms
bool update = false;

// Adjust color by brightness level (0-100)
byte applyBrightness(byte colorValue) {
  return (colorValue * brightness) / 100;
}

// Send MIDI note on/off messages
void sendMidiMessage(byte pitch, byte velocity) {
  midiEventPacket_t event;
  event.header = (velocity > 0) ? 0x9 : 0x8; // Note On or Note Off
  event.byte1 = 0x90;    // Channel 1
  event.byte2 = pitch;   // Note number
  event.byte3 = velocity; // Velocity
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();       // Ensure the message is sent
}

// Convert MIDI note to LED index using the noteToLED array
void updateLEDs(byte pitch, byte velocity) {
  byte ledIndex = 0;
  bool noteFound = false;

  for (byte row = 0; row < 4; row++) {
    for (byte col = 0; col < 4; col++) {
      if (noteToLED[row][col] == pitch) {
        ledIndex = row * 4 + col;  // Calculate the 1D index
        noteFound = true;
        break;
      }
    }
    if (noteFound) break;
  }

  if (noteFound) {
    if (velocity > 0) {
      // Set the LED color based on the received velocity
      _LED.setPixelColor(ledIndex, 
                         applyBrightness(_R[velocity]), 
                         applyBrightness(_G[velocity]), 
                         applyBrightness(_B[velocity]));
    } else {
      // Turn off the LED
      _LED.setPixelColor(ledIndex, _LED.Color(0, 0, 0)); // Set to off
    }
    update = true;
  }
}

// Pins for the rows and columns of the button matrix
const int rowPins[4] = {2, 3, 4, 5};
const int colPins[4] = {6, 7, 8, 9};

// Matrix button setup
void setup() {
  Serial.begin(115200);  // Start serial communication
  _LED.begin();
  _LED.show();

  // Initialize button pins
  for (byte i = 0; i < 4; i++) {
    pinMode(rowPins[i], OUTPUT);   
    digitalWrite(rowPins[i], HIGH); 
    pinMode(colPins[i], INPUT_PULLUP); 
  }
}

// Keep track of the previous button state
bool previousButtonState[4][4] = {false};

void loop() {
  midiEventPacket_t rx;

  // Read MIDI messages
  do { 
    rx = MidiUSB.read();
    if (rx.header == 0x9) updateLEDs(rx.byte2, rx.byte3);  // Note on, update LEDs
    if (rx.header == 0x8) updateLEDs(rx.byte2, 0);         // Note off, turn off color
  } while (rx.header != 0);

  // Check matrix buttons
  for (byte row = 0; row < 4; row++) {
    digitalWrite(rowPins[row], LOW);  // Activate the row
    for (byte col = 0; col < 4; col++) {
      bool currentButtonState = (digitalRead(colPins[col]) == LOW);  // Button pressed

      if (currentButtonState && !previousButtonState[row][col]) {
        // Button pressed: Send Note On with max velocity
        sendMidiMessage(noteToLED[row][col], 127);
        previousButtonState[row][col] = true;  // Update the previous state
      } else if (!currentButtonState && previousButtonState[row][col]) {
        // Button released: Send Note Off
        sendMidiMessage(noteToLED[row][col], 0);  // Note Off
        previousButtonState[row][col] = false;  // Update the previous state
        // Turn off the LED
        byte ledIndex = row * 4 + col;  // Calculate the 1D index
        _LED.setPixelColor(ledIndex, _LED.Color(0, 0, 0)); // Set to off
        update = true;
      }
    }
    digitalWrite(rowPins[row], HIGH);  // Deactivate the row
  }

  // Update LEDs if needed
  unsigned long currentTime = millis();
  if (update && currentTime - lastUpdate >= updateInterval) {
    _LED.show();
    lastUpdate = currentTime;  // Update time
    update = false;
  }
}
tttapa commented 3 weeks ago

I'd recommend having a look at the MIDI tutorial. Your sendMidiMessage function and the MidiUSB.read() do-loop should be trivial to convert to Control Surface's MIDI interface API.