I'm working on an LCD sequencer for the Bleep Labs drum machine, and I've got it working about 95%. The remaining 5% is that, every so often, the program seems to lag out for just a second. There is a momentary pause that would probably normally be irrelevant but, considering it's a drum machine, is very noticeable. Oddly enough, this lag-out only happens when the tempo is set to 114 or above. The way I've done debounce and things like that is a little bit janky I'm sure, and I assume that might have something to do with it.
Here's the code. If you see any glaring issue that would cause this to get ahead of itself or something like that, please let me know as I really want this functioning at 100%. FYI, the pads will trigger on a low pulse, and the pulse clock ensures that each pulse is long enough for the drum machine to see.
#include <SPI.h>
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);
int butClk= 0; //debounce buttons
int trigClk = 0; //debounce pad triggers
int pulClk = 0; //send pulses
boolean butStr = false;
boolean triStr = false;
boolean pulStr = false;
long t = 110; //t
long tLast = 110; //last recorded ts
long tMil; //space in millis between beat triggers
const int y = 12; //kick
const int b = 3; //tom
const int g = 2; //clap
const int r = 11; //snareq
int seqLoc = 0; //playb location in seq
int seqSel = 0; //selection location
int padSel = 0; //selected pad
int tempSel = 0; //selected t digit
boolean tEdit = false; //editing t
int seqR[32] = {
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};
int seqB[32] = {
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};
int seqG[32] = {
0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0};
int seqY[32] = {
1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0};
String fr, fb, fg, fy, br, bb, bg, by; //display seqs
void setup() {
Serial.begin(9600);
tMil = newtMil(t);
pinMode(y, OUTPUT);
pinMode(b, OUTPUT);
pinMode(r, OUTPUT);
pinMode(g, OUTPUT);
digitalWrite(y, HIGH);
digitalWrite(b, HIGH);
digitalWrite(r, HIGH);
digitalWrite(g, HIGH);
lcd.begin(16, 2);
lcd.print("BPM:110");
lcd.setCursor(0,1);
genSeqStrings();
lcd.print(fr);
lcd.setCursor(9,0);
lcd.print("S:");
lcd.setCursor(12, 0);
lcd.print("1-16");
lcd.setCursor(0,1);
lcd.cursor();
}
void loop() {
//t changes
if (t != tLast) {
tLast = t;
tMil = newtMil(t);
}
if (analogRead(0) < 800 && !butStr) {
butStr = true;
buttonRead();
}
if (butStr && butClk < 1000) {
butClk += 1;
}
else {
butClk = 0;
butStr = false;
}
//trigger control
if (millis() % tMil == 0 && !triStr) {
playNext();
triStr = true;
}
else if (triStr && trigClk < 10) {
trigClk += 1;
}
else {
triStr = false;
trigClk = 0;
}
//pulse control
if (pulStr) {
if (pulClk >= 10) {
digitalWrite(r, HIGH);
digitalWrite(b, HIGH);
digitalWrite(g, HIGH);
digitalWrite(y, HIGH);
pulClk = 0;
pulStr = false;
}
else {
pulClk += 1;
}
}
}
void buttonRead() {
int x = analogRead(0);
if (x < 100) { //RIGHT
if (!tEdit) {
if (seqSel >= 31) {
tEdit = true;
tempSel = 2;
}
else {
seqSel += 1;
}
}
else {
if (tempSel >= 2) {
tEdit = false;
seqSel = 31;
}
else {
tempSel += 1;
}
}
}
else if (x < 200){ //UP
if (!tEdit) {
if (padSel >= 3) {
padSel = 0;
}
else {
padSel += 1;
}
}
else {
switch(tempSel) {
case 0:
t += 100;
break;
case 1:
t += 10;
break;
case 2:
t += 1;
break;
}
if (t > 480) {
t = 480;
}
}
}
else if (x < 400){ //DOWN
if (!tEdit) {
if (padSel <= 0) {
padSel = 3;
}
else {
padSel -= 1;
}
}
else {
switch(tempSel) {
case 0:
t -= 100;
break;
case 1:
t -= 10;
break;
case 2:
t -= 1;
break;
}
if (t < 30) {
t = 30;
}
}
}
else if (x < 600){ //LEFT
if (!tEdit) {
if (seqSel <= 0) {
tEdit = true;
tempSel = 0;
}
else {
seqSel -= 1;
}
}
else {
if (tempSel <= 0) {
tEdit = false;
seqSel = 0;
}
else {
tempSel -= 1;
}
}
}
else if (x < 800){ //SELECT
if (!tEdit) {
if (padSel == 0) {
if (seqR[seqSel] == 0) {
seqR[seqSel] = 1;
}
else {
seqR[seqSel] = 0;
}
}
else if (padSel == 1) {
if (seqB[seqSel] == 0) {
seqB[seqSel] = 1;
}
else {
seqB[seqSel] = 0;
}
}
else if (padSel == 2) {
if (seqG[seqSel] == 0) {
seqG[seqSel] = 1;
}
else {
seqG[seqSel] = 0;
}
}
else if (padSel == 3) {
if (seqY[seqSel] == 0) {
seqY[seqSel] = 1;
}
else {
seqY[seqSel] = 0;
}
}
}
}
updateDisplay();
}
void genSeqStrings() {
fr = "";
fb = "";
fg = "";
fy = "";
br = "";
bb = "";
bg = "";
by = "";
for (int i = 0; i<16; i++) {
fr += seqR[i];
br += seqR[i+16];
fb += seqB[i];
bb += seqB[i+16];
fg += seqG[i];
bg += seqG[i+16];
fy += seqY[i];
by += seqY[i+16];
}
}
void updateDisplay() {
lcd.clear();
lcd.print("BPM:");
if (t >= 100) {
lcd.print(t);
}
else {
lcd.print(" ");
lcd.print(t);
}
lcd.setCursor(9,0);
switch(padSel) {
case 0:
lcd.print("S:");
break;
case 1:
lcd.print("T:");
break;
case 2:
lcd.print("C:");
break;
case 3:
lcd.print("K:");
break;
}
lcd.setCursor(0,1);
genSeqStrings();
switch(padSel) {
case 0:
if (seqSel <= 15) {
lcd.print(fr);
}
else {
lcd.print(br);
}
break;
case 1:
if (seqSel <= 15) {
lcd.print(fb);
}
else {
lcd.print(bb);
}
break;
case 2:
if (seqSel <= 15) {
lcd.print(fg);
}
else {
lcd.print(bg);
}
break;
case 3:
if (seqSel <= 15) {
lcd.print(fy);
}
else {
lcd.print(by);
}
break;
}
if (seqSel > 15) {
lcd.setCursor(11, 0);
lcd.print("17-32");
}
else {
lcd.setCursor(12, 0);
lcd.print("1-16");
}
if (!tEdit) {
if (seqSel > 15) {
lcd.setCursor(seqSel - 16, 1);
}
else {
lcd.setCursor(seqSel, 1);
}
}
else {
lcd.setCursor(tempSel + 4, 0);
}
lcd.cursor();
}
void playNext() {
if (seqR[seqLoc] == 1) {
digitalWrite(r, LOW);
}
if (seqB[seqLoc] == 1) {
digitalWrite(b, LOW);
}
if (seqG[seqLoc] == 1) {
digitalWrite(g, LOW);
}
if (seqY[seqLoc] == 1) {
digitalWrite(y, LOW);
}
if (seqLoc >= 31) {
seqLoc = 0;
}
else {
seqLoc += 1;
}
pulStr = true;
}
long newtMil(int t) {
float s1 = 60.0/t;
float s2 = s1/4.0;
float s3 = s2 * 1000.0;
long final = long(s3);
return final;
}