no problem but it will be allot.
main pad:
.INO
#include "pads.h"
#include "oled.h"
pads *pad[127];
uint8_t i2cAddress[127];
uint8_t padsCount;
uint32_t prevMillisI2C;
void setup() {
//Serial.begin(9600);
pinMode(ENCBUTTON, INPUT_PULLUP);
Wire.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
display.setRotation(2);
display.clearDisplay();
display.setTextSize(2);
display.display();
createPadItem(MAIN, 0);
//MEMINFO();
}
void loop() {
oled();
uint8_t midi_data1 = 255;
uint8_t midi_data2 = 255;
uint8_t midi_channel = 255;
if (usbMIDI.read() == true) {
midi_data1 = usbMIDI.getData1();
midi_data2 = usbMIDI.getData2();
midi_channel = usbMIDI.getChannel();
}
uint8_t error;
for (uint8_t x = 0; x < 127; x++) {
if (pad[x] != NULL) {
error = pad[x]->scanData();
if (error == I2CDISCONNECTED) { // disconected
uint8_t i2cID = pad[x]->getI2cAdress();
for (uint8_t y = 1; y < 127; y++) {
delete pad[y];
pad[y] = NULL;
padsCount = 1; //1 because mainpad stays
menuItem[y].title = "";
menuItem[y].function = NULL;
menuItem[y].data1 = NULL;
menuItem[y].data2 = NULL;
menuItem[y].pStruct = NULL;
}
//padsCount--;
//i2cAddress[i2cID] = 0;
padMenu.numItems = padsCount;
currentMenu = &padMenu;
//MEMINFO();
} else {
pad[x]->sendData(midi_channel, midi_data1, midi_data2);
pad[x]->saveData();
}
}
}
if (millis() - prevMillisI2C >= 1000) {
I2C();
prevMillisI2C = millis();
}
}
void I2C() {
uint8_t error;
uint8_t type = 0;
for (uint8_t address = 1; address < 127; address++) {
//if (i2cAddress[address] == 0) {
if (pad[address] == NULL) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) { // Connecton is good
//i2cAddress[address] = 1;
Wire.beginTransmission(address);
Wire.write(0); // 0 = code to ask TYPE
Wire.endTransmission();
Wire.requestFrom(address, (size_t)1, true);
while (Wire.available()) {
type = Wire.read();
}
}
switch (type) {
case FADERPAD: //1
createPadItem(FADERPAD, address);
//MEMINFO();
type = false;
break;
case ENCODERPAD: //2
createPadItem(ENCODERPAD, address);
//MEMINFO();
type = false;
break;
}
}
}
}
void createPadItem(uint8_t type, uint8_t i2cAddress) {
switch (type) {
case MAIN:
{
pads *pMain = new main(i2cAddress);
pad[i2cAddress] = pMain;
String test;
test = String(".MainPad");
test = (i2cAddress) + test;
menuItem[i2cAddress].title = test;
menuItem[i2cAddress].function = NULL;
menuItem[i2cAddress].data1 = NULL;
menuItem[i2cAddress].data2 = NULL;
menuItem[i2cAddress].pStruct = &pad[i2cAddress]->menu;
//padsCount++;
//padMenu.numItems = padsCount;
padMenu.numItems = 127;
break;
}
case FADERPAD:
{
pads *pMain = new fader(i2cAddress);
pad[i2cAddress] = pMain;
String test;
test = String(".Faderpad");
test = (i2cAddress) + test;
menuItem[i2cAddress].title = test;
menuItem[i2cAddress].function = NULL;
menuItem[i2cAddress].data1 = NULL;
menuItem[i2cAddress].data2 = NULL;
menuItem[i2cAddress].pStruct = &pad[i2cAddress]->menu;
//padsCount++;
//padMenu.numItems = padsCount;
padMenu.numItems = 127;
break;
}
case ENCODERPAD:
{
pads *pMain = new encoderpad(i2cAddress);
pad[i2cAddress] = pMain;
String test;
test = String(".Encpad");
test = (i2cAddress) + test;
menuItem[i2cAddress].title = test;
menuItem[i2cAddress].function = NULL;
menuItem[i2cAddress].data1 = NULL;
menuItem[i2cAddress].data2 = NULL;
menuItem[i2cAddress].pStruct = &pad[i2cAddress]->menu;
//padsCount++;
//padMenu.numItems = padsCount;
padMenu.numItems = 127;
break;
}
}
}
#define printf Serial.printf
#if ARDUINO_TEENSY41
extern "C" uint8_t external_psram_size;
#endif
void MEMINFO() {
constexpr auto RAM_BASE = 0x2020'0000;
constexpr auto RAM_SIZE = 512 << 10;
constexpr auto FLASH_BASE = 0x6000'0000;
#if ARDUINO_TEENSY40
constexpr auto FLASH_SIZE = 2 << 20;
#elif ARDUINO_TEENSY41
constexpr auto FLASH_SIZE = 8 << 20;
#endif
// note: these values are defined by the linker, they are not valid memory
// locations in all cases - by defining them as arrays, the C++ compiler
// will use the address of these definitions - it's a big hack, but there's
// really no clean way to get at linker-defined symbols from the .ld file
extern char _stext[], _etext[], _sbss[], _ebss[], _sdata[], _edata[],
_estack[], _heap_start[], _heap_end[], _itcm_block_count[], *__brkval;
auto sp = (char *)__builtin_frame_address(0);
/*printf("_stext %08x\n", _stext);
printf("_etext %08x +%db\n", _etext, _etext - _stext);
printf("_sdata %08x\n", _sdata);
printf("_edata %08x +%db\n", _edata, _edata - _sdata);
printf("_sbss %08x\n", _sbss);
printf("_ebss %08x +%db\n", _ebss, _ebss - _sbss);
printf("curr stack %08x +%db\n", sp, sp - _ebss);
printf("_estack %08x +%db\n", _estack, _estack - sp);
printf("_heap_start %08x\n", _heap_start);
printf("__brkval %08x +%db\n", __brkval, __brkval - _heap_start);
printf("_heap_end %08x +%db\n", _heap_end, _heap_end - __brkval);*/
#if ARDUINO_TEENSY41
extern char _extram_start[], _extram_end[], *__brkval;
printf("_extram_start %08x\n", _extram_start);
printf("_extram_end %08x +%db\n", _extram_end,
_extram_end - _extram_start);
#endif
/*printf("\n");
printf("<ITCM> %08x .. %08x\n",
_stext, _stext + ((int) _itcm_block_count << 15) - 1);
printf("<DTCM> %08x .. %08x\n",
_sdata, _estack - 1);
printf("<RAM> %08x .. %08x\n",
RAM_BASE, RAM_BASE + RAM_SIZE - 1);
printf("<FLASH> %08x .. %08x\n",
FLASH_BASE, FLASH_BASE + FLASH_SIZE - 1);*/
#if ARDUINO_TEENSY41
if (external_psram_size > 0)
printf("<PSRAM> %08x .. %08x\n",
_extram_start, _extram_start + (external_psram_size << 20) - 1);
#endif
printf("\n");
auto stack = sp - _ebss;
printf("avail STACK %8d b %5d kb\n", stack, stack >> 10);
auto heap = _heap_end - __brkval;
printf("avail HEAP %8d b %5d kb\n", heap, heap >> 10);
#if ARDUINO_TEENSY41
auto psram = _extram_start + (external_psram_size << 20) - _extram_end;
printf("avail PSRAM %8d b %5d kb\n", psram, psram >> 10);
#endif
}
fade.cpp
#include <Arduino.h>
#include <Wire.h>
#include "pads.h"
fader::fader(uint8_t adress)
: _i2cAdress(adress) {
for (uint8_t x = 0; x < 4; x++) {
pMenuItemsFunc = new MENUITEMS[10];
pMenuItemsFunc[0] = (MENUITEMS){
"Mode", toggle, (void*)&_modeData, (void*)&modeNames, NULL
};
pMenuItemsFunc[1] = (MENUITEMS){
"Ch", variable, (void*)&_channelData[x], (void*)16, NULL
};
pMenuItemsFunc[2] = (MENUITEMS){
"Note", variable, (void*)&_noteData[x], (void*)127, NULL
};
pMenuItemsFunc[3] = (MENUITEMS){
"ColOn", toggle, (void*)&_colorOn[x], (void*)&colorNames, NULL
};
pMenuItemsFunc[4] = (MENUITEMS){
"ColOff", toggle, (void*)&_colorOff[x], (void*)&colorNames, NULL
};
pMenuItemsFunc[5] = (MENUITEMS){
"Min", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[6] = (MENUITEMS){
"Max", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[7] = (MENUITEMS){
"Mod", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[8] = (MENUITEMS){
"Key", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[9] = (MENUITEMS){
//"Back", NULL, NULL, NULL, &menu
"Back", eeprom, (void*)&_id[x], (void*)&_eepromFlag, &menu
};
menuItemsFunc[x] = pMenuItemsFunc;
}
for (uint8_t x = 0; x < 4; x++) {
String test;
test = String("-Fader ");
test = test + (x + 1);
test = test + String("-");
menuFunc[x].title = test;
menuFunc[x].numItems = 10;
menuFunc[x].pStruct = menuItemsFunc[x];
}
//Serial.println("a");
pMenuItems = new MENUITEMS[5];
for (uint8_t x = 0; x < 4; x++) {
String test;
test = String("Fader ");
test = test + (x + 1);
pMenuItems[x].title = test;
pMenuItems[x].function = NULL;
pMenuItems[x].data1 = NULL;
pMenuItems[x].data2 = NULL;
pMenuItems[x].pStruct = &menuFunc[x];
}
pMenuItems[4].title = "Back";
pMenuItems[4].function = NULL;
pMenuItems[4].data1 = NULL;
pMenuItems[4].data2 = NULL;
pMenuItems[4].pStruct = &padMenu;
menuItems = pMenuItems;
menu.title = "-FaderPad-";
menu.numItems = 5;
menu.pStruct = menuItems;
Serial.println("Faderpad + menuStruct");
Wire.beginTransmission(_i2cAdress);
Wire.write(GETEEPROM);
Wire.endTransmission();
Wire.requestFrom(_i2cAdress, (size_t)28, true);
uint8_t x = 0;
while (Wire.available()) {
//Serial.println(Wire.read());
_modeData[x] = Wire.read();
_channelData[x] = Wire.read();
_noteData[x] = Wire.read();
_colorOn[x] = Wire.read();
_colorOff[x] = Wire.read();
_min[x] = Wire.read();
_max[x] = Wire.read();
x++;
}
}
//---------------------------------------------------------------------------------------------------------
fader::~fader() {
pMenuItemsFunc = menuItemsFunc[0];
delete[] pMenuItemsFunc;
pMenuItemsFunc = menuItemsFunc[1];
delete[] pMenuItemsFunc;
pMenuItemsFunc = menuItemsFunc[2];
delete[] pMenuItemsFunc;
pMenuItemsFunc = menuItemsFunc[3];
delete[] pMenuItemsFunc;
delete[] pMenuItems;
Serial.print("Faderpad + menu structs are ");
}
//---------------------------------------------------------------------------------------------------------
uint8_t fader::scanData() {
uint8_t error;
Wire.beginTransmission(_i2cAdress);
Wire.write(GET4FADERDATA);
error = Wire.endTransmission();
if (error == I2CDISCONNECTED) {
return I2CDISCONNECTED;
}
Wire.requestFrom(_i2cAdress, (size_t)4, true);
uint8_t num = 0;
while (Wire.available()) {
_faderState[num] = Wire.read();
num++;
}
return 0;
}
//---------------------------------------------------------------------------------------------------------
void fader::sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData) {
//Send data to PC
for (uint8_t num = 0; num < 4; num++) {
if (_faderState[num] != _faderPrev[num]) {
usbMIDI.sendControlChange(_noteData[num], _faderState[num], _channelData[num]);
_faderPrev[num] = _faderState[num];
}
}
//Send data to pad
// effe kijken of dit anders kan, 1 fader per x ipv alle 4 altijd
for (uint8_t num = 0; num < 4; num++) {
if (noteData == _noteData[num]) {
_dataToSend[num] = velocityData;
Wire.beginTransmission(_i2cAdress);
Wire.write(SEND4FADERDATA);
uint8_t x = 0;
while (x < 4) {
Wire.write(_dataToSend[x]);
x++;
}
Wire.endTransmission();
}
}
}
//---------------------------------------------------------------------------------------------------------
void fader::saveData() {
if (_eepromFlag != 255) {
Wire.beginTransmission(_i2cAdress);
Wire.write(SEND2EEPROM);
for (uint8_t num = 0; num < 4; num++) {
Wire.write(_modeData[num]);
Wire.write(_channelData[num]);
Wire.write(_noteData[num]);
Wire.write(_colorOn[num]);
Wire.write(_colorOff[num]);
Wire.write(_min[num]);
Wire.write(_max[num]);
}
Wire.endTransmission();
_eepromFlag = 255;
}
}
//---------------------------------------------------------------------------------------------------------
uint8_t fader::getI2cAdress() {
return _i2cAdress;
}
encoderpad.cpp
#include <Arduino.h>
#include <Wire.h>
#include "pads.h"
encoderpad::encoderpad(uint8_t adress)
: _i2cAdress(adress) {
for (uint8_t x = 0; x < 12; x++) {
pMenuItemsFunc = new MENUITEMS[10];
pMenuItemsFunc[0] = (MENUITEMS){
"Mode", toggle, (void*)&_modeData, (void*)&modeNames, NULL
};
pMenuItemsFunc[1] = (MENUITEMS){
"Ch", variable, (void*)&_channelData[x], (void*)16, NULL
};
pMenuItemsFunc[2] = (MENUITEMS){
"Note", variable, (void*)&_noteData[x], (void*)127, NULL
};
pMenuItemsFunc[3] = (MENUITEMS){
"ColOn", toggle, (void*)&_colorOn[x], (void*)&colorNames, NULL
};
pMenuItemsFunc[4] = (MENUITEMS){
"ColOff", toggle, (void*)&_colorOff[x], (void*)&colorNames, NULL
};
pMenuItemsFunc[5] = (MENUITEMS){
"Min", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[6] = (MENUITEMS){
"Max", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[7] = (MENUITEMS){
"Mod", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[8] = (MENUITEMS){
"Key", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[9] = (MENUITEMS){
"Back", NULL, NULL, NULL, &menu
//"Back", eeprom, (void*)&_id[x], (void*)&_eepromFlag, &menu
};
menuItemsFunc[x] = pMenuItemsFunc;
}
for (uint8_t x = 0; x < 12; x++) {
String test;
test = String("-test ");
test = test + (x + 1);
test = test + String("-");
menuFunc[x].title = test;
menuFunc[x].numItems = 10;
menuFunc[x].pStruct = menuItemsFunc[x];
}
//Serial.println("a");
pMenuItems = new MENUITEMS[13];
for (uint8_t x = 0; x < 12; x++) {
String test;
test = String("Fader ");
test = test + (x + 1);
pMenuItems[x].title = test;
pMenuItems[x].function = NULL;
pMenuItems[x].data1 = NULL;
pMenuItems[x].data2 = NULL;
pMenuItems[x].pStruct = &menuFunc[x];
}
pMenuItems[12].title = "Back";
pMenuItems[12].function = NULL;
pMenuItems[12].data1 = NULL;
pMenuItems[12].data2 = NULL;
pMenuItems[12].pStruct = &padMenu;
menuItems = pMenuItems;
menu.title = "-EncPad-";
menu.numItems = 13;
menu.pStruct = menuItems;
Serial.println("EncoderPad + menuStruct");
/*Wire.beginTransmission(_i2cAdress);
Wire.write(GETEEPROM);
Wire.endTransmission();
Wire.requestFrom(_i2cAdress, (size_t)28, true);
uint8_t x = 0;
while (Wire.available()) {
//Serial.println(Wire.read());
_modeData[x] = Wire.read();
_channelData[x] = Wire.read();
_noteData[x] = Wire.read();
_colorOn[x] = Wire.read();
_colorOff[x] = Wire.read();
_min[x] = Wire.read();
_max[x] = Wire.read();
x++;
}*/
}
encoderpad::~encoderpad() {
pMenuItemsFunc = menuItemsFunc[0];
delete[] pMenuItemsFunc;
pMenuItemsFunc = menuItemsFunc[1];
delete[] pMenuItemsFunc;
pMenuItemsFunc = menuItemsFunc[2];
delete[] pMenuItemsFunc;
pMenuItemsFunc = menuItemsFunc[3];
delete[] pMenuItemsFunc;
delete[] pMenuItems;
Serial.print("Encoderpad + menu structs are ");
}
//---------------------------------------------------------------------------------------------------------
uint8_t encoderpad::scanData() {
uint8_t error;
Wire.beginTransmission(_i2cAdress);
Wire.write(GET4FADERDATA);
error = Wire.endTransmission();
if (error == I2CDISCONNECTED) {
return I2CDISCONNECTED;
}
Wire.requestFrom(_i2cAdress, (size_t)12, true);
uint8_t num = 0;
while (Wire.available()) {
_dataState[num] = Wire.read();
num++;
}
return 0;
}
//---------------------------------------------------------------------------------------------------------
void encoderpad::sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData) {
//Send data to PC
for (uint8_t num = 0; num < 12; num++) {
if (_dataState[num] != _dataPrev[num]) {
usbMIDI.sendControlChange(_noteData[num], _dataState[num], _channelData[num]);
_dataPrev[num] = _dataState[num];
}
}
//Send data to pad
// effe kijken of dit anders kan, 1 fader per x ipv alle 4 altijd
for (uint8_t num = 0; num < 12; num++) {
if (noteData == _noteData[num]) {
_dataToSend[num] = velocityData;
Wire.beginTransmission(_i2cAdress);
Wire.write(SEND4FADERDATA);
uint8_t x = 0;
while (x < 12) {
Wire.write(_dataToSend[x]);
x++;
}
Wire.endTransmission();
}
}
}
//---------------------------------------------------------------------------------------------------------
void encoderpad::saveData() {
/*if (_eepromFlag != 255) {
Wire.beginTransmission(_i2cAdress);
Wire.write(SEND2EEPROM);
for (uint8_t num = 0; num < 4; num++) {
Wire.write(_modeData[num]);
Wire.write(_channelData[num]);
Wire.write(_noteData[num]);
Wire.write(_colorOn[num]);
Wire.write(_colorOff[num]);
Wire.write(_min[num]);
Wire.write(_max[num]);
}
Wire.endTransmission();
_eepromFlag = 255;
}*/
}
//---------------------------------------------------------------------------------------------------------
uint8_t encoderpad::getI2cAdress() {
return _i2cAdress;
}
main.cpp
#include <Arduino.h>
#include <EEPROM.h>
#include <FastLED.h>
#include "pads.h"
#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
#define NUM_LEDS 17
#define DATA_PIN 20
uint8_t _colorValue[8][3] = {
{ 255, 0, 0 },
{ 0, 255, 0 },
{ 0, 0, 255 },
{ 0, 255, 255 },
{ 255, 0, 255 },
{ 255, 255, 0 },
{ 255, 128, 0 },
{ 255, 255, 255 }
};
CRGB _leds[NUM_LEDS];
main::main(uint8_t adress)
: _i2cAdress(adress) {
for (uint8_t x = 0; x < 16; x++) {
MENUITEMS *pMenuItemsFunc = new MENUITEMS[10];
//Title, Function, Data1, Data2, pStruct
pMenuItemsFunc[0] = (MENUITEMS){
"Mode", toggle, (void *)&_modeData, (void *)&modeNames, NULL
};
pMenuItemsFunc[1] = (MENUITEMS){
"Ch", variable, (void *)&_channelData[x], (void *)16, NULL
};
pMenuItemsFunc[2] = (MENUITEMS){
"Note", variable, (void *)&_noteData[x], (void *)127, NULL
};
pMenuItemsFunc[3] = (MENUITEMS){
"ColOn", toggle, (void *)&_colorOn[x], (void *)&colorNames, NULL
};
pMenuItemsFunc[4] = (MENUITEMS){
"ColOff", toggle, (void *)&_colorOff[x], (void *)&colorNames, NULL
};
pMenuItemsFunc[5] = (MENUITEMS){
"Min", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[6] = (MENUITEMS){
"Max", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[7] = (MENUITEMS){
"Mod", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[8] = (MENUITEMS){
"Key", NULL, NULL, NULL, NULL
};
pMenuItemsFunc[9] = (MENUITEMS){
"Back", eeprom, (void *)&_id[x], (void *)&_eepromFlag, &menu
};
menuItemsFunc[x] = pMenuItemsFunc;
}
for (uint8_t x = 0; x < 16; x++) {
String test;
test = String("-Button ");
test = test + (x + 1);
test = test + String("-");
menuFunc[x].title = test;
menuFunc[x].numItems = 10;
menuFunc[x].pStruct = menuItemsFunc[x];
}
//Serial.println("a");
MENUITEMS *pMenuItems = new MENUITEMS[17];
for (uint8_t x = 0; x < 16; x++) {
String test;
test = String("Button ");
test = test + (x + 1);
pMenuItems[x].title = test;
pMenuItems[x].function = NULL;
pMenuItems[x].data1 = NULL;
pMenuItems[x].data2 = NULL;
pMenuItems[x].pStruct = &menuFunc[x];
}
pMenuItems[16].title = "Back";
pMenuItems[16].function = NULL;
pMenuItems[16].data1 = NULL;
pMenuItems[16].data2 = NULL;
pMenuItems[16].pStruct = &padMenu;
menuItems = pMenuItems;
menu.title = "-MainPad-";
menu.numItems = 17;
menu.pStruct = menuItems;
for (uint8_t x = 0; x < 4; x++) {
pinMode(_colomPin[x], INPUT_PULLUP);
}
for (uint8_t x = 0; x < 4; x++) {
pinMode(_rowPin[x], OUTPUT);
}
FastLED.addLeds<SK6812, DATA_PIN, GRB>(_leds, NUM_LEDS);
MIDI.begin();
for (uint8_t x = 0; x < 16; x++) {
_modeData[x] = EEPROM.read((x * 9));
_channelData[x] = EEPROM.read((x * 9) + 1);
_noteData[x] = EEPROM.read((x * 9) + 2);
_colorOn[x] = EEPROM.read((x * 9) + 3);
_colorOff[x] = EEPROM.read((x * 9) + 4);
}
for (uint8_t num = 0; num < 16; num++) {
_leds[num + 1] = CRGB((float)_colorValue[_colorOff[num]][0] / 255 * 3,
(float)_colorValue[_colorOff[num]][1] / 255 * 3,
(float)_colorValue[_colorOff[num]][2] / 255 * 3);
}
FastLED.show();
Serial.println("Mainpad + menu structs");
}
//---------------------------------------------------------------------------------------------------------
main::~main() {
Serial.print("Mainpad + menu structs are ");
}
//---------------------------------------------------------------------------------------------------------
uint8_t main::scanData() {
uint8_t num = 0;
for (uint8_t row = 0; row < 4; row++) {
digitalWrite(_rowPin[row], LOW);
delayMicroseconds(1);
for (uint8_t colom = 0; colom < 4; colom++) {
_buttonState[num] = digitalRead(_colomPin[colom]);
num++;
}
digitalWrite(_rowPin[row], HIGH);
}
return 0;
}
//---------------------------------------------------------------------------------------------------------
void main::sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData) {
//Send data to PC
for (uint8_t num = 0; num < 16; num++) {
if (_buttonState[num] != _buttonPrev[num]) {
if (_buttonState[num] == false) {
usbMIDI.sendControlChange(_noteData[num], 127, _channelData[num]);
MIDI.sendControlChange(_noteData[num], 127, _channelData[num]);
} else {
usbMIDI.sendControlChange(_noteData[num], 0, _channelData[num]);
MIDI.sendControlChange(_noteData[num], 0, _channelData[num]);
}
_buttonPrev[num] = _buttonState[num];
}
}
//Send data to pad
for (uint8_t num = 0; num < 16; num++) {
if (noteData == _noteData[num]) {
if (velocityData >= 100) {
_leds[num + 1] = CRGB(_colorValue[_colorOn[num]][0],
_colorValue[_colorOn[num]][1],
_colorValue[_colorOn[num]][2]);
} else {
_leds[num + 1] = CRGB((float)_colorValue[_colorOff[num]][0] / 255 * 3,
(float)_colorValue[_colorOff[num]][1] / 255 * 3,
(float)_colorValue[_colorOff[num]][2] / 255 * 3);
}
}
}
FastLED.show();
}
//---------------------------------------------------------------------------------------------------------
void main::saveData() {
if (_eepromFlag != 255) {
uint8_t a = _eepromFlag * 9;
EEPROM.write(a + 0, _modeData[_eepromFlag]);
EEPROM.write(a + 1, _channelData[_eepromFlag]);
EEPROM.write(a + 2, _noteData[_eepromFlag]);
EEPROM.write(a + 3, _colorOn[_eepromFlag]);
EEPROM.write(a + 4, _colorOff[_eepromFlag]);
EEPROM.write(a + 5, _min[_eepromFlag]);
EEPROM.write(a + 6, _max[_eepromFlag]);
EEPROM.write(a + 7, _mod[_eepromFlag]);
EEPROM.write(a + 8, _key[_eepromFlag]);
Serial.println("ALARM!!! EEPROM WRITE!");
}
_eepromFlag = 255;
}
//---------------------------------------------------------------------------------------------------------
uint8_t main::getI2cAdress() {
return _i2cAdress;
}
oled.h
#define APIN 22
#define BPIN 23
#include <Encoder.h>
Encoder enc(22, 23);
#define ENCBUTTON 21
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, OLED_RESET);
#define RELEASED 0
#define SHORTPRESS 1
#define LONGPRESS 2
//---------------------------------------------------------------------------------------------------------
bool (*currentAction)(void *ptr1, void *ptr2) = NULL;
void *currentParam1 = NULL;
void *currentParam2 = NULL;
bool value(void *ptr1, void *ptr2);
bool variable(void *ptr1, void *ptr2);
bool toggle(void *ptr1, void *ptr2);
bool Eeprom(void *ptr1, void *ptr2);
void subMenu();
//---------------------------------------------------------------------------------------------------------
uint8_t pressState = RELEASED;
uint8_t prevPress = HIGH;
uint32_t prevMillisPressed;
uint32_t currentMillisPressed;
uint8_t encVal;
uint8_t encMode;
uint32_t prevMillis;
//---------------------------------------------------------------------------------------------------------
void oled() {
if (encMode == 0) {
encVal = enc.read() / 4;
encVal = encVal % currentMenu->numItems;
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
display.setCursor(0, 0);
display.print(currentMenu->title);
display.setCursor(0, 16);
display.print(currentMenu->pStruct[encVal].title);
if (currentMenu->pStruct[encVal].function != NULL) {
currentAction = currentMenu->pStruct[encVal].function;
currentParam1 = currentMenu->pStruct[encVal].data1;
currentParam2 = currentMenu->pStruct[encVal].data2;
currentAction(currentParam1, currentParam2);
}
if (currentMenu->pStruct[encVal].pStruct != NULL) {
subMenu();
}
if (millis() - prevMillis >= 33) { // refresh 30 times a second
display.display(); // slows down midi
prevMillis = millis();
}
pressState = RELEASED;
}
//---------------------------------------------------------------------------------------------------------
bool encButton() {
uint8_t currentPress;
currentPress = digitalRead(ENCBUTTON);
if (prevPress == HIGH && currentPress == LOW) {
currentMillisPressed = millis();
} else if (prevPress == LOW && currentPress == HIGH) {
prevMillisPressed = millis();
uint32_t durationMillisPressed = prevMillisPressed - currentMillisPressed;
if (durationMillisPressed < 1000) {
pressState = SHORTPRESS;
}
if (durationMillisPressed > 1000) {
pressState = LONGPRESS;
}
}
prevPress = currentPress;
return pressState;
}
//---------------------------------------------------------------------------------------------------------
void subMenu() {
if (encButton() == SHORTPRESS) {
currentMenu = currentMenu->pStruct[encVal].pStruct;
encVal = 0;
enc.write(0);
}
}
//---------------------------------------------------------------------------------------------------------
bool value(void *ptr1, void *ptr2) {
uint8_t *value = (uint8_t *)ptr1;
display.setCursor(80, 16);
display.print(*value);
return true;
}
//---------------------------------------------------------------------------------------------------------
bool variable(void *ptr1, void *ptr2) {
uint8_t data;
uint8_t *val = (uint8_t *)ptr1;
uint8_t maxVal = (uint8_t *)ptr2; // <--- dit is trikky? ------------------------------------------------
if (encMode == 0) {
display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
display.setCursor(80, 16);
display.print(*val);
if (encButton() == SHORTPRESS) {
encMode = 1;
enc.write(*val * 4);
pressState = RELEASED;
}
}
if (encMode == 1) {
data = enc.read() / 4;
data = data % maxVal;
if (maxVal == 16) {
*val = data + 1;
} else {
*val = data;
}
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.setCursor(80, 16);
display.print(*val);
if (encButton() == SHORTPRESS) {
encMode = 0;
}
}
return true;
}
//---------------------------------------------------------------------------------------------------------
bool toggle(void *ptr1, void *ptr2) {
uint8_t *num = (uint8_t *)ptr1;
String *titles = (String *)ptr2;
uint8_t i = 0;
while (titles[i]) {
i++;
}
display.setCursor(75, 16);
display.print(titles[*num]);
if (encButton() == SHORTPRESS) {
++*num;
if (*num == i) {
*num = 0;
}
}
return true;
}
//---------------------------------------------------------------------------------------------------------
bool eeprom(void *ptr1, void *ptr2) {
uint8_t *adress = (uint8_t *)ptr1;
uint8_t *flag = (uint8_t *)ptr2;
if (encButton() == SHORTPRESS) {
*flag = *adress;
}
return true;
}
//---------------------------------------------------------------------------------------------------------
pads.cpp
#include <Arduino.h>
#include "pads.h"
pads::pads() {
//Serial.print("I created a ");
}
pads::~pads() {
//Serial.println("Deleted");
}
pads.h
#ifndef pads_h
#define pads_h
#define MAIN 0
#define FADERPAD 1
#define ENCODERPAD 2
#define GETTYPE 0
#define GETEEPROM 253
#define SEND2EEPROM 254
//I2C registers faders
#define GET4FADERDATA 1
#define SEND4FADERDATA 2
//I2C registers encoders
#define GETDATA 1
#define SEDNDATA 2
#define I2CCONNECTED 0
#define I2CDISCONNECTED 2
inline String colorNames[9] = { "Red", "Green", "Blue", "Cyan", "Magenta", "Yellow", "Orange", "White" }; // add 1 to array size
inline String modeNames[4] = { "Midi", "Key", "M+K" }; // add 1 to array size
bool value(void *ptr1, void *ptr2);
bool variable(void *ptr1, void *ptr2);
bool toggle(void *ptr1, void *ptr2);
bool eeprom(void *ptr1, void *ptr2);
struct MENUITEMS {
String title;
bool (*function)(void *ptr1, void *ptr2);
void *data1;
void *data2;
struct MENU *pStruct;
/* ~MENUITEMS() {
Serial.print("create/delete struct items ");
Serial.println(title);
}*/
};
struct MENU {
String title;
uint8_t numItems;
uint8_t menuVal;
MENUITEMS *pStruct;
/*~MENU() {
Serial.print("create/delete struct Menu");
Serial.println(title);
}*/
};
inline MENUITEMS menuItem[127];
inline MENU padMenu = {
"-Pads-", 0, 0, &menuItem[0]
};
inline MENU *currentMenu = &padMenu;
// -------------------------------------------------------------------------------------------------------------------------------
class pads {
public:
MENUITEMS *menuItemsFunc[16];
MENU menuFunc[16];
MENUITEMS *menuItems;
MENU menu;
pads();
virtual ~pads();
virtual uint8_t scanData() = 0;
virtual void sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData) = 0;
virtual void saveData() = 0;
virtual uint8_t getI2cAdress() = 0;
};
// -------------------------------------------------------------------------------------------------------------------------------
class main : public pads {
public:
main(uint8_t adress);
~main();
uint8_t scanData();
void sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData);
void saveData();
uint8_t getI2cAdress();
private:
//CRGB _leds[NUM_LEDS];
uint8_t _rowPin[4] = { 6, 9, 8, 7 };
uint8_t _colomPin[4] = { 15, 14, 5, 4 };
uint8_t _i2cAdress;
uint8_t _eepromFlag = 255;
uint8_t _buttonState[16];
uint8_t _buttonPrev[16];
uint8_t _id[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
uint8_t _modeData[16];
uint8_t _channelData[16];
uint8_t _noteData[16];
uint8_t _colorOn[16];
uint8_t _colorOff[16];
uint8_t _min[16];
uint8_t _max[16];
uint8_t _mod[16];
uint8_t _key[16];
};
// -------------------------------------------------------------------------------------------------------------------------------
class fader : public pads {
public:
MENUITEMS *pMenuItemsFunc;
MENUITEMS *pMenuItems;
fader(uint8_t adress);
~fader();
uint8_t scanData();
void sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData);
void saveData();
uint8_t getI2cAdress();
private:
uint8_t _i2cAdress;
uint8_t _eepromFlag = 255;
uint8_t _dataToSend[4];
uint8_t _faderState[4];
uint8_t _faderPrev[4];
uint8_t _id[4] = { 0, 1, 2, 3 };
uint8_t _modeData[4];
uint8_t _channelData[4];
uint8_t _noteData[4];
uint8_t _colorOn[4];
uint8_t _colorOff[4];
uint8_t _min[4];
uint8_t _max[4];
};
// -------------------------------------------------------------------------------------------------------------------------------
class encoderpad : public pads {
public:
MENUITEMS *pMenuItemsFunc;
MENUITEMS *pMenuItems;
encoderpad(uint8_t adress);
~encoderpad();
uint8_t scanData();
void sendData(uint8_t channelData, uint8_t noteData, uint8_t velocityData);
void saveData();
uint8_t getI2cAdress();
private:
uint8_t _i2cAdress;
uint8_t _eepromFlag = 255;
uint8_t _dataToSend[12];
uint8_t _dataState[12];
uint8_t _dataPrev[12];
uint8_t _id[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
uint8_t _modeData[12];
uint8_t _channelData[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
uint8_t _noteData[12] = { 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 };
uint8_t _colorOn[12];
uint8_t _colorOff[12];
uint8_t _min[12];
uint8_t _max[12];
};
#endif
// als je een nieuwe class toevoegd moet je alle functies in de nieuwe class(.cpp) stoppen anders krijg je irittante fout melding.
macropad_faders.ino
//nologo esp32c3 supermini
#include <Wire.h>
#include <EEPROM.h>
#include <FastLED.h>
#define NUM_LEDS 12
#define DATA_PIN 10
CRGB leds[NUM_LEDS];
#define FADER1 A0
#define FADER2 A1
#define FADER3 A2
#define FADER4 A3
uint8_t faderPin[4] = { A0, A1, A2, A3 };
uint16_t analogState[4];
uint16_t prevanalog[4];
#define FADER 1 //3
uint8_t receiveVal = 0;
uint8_t fadervalRev[4];
//---------------------------------------------------------------------------------------------------------
void setup() {
//delay(3000);
//Serial.begin(115200);
EEPROM.begin(28);
Wire.begin(3); // fader 1, encoder 2, fader 3
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
//while (!Serial);
FastLED.addLeds<SK6812, DATA_PIN, GRB>(leds, NUM_LEDS);
for (uint8_t z = 0; z < 12; z++) {
leds[z] = CRGB(10, 10, 1);
}
FastLED.show();
delay(1000);
/*for(uint8_t x = 0; x < 50; x++){
EEPROM.write(x,0);
}
EEPROM.commit();*/
}
//---------------------------------------------------------------------------------------------------------
void loop() {
leds[0] = CRGB(fadervalRev[0], fadervalRev[0], fadervalRev[0]);
leds[1] = CRGB(fadervalRev[0], fadervalRev[0], fadervalRev[0]);
leds[2] = CRGB(fadervalRev[0], fadervalRev[0], fadervalRev[0]);
leds[3] = CRGB(fadervalRev[1], fadervalRev[1], fadervalRev[1]);
leds[4] = CRGB(fadervalRev[1], fadervalRev[1], fadervalRev[1]);
leds[5] = CRGB(fadervalRev[1], fadervalRev[1], fadervalRev[1]);
leds[6] = CRGB(fadervalRev[2], fadervalRev[2], fadervalRev[2]);
leds[7] = CRGB(fadervalRev[2], fadervalRev[2], fadervalRev[2]);
leds[8] = CRGB(fadervalRev[2], fadervalRev[2], fadervalRev[2]);
leds[9] = CRGB(fadervalRev[3], fadervalRev[3], fadervalRev[3]);
leds[10] = CRGB(fadervalRev[3], fadervalRev[3], fadervalRev[3]);
leds[11] = CRGB(fadervalRev[3], fadervalRev[3], fadervalRev[3]);
FastLED.show();
for (uint8_t i = 0; i < 4; i++) {
if (analogRead(faderPin[i]) < (prevanalog[i] - 30) || analogRead(faderPin[i]) > (prevanalog[i] + 30)) {
prevanalog[i] = analogRead(faderPin[i]);
analogState[i] = analogRead(faderPin[i]) / 32;
}
}
}
//---------------------------------------------------------------------------------------------------------
void receiveEvent(int howMany) {
if (Wire.available()) {
receiveVal = Wire.read();
//Serial.println(receiveVal);
}
switch (receiveVal) {
case 2:
for (uint8_t x = 0; x < 4; x++) {
fadervalRev[x] = Wire.read();
}
break;
case 254:
for (uint8_t x = 0; x < 28; x++) {
uint8_t t = Wire.read();
EEPROM.write(x, t);
}
EEPROM.commit();
//Serial.println("ALARM!!! EEPROM WRITE!");
break;
}
}
//---------------------------------------------------------------------------------------------------------
void requestEvent() {
switch (receiveVal) {
case 0:
Wire.write(FADER); // type = "1" FADERPAD
break;
case 1:
{
for (uint8_t x = 0; x < 4; x++) {
Wire.write(analogState[x]);
}
}
break;
case 253:
{
for (uint8_t x = 0; x < 28; x++) {
Wire.write(EEPROM.read(x));
}
}
break;
}
}
macropad_encoder.ino
//nologo esp32c3 supermini
// miso 5
// mosi 6
// ss 7 MCP23C17
// SDA 8
// SCL 9
// SS2 10 LCD
// INT 20
// CLK 4
// encButtons 3,A3 - r17 1k, r18 2k , r19 3k , r20 10k
// reset 2,A2 LCD
// DC 1,A1
// LED 0,A0
#define ENCODER 2
#include <Wire.h>
#include <FastLED.h>
#define NUM_LEDS 12
#define DATA_PIN 0
CRGB leds[NUM_LEDS];
#include "MCP23S17.h"
MCP23S17 MCP(7);
#include <U8g2lib.h>
#include <SPI.h>
U8G2_SH1122_256X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/10, /* dc=*/1, /* reset=*/2);
//U8G2_SH1122_256X64_F_4W_HW_SPI u8g2(U8G2_R0, /* clock=*/ 4, /* data=*/ 6, /* cs=*/ 10, /* dc=*/ 1, /* reset=*/ 2);
int16_t encoderVal[4];
uint8_t aLastState[4];
uint8_t buttonState[8];
uint8_t buttonPrev[8];
uint8_t receiveVal;
uint32_t prevtime;
void setup() {
Serial.begin(115200);
pinMode(20, INPUT);
Wire.begin(2);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
FastLED.addLeds<SK6812, DATA_PIN, RGB>(leds, NUM_LEDS);
for (uint8_t z = 0; z < 12; z++) {
leds[z] = CRGB(10, 10, 1);
}
FastLED.show();
Serial.println();
Serial.print("MCP23S17_LIB_VERSION: ");
Serial.println(MCP23S17_LIB_VERSION);
delay(100);
SPI.begin();
u8g2.begin();
u8g2.clearBuffer(); // clear the internal memory
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
u8g2.drawStr(0, 50, "Hello World!"); // write something to the internal memory
u8g2.sendBuffer();
MCP.begin();
MCP.pinMode8(0, 0xFF);
MCP.pinMode8(1, 0xFF);
}
void loop() {
encoder(&encoderVal[0], &aLastState[0], 7, 6);
encoder(&encoderVal[1], &aLastState[1], 5, 4);
encoder(&encoderVal[2], &aLastState[2], 3, 2);
encoder(&encoderVal[3], &aLastState[3], 1, 0);
for (uint8_t x = 0; x < 8; x++) {
uint8_t currentState = MCP.read1(x + 8);
if (currentState != buttonPrev[x]) {
if (currentState == HIGH) {
buttonState[x] = 0;
} else {
buttonState[x] = 127;
}
}
buttonPrev[x] = currentState;
}
uint32_t time = millis();
if (time - prevtime >= 33) {
prevtime = time;
u8g2.clearBuffer();
u8g2.setCursor(0, 15);
u8g2.print(u8g2_u8toa((uint8_t)(encoderVal[0]), 3));
u8g2.sendBuffer();
}
}
void encoder(int16_t *val, uint8_t *last, uint8_t pin1, uint8_t pin2) {
uint8_t aState = MCP.read1(pin1);
if (aState != *last) {
if (MCP.read1(pin2) != aState) {
//++*val;
*val = *val + 4;
} else {
//--*val;
*val = *val - 4;
}
*last = aState;
*val = constrain(*val, 0, 127);
}
}
void receiveEvent(int howMany) {
if (Wire.available()) {
receiveVal = Wire.read();
}
switch (receiveVal) {
case 2:
for (uint8_t x = 0; x < 4; x++) {
encoderVal[x] = Wire.read();
}
for (uint8_t x = 0; x < 8; x++) {
buttonState[x] = Wire.read();
}
break;
/*case 254:
for (uint8_t x = 0; x < 28; x++) {
uint8_t t = Wire.read();
EEPROM.write(x, t);
}
EEPROM.commit();
//Serial.println("ALARM!!! EEPROM WRITE!");
break;*/
}
}
void requestEvent() {
switch (receiveVal) {
case 0:
Wire.write(ENCODER); // type = 2 ENCODERPAD
break;
case 1:
Wire.write(encoderVal[0]);
Wire.write(encoderVal[1]);
Wire.write(encoderVal[2]);
Wire.write(encoderVal[3]);
Wire.write(buttonState[0]);
Wire.write(buttonState[1]);
Wire.write(buttonState[2]);
Wire.write(buttonState[3]);
Wire.write(buttonState[4]);
Wire.write(buttonState[5]);
Wire.write(buttonState[6]);
Wire.write(buttonState[7]);
break;
}
}
code seems to work fine the issue is the order of power up, with or without extra pad