Almost done with the menu

This commit is contained in:
2023-07-29 10:55:39 +03:00
parent b4f89a838d
commit 1b9611f374
4 changed files with 212 additions and 276 deletions

View File

@ -20,33 +20,28 @@
#define ENC_D1_PIN 17
#define ENC_D2_PIN 4
#define START_STOP_BTN_PIN 5
#define EXT_INPUT_PIN 2 //needs to be an interrupt pin
#define ANALOGUE_INPUT_1_PIN A2
#define ANALOGUE_INPUT_2_PIN A1
const int outsPins[6] = {6, 11, 7, 10, 8, 9};
*/
///* Rev 2 Config
// Rev 2 and 3 Config
#define ENC_BTN_PIN 14
#define ENC_D1_PIN 17
#define ENC_D2_PIN 4
#define START_STOP_BTN_PIN 5
#define SHIFT_BTN_PIN 12
#define EXT_INPUT_PIN 2 //needs to be an interrupt pin
#define ANALOGUE_INPUT_1_PIN A7
#define ANALOGUE_INPUT_2_PIN A6
const int outsPins[6] = { 7, 8, 10, 6, 9, 11 };
//*/
const byte outsPins[6] = { 7, 8, 10, 6, 9, 11 };
const int subDivs[17] = { -24, -12, -8, -6, -4, -3, -2, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32 }; //positive - divide, negative - multiply, 0 - off
unsigned int bpm = 130;
bool bpmModulationChannel; //0 - CV1, 1 - CV2
byte bpm = 130;
byte bpmModulationChannel = 200; //0 - CV1, 1 - CV2, 255 - OFF
byte bpmModulationRange = 0;
struct channel {
@ -62,14 +57,27 @@ struct channel {
};
channel channels[6] = { //array of channel settings
{ 0, 7, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 1, 0, 0, 0, 0, 0 },
{ 0, 7, 2, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 3, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0 }
{ 2, 10, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 1, 0, 0, 0 }
};
bool sequences[8][16] {
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0}
};
byte seqStepCount[8] = {0,0,0,0,0,0,0,0};
byte memCode = 'A'; //Change to different letter if you changed the data structure
int channelPulseCount[6];
@ -112,23 +120,30 @@ Adafruit_SSD1306 display(128, 64, &Wire, -1);
RotaryEncoder encoder(ENC_D1_PIN, ENC_D2_PIN, RotaryEncoder::LatchMode::TWO03);
const unsigned char splash_logo[] PROGMEM = {
0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x03,
0xfc, 0x1f, 0xe0, 0x00, 0x07, 0xe0, 0x03, 0xf0, 0x00, 0x0f, 0x80, 0x00, 0xf8, 0x00, 0x1f, 0x00,
0x00, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x3c, 0x00, 0x00,
0x1e, 0x00, 0x78, 0x0c, 0x18, 0x0f, 0x00, 0x78, 0x1e, 0x3c, 0x0f, 0x00, 0x70, 0x1e, 0x3c, 0x07,
0x00, 0xf0, 0x1e, 0x3c, 0x07, 0x80, 0xf0, 0x1e, 0x3c, 0x07, 0x80, 0xf0, 0x1e, 0x3c, 0x07, 0x80,
0xf0, 0x1e, 0x3c, 0x07, 0x80, 0xf0, 0x0c, 0x18, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x0c, 0x18, 0x10, 0x00, 0x0f, 0x1e, 0x3c, 0x78, 0x00, 0x0f, 0x1e,
0x3c, 0x78, 0x00, 0x1e, 0x0c, 0x18, 0x3c, 0x00, 0x1e, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x00,
0x1e, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x78, 0x00, 0x00, 0x0f, 0x00, 0x78, 0x00, 0x00, 0x0f,
0x00, 0xf0, 0x00, 0x00, 0x07, 0x80, 0xf0, 0x00, 0x00, 0x07, 0x80, 0xf0, 0x00, 0x00, 0x07, 0x80,
0x78, 0x00, 0x00, 0x0f, 0x00, 0x7c, 0x00, 0x00, 0x1f, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x3f,
0xff, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xf0, 0x00, 0x01, 0xff,
0xff, 0xc0, 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0xf8, 0x03, 0xff, 0xc0, 0x03, 0xf8, 0x1f, 0x00, 0x7c, 0x7c, 0x3f, 0xff, 0xc7, 0xc0, 0x3e,
0x0f, 0xfe, 0x03, 0xff, 0xe0, 0x07, 0xf8, 0x0f, 0x00, 0x78, 0x7c, 0x3f, 0xff, 0xc3, 0xe0, 0x7c,
0x1f, 0xff, 0x03, 0xff, 0xf0, 0x07, 0xf8, 0x0f, 0x80, 0xf8, 0x7c, 0x3f, 0xff, 0xc3, 0xe0, 0x78,
0x3f, 0xff, 0x03, 0xff, 0xf8, 0x07, 0xfc, 0x0f, 0x80, 0xf8, 0x7c, 0x3f, 0xff, 0xc1, 0xf0, 0xf8,
0x7e, 0x0f, 0x83, 0xe0, 0xf8, 0x0f, 0x3c, 0x07, 0x80, 0xf0, 0x7c, 0x00, 0xf8, 0x00, 0xf8, 0xf0,
0x7c, 0x07, 0x83, 0xe0, 0x78, 0x0f, 0x3c, 0x07, 0xc0, 0xf0, 0x7c, 0x00, 0xf0, 0x00, 0xf9, 0xf0,
0x7c, 0x00, 0x03, 0xe0, 0xf8, 0x0f, 0x3e, 0x07, 0xc1, 0xf0, 0x7c, 0x00, 0xf0, 0x00, 0x7d, 0xe0,
0x78, 0x00, 0x03, 0xe0, 0xf8, 0x1e, 0x1e, 0x03, 0xc1, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x7f, 0xc0,
0x78, 0x3f, 0xc3, 0xff, 0xf0, 0x1e, 0x1e, 0x03, 0xe1, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x3f, 0xc0,
0x78, 0x3f, 0xc3, 0xff, 0xe0, 0x1e, 0x1f, 0x01, 0xe3, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x1f, 0x80,
0x78, 0x3f, 0xc3, 0xff, 0xc0, 0x3e, 0x1f, 0x01, 0xe3, 0xc0, 0x7c, 0x00, 0xf0, 0x00, 0x1f, 0x80,
0x7c, 0x3f, 0xc3, 0xe7, 0xc0, 0x3f, 0xff, 0x01, 0xf3, 0xc0, 0x7c, 0x00, 0xf0, 0x00, 0x0f, 0x00,
0x7e, 0x07, 0xc3, 0xe3, 0xe0, 0x3f, 0xff, 0x80, 0xf7, 0xc0, 0x7c, 0x00, 0xf0, 0x00, 0x0f, 0x00,
0x3f, 0x1f, 0xc3, 0xe1, 0xe0, 0x7f, 0xff, 0x80, 0xff, 0x80, 0x7c, 0x00, 0xf0, 0x00, 0x0f, 0x00,
0x1f, 0xff, 0xc3, 0xe1, 0xf0, 0x78, 0x07, 0x80, 0xff, 0x80, 0x7c, 0x00, 0xf0, 0x00, 0x0f, 0x00,
0x0f, 0xff, 0xc3, 0xe0, 0xf8, 0xf8, 0x07, 0xc0, 0x7f, 0x00, 0x7c, 0x00, 0xf0, 0x00, 0x0f, 0x00,
0x07, 0xf3, 0xc3, 0xe0, 0xf8, 0xf8, 0x07, 0xc0, 0x7f, 0x00, 0x7c, 0x00, 0xf0, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup() {
//Serial.begin(9600);
Serial.begin(9600);
//check last bit in eeprom to know if the correct settings were stored
if (EEPROM.read(1023) == memCode) {
@ -153,7 +168,7 @@ void setup() {
pinMode(EXT_INPUT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(EXT_INPUT_PIN), externalClock, FALLING);
for (int i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
pinMode(outsPins[i], OUTPUT);
}
@ -162,7 +177,7 @@ void setup() {
display.clearDisplay();
//Splash screen
display.drawBitmap(48, 0, splash_logo, 33, 39, 1);
display.drawBitmap(0, 16, splash_logo, 128, 19, 1);
display.setCursor(0, 56);
display.setTextSize(1);
@ -185,10 +200,9 @@ void loop() {
/*if ((millis() - lastInteractionTime) > SCREEN_TIMEOUT) {
display.clearDisplay();
display.display();
}*/
if (masterClockMode == 2 || masterClockMode == 3) {
calculateBPMTiming();
}
}}*/
}
void clock() {
@ -216,26 +230,9 @@ void clock() {
}
}
//EXT-B
if (masterClockMode == 2) {
if (tickCount >= pulsePeriod && pulseCount < (PPQN - 1)) {
tickCount = 0;
pulseCount++;
}
}
//EXT-16
if (masterClockMode == 3) {
if (tickCount >= pulsePeriod && pulseCount < (PPQN - 1)) { // ((6 * (extTriggerCount + 1)) - 1)) { //this formula puts it out of sync, so there's PPQN-1 for now
tickCount = 0;
pulseCount++;
}
}
// pull low all outputs after set pulse length
if (tickCount >= PULSE_LENGTH) {
for (int i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
digitalWrite(outsPins[i], LOW);
}
}
@ -249,7 +246,7 @@ void externalClock() {
if (masterClockMode == 1) { // EXT-24
//reset cycles if there was no pulses for a while
if ((newExtPulseTime - lastExtPulseTime) > 125) { //125ms is 20bpm
for (int i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
channelPulseCount[i] = 0;
}
}
@ -264,56 +261,13 @@ void externalClock() {
pulseCount = 0;
}
} else if (masterClockMode == 2) { // EXT-Beat
if (!isPlaying) {
isPlaying = true;
}
if ((newExtPulseTime - lastExtPulseTime) > 3000) { //3000ms is 1/4 at 20bpm
resetClocks();
extResetCountdown = 0;
}
tickCount = 0;
pulseCount = 0;
if (extResetCountdown < 1) { //reset on the second pulse, so that BPM is already calculated correctly
extResetCountdown++;
} else if (extResetCountdown == 1) {
resetClocks();
extResetCountdown++; //to get out of the loop
}
} else if (masterClockMode == 3) { // EXT-16
if (!isPlaying) {
isPlaying = true;
}
if ((newExtPulseTime - lastExtPulseTime) > 750) {
resetClocks();
extResetCountdown = 0;
extTriggerCount = 0;
}
if (extTriggerCount == 0) { //happens on beat
pulseCount = 0;
tickCount = 0;
}
if (extTriggerCount < 3) {
extTriggerCount++;
} else {
extTriggerCount = 0;
}
if (extResetCountdown < 4) { //reset on the second beat (5th pulse), so that BPM is already calculated correctly
extResetCountdown++;
} else if (extResetCountdown == 4) {
resetClocks();
extResetCountdown++; //to get out of the loop
}
}
}
void sendTriggers() {
for (int i = 0; i < 6; i++) {
if (playingModes[i] != subDivs[channels[i].mode]) {
for (byte i = 0; i < 6; i++) {
if (playingModes[i] != subDivs[channels[i].subDiv]) {
needPulseReset[i] = true;
}
}
@ -321,7 +275,7 @@ void sendTriggers() {
//switching modes on the beat and resetting channel clock
if (pulseCount == 0) {
calculateCycles();
for (int i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
if (needPulseReset[i] == true) {
channelPulseCount[i] = 0;
needPulseReset[i] = false;
@ -330,11 +284,13 @@ void sendTriggers() {
}
//multiplier
for (int i = 0; i < 6; i++) {
if (channelPulseCount[i] == channels[i].offset) { //Pulse on 0
if (channels[i].random == 0 || random(10) > channels[i].random) { //random
for (byte i = 0; i < 6; i++) {
int currentSeq = channels[i].seqPattern;
if ((channels[i].mode == 0 && channelPulseCount[i] == channels[i].offset) || //CLK with offset
(channels[i].mode == 1 && channelPulseCount[i] == 0 && random(10) > channels[i].random) //|| //RND
//(channels[i].mode == 2 && channelPulseCount[i] == 0 && sequences[currentSeq][0]) //SEQ (for some reason doesn't lke variables inside the index)
) {
digitalWrite(outsPins[i], HIGH);
}
}
if (channelPulseCount[i] < channelPulsesPerCycle[i]) {
channelPulseCount[i]++;
@ -346,19 +302,19 @@ void sendTriggers() {
void calculateCycles() {
for (int i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
if (channels[i].CV1Target != 1 && channels[i].CV2Target != 1) {
playingModes[i] = subDivs[channels[i].mode];
playingModes[i] = subDivs[channels[i].subDiv];
} else if (channels[i].CV1Target == 1) { //modulation happens here
int mod;
mod = a1Input;
mod = map(mod, 0, 1023, 0, channels[i].CV1Value);
playingModes[i] = subDivs[channels[i].mode - mod]; //subtracting because the innitial array is backwards
mod = map(mod, 0, 1023, (channels[i].CV1Value * -1), channels[i].CV1Value);
playingModes[i] = subDivs[channels[i].subDiv - mod]; //subtracting because the innitial array is backwards
} else if (channels[i].CV2Target == 1) { //modulation happens here
int mod;
mod = a1Input;
mod = map(mod, 0, 1023, 0, channels[i].CV2Value);
playingModes[i] = subDivs[channels[i].mode - mod]; //subtracting because the innitial array is backwards
mod = a2Input;
mod = map(mod, 0, 1023, (channels[i].CV2Value * -1), channels[i].CV2Value);
playingModes[i] = subDivs[channels[i].subDiv - mod]; //subtracting because the innitial array is backwards
}
if (playingModes[i] > 0) {
@ -366,16 +322,19 @@ void calculateCycles() {
} else {
channelPulsesPerCycle[i] = (PPQN / abs(playingModes[i])) - 1;
}
if (channels[i].offset > channelPulsesPerCycle[i]) {
channels[i].offset = channelPulsesPerCycle[i];
}
}
}
void calculateBPMTiming() {
int mod = 0;
if (masterClockMode == 0) { //Internal clock
if (bpmModulationRange != 0 && !bpmModulationChannel) {
mod = map(a1Input, 0, 1023, 0, bpmModulationRange * 10);
} else if (bpmModulationRange != 0 && bpmModulationChannel) {
mod = map(a2Input, 0, 1023, 0, bpmModulationRange * 10);
if (bpmModulationRange != 0 && bpmModulationChannel == 0) {
mod = map(a1Input, 0, 1023, bpmModulationRange * -10, bpmModulationRange * 10);
} else if (bpmModulationRange != 0 && bpmModulationChannel == 1) {
mod = map(a2Input, 0, 1023, bpmModulationRange * -10, bpmModulationRange * 10);
}
pulsePeriod = 60000 / ((bpm + mod) * PPQN);
@ -388,7 +347,7 @@ void calculateBPMTiming() {
}
void resetClocks() {
for (int i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
channelPulseCount[i] = 0;
digitalWrite(outsPins[i], LOW); //to avoid stuck leds
}