switched to from ms based to internal ppqn clock
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
software/.DS_Store
|
||||
.DS_Store
|
||||
@ -1,8 +1,17 @@
|
||||
Features:
|
||||
- 6 output channels
|
||||
- Master BPM
|
||||
- Separate divider per chennel
|
||||
|
||||
TODO:
|
||||
- Add multipliers
|
||||
- Add min and max values
|
||||
- External clock
|
||||
- Switch to U8G2 for screen
|
||||
- Save state to EEPROM when stopped
|
||||
- swing
|
||||
- long-press encoder for settings (input mode, pulse length)
|
||||
- analogue input for modulations
|
||||
|
||||
Timer library available here
|
||||
https://github.com/PaulStoffregen/FlexiTimer2
|
||||
|
||||
@ -7,30 +7,35 @@
|
||||
|
||||
#define SCREEN_ADDRESS 0x3C
|
||||
|
||||
#define PPQN 24 //24 is good for triplets. each pulse is 1/512th note
|
||||
#define PULSE_LENGTH 5
|
||||
|
||||
#define INPUT_CONNECTED_PIN 12
|
||||
#define INPUT_PIN 2
|
||||
#define ENC_BTN_PIN 17
|
||||
#define ENC_D1_PIN 4
|
||||
#define ENC_D2_PIN 3
|
||||
#define START_STOP_BTN_PIN 14
|
||||
//Output pins are defined in the array below
|
||||
|
||||
int outsPins[6] = {5, 6, 7, 8, 9, 10};
|
||||
|
||||
int outsValues[6] = {1, 2, 4, -4, 1, 1}; //positive - divide, negative - multiply, 0 - off
|
||||
|
||||
int outsValues[6] = {1, 2, 4, -4, 0, 0}; //positive - divide, negative - multiply, 0 - off /2 /3 /4 /5 /6 /7 /8 /16 /32 /random x2 x3 x4 x6 x8 x12 x16 x24
|
||||
int outsPeriods[6];
|
||||
int outsClocksCounts[6] = {0, 0, 0, 0, 0, 0};
|
||||
int outsClocksCounts[6];
|
||||
|
||||
bool clockMode;
|
||||
bool clockModeOld;
|
||||
int inputMode; //clock, reset, start/stop
|
||||
int clockCount = 0;
|
||||
|
||||
int bpm = 120;
|
||||
int bpmPeriod;
|
||||
int bpmClockCount;
|
||||
int bpm = 127;
|
||||
int pulseClockCount = 0;
|
||||
int pulseCount = 0;
|
||||
int pulsePeriod;
|
||||
bool isPlaying = 0;
|
||||
int needToResetChannel;
|
||||
bool pulseCounted = false;
|
||||
|
||||
int displayTab = 0;
|
||||
int displayTabOld;
|
||||
@ -71,40 +76,51 @@ void loop() {
|
||||
|
||||
void internalClock() {
|
||||
if (isPlaying) {
|
||||
|
||||
// pulse rules for dividers (multipliers should be in separate for loop, as this one occurs only on pulse 0 (bpm))
|
||||
if (pulseCount == 0 && !pulseCounted) {
|
||||
for (int i = 0; i<6; i++) {
|
||||
if (outsClocksCounts[i] >= outsPeriods[i]) {
|
||||
outsClocksCounts[i] = 0;
|
||||
}
|
||||
if (outsClocksCounts[i] == 0) {
|
||||
if (outsValues[i] > 0) { //Dividers (>0)
|
||||
if (outsClocksCounts[i] == 0) { //Pulse on 0
|
||||
digitalWrite(outsPins[i], HIGH);
|
||||
}
|
||||
if (outsClocksCounts[i] == 15) { //15ms pulse
|
||||
if (outsClocksCounts[i] < (outsValues[i]-1)) {
|
||||
outsClocksCounts[i]++;
|
||||
if (i == 0) {Serial.println(outsClocksCounts[i]);}
|
||||
} else {
|
||||
outsClocksCounts[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
pulseCounted = true;
|
||||
}
|
||||
|
||||
//lets get internal pulse going
|
||||
if (pulseClockCount == 0) {
|
||||
pulseCount++;
|
||||
pulseCounted = false;
|
||||
}
|
||||
if (pulseClockCount < pulsePeriod) {
|
||||
pulseClockCount++;
|
||||
} else {
|
||||
pulseClockCount = 0;
|
||||
}
|
||||
if (pulseCount >= PPQN) {
|
||||
pulseCount = 0;
|
||||
}
|
||||
|
||||
// pull low all outputs after set pulse length
|
||||
if (pulseClockCount >= PULSE_LENGTH) {
|
||||
for (int i = 0; i<6; i++) {
|
||||
digitalWrite(outsPins[i], LOW);
|
||||
}
|
||||
outsClocksCounts[i]++;
|
||||
}
|
||||
if (bpmClockCount < bpmPeriod) {
|
||||
bpmClockCount++;
|
||||
} else {
|
||||
bpmClockCount = 0;
|
||||
if (needToResetChannel>=0) {
|
||||
outsClocksCounts[needToResetChannel] = 0;
|
||||
updatePeriods();
|
||||
needToResetChannel = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void updatePeriods() {
|
||||
bpmPeriod = 60000 / bpm;
|
||||
for (int i = 0; i<6; i++) {
|
||||
if (outsValues[i]>0) {
|
||||
outsPeriods[i] = bpmPeriod * outsValues[i];
|
||||
} else {
|
||||
outsPeriods[i] = bpmPeriod / outsValues[i] * - 1;
|
||||
}
|
||||
}
|
||||
pulsePeriod = 60000 / (bpm * PPQN);
|
||||
}
|
||||
|
||||
void resetClocks() {
|
||||
@ -114,16 +130,18 @@ void resetClocks() {
|
||||
}
|
||||
|
||||
void checkInputs() {
|
||||
|
||||
//input jack switcch
|
||||
clockMode = digitalRead(INPUT_CONNECTED_PIN);
|
||||
if (clockMode != clockModeOld) {
|
||||
updateScreen();
|
||||
clockModeOld = clockMode;
|
||||
}
|
||||
|
||||
//encoder button
|
||||
if (needToChangeTab == 0 && digitalRead(ENC_BTN_PIN) == 0) {
|
||||
needToChangeTab = 1;
|
||||
}
|
||||
|
||||
if (needToChangeTab == 1 && digitalRead(ENC_BTN_PIN) == 1) {
|
||||
} else if (needToChangeTab == 1 && digitalRead(ENC_BTN_PIN) == 1) {
|
||||
displayTabOld = displayTab;
|
||||
displayTab++;
|
||||
if (displayTab>6) {
|
||||
@ -133,6 +151,7 @@ void checkInputs() {
|
||||
updateScreen();
|
||||
}
|
||||
|
||||
//encoder
|
||||
encoder.tick();
|
||||
int encPosition = encoder.getPosition();
|
||||
if (encPositionOld != encPosition) {
|
||||
@ -147,6 +166,7 @@ void checkInputs() {
|
||||
encPositionOld = encPosition;
|
||||
}
|
||||
|
||||
//play button
|
||||
if (!digitalRead(START_STOP_BTN_PIN) && !buttonPushed) {
|
||||
isPlaying = !isPlaying;
|
||||
resetClocks();
|
||||
@ -163,7 +183,7 @@ void updateScreen() {
|
||||
display.setCursor(0,0);
|
||||
display.setTextSize(1);
|
||||
if (displayTab == 0) {
|
||||
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);resetClocks();
|
||||
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
|
||||
display.print(F(" "));
|
||||
display.setTextColor(SSD1306_WHITE);
|
||||
display.print(F(" bpm "));
|
||||
@ -186,27 +206,27 @@ void updateScreen() {
|
||||
display.print(i);
|
||||
}
|
||||
}
|
||||
|
||||
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
|
||||
display.println(F(" "));
|
||||
|
||||
display.println();
|
||||
|
||||
//Content
|
||||
display.setTextSize(3);
|
||||
display.setTextColor(SSD1306_WHITE);
|
||||
|
||||
if (displayTab == 0) {
|
||||
display.print(bpm);
|
||||
display.println(F("bpm"));
|
||||
} else {
|
||||
if (outsValues[displayTab-1]>0) {
|
||||
if (outsValues[displayTab-1]==0) {
|
||||
display.print(F("OFF"));
|
||||
} else if (outsValues[displayTab-1]>0) {
|
||||
display.print(F("/"));
|
||||
display.print(abs(outsValues[displayTab-1]));
|
||||
} else {
|
||||
display.print(F("x"));
|
||||
}
|
||||
display.print(abs(outsValues[displayTab-1]));
|
||||
}
|
||||
}
|
||||
|
||||
display.display();
|
||||
}
|
||||
Reference in New Issue
Block a user