Hi All
I've been working for ages on a MIDI remote control to talk to a mixing desk. It controls the bus sends on the desk, allowing a musician to control their own mix using a single rotary click encoder. I have the code working and whilst it's pretty untidy and i'm sure it can be massively improved upon, it works! It fetches the channel names from the desk, it has a menu structure that is accessible by a long hold on the encoder (allowing the setting of model type for the connected mixing desk and also which of the desk's mixes you want to control), it controls the desk sends correctly. I'm frankly amazed that i've got this far!
My problem now is that the Teensy 3.2 is out of stock. I own one of them, but last week managed to fry it by splashing 12V on to its' 5V pin! I tried an LC but there's not enough RAM on it - the screen is unstable. Instead I bought a Teensy 4. I'll eventually need 12 of these things, so the LC is more attractive, but I think I just have to accept that it's not going to be able to hack it.
The code compiles and works a-ok on the 3.2, however as soon as I try and compile for 4, it refuses. I get the "Error compiling for board Teensy 4.0
I know I have multiple instances of the same library on my machine, and to be honest i'm not sure how that's happened. I had to completely uninstall Arduino IDE a month ago as I ran in to a problem where an edited version of the Adafruit SSD1306 display library (for a tiny display for another project) was always being used in sketches even though i'd changed the filename of the edited version. Had to uninstall, clear out the registries etc. and reinstall before I could use the library I wanted to again. It's therefore a pretty recent install. I know Teensy comes with its' own set of libraries, which might be the problem, though I don't think i'd installed them where the error messages are telling me they're located. Given that it compiles ok for 3.2, i'm inclined to think that they're a red herring.
I do wonder if the problem might be with my use of the TimerOne library, knowing the faster clock speed of the 4.0, but I can't see it stopping the code from compiling.
I tried going back to an older Arduin IDE as i'd seen somebody else have issues with compiling for a 4.0 that this solved, but it's been no use.
Can someone help me make sense of these error messages please! I can't make much sense of what they mean.
When I compile for 3.2 I just get the following (but it works);
And here's my code;
I've been working for ages on a MIDI remote control to talk to a mixing desk. It controls the bus sends on the desk, allowing a musician to control their own mix using a single rotary click encoder. I have the code working and whilst it's pretty untidy and i'm sure it can be massively improved upon, it works! It fetches the channel names from the desk, it has a menu structure that is accessible by a long hold on the encoder (allowing the setting of model type for the connected mixing desk and also which of the desk's mixes you want to control), it controls the desk sends correctly. I'm frankly amazed that i've got this far!
My problem now is that the Teensy 3.2 is out of stock. I own one of them, but last week managed to fry it by splashing 12V on to its' 5V pin! I tried an LC but there's not enough RAM on it - the screen is unstable. Instead I bought a Teensy 4. I'll eventually need 12 of these things, so the LC is more attractive, but I think I just have to accept that it's not going to be able to hack it.
The code compiles and works a-ok on the 3.2, however as soon as I try and compile for 4, it refuses. I get the "Error compiling for board Teensy 4.0
I know I have multiple instances of the same library on my machine, and to be honest i'm not sure how that's happened. I had to completely uninstall Arduino IDE a month ago as I ran in to a problem where an edited version of the Adafruit SSD1306 display library (for a tiny display for another project) was always being used in sketches even though i'd changed the filename of the edited version. Had to uninstall, clear out the registries etc. and reinstall before I could use the library I wanted to again. It's therefore a pretty recent install. I know Teensy comes with its' own set of libraries, which might be the problem, though I don't think i'd installed them where the error messages are telling me they're located. Given that it compiles ok for 3.2, i'm inclined to think that they're a red herring.
I do wonder if the problem might be with my use of the TimerOne library, knowing the faster clock speed of the 4.0, but I can't see it stopping the code from compiling.
I tried going back to an older Arduin IDE as i'd seen somebody else have issues with compiling for a 4.0 that this solved, but it's been no use.
Can someone help me make sense of these error messages please! I can't make much sense of what they mean.
Arduino: 1.8.15 (Windows 7), TD: 1.56, Board: "Teensy 4.0, Serial + MIDI, 600 MHz, Faster, US English"
In file included from C:\arduino-1.8.15\Projects\MidiPersonalMonitor\ModelMixNumMenu\ModelMixNumMenu.ino:8:0:
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::setPeriod(long unsigned int)':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:180:32: error: 'F_TIMER' was not declared in this scope
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:216:16: error: 'FTM1_SC' was not declared in this scope
uint32_t sc = FTM1_SC;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:218:2: error: 'FTM1_MOD' was not declared in this scope
FTM1_MOD = pwmPeriod;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:219:25: error: 'FTM_SC_CLKS' was not declared in this scope
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:219:29: error: 'FTM_SC_CPWMS' was not declared in this scope
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:219:68: error: 'FTM_SC_TOIE' was not declared in this scope
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::start()':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:227:2: error: 'FTM1_CNT' was not declared in this scope
FTM1_CNT = 0;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::stop()':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:231:2: error: 'FTM1_SC' was not declared in this scope
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:231:23: error: 'FTM_SC_TOIE' was not declared in this scope
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:231:37: error: 'FTM_SC_CPWMS' was not declared in this scope
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:231:63: error: 'FTM_SC_PS' was not declared in this scope
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::resume()':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:237:2: error: 'FTM1_SC' was not declared in this scope
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:237:24: error: 'FTM_SC_TOIE' was not declared in this scope
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:237:49: error: 'FTM_SC_PS' was not declared in this scope
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:237:55: error: 'FTM_SC_CPWMS' was not declared in this scope
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:237:83: error: 'FTM_SC_CLKS' was not declared in this scope
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::setPwmDuty(char, unsigned int)':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:247:13: error: 'TIMER1_A_PIN' was not declared in this scope
if (pin == TIMER1_A_PIN) {
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:248:3: error: 'FTM1_C0V' was not declared in this scope
FTM1_C0V = dutyCycle;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:249:20: error: 'TIMER1_B_PIN' was not declared in this scope
} else if (pin == TIMER1_B_PIN) {
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:250:3: error: 'FTM1_C1V' was not declared in this scope
FTM1_C1V = dutyCycle;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne:wm(char, unsigned int)':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:255:13: error: 'TIMER1_A_PIN' was not declared in this scope
if (pin == TIMER1_A_PIN) {
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:256:53: error: 'PORT_PCR_MUX' was not declared in this scope
*portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:256:57: error: 'PORT_PCR_DSE' was not declared in this scope
*portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:256:72: error: 'PORT_PCR_SRE' was not declared in this scope
*portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:257:20: error: 'TIMER1_B_PIN' was not declared in this scope
} else if (pin == TIMER1_B_PIN) {
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:258:53: error: 'PORT_PCR_MUX' was not declared in this scope
*portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:258:57: error: 'PORT_PCR_DSE' was not declared in this scope
*portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:258:72: error: 'PORT_PCR_SRE' was not declared in this scope
*portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::disablePwm(char)':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:266:13: error: 'TIMER1_A_PIN' was not declared in this scope
if (pin == TIMER1_A_PIN) {
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:268:20: error: 'TIMER1_B_PIN' was not declared in this scope
} else if (pin == TIMER1_B_PIN) {
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::attachInterrupt(void (*)())':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:278:2: error: 'FTM1_SC' was not declared in this scope
FTM1_SC |= FTM_SC_TOIE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:278:13: error: 'FTM_SC_TOIE' was not declared in this scope
FTM1_SC |= FTM_SC_TOIE;
^
In file included from C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/core_pins.h:32:0,
from C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/wiring.h:39,
from C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/WProgram.h:45,
from C:\Users\Chris\AppData\Local\Temp\arduino_build_551922\pch\Arduino.h:6:
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:279:18: error: 'IRQ_FTM1' was not declared in this scope
NVIC_ENABLE_IRQ(IRQ_FTM1);
^
C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/imxrt.h:9846:52: note: in definition of macro 'NVIC_ENABLE_IRQ'
#define NVIC_ENABLE_IRQ (*(&NVIC_ISER0 + ( >> 5)) = (1 << ( & 31)))
^
In file included from C:\arduino-1.8.15\Projects\MidiPersonalMonitor\ModelMixNumMenu\ModelMixNumMenu.ino:8:0:
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h: In member function 'void TimerOne::detachInterrupt()':
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:286:2: error: 'FTM1_SC' was not declared in this scope
FTM1_SC &= ~FTM_SC_TOIE;
^
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:286:14: error: 'FTM_SC_TOIE' was not declared in this scope
FTM1_SC &= ~FTM_SC_TOIE;
^
In file included from C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/core_pins.h:32:0,
from C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/wiring.h:39,
from C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/WProgram.h:45,
from C:\Users\Chris\AppData\Local\Temp\arduino_build_551922\pch\Arduino.h:6:
C:\Users\Chris\Documents\Arduino\libraries\TimerOne/TimerOne.h:287:19: error: 'IRQ_FTM1' was not declared in this scope
NVIC_DISABLE_IRQ(IRQ_FTM1);
^
C:\arduino-1.8.15\hardware\teensy\avr\cores\teensy4/imxrt.h:9847:52: note: in definition of macro 'NVIC_DISABLE_IRQ'
#define NVIC_DISABLE_IRQ (*(&NVIC_ICER0 + ( >> 5)) = (1 << ( & 31)))
^
ModelMixNumMenu: In function 'void setup()':
C:\arduino-1.8.15\Projects\MidiPersonalMonitor\ModelMixNumMenu\ModelMixNumMenu.ino:112:44: warning: invalid conversion from 'void (*)(const byte*, uint16_t, bool) {aka void (*)(const unsigned char*, short unsigned int, bool)}' to 'midi::SystemExclusiveCallback {aka void (*)(unsigned char*, unsigned int)}' [-fpermissive]
MIDI.setHandleSystemExclusive(receivemidi);
^
In file included from C:\arduino-1.8.15\Projects\MidiPersonalMonitor\ModelMixNumMenu\ModelMixNumMenu.ino:6:0:
C:\arduino-1.8.15\hardware\teensy\avr\libraries\MIDI\src/MIDI.h:195:17: note: initializing argument 1 of 'void midi::MidiInterface<Transport, _Settings, _Platform>::setHandleSystemExclusive(midi::SystemExclusiveCallback) [with Transport = midi::SerialMIDI<HardwareSerial>; _Settings = midi:efaultSettings; _Platform = midi:efaultPlatform; midi::SystemExclusiveCallback = void (*)(unsigned char*, unsigned int); byte = unsigned char]'
inline void setHandleSystemExclusive(SystemExclusiveCallback fptr) { mSystemExclusiveCallback = fptr; }
^
ModelMixNumMenu: In function 'void loop()':
ModelMixNumMenu:127: warning: enumeration value 'Open' not handled in switch
switch (b) {
^
ModelMixNumMenu:127: warning: enumeration value 'Closed' not handled in switch
ModelMixNumMenu:127: warning: enumeration value 'Pressed' not handled in switch
ModelMixNumMenu:127: warning: enumeration value 'Released' not handled in switch
ModelMixNumMenu: In function 'void sendmidi()':
ModelMixNumMenu:395: warning: right shift count >= width of type
if (checksum >> 127){
^
ModelMixNumMenu: In function 'void getnames()':
ModelMixNumMenu:425: warning: right shift count >= width of type
if (checksum >> 127){
^
Multiple libraries were found for "MIDI.h"
Used: C:\arduino-1.8.15\hardware\teensy\avr\libraries\MIDI
Not used: C:\Users\Chris\Documents\Arduino\libraries\MIDI_Library
Multiple libraries were found for "TimerOne.h"
Used: C:\Users\Chris\Documents\Arduino\libraries\TimerOne
Not used: C:\arduino-1.8.15\hardware\teensy\avr\libraries\TimerOne
Error compiling for board Teensy 4.0.
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
When I compile for 3.2 I just get the following (but it works);
ModelMixNumMenu: In function 'void setup()':
C:\arduino-1.8.15\Projects\MidiPersonalMonitor\ModelMixNumMenu\ModelMixNumMenu.ino:112:44: warning: invalid conversion from 'void (*)(const byte*, uint16_t, bool) {aka void (*)(const unsigned char*, short unsigned int, bool)}' to 'midi::SystemExclusiveCallback {aka void (*)(unsigned char*, unsigned int)}' [-fpermissive]
MIDI.setHandleSystemExclusive(receivemidi);
^
In file included from C:\arduino-1.8.15\Projects\MidiPersonalMonitor\ModelMixNumMenu\ModelMixNumMenu.ino:6:0:
C:\arduino-1.8.15\hardware\teensy\avr\libraries\MIDI\src/MIDI.h:195:17: note: initializing argument 1 of 'void midi::MidiInterface<Transport, _Settings, _Platform>::setHandleSystemExclusive(midi::SystemExclusiveCallback) [with Transport = midi::SerialMIDI<HardwareSerial>; _Settings = midi:efaultSettings; _Platform = midi:efaultPlatform; midi::SystemExclusiveCallback = void (*)(unsigned char*, unsigned int); byte = unsigned char]'
inline void setHandleSystemExclusive(SystemExclusiveCallback fptr) { mSystemExclusiveCallback = fptr; }
^
ModelMixNumMenu: In function 'void loop()':
ModelMixNumMenu:127: warning: enumeration value 'Open' not handled in switch
switch (b) {
^
ModelMixNumMenu:127: warning: enumeration value 'Closed' not handled in switch
ModelMixNumMenu:127: warning: enumeration value 'Pressed' not handled in switch
ModelMixNumMenu:127: warning: enumeration value 'Released' not handled in switch
ModelMixNumMenu: In function 'void sendmidi()':
ModelMixNumMenu:395: warning: right shift count >= width of type
if (checksum >> 127){
^
ModelMixNumMenu: In function 'void getnames()':
ModelMixNumMenu:425: warning: right shift count >= width of type
if (checksum >> 127){
^
In file included from C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:12:0:
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h: In constructor 'ClickEncoder::ClickEncoder(uint8_t, uint8_t, uint8_t, uint8_t, bool)':
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:112:8: warning: 'ClickEncoder::doubleClickEnabled' will be initialized after [-Wreorder]
bool doubleClickEnabled;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:106:8: warning: 'bool ClickEncoder::accelerationEnabled' [-Wreorder]
bool accelerationEnabled;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:46:1: warning: when initialized here [-Wreorder]
ClickEncoder::ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN, uint8_t stepsPerNotch, bool active)
^
In file included from C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:12:0:
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:106:8: warning: 'ClickEncoder::accelerationEnabled' will be initialized after [-Wreorder]
bool accelerationEnabled;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:102:20: warning: 'volatile int16_t ClickEncoder::delta' [-Wreorder]
volatile int16_t delta;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:46:1: warning: when initialized here [-Wreorder]
ClickEncoder::ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN, uint8_t stepsPerNotch, bool active)
^
In file included from C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:12:0:
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:111:19: warning: 'ClickEncoder::button' will be initialized after [-Wreorder]
volatile Button button;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:104:11: warning: 'uint8_t ClickEncoder::steps' [-Wreorder]
uint8_t steps;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:46:1: warning: when initialized here [-Wreorder]
ClickEncoder::ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN, uint8_t stepsPerNotch, bool active)
^
In file included from C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:12:0:
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:104:11: warning: 'ClickEncoder::steps' will be initialized after [-Wreorder]
uint8_t steps;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.h:98:17: warning: 'const uint8_t ClickEncoder:inA' [-Wreorder]
const uint8_t pinA;
^
C:\Users\Chris\Documents\Arduino\libraries\encoder-master\ClickEncoder.cpp:46:1: warning: when initialized here [-Wreorder]
ClickEncoder::ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN, uint8_t stepsPerNotch, bool active)
^
Sketch uses 43340 bytes (16%) of program storage space. Maximum is 262144 bytes.
Global variables use 6956 bytes (10%) of dynamic memory, leaving 58580 bytes for local variables. Maximum is 65536 bytes.
And here's my code;
Code:
#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <EEPROM.h>
#include <MIDI.h>
#include <ClickEncoder.h>
#include <TimerOne.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
MIDI_CREATE_INSTANCE(HardwareSerial,Serial2,MIDI);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
byte numchans = 32;
byte maxnumaux = 8;
ClickEncoder *encoder;
int16_t last, value;
byte startchan = 1;
byte selchan = 0;
byte activechan = 1;
byte lastchannelval = 0;
byte chselflag = 0;
byte lastchselflag = 0;
byte channelvalmax = 30;
byte chpos = 5;
byte chwidth = 10;
byte upflag = 0;
byte downflag = 0;
int nametimer = 0;
int txtimeout = 5000;
byte sysexarray[15] = {0xF0,0x41,0x7F,0x00,0x00,0x24,0x12,0x04,00,0x12,00,00,00,00,0xF7};
byte namereq[17] = {0xF0,0x41,0x7F,0x00,0x00,0x24,0x11,0x04,00,00,00,00,00,00,0x06,00,0xF7};
byte high_part;
byte low_part;
int midisendval;
byte auxnumber = 0;
byte auxarray[24] = {0x02,0x0A,0x12,0x1A,0x22,0x2A,0x32,0x3A,0x42,0x4a,0x52,0x5a,0x62,0x6a,0x72,0x7a,0x02,0x0A,0x12,0x1A,0x22,0x2A,0x32,0x3A};
byte checksum; //was int - change back if doesn't work
byte chan;
byte rxflag = 0;
byte namesflag = 0;
byte setupmenuflag = 0;
byte editflag = 0;
byte channelindex = 0;
int namereqdelay = 1000;
byte namecount = 0;
byte namerxflag = 0;
int receivednames[234];
byte nameflag[48] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte channelvals[48];
String menunames[2] = {"Mix","Model"};
byte menu;
byte numbermenu = 1;
String modelnames[2] = {"M300","M480"};
byte modelchannels[2] = {31,47};
byte menuvals[2] = {3,1}; //0 is where the selected aux lives. 1 is where the selected model lives
byte menuvallimits[2] = {23,2}; // maximum limits for the menuvals
byte meterx = 110;
byte metery;
byte meterw;
byte meterh = 15;
byte sendindex = 0;
void timerIsr() {
encoder->service();
}
void setup() {
numchans = numchans - 1;
menuvals[0] = EEPROM.read(0);
menuvals[1] = EEPROM.read(1);
if(menuvals[0]>>maxnumaux){
menuvals[0] = 1;
EEPROM.write(0,menuvals[0]);
setupmenuflag = 1;
}
Serial.begin(9600);
Serial3.begin(4800);
MIDI.begin();
MIDI.turnThruOff();
encoder = new ClickEncoder(A1, A0, A2, 4);
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);
last = -1;
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
MIDI.setHandleSystemExclusive(receivemidi);
}
void loop() {
if (namesflag == 0){
getnames();
}
auxnumber = auxarray[menuvals[0]];
MIDI.read();
ClickEncoder::Button b = encoder->getButton(); //encoder
if (b != ClickEncoder::Open) {
#define VERBOSECASE(label) case label: Serial.println(#label); break;
switch (b) {
//VERBOSECASE(ClickEncoder::Pressed);
//VERBOSECASE(ClickEncoder::Held)
//VERBOSECASE(ClickEncoder::Released)
case ClickEncoder::DoubleClicked:
break;
case ClickEncoder::Held:
if (setupmenuflag == 0){
setupmenuflag = 1;
display.clearDisplay();
display.display();
delay(500);
}
else{
setupmenuflag = 0;
display.clearDisplay();
display.display();
if (EEPROM.read(0) != menuvals[0]){
EEPROM.write(0,menuvals[0]);
}
if (EEPROM.read(1) != menuvals[1]){
EEPROM.write(1,menuvals[1]);
}
delay(500);
}
break;
case ClickEncoder::Clicked:
if(setupmenuflag == 1){
if (editflag == 0){
editflag = 1;
}
else{editflag = 0;}
}
if (chselflag == 0){
activechan = selchan;
chselflag = 1;
}
else{
chselflag = 0;
}
break;
}
}
if (setupmenuflag == 1){
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(35,0);
display.print("Setup");
display.setCursor(3, 28);
display.print(menunames[menu]);
if (editflag == 0){
value += encoder->getValue();
if (value > last){menu++;}
if (value < last){menu--;}
if (menu < 0){menu = 0;}
if (menu > numbermenu){menu = numbermenu;}
last = value;
display.drawRect(0, 26, 80, 18, SSD1306_WHITE);
}
else{
value += encoder->getValue();
if (value > last){menuvals[menu]++;
if (menu == 0){
if(menuvals[1] == 0){
if(7<menuvals[0] && menuvals[0]<16){
menuvals[0] = 16 ;
}
if (19<menuvals[0]){
menuvals[0]=19;
}
}
}
}
if (value < last){menuvals[menu]--;
if (menu == 0){
if(menuvals[1] == 0){
if(7<menuvals[0] && menuvals[0]<16){
menuvals[0] = 7 ;
}
}
}
}
if (menuvals[menu] < 0){menuvals[menu] = 0;}
if (menuvals[menu] > menuvallimits[menu]){menuvals[menu] = menuvallimits[menu];}
if (menu == 0){
if(menuvals[1] == 0){
if(7<menuvals[0] && menuvals[0]<16){
display.drawLine(0,46, 80, 46, SSD1306_WHITE); ;
}
}
}
last = value;
display.drawRect(0, 42, 80, 19, SSD1306_WHITE);
}
display.setCursor(3, 45);
if(menu == 0){
String mixnames[24] = {"Aux 1","Aux 2","Aux 3","Aux 4","Aux 5","Aux 6","Aux 7","Aux 8","Aux 9","Aux 10","Aux 11","Aux 12","Aux 13","Aux 14","Aux 15","Aux 16","Mtx 1","Mtx 2","Mtx 3","Mtx 4","Mtx 5","Mtx 6","Mtx 7","Mtx 8"};
display.print(mixnames[menuvals[0]]);
}
else if (menu == 1){
display.print(modelnames[menuvals[1]]);
}
display.display();
numchans = modelchannels[menuvals[1]];
}
else{
value += encoder->getValue();
if (chselflag == 0){ //channel select menu
lastchselflag = 0;
if (value > last){selchan++;}
if (value < last){selchan--;}
if (selchan < 1){selchan = numchans;}
if (selchan > numchans){selchan = startchan;}
last = value;
}
else{ //value set menu
lastchannelval = channelvals[selchan];
if (value > last){channelvals[selchan]++;
}
if (value < last){channelvals[selchan]--;
}
if (channelvals[selchan] < 1){channelvals[selchan] = 0;}
if (channelvals[selchan] > channelvalmax){channelvals[selchan] = channelvalmax;}
last = value;
if((lastchannelval != channelvals[selchan]) && (rxflag == 0)){
sendmidi();
}
rxflag = 0;
}
if (chselflag == 0){
meterw = map(channelvals[selchan], 0, 30, 0, 100);
}
else{
meterw = map(channelvals[selchan], 0, 30, 0, 100);
}
chwidth = 128/numchans;
chpos = chwidth*(selchan-1);
disp();
}
}
void disp(){
String namearray[48] = {"chan01","chan02","chan03","chan04","chan05","chan06","chan07","chan08","chan09","chan10","chan11","chan12","chan14","chan15","chan16","chan17","chan18","chan19","chan20","chan21","chan22","chan23","chan24","chan25","chan26","chan27","chan28","chan29","chan30","chan31","chan32","chan33","chan34","chan35","chan36","chan37","chan38","chan39","chan40","chan41","chan42","chan43","chan44","chan45","chan46","chan47","chan48"};
display.clearDisplay();
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(10,35);
if(nameflag[selchan-1]==0){
display.print(namearray[selchan-1]);
}
else{
display.write(receivednames[(selchan-1)*6]);
display.setCursor(26,35);
display.write(receivednames[((selchan-1)*6)+1]);
display.setCursor(42,35);
display.write(receivednames[((selchan-1)*6)+2]);
display.setCursor(58,35);
display.write(receivednames[((selchan-1)*6)+3]);
display.setCursor(74,35);
display.write(receivednames[((selchan-1)*6)+4]);
display.setCursor(90,35);
display.write(receivednames[((selchan-1)*6)+5]);
}
display.setTextSize(2);
display.setCursor(103,0);
display.println(channelvals[selchan]);
if (chselflag == 0){
display.drawRect(0, 32, 128, 29, SSD1306_WHITE);
}
else{
display.drawRect(00, 00, 128, 15, SSD1306_WHITE);
}
display.fillRoundRect(0, 0, meterw, meterh, 2, SSD1306_WHITE);
display.fillRoundRect(chpos, 20, chwidth, 9, 2, SSD1306_WHITE);
display.drawLine(0,19, 0, 29, SSD1306_WHITE);
display.drawLine(127,19, 127, 29, SSD1306_WHITE);
display.drawLine(0,29, 127, 29, SSD1306_WHITE);
display.drawLine(70,0, 70,14, SSD1306_WHITE);
display.drawLine(00,0, 00,14, SSD1306_WHITE);
display.drawLine(100,0, 100,14, SSD1306_WHITE);
display.display();
}
void receivemidi(const byte *a, uint16_t sizeofsysex, bool last){
const byte *received = MIDI.getSysExArray();
if(received[6] == 0x12){ //it's a Data set
if(received[7] == 0x04 && received[9] == 0x12){ //it's aux data
if (received[10] == auxnumber){ //it's for my aux
chan = received[8]+1;
//Serial.print("aux data");
byte rxhigh_part = received[11];
byte rxlow_part = received[12];
int val = ((rxhigh_part&0x7F)<<7)|(rxlow_part&0x7F);
if((val&0x2000)!=0)val|=0xffffC000;
val = map(val,-905,100,0,99);
channelvals[received[8]+1]=val;
rxflag = 1;
}
}
else if((received[7] == 0x04) && ((received[9] == 0x00)) && (received[10] == 0x00)){ //it's a name
//Serial.println("name received");
chan = received[8];
receivednames[chan*6] = received[11];
receivednames[(chan*6)+1] = received[12];
receivednames[(chan*6)+2] = received[13];
receivednames[(chan*6)+3] = received[14];
receivednames[(chan*6)+4] = received[15];
receivednames[(chan*6)+5] = received[16];
nameflag[chan] = 1;
namerxflag = 1;
delay(200);
}
}
}
void sendmidi(){
midisendval = log(channelvals[selchan]+1)/log(30)*1000;
midisendval = map(midisendval, 0, 1010, -905, 100); //or 16129
//Serial.println(midisendval);
high_part = (midisendval>>7)&0x7F;
low_part = midisendval&0x7F;
//Serial.print(high_part,HEX);
//Serial.print(" : ");
//Serial.println(low_part,HEX);
sysexarray[8]=(activechan-1);
if (menuvals[0]<= 15){
sysexarray[9] = 0x12;
}
else{ sysexarray[9] = 0x13;}
sysexarray[10]=auxnumber;
sysexarray[11]=high_part;
sysexarray[12]=low_part;
checksum = sysexarray[7]+sysexarray[8]+sysexarray[9]+sysexarray[10]+sysexarray[11]+sysexarray[12];
if (checksum >> 127){
checksum=checksum-128;
}
checksum=128-checksum;
checksum=checksum&0x7F;
sysexarray[13]=checksum;
//Serial.println(checksum,HEX);
//usbMIDI.sendSysEx(15,sysexarray,true);
MIDI.sendSysEx(15,sysexarray,true);
}
void getnames(){
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(00,00);
display.write("Stand By");
display.setCursor(00,20);
display.write("Getting");
display.setCursor(00,40);
display.write("Names");
display.display();
while(namecount <= numchans+1){
if (nametimer == 0){
namereq[8]=namecount;
checksum = namereq[7]+namereq[8]+namereq[9]+namereq[10]+namereq[11]+namereq[12]+namereq[13]+namereq[14];
if (checksum >> 127){
checksum=checksum-128;
}
checksum=128-checksum;
checksum=checksum&0x7F;
namereq[15]=checksum;
MIDI.sendSysEx(17,namereq,true);
//usbMIDI.sendSysEx(17,namereq,true);
}
nametimer++;
MIDI.read();
if(nameflag[namecount] == 1){
namecount++;
nametimer = 0;
}
if (nametimer == txtimeout){
namecount++;
nametimer = 0;
}
if (namecount == numchans){
namesflag = 1;
}
}
}