Here is the complete code. I really don't use any arrays. All it does is listen to the serial port and make changes to the display based on messages it receives. The only array used is in the recvBytesWithStartEndMarkers() function which is used to process the incoming serial data. Thanks for taking the time to comment.
In this code, I just copied case 20 into case 21 and it causes the glitch. If I delete case 21, there is no glitch.
/**************************************************************************
Twin Midi Serial Display
**************************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/Org_01.h>
#include <ReceiveOnlySoftwareSerial.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define debugByte 0x10
#define div1Byte 0x11
#define div2Byte 0x12
#define div3Byte 0x13
#define bpmByte 0x14
#define div1PlayByte 0x15
#define div2PlayByte 0x16
#define div3PlayByte 0x17
#define div1StopByte 0x18
#define div2StopByte 0x19
#define div3StopByte 0x20
#define intExtClockByte 0x21
#define menuModeByte 0x22
#define encoderDirByte 0x23
#define encoderPushByte 0x24
#define menuPageByte 0x25
#define menuCursorByte 0x26
#define div1FilterByte 0x27
#define div2FilterByte 0x28
#define div3FilterByte 0x29
#define div1PlaySyncByte 0x30
#define div2PlaySyncByte 0x31
#define div3PlaySyncByte 0x32
#define div1BeatSyncByte 0x33
#define div2BeatSyncByte 0x34
#define div3BeatSyncByte 0x35
#define settingsSavedByte 0x36
#define eurModeByte 0x37
#define eurOnButtonByte 0x38
#define eur16_8_4 0x00
#define eur16_8_8tr 0x01
#define eurDivide 0x02
#define eurConstant 0x00
#define eurButton 0x01
bool debugMode = false;
bool firstBoot = true;
bool newPlayRecieved = false;
const byte numBytes = 64;
byte receivedBytes[numBytes];
unsigned int long newChangeOneReceivedMS = 0;
unsigned int long newChangeTwoReceivedMS = 0;
unsigned int long newChangeThreeReceivedMS = 0;
unsigned int long newPlayPulse = 500;
byte numReceived = 0;
int debugData = 1;
boolean newData = false;
boolean intClock = true;
boolean menuMode = false;
boolean encoderPush = false;
int div1 = 20;
int div2 = 20;
int div3 = 20;
bool channelOnePlayStatus = false;
bool channelTwoPlayStatus = false;
bool channelThreePlayStatus = false;
int bpm = 128;
long encPos = 0;
int menuPage = 0;
int menuCursor = 0;
int numMenuPages = 19;
int numMenuItems = 4;
byte inByte = 0x00;
bool div1Filter = false;
bool div2Filter = false;
bool div3Filter = false;
bool div1PlaySync = false;
bool div2PlaySync = false;
bool div3PlaySync = false;
bool div1BeatSync = false;
bool div2BeatSync = false;
bool div3BeatSync = false;
int eurOnButton = eurConstant;
int eurMode = eur16_8_4;
void setup() {
//delay(1500);
pinMode(9,INPUT);
pinMode(10, INPUT);
pinMode(11, INPUT);
Serial.begin(115200);
display.setFont(&Org_01);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.display();
display.clearDisplay();
display.display();
drawDisplayBackground();
updateDisplay();
menuMode = false;
}
void loop() {
recvBytesWithStartEndMarkers();
processNewData();
if (menuMode == false) updateDisplay();
if (menuMode == true) drawMenu();
}
void drawDisplayBackground(){
display.clearDisplay();
display.fillRect(0, 0, 83, 15, WHITE);
display.fillRect(85, 0, 43, 15, WHITE);
display.drawFastVLine(39,15,49,WHITE);
display.drawFastVLine(40,15,49,WHITE);
display.drawFastVLine(83,15,49,WHITE);
display.drawFastVLine(84,15,49,WHITE);
display.drawFastHLine(0,40,128,WHITE);
display.drawFastHLine(0,41,128,WHITE);
display.display();
}
bool itemBool(int x){
switch(x){
case 2:
return div1Filter;
case 3:
return div2Filter;
case 4:
return div3Filter;
case 7:
return div1PlaySync;
case 8:
return div2PlaySync;
case 9:
return div3PlaySync;
case 17:
return div1BeatSync;
case 18:
return div2BeatSync;
case 19:
return div3BeatSync;
}
}
void drawMenu(){
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
switch(menuPage){
case 0:
display.setCursor(10,10);
display.print("START/STOP");
display.setCursor(10,25);
display.print("PASS THRU");
dispNext(40);
display.setCursor(10,55);
display.print("EXIT");
break;
case 1:
case 6:
case 16:
display.setCursor(10,10);
display.print("CHANNEL 1");
display.setCursor(10,25);
display.print("CHANNEL 2");
display.setCursor(10,40);
display.print("CHANNEL 3");
display.setCursor(10,55);
display.print("BACK");
break;
case 2: case 3: case 4: case 7: case 8: case 9: case 17: case 18: case 19:
display.setCursor(10,10);
if (itemBool(menuPage)==true)
display.print("ON *");
else display.print("ON");
display.setCursor(10,25);
if (itemBool(menuPage)==false)
display.print("OFF *");
else display.print("OFF");
display.setCursor(10,55);
display.print("BACK");
break;
case 5:
display.setCursor(10,10);
display.print("QUANTIZE");
dispNext(40);
display.setCursor(10,55);
display.print("BACK");
break;
case 10:
display.setCursor(10,10);
display.print("ANALOG OUT");
display.setCursor(10,25);
display.print(" CLK DIV");
dispNext(40);
display.setCursor(10,55);
display.print("EXIT");
break;
case 11:
display.setCursor(10,10);
if (eurMode == eur16_8_4)
display.print("16-8-4 *");
else display.print("16-8-4");
display.setCursor(10,25);
if (eurMode == eur16_8_8tr)
display.print("16-8trip-8 *");
else display.print("16-8trip-8");
display.setCursor(10,40);
if (eurMode == eurDivide)
display.print("DIVIDE *");
else display.print("DIVIDE");
display.setCursor(10,55);
display.print("BACK");
break;
case 12:
display.setCursor(10,10);
display.print("ANALOG OUT");
display.setCursor(10,25);
display.print("CLK MODE");
dispNext(40);
display.setCursor(10,55);
display.print("EXIT");
break;
case 13:
display.setCursor(10,10);
display.print("BUTTON");
if (eurOnButton==eurButton)
display.print(" *");
display.setCursor(10,25);
display.print("CONSTANT");
if (eurOnButton==eurConstant)
display.print("*");
display.setCursor(10,55);
display.print("BACK");
break;
case 15:
display.setCursor(10,10);
display.print("BEATSYNC");
dispNext(40);
display.setCursor(10,55);
display.print("BACK");
break;
case 20:
display.setCursor(10,10);
display.print("SAVE");
display.setCursor(10,25);
display.print("SETTINGS?");
display.setCursor(10,40);
display.print("-SAVE");
dispNext(55);
break;
case 21:
display.setCursor(10,10);
display.print("SAVE");
display.setCursor(10,25);
display.print("SETTINGS?");
display.setCursor(10,40);
display.print("-SAVE");
dispNext(55);
break;
default:
break;
}
display.fillRect(1, (2 + (15*menuCursor)), 8, 8, WHITE);
display.display();
}
void dispNext(int x){
display.setCursor(10,x);
display.print("NEXT");
}
void savedMessage()
{
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(10,30);
display.print("Saved");
display.display();
delay(1000);
}
void updateDisplay(){
display.clearDisplay();
display.fillRect(0, 0, 83, 15, WHITE);
display.fillRect(85, 0, 43, 15, WHITE);
display.drawFastVLine(39,15,49,WHITE);
display.drawFastVLine(40,15,49,WHITE);
display.drawFastVLine(83,15,49,WHITE);
display.drawFastVLine(84,15,49,WHITE);
display.drawFastHLine(0,40,128,WHITE);
display.drawFastHLine(0,41,128,WHITE);
display.setTextColor(WHITE);
display.setTextSize(2);
display.fillRect(0,17,37,22, BLACK);
display.setCursor(8,28);
display.print(div1);
if (div1Filter == true) {
display.setTextSize(1);
display.setCursor(32,20);
display.print('S');
}
if (div1PlaySync == true) {
display.setTextSize(1);
display.setCursor(32,28);
display.print('Q');
}
if (div1BeatSync == true) {
display.setTextSize(1);
display.setCursor(32,36);
display.print('B');
}
display.fillRect(42,17,39,22, BLACK);
display.setTextSize(2);
display.setCursor(56,28);
display.print(div2);
if (div2Filter == true) {
display.setTextSize(1);
display.setCursor(76,20);
display.print('S');
}
if (div2PlaySync == true) {
display.setTextSize(1);
display.setCursor(76,28);
display.print('Q');
}
if (div2BeatSync == true) {
display.setTextSize(1);
display.setCursor(76,36);
display.print('B');
}
display.fillRect(86,17,39,22, BLACK);
display.setTextSize(2);
display.setCursor(102,28);
display.print(div3);
if (div3Filter == true) {
display.setTextSize(1);
display.setCursor(122,20);
display.print('S');
}
if (div3PlaySync == true) {
display.setTextSize(1);
display.setCursor(122,28);
display.print('Q');
}
if (div3BeatSync == true) {
display.setTextSize(1);
display.setCursor(122,36);
display.print('B');
}
display.fillRect(0, 0, 83, 15, WHITE);
display.setTextColor(BLACK);
display.setTextSize(1);
display.setCursor(16,8);//4
if (intClock) {
display.print("INTERNAL");
}
else {
display.print("EXTERNAL");
}
if (debugMode==true) {
display.setCursor(0,8);
display.print(debugData);
}
if (channelOnePlayStatus) {
if (millis() < (newChangeOneReceivedMS + newPlayPulse)){
display.fillRect(0, 42, 37, 21, BLACK);
display.fillTriangle(9, 44, 9, 60, 27, 52, WHITE); //play
}
else {
display.fillRect(0, 42, 37, 21, BLACK);;
display.fillTriangle(12, 47, 12, 57, 24, 52, WHITE);
}
}
else {
if (millis() < (newChangeOneReceivedMS + newPlayPulse)){
display.fillRect(0, 42, 37, 21, BLACK); //Stop
display.fillRect(9, 44, 15, 15, WHITE); //stop
}
else {
display.fillRect(0, 42, 37, 21, BLACK); //Stop
display.fillRect(11, 46, 12, 12, WHITE); //stop
}
}
if (channelTwoPlayStatus) {
if (millis() < (newChangeTwoReceivedMS + newPlayPulse)){
display.fillRect(41, 42, 40, 21, BLACK);
display.fillTriangle(54, 44, 54, 60, 72, 52, WHITE); //play
}
else {
display.fillRect(41, 42, 40, 21, BLACK);
display.fillTriangle(56, 47, 56, 57, 69, 52, WHITE);
}
}
else {
if (millis() < (newChangeTwoReceivedMS + newPlayPulse)){
display.fillRect(41, 42, 40, 21, BLACK);
display.fillRect(54, 44, 15, 15, WHITE); //stop
}
else {
display.fillRect(41, 42, 40, 21, BLACK); //Stop
display.fillRect(54, 46, 12, 12, WHITE); //stop
}
}
//CHANNEL THREE
if (channelThreePlayStatus) {
if (millis() < (newChangeThreeReceivedMS + newPlayPulse)){
display.fillRect(85, 42, 40, 21, BLACK);
display.fillTriangle(97, 44, 97, 60, 116, 52, WHITE); //play
}
else {
display.fillRect(85, 42, 40, 21, BLACK);
display.fillTriangle(99, 47, 99, 57, 112, 52, WHITE);
}
}
else {
if (millis() < (newChangeThreeReceivedMS + newPlayPulse)){
display.fillRect(85, 42, 40, 21, BLACK);
display.fillRect(95, 44, 15, 15, WHITE); //stop
}
else {
display.fillRect(85, 42, 40, 21, BLACK); //Stop
display.fillRect(97, 46, 12, 12, WHITE); //stop
}
}
display.fillRect(85, 0, 43, 15, WHITE);
display.setTextColor(BLACK);
display.setCursor(90,10);//85,4
display.setTextSize(2);
display.print(bpm);
display.display();
}
void recvBytesWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
byte startMarker = 0x3C;
byte endMarker = 0x3E;
byte rb;
while (Serial.available() > 0 && newData == false) {
rb = Serial.read();
if (recvInProgress == true) {
if (rb != endMarker) {
receivedBytes[ndx] = rb;
ndx++;
if (ndx >= numBytes) {
ndx = numBytes - 1;
}
}
else {
receivedBytes[ndx] = '\0'; // terminate the string
recvInProgress = false;
numReceived = ndx; // save the number for use when printing
ndx = 0;
newData = true;
}
}
else if (rb == startMarker) {
recvInProgress = true;
}
}
}
void processNewData() {
if (newData == true) {
switch(receivedBytes[0]){
case debugByte:
debugData = int(receivedBytes[1]);
break;
case div1Byte:
div1 = int(receivedBytes[1]);
break;
case div2Byte:
div2 = int(receivedBytes[1]);
break;
case div3Byte:
div3 = int(receivedBytes[1]);
break;
case div1PlayByte:
if ( int(receivedBytes[1]) == 0) {
channelOnePlayStatus = false;
newChangeOneReceivedMS = millis();
}
if ( int(receivedBytes[1]) == 1) {
channelOnePlayStatus = true;
newChangeOneReceivedMS = millis();
}
break;
case div2PlayByte:
if ( int(receivedBytes[1]) == 0) {
channelTwoPlayStatus = false;
newChangeTwoReceivedMS = millis();
}
if ( int(receivedBytes[1]) == 1) {
channelTwoPlayStatus = true;
//newPlayReceived = true;
newChangeTwoReceivedMS = millis();
}
break;
case div3PlayByte:
if ( int(receivedBytes[1]) == 0) {
channelThreePlayStatus = false;
newChangeThreeReceivedMS = millis();
}
if ( int(receivedBytes[1]) == 1) {
channelThreePlayStatus = true;
//newPlayReceived = true;
newChangeThreeReceivedMS = millis();
}
break;
case intExtClockByte:
if ( int(receivedBytes[1]) == 0) intClock = false;
if ( int(receivedBytes[1]) == 1) intClock = true;
break;
case bpmByte:
bpm = int(receivedBytes[1]);
break;
case menuModeByte:
if ( int(receivedBytes[1]) == 0) {
menuMode = false;
debugData = 128;
}
if ( int(receivedBytes[1]) == 1) {
menuCursor = 0;
menuMode = true;
}
break;
case menuCursorByte:
menuCursor = (int (receivedBytes[1]));
break;
case menuPageByte:
menuPage = (int (receivedBytes[1]));
break;
case encoderPushByte:
if (int(receivedBytes[1] == 1)) encoderPush = true;
break;
case div1FilterByte:
if (int(receivedBytes[1] == 0)) div1Filter = false;
if (int(receivedBytes[1] == 1)) div1Filter = true;
break;
case div2FilterByte:
if (int(receivedBytes[1] == 0)) div2Filter = false;
if (int(receivedBytes[1] == 1)) div2Filter = true;
break;
case div3FilterByte:
if (int(receivedBytes[1] == 0)) div3Filter = false;
if (int(receivedBytes[1] == 1)) div3Filter = true;
break;
case div1PlaySyncByte:
if (int(receivedBytes[1] == 0)) div1PlaySync = false;
if (int(receivedBytes[1] == 1)) div1PlaySync = true;
break;
case div2PlaySyncByte:
if (int(receivedBytes[1] == 0)) div2PlaySync = false;
if (int(receivedBytes[1] == 1)) div2PlaySync = true;
break;
case div3PlaySyncByte:
if (int(receivedBytes[1] == 0)) div3PlaySync = false;
if (int(receivedBytes[1] == 1)) div3PlaySync = true;
break;
case div1BeatSyncByte:
if (int(receivedBytes[1] == 0)) div1BeatSync = false;
if (int(receivedBytes[1] == 1)) div1BeatSync = true;
break;
case div2BeatSyncByte:
if (int(receivedBytes[1] == 0)) div2BeatSync = false;
if (int(receivedBytes[1] == 1)) div2BeatSync = true;
break;
case div3BeatSyncByte:
if (int(receivedBytes[1] == 0)) div3BeatSync = false;
if (int(receivedBytes[1] == 1)) div3BeatSync = true;
break;
case settingsSavedByte:
debugData = int(receivedBytes[1]);
savedMessage();
break;
case eurModeByte:
eurMode = int(receivedBytes[1]);
break;
case eurOnButtonByte:
eurOnButton = int(receivedBytes[1]);
break;
}
newData = false;
}
}