3 Commits

11 changed files with 4919 additions and 549 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,21 @@
/*
Fontname: Velvet Screen
Copyright: Created with Fony 1.4.7
Glyphs: 52/256
BBX Build Mode: 0
*/
const uint8_t velvetscreen[437] U8G2_FONT_SECTION("velvetscreen") =
"\64\0\2\2\3\3\2\3\4\5\5\0\0\5\0\5\0\0\221\0\0\1\230 \4\200\134%\11\255tT"
"R\271RI(\6\252\334T\31)\7\252\134bJ\12+\7\233\345\322J\0,\5\221T\4-\5\213"
"f\6.\5\211T\2/\6\244\354c\33\60\10\254\354T\64\223\2\61\7\353\354\222\254\6\62\11\254l"
"\66J*\217\0\63\11\254l\66J\32\215\4\64\10\254l\242\34\272\0\65\11\254l\206\336h$\0\66"
"\11\254\354T^\61)\0\67\10\254lF\216u\4\70\11\254\354TL*&\5\71\11\254\354TL;"
")\0:\6\231UR\0A\10\254\354T\34S\6B\11\254lV\34)\216\4C\11\254\354T\324\61"
")\0D\10\254lV\64G\2E\10\254l\206\36z\4F\10\254l\206^\71\3G\11\254\354TN"
"\63)\0H\10\254l\242\34S\6I\6\251T\206\0J\10\254\354k\231\24\0K\11\254l\242J\62"
"\225\1L\7\254lr{\4M\11\255t\362ZI\353\0N\11\255t\362TI\356\0O\10\254\354T"
"\64\223\2P\11\254lV\34)g\0Q\10\254\354T\264b\12R\10\254lV\34\251\31S\11\254\354"
"FF\32\215\4T\7\253dVl\1U\10\254l\242\63)\0V\11\255t\262Ne\312\21W\12\255"
"t\262J*\251.\0X\11\254l\242L*\312\0Y\12\255tr\252\63\312(\2Z\7\253df*"
"\7p\10\255\364V\266\323\2q\7\255\364\216\257\5r\10\253d\242\32*\2t\6\255t\376#w\11"
"\255\364V\245FN\13x\6\233dR\7\0\0\0\4\377\377\0";

BIN
Extra/Fonts/theory.fon Normal file

Binary file not shown.

View File

@ -1,152 +1,194 @@
#include <Wire.h>
#include <RotaryEncoder.h>
#include <FlexiTimer2.h>
#include <EEPROM.h>
#include <U8g2lib.h>
#include <avr/wdt.h>
#include <NeoHWSerial.h>
#include "config.h"
#include "fonts.h"
#define VERSION "V:1.1.2"
#define VERSION "V:1.2A2"
byte memCode = 'D'; //Change to different letter if you changed the data structure
#define PPQN 24
#define PULSE_LENGTH 120 //1/10ms resolution. 12ms was failing at 1ms resolution at higher bpm. 60000/200/24 = 12.5 the max pulse length at 1ms resolution for 200bpm is 11ms
#define MAXBPM 200 //250 at 24ppqn with 5ms pulse will be 50/50 square wave
#define MINBPM 20
#define SCREEN_ADDRESS 0x3C
// Rev 2+ 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 byte outsPins[6] = { 7, 8, 10, 6, 9, 11 };
const byte clockOutPin = 3;
bool rotateScreen = false;
bool reverseEnc = false;
//
/* Rev 1 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 100
#define EXT_INPUT_PIN 2 //needs to be an interrupt pin
#define ANALOGUE_INPUT_1_PIN A2
#define ANALOGUE_INPUT_2_PIN A1
const byte clockOutPin = 13;
const byte outsPins[6] = {6, 11, 7, 10, 8, 9};
bool rotateScreen = true;
*/
uint8_t memCode = '0'; //Change to different letter if you changed the data structure
uint16_t CV1Calibration = 512;
uint16_t CV2Calibration = 512;
bool showDone = false;
const int subDivs[] = { -24, -12, -8, -6, -4, -3, -2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 24, 32, 64, 128 }; //positive - divide, negative - multiply, 0 - off
const int subDivs[20] = { -24, -12, -8, -6, -4, -3, -2, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 64, 128 }; //positive - divide, negative - multiply, 0 - off
uint8_t bpm = 130;
uint8_t bpmModulationChannel = 200; //0 - CV1, 1 - CV2, 255 - OFF
uint8_t bpmModulationRange = 0;
enum modes {Clock, Random, Sequencer, Swing, Gate};
byte bpm = 130;
byte bpmModulationChannel = 200; //0 - CV1, 1 - CV2, 255 - OFF
byte bpmModulationRange = 0;
struct channel {
enum modes mode : 3; //mv: 7. 0 - CLK, 1 - RND, 2 - SEQ, 3 - SWING, 4 - Gate
uint8_t subDiv : 5; //mv: 31
uint8_t random : 4; //mv: 15
uint8_t seqPattern : 5;
uint8_t CV1Target : 3; //0 - Off, 1 - Subdiv, 2 - RND, 3 - SeqPattern
uint8_t CV2Target : 3;
uint8_t swing : 3;
uint8_t offset : 7; //mv: 127
uint8_t gate : 7;
bool isMute : 1;
byte mode; //0 - CLK, 1 - RND, 2 - SEQ
byte subDiv;
byte CV1Target; //0 - Off, 1 - Subdiv, 2 - RND, 3 - SeqPattern
byte CV1Range;
byte CV2Target;
byte CV2Range;
uint8_t offset;
byte random;
byte seqPattern;
};
channel channels[7] = { //array of channel settings
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 1, 0 }
channel channels[6] = { //array of channel settings
{ 0, 7, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 7, 0, 0, 0, 0, 0, 0, 0 }
};
struct sequence {
uint32_t sequence;
uint8_t length : 5 ; //don't forget to add 1 where needed, values 0 - 31
};
bool seqA1[16] = {1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1};
bool seqA2[16] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0};
bool seqA3[16] = {1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0};
bool seqA4[16] = {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1};
bool seqA5[16] = {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1};
bool seqA6[16] = {0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0};
bool seqA7[16] = {1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0};
bool seqA8[16] = {1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1};
bool seqB1[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB2[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB3[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB4[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB5[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB6[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB7[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool seqB8[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte currentStep = 0;
byte stepNumSelected = 0;
bool *patternToEdit;
sequence sequences[] {
{0b000000000000000001001000100010001, 15},
{0b000000000000000000000100000010000, 11},
{0b000000000000000000001001001001001, 6},
{0b000000000000000001100110011001100, 20},
{0b000000000000000001110111011101110, 30},
{0b000000000000000000101010001010100, 31},
{0b000000000000000000111111111011111, 15},
{0b000000000000000001101101110110011, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15},
{0b000000000000000000000000000000000, 15}
};
unsigned int channelPulseCount[6];
unsigned int channelPulsesPerCycle[6];
byte sixteenthPulseCount = 0;
int playingModes[6]; // should be renamed to currentSubdivs or something. Updated from channels object on beat and with applied CV modulation
int playingModesOld[6];
uint8_t currentStep[7] = {0};
int8_t stepNumSelected = 0;
uint8_t patternToEdit;
unsigned int channelPulseCount[7];
unsigned int channelPulsesPerCycle[7];
uint8_t sixteenthPulseCount = 0;
int playingModes[7]; // should be renamed to currentSubdivs or something. Updated from channels object on beat and with applied CV modulation
int playingModesOld[7];
uint16_t pulsePeriod;
bool isPlaying;// = false; // replace with some flags like uint8_t status where 1xxxxxx isPlaying, x1xxxxx isRecording etc
unsigned int pulsePeriod;
bool isPlaying;// = false;
bool isRecording = false;
bool recordToNextStep = false;
bool MIDIClockReceived = false;
uint16_t tickCount = 0;
uint16_t pulseCount = 0;
unsigned int tickCount = 0;
unsigned int pulseCount = 0;
uint8_t masterClockMode = 0; // 0 - internal, 1 - external 24ppqn, 2 - MIDI
uint8_t extClockPPQN = 0; // 0 - 24, 1 - 4 (1/16)
uint8_t extraChannel = 0; // 0 - off, 1 - pulse out = 7th channel
uint32_t lastExtPulseTime = 0;
uint32_t newExtPulseTime = 0;
byte masterClockMode = 0; // 0 - internal, 1 - external 24ppqn, 2 - MIDI
byte extClockPPQN = 0; // 0 - 24, 1 - 4 (1/16)
unsigned long lastExtPulseTime = 0;
unsigned long newExtPulseTime = 0;
bool needPulseReset[] = { true, true, true, true, true, true, true }; //to optimise, can be switched to uint8_t
uint16_t gateLengthTime[] = {0, 0, 0, 0, 0, 0, 0};
uint16_t gateCountDown[7];
bool stepIsOdd = 1;
bool needPulseReset[6] = { true, true, true, true, true, true };
uint8_t displayTab = 0;
byte displayTab = 0;
bool insideTab = false;
uint8_t menuItem = 0;
byte menuItem = 0;
bool menuItemSelected = false;
uint8_t lastMenuItem = 3;
uint8_t displayScreen = 0; //0 - main, 1 - sequencer, 2 - settings
int16_t CV1Input = 0;
int16_t CV2Input = 0;
byte lastMenuItem = 3;
byte displayScreen = 0; //0 - main, 1 - sequencer, 2 - settings
bool playBtnPushed = false;
bool shiftBtnPushed = false;
bool encBtnPushed;
int CV1Input = 0;
int CV2Input = 0;
int encPositionOld = 0;
uint8_t encDirectionOld = 0;
uint32_t encPressedTime;
uint32_t encReleasedTime;
uint32_t playPressedTime;
uint32_t playReleasedTime;
uint32_t shiftPressedTime;
uint32_t shiftReleasedTime;
int encDirectionOld = 0;
unsigned long encPressedTime;
unsigned long encReleasedTime;
unsigned long playPressedTime;
unsigned long playReleasedTime;
unsigned long shiftPressedTime;
unsigned long shiftReleasedTime;
bool encBtnPushed;
int extResetCountdown;
int extTriggerCount;
//uint32_t lastInteractionTime; // used for display timeout
//unsigned long lastInteractionTime; // used for display timeout
U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g2(U8G2_R2, SCL, SDA, U8X8_PIN_NONE);
RotaryEncoder encoder(ENC_D1_PIN, ENC_D2_PIN, RotaryEncoder::LatchMode::TWO03);
//Font
const PROGMEM uint8_t velvetscreen[437] U8G2_FONT_SECTION("velvetscreen") =
"\64\0\2\2\3\3\2\3\4\5\5\0\0\5\0\5\0\0\221\0\0\1\230 \4\200\134%\11\255tT"
"R\271RI(\6\252\334T\31)\7\252\134bJ\12+\7\233\345\322J\0,\5\221T\4-\5\213"
"f\6.\5\211T\2/\6\244\354c\33\60\10\254\354T\64\223\2\61\7\353\354\222\254\6\62\11\254l"
"\66J*\217\0\63\11\254l\66J\32\215\4\64\10\254l\242\34\272\0\65\11\254l\206\336h$\0\66"
"\11\254\354T^\61)\0\67\10\254lF\216u\4\70\11\254\354TL*&\5\71\11\254\354TL;"
")\0:\6\231UR\0A\10\254\354T\34S\6B\11\254lV\34)\216\4C\11\254\354T\324\61"
")\0D\10\254lV\64G\2E\10\254l\206\36z\4F\10\254l\206^\71\3G\11\254\354TN"
"\63)\0H\10\254l\242\34S\6I\6\251T\206\0J\10\254\354k\231\24\0K\11\254l\242J\62"
"\225\1L\7\254lr{\4M\11\255t\362ZI\353\0N\11\255t\362TI\356\0O\10\254\354T"
"\64\223\2P\11\254lV\34)g\0Q\10\254\354T\264b\12R\10\254lV\34\251\31S\11\254\354"
"FF\32\215\4T\7\253dVl\1U\10\254l\242\63)\0V\11\255t\262Ne\312\21W\12\255"
"t\262J*\251.\0X\11\254l\242L*\312\0Y\12\255tr\252\63\312(\2Z\7\253df*"
"\7p\10\255\364V\266\323\2q\7\255\364\216\257\5r\10\253d\242\32*\2t\6\255t\376#w\11"
"\255\364V\245FN\13x\6\233dR\7\0\0\0\4\377\377\0";
const PROGMEM uint8_t stkL[569] U8G2_FONT_SECTION("stk-l") =
"\25\0\4\4\4\5\2\1\6\17\27\1\0\27\0\0\0\1\77\0\0\2\34%'\17\37\313\330R#&"
"\32!F\14\211I\310\24!\65\204(MF\21)Cd\304\10\62b\14\215\60Vb\334\20\0/\14"
"\272\336\336d\244\350\263q\343\0\60\37|\377\12\32\25\17\2\35\263\253ChD\30\21bB\14\242S"
"\306lv\350A\10\65H\0\61\24z\337\322\60R\205\314\234\31\61F\310\270\371\177\224\42\3\62\33|"
"\377\216\251$*\10\35\63\66r\206\304\314`c\252\34\301\221\263|\360\300\0\63\34|\377\216)\64*"
"\10\35\63\66r \71\332YIr\226\306\16\221P\203\312\14\0\64 |\377\226\220AC\306\20\31B"
"f\310\240\21\204F\214\32\61j\304(cv\366\200\305\312\371\0\65\32}\17\307\12.\206\316\213Bj"
"\226\214\42JtN\315\235\42\261&\325\31\0\66\33}\17\317\251\64+\206\235\63:/\314,aA\352"
"\234\335\235\42\261&\325\31\0\67\23|\377\302\212\7)\347Crt\70\345\300\221\363\16\0\70 |\377"
"\216)\64*\10\35\263\331!\22D\310\240\62\205\206\10\11B\307lv\210\204\32Tf\0\71\32|\377"
"\216)\64*\10\35\263\263C$\226\250I\71_\14\42\241\6\225\31\0A\26}\17S\271Si(\31"
"\65d\324\210q\366\356\301w\366\273\1B$}\17\203\232%KF\221\30\66b\330\210a#\206\215\30"
"Eb\311&\243H\14;g\317\36\204`\261\4\0D\33}\17C\42\65KF\15\31\66b\330\210q"
"\366\77;\66b\24\211%j\22\1E\21|\377\302\7)\347%\42\214F\316/\37<\60I\7so"
"\302\37$M$}\17\203\310r\346N\245Q\263\202E\12)L\224\60Q\302\310\20#C\214\14\61\23"
"\306L\30s\366\335\0T\15}\17\303\7\251\206\316\377\377\12\0X)~\37\303@\203\307H\14\33B"
"\210\14\21RC\206\241\63h\222(I\203\346\220\15\31E\204\14!\42\303F\20;h\341\0x\24\312"
"\336\302 CGH\240\61E\312\14\222)\6Y\64\0\0\0\0\4\377\377\0";
String version;
@ -162,22 +204,12 @@ void setup() {
pinMode(EXT_INPUT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(EXT_INPUT_PIN), externalClock, FALLING);
for (uint8_t i = 0; i < 6; i++) {
for (byte i = 0; i < 6; i++) {
pinMode(outsPins[i], OUTPUT);
}
pinMode(clockOutPin, OUTPUT);
pinMode(ENC_D1_PIN, INPUT_PULLUP);
pinMode(ENC_D2_PIN, INPUT_PULLUP);
//Enabling PinChange Interrupts for the encoder
//pins 17 (PC3/PCINT11) and 4 (PD4/PCINT20), ports C and D
PCICR |= 0b00000110;
PCMSK1 |= 0b00001000;
PCMSK2 |= 0b00010000;
loadState();
u8g2.begin();
@ -186,11 +218,10 @@ void setup() {
calculateCycles();
calculateBPMTiming();
checkEncoderStatus();
resetClocks();
FlexiTimer2::set(1, 1.0 / 10000, clock); // 1.0/1000 = 1ms period
FlexiTimer2::set(1, 1.0 / 10000, clock); // 1.0/1000 = 1ms period. If other than 1ms calculateBPMTiming() might need tweaking
FlexiTimer2::start();
}
@ -201,62 +232,6 @@ void loop() {
checkInputs();
}
//Encoder interrupts
ISR (PCINT1_vect) {
checkEncoderStatus();
}
ISR (PCINT2_vect) {
checkEncoderStatus();
}
uint8_t encoderStatus;
uint32_t encoderCheckTime = 0;
uint32_t encoderTimeBetweenPulses = 0;
bool encoderDirectionOld; //0 = -, 1 = +, Old because current direction can be determined by encoderChange
int8_t encoderChange = 0;
uint8_t encoderBurstCount = 0;
void checkEncoderStatus() {
//bool pin1Status = digitalRead(ENC_D1_PIN);
//bool pin2Status = digitalRead(ENC_D2_PIN);
uint8_t newStatus = (digitalRead(ENC_D1_PIN) << 1) | digitalRead(ENC_D2_PIN);
switch(encoderStatus) { // encoderStatus & 0b00000011 - to check only 2 last bits
case 0b00:
if (newStatus == 0b01) {
encoderChange++;
} else if (newStatus == 0b10) {
encoderChange--;
}
break;
case 0b01:
if (newStatus == 0b11) {
encoderChange++;
} else if (newStatus == 0b00) {
encoderChange--;
}
break;
case 0b11:
if (newStatus == 0b10) {
encoderChange++;
} else if (newStatus == 0b01) {
encoderChange--;
}
break;
case 0b10:
if (newStatus == 0b00) {
encoderChange++;
} else if (newStatus == 0b11) {
encoderChange--;
}
break;
}
encoderStatus = newStatus;
uint32_t currentTime = millis();
encoderTimeBetweenPulses = currentTime - encoderCheckTime;
encoderCheckTime = currentTime;
}
void sendMIDIClock() {
NeoSerial.write(0xF8);
}
@ -269,12 +244,17 @@ void sendMIDIStop() {
void receiveMIDI( uint8_t msg, uint8_t status ) {
if (masterClockMode == 2) {
if (msg == 0xF8) { //Clock tick
//int msg = NeoSerial.read();
if (msg == 0xF8) { //Clock
MIDIClockReceived = true;
} else if (msg == 0xFC) { //stop
isPlaying = false;
resetClocks();
sendMIDIStop();
} else if (msg == 0xFA || msg == 0xFB) { //start and continue
resetClocks();
isPlaying = true;
sendMIDIStart();
}
}
}
@ -286,9 +266,7 @@ void clock() {
// Action on each pulse
if (tickCount == 0) {
sendTriggers();
if (!extraChannel) {
digitalWrite(clockOutPin, HIGH);
}
digitalWrite(clockOutPin, HIGH);
sendMIDIClock();
}
@ -305,11 +283,6 @@ void clock() {
}
if (bpmModulationRange != 0) {
calculateBPMTiming();
for (uint8_t i; i < 7; i++) {
if (channels[i].mode == Gate) {
calculateGate(i);
}
}
}
}
}
@ -320,7 +293,7 @@ void clock() {
}
}
if (masterClockMode == 2 && MIDIClockReceived) {
if (masterClockMode == 2 && MIDIClockReceived) { // MIDI should happen here (needs testing)
tickCount = 0; //to make things happen in the main clock function
if (pulseCount < (PPQN - 1)) {
pulseCount++;
@ -331,17 +304,12 @@ void clock() {
}
// pull low all outputs after set pulse length
for (uint8_t i = 0; i < 7; i++) {
if (channels[i].mode != Gate && tickCount >= PULSE_LENGTH) { //everything but gate mode
if (tickCount >= PULSE_LENGTH) {
for (byte i = 0; i < 6; i++) {
digitalWrite(outsPins[i], LOW);
} else if (channels[i].mode == Gate && tickCount >= gateCountDown[i]) { //gate mode gateLengthTime[i] < pulsePeriod
digitalWrite(outsPins[i], LOW);
gateCountDown[i] = gateLengthTime[i];
} else if (channels[i].mode == Gate && gateCountDown[i] > pulsePeriod && tickCount == 0) {
gateCountDown[i] = gateCountDown[i] - pulsePeriod;
}
digitalWrite(clockOutPin, LOW);
}
}
}
@ -356,6 +324,7 @@ void externalClock() {
//reset cycles if there were no pulses for a while
if ((newExtPulseTime - lastExtPulseTime) > 125) { //125ms is 20bpm
resetClocks();
}
@ -394,22 +363,24 @@ void externalClock() {
}
}
void sendTriggers() { //rename to onPulse or something
void sendTriggers() {
for (uint8_t i = 0; i < (extraChannel ? 7 : 6); i++) {
for (byte i = 0; i < 6; i++) {
if (playingModes[i] != subDivs[channels[i].subDiv] && playingModesOld[i] != playingModes[i]) {
needPulseReset[i] = true;
playingModesOld[i] = playingModes[i];
}
}
//16th notes for sequencer and swing
//16th notes for sequencer
if (sixteenthPulseCount == 0) {
stepIsOdd = !stepIsOdd;
for (uint8_t i = 0; i < (extraChannel ? 7 : 6); i++) {
bool *currentSeq;
for (byte i = 0; i < 6; i++) {
//pattern modulation
int seqMod = 0;
uint8_t seqPattern;
byte seqPattern;
if (channels[i].CV2Target == 3) {
seqMod = map(CV2Input, -1, 1024, -8, 8); //-1 and 1024 are to try to make the last step not at max value (should make the range from -7 to +7)
} else if (channels[i].CV1Target == 3) {
@ -427,8 +398,40 @@ void sendTriggers() { //rename to onPulse or something
seqPattern = channels[i].seqPattern + seqMod;
}
bool currentStepValue = bitRead(sequences[channels[i].seqPattern].sequence, currentStep[i]);
if (channels[i].mode == Sequencer && currentStepValue && !channels[i].isMute) {
if (seqPattern == 0) {
currentSeq = seqA1;
} else if (seqPattern == 1) {
currentSeq = seqA2;
} else if (seqPattern == 2) {
currentSeq = seqA3;
} else if (seqPattern == 3) {
currentSeq = seqA4;
} else if (seqPattern == 4) {
currentSeq = seqA5;
} else if (seqPattern == 5) {
currentSeq = seqA6;
} else if (seqPattern == 6) {
currentSeq = seqA7;
} else if (seqPattern == 7) {
currentSeq = seqA8;
} else if (seqPattern == 8) {
currentSeq = seqB1;
} else if (seqPattern == 9) {
currentSeq = seqB2;
} else if (seqPattern== 10) {
currentSeq = seqB3;
} else if (seqPattern == 11) {
currentSeq = seqB4;
} else if (seqPattern == 12) {
currentSeq = seqB5;
} else if (seqPattern == 13) {
currentSeq = seqB6;
} else if (seqPattern == 14) {
currentSeq = seqB7;
} else if (seqPattern == 15) {
currentSeq = seqB8;
}
if (channels[i].mode == 2 && currentSeq[currentStep]) { // EXT CLOCK SEQUENCER BUG IS SOMEWHERE HERE ???? && channelPulseCount[i] == 0 might be related to channelPulsesPerCycle not calculated in time
digitalWrite(outsPins[i], HIGH);
}
}
@ -440,12 +443,10 @@ void sendTriggers() { //rename to onPulse or something
}
} else {
sixteenthPulseCount = 0;
for (uint8_t i; i < 7; i++) {
if (channels[i].mode == Sequencer && currentStep[i] < sequences[channels[i].seqPattern].length) {
currentStep[i] ++;
} else {
currentStep[i] = 0;
}
if (currentStep < 15) {
currentStep ++;
} else {
currentStep = 0;
}
recordToNextStep = false;
}
@ -453,22 +454,19 @@ void sendTriggers() { //rename to onPulse or something
//switching modes on the beat and resetting channel clock
if (pulseCount == 0) {
calculateCycles();
for (uint8_t i = 0; i < (extraChannel ? 7 : 6); i++) {
for (byte i = 0; i < 6; i++) {
if (needPulseReset[i] == true) {
channelPulseCount[i] = 0;
needPulseReset[i] = false;
}
if (channels[i].mode == Gate) {
calculateGate(i);
}
}
}
//multiplier
for (uint8_t i = 0; i < (extraChannel ? 7 : 6); i++) {
for (byte i = 0; i < 6; i++) {
//RND modulation
uint8_t randMod = 0;
byte randMod = 0;
if (channels[i].CV1Target == 2) {
randMod = randMod + CV1Input;
}
@ -478,26 +476,17 @@ void sendTriggers() { //rename to onPulse or something
if (channels[i].CV1Target == 2 || channels[i].CV2Target == 2) {
randMod = map(randMod, 0, 1023, -5, +5);
}
uint8_t randAmount = channels[i].random + randMod;
byte randAmount = channels[i].random + randMod;
if (randAmount > 100) {
randAmount = 0;
} else if (randAmount > 10) {
randAmount = 10;
}
if (!channels[i].isMute) {
if ((channels[i].mode == Swing && channelPulseCount[i] == 0 && stepIsOdd == 0)
|| (channels[i].mode == Swing && channelPulseCount[i] == channels[i].swing && stepIsOdd == 1) //swing
) {
digitalWrite(outsPins[i], HIGH);
}
if ((channels[i].mode == Clock && channelPulseCount[i] == channels[i].offset) //CLK with offset
|| (channels[i].mode == Random && channelPulseCount[i] == 0 && (random(10) + 1) > randAmount) //RND
|| (channels[i].mode == Gate && channelPulseCount[i] == 0) //Gate
) {
digitalWrite(outsPins[i], HIGH);
}
if ((channels[i].mode == 0 && channelPulseCount[i] == channels[i].offset) //CLK with offset
|| (channels[i].mode == 1 && channelPulseCount[i] == 0 && (random(10) + 1) > randAmount) //RND
) {
digitalWrite(outsPins[i], HIGH);
}
if (channelPulseCount[i] < channelPulsesPerCycle[i]) {
channelPulseCount[i]++;
@ -505,11 +494,12 @@ void sendTriggers() { //rename to onPulse or something
channelPulseCount[i] = 0;
}
}
}
void calculateCycles() {
for (uint8_t i = 0; i < (extraChannel ? 7 : 6); i++) {
for (byte i = 0; i < 6; i++) {
int mod = 0; //subdiv modulation happens here
if (channels[i].CV1Target == 1) {
mod = map(CV1Input, -1, 1024, -5, 5);
@ -518,24 +508,17 @@ void calculateCycles() {
}
playingModes[i] = subDivs[channels[i].subDiv - mod]; //subtracting because the innitial array is backwards
if (channels[i].mode == Sequencer || channels[i].mode == Swing) { //Sequencer and swing plays 1/16th
if (channels[i].mode == 2) { //Sequencer plays 1/16th
channelPulsesPerCycle[i] = (PPQN / 4) - 1;
} else if (playingModes[i] > 0) {
channelPulsesPerCycle[i] = (playingModes[i] * PPQN) - 1;
} else if (playingModes[i] < 0) {
channelPulsesPerCycle[i] = (PPQN / abs(playingModes[i])) - 1;
}
}
}
void calculateGate(uint8_t channel) {
//if (subDivs[channels[channel].subDiv] > 0) {
gateLengthTime[channel] = ((channelPulsesPerCycle[channel] + 1) * (pulsePeriod + 1) / 100) * channels[channel].gate;
gateCountDown[channel] = gateLengthTime[channel];
//}
}
void calculateBPMTiming() {
int mod = 0;
if (masterClockMode == 0) { //Internal clock
@ -544,31 +527,28 @@ void calculateBPMTiming() {
} else if (bpmModulationRange != 0 && bpmModulationChannel == 1) {
mod = map(CV2Input, 0, 1023, bpmModulationRange * -10, bpmModulationRange * 10);
}
uint8_t calcbpm = bpm + mod;
byte calcbpm = bpm + mod;
if (calcbpm > MAXBPM) { calcbpm = MAXBPM; };
pulsePeriod = 600000 / (calcbpm * PPQN); // 600000.0 / ((float)(calcbpm * PPQN)) - floats eat up ~2% of program memory, but are they more precise? need to measure
pulsePeriod = 600000 / (calcbpm * PPQN);
} else if (masterClockMode == 1 && extClockPPQN == 1) { //for ext 1/16 clock
pulsePeriod = (newExtPulseTime - lastExtPulseTime) * 10 / 6;
} else if (masterClockMode == 1 && extClockPPQN == 1) { //for ext 1/16 clock (hardcoded)
pulsePeriod = ((newExtPulseTime - lastExtPulseTime) * 10) / 6;
}
}
void resetClocks() {
for (uint8_t i = 0; i < (extraChannel ? 7 : 6); i++) {
for (byte i = 0; i < 6; i++) {
channelPulseCount[i] = 0;
digitalWrite(outsPins[i], LOW); //to avoid stuck leds
}
pulseCount = 0;
tickCount = 0;
sixteenthPulseCount = 0;
for (uint8_t i; i < 7; i++) {
currentStep[i] = 0;
}
stepIsOdd = 1;
currentStep = 0;
}
void saveState() {
uint16_t addr = 0;
int addr = 0;
EEPROM.put(addr, bpm);
addr = addr + sizeof(bpm);
EEPROM.put(addr, bpmModulationChannel);
@ -579,8 +559,38 @@ void saveState() {
addr = addr + sizeof(masterClockMode);
EEPROM.put(addr, channels);
addr = addr + sizeof(channels);
EEPROM.put(addr, sequences);
addr = addr + sizeof(sequences);
EEPROM.put(addr, seqA1);
addr = addr + sizeof(seqA1);
EEPROM.put(addr, seqA2);
addr = addr + sizeof(seqA2);
EEPROM.put(addr, seqA3);
addr = addr + sizeof(seqA3);
EEPROM.put(addr, seqA4);
addr = addr + sizeof(seqA4);
EEPROM.put(addr, seqA5);
addr = addr + sizeof(seqA5);
EEPROM.put(addr, seqA6);
addr = addr + sizeof(seqA6);
EEPROM.put(addr, seqA7);
addr = addr + sizeof(seqA7);
EEPROM.put(addr, seqA8);
addr = addr + sizeof(seqA8);
EEPROM.put(addr, seqB1);
addr = addr + sizeof(seqB1);
EEPROM.put(addr, seqB2);
addr = addr + sizeof(seqB2);
EEPROM.put(addr, seqB3);
addr = addr + sizeof(seqB3);
EEPROM.put(addr, seqB4);
addr = addr + sizeof(seqB4);
EEPROM.put(addr, seqB5);
addr = addr + sizeof(seqB5);
EEPROM.put(addr, seqB6);
addr = addr + sizeof(seqB6);
EEPROM.put(addr, seqB7);
addr = addr + sizeof(seqB7);
EEPROM.put(addr, seqB8);
addr = addr + sizeof(seqB8);
EEPROM.put(addr, CV1Calibration);
addr = addr + sizeof(CV1Calibration);
EEPROM.put(addr, CV2Calibration);
@ -590,14 +600,12 @@ void saveState() {
EEPROM.put(addr, extClockPPQN);
addr = addr + sizeof(extClockPPQN);
EEPROM.put(addr, reverseEnc);
addr = addr + sizeof(reverseEnc);
EEPROM.put(addr, extraChannel);
}
void loadState() { //optimisation: try to make an abstraction that can take an array (of pointers?) of settings to be loaded/saved
void loadState() {
//check last bit in eeprom to know if the correct settings were stored
if (EEPROM.read(1023) == memCode) {
uint16_t addr = 0;
int addr = 0;
EEPROM.get(addr, bpm);
addr = addr + sizeof(bpm);
EEPROM.get(addr, bpmModulationChannel);
@ -608,8 +616,38 @@ void loadState() { //optimisation: try to make an abstraction that can take an a
addr = addr + sizeof(masterClockMode);
EEPROM.get(addr, channels);
addr = addr + sizeof(channels);
EEPROM.get(addr, sequences);
addr = addr + sizeof(sequences);
EEPROM.get(addr, seqA1);
addr = addr + sizeof(seqA1);
EEPROM.get(addr, seqA2);
addr = addr + sizeof(seqA2);
EEPROM.get(addr, seqA3);
addr = addr + sizeof(seqA3);
EEPROM.get(addr, seqA4);
addr = addr + sizeof(seqA4);
EEPROM.get(addr, seqA5);
addr = addr + sizeof(seqA5);
EEPROM.get(addr, seqA6);
addr = addr + sizeof(seqA6);
EEPROM.get(addr, seqA7);
addr = addr + sizeof(seqA7);
EEPROM.get(addr, seqA8);
addr = addr + sizeof(seqA8);
EEPROM.get(addr, seqB1);
addr = addr + sizeof(seqB1);
EEPROM.get(addr, seqB2);
addr = addr + sizeof(seqB2);
EEPROM.get(addr, seqB3);
addr = addr + sizeof(seqB3);
EEPROM.get(addr, seqB4);
addr = addr + sizeof(seqB4);
EEPROM.get(addr, seqB5);
addr = addr + sizeof(seqB5);
EEPROM.get(addr, seqB6);
addr = addr + sizeof(seqB6);
EEPROM.get(addr, seqB7);
addr = addr + sizeof(seqB7);
EEPROM.get(addr, seqB8);
addr = addr + sizeof(seqB8);
EEPROM.get(addr, CV1Calibration);
addr = addr + sizeof(CV1Calibration);
EEPROM.get(addr, CV2Calibration);
@ -619,8 +657,6 @@ void loadState() { //optimisation: try to make an abstraction that can take an a
EEPROM.get(addr, extClockPPQN);
addr = addr + sizeof(extClockPPQN);
EEPROM.get(addr, reverseEnc);
addr = addr + sizeof(reverseEnc);
EEPROM.get(addr, extraChannel);
} else {
saveState(); //write default values to EEPROM
EEPROM.write(1023, memCode);

View File

@ -12,8 +12,40 @@ void checkInputs() {
} else if (encReleasedTime - encPressedTime <= 300) { // press shorter than .3s is for entering the submenu
if (!insideTab && displayScreen == 0) {
insideTab = true;
} else if (insideTab && channels[displayTab - 1].mode == Sequencer && menuItem == 2 && displayScreen == 0) { //enter the pattern editor
patternToEdit = channels[displayTab - 1].seqPattern;
} else if (insideTab && channels[displayTab - 1].mode == 2 && menuItem == 2 && displayScreen == 0) { //enter the pattern editor
if (channels[displayTab - 1].seqPattern == 0) {
patternToEdit = seqA1;
} else if (channels[displayTab - 1].seqPattern == 1) {
patternToEdit = seqA2;
} else if (channels[displayTab - 1].seqPattern == 2) {
patternToEdit = seqA3;
} else if (channels[displayTab - 1].seqPattern == 3) {
patternToEdit = seqA4;
} else if (channels[displayTab - 1].seqPattern == 4) {
patternToEdit = seqA5;
} else if (channels[displayTab - 1].seqPattern == 5) {
patternToEdit = seqA6;
} else if (channels[displayTab - 1].seqPattern == 6) {
patternToEdit = seqA7;
} else if (channels[displayTab - 1].seqPattern == 7) {
patternToEdit = seqA8;
} else if (channels[displayTab - 1].seqPattern == 8) {
patternToEdit = seqB1;
} else if (channels[displayTab - 1].seqPattern == 9) {
patternToEdit = seqB2;
} else if (channels[displayTab - 1].seqPattern == 10) {
patternToEdit = seqB3;
} else if (channels[displayTab - 1].seqPattern == 11) {
patternToEdit = seqB4;
} else if (channels[displayTab - 1].seqPattern == 12) {
patternToEdit = seqB5;
} else if (channels[displayTab - 1].seqPattern == 13) {
patternToEdit = seqB6;
} else if (channels[displayTab - 1].seqPattern == 14) {
patternToEdit = seqB7;
} else if (channels[displayTab - 1].seqPattern == 15) {
patternToEdit = seqB8;
}
displayScreen = 1;
isRecording = 0;
} else if (insideTab && displayScreen == 0) {
@ -35,9 +67,6 @@ void checkInputs() {
showDone = true;
updateScreen();
} else if (displayScreen == 2 && menuItem == 3) {
extraChannel = !extraChannel;
updateScreen();
} else if (displayScreen == 2 && menuItem == 4) {
EEPROM.put(1023, memCode - 1);
reboot();
}
@ -45,9 +74,7 @@ void checkInputs() {
if (menuItemSelected == 1) {
menuItemSelected = 0;
} else if (displayScreen != 0) {
menuItem = 0;
displayScreen = 0;
menuItemSelected = 0;
} else if (insideTab == 1) {
insideTab = 0;
menuItem = 0;
@ -61,40 +88,37 @@ void checkInputs() {
}
//encoder
if (encoderChange != 0) {
if (!reverseEnc) {
encoderChange = encoderChange * -1;
encoder.tick();
int encPosition = encoder.getPosition();
int encDirection = (int)(encoder.getDirection());
if (encPositionOld != encPosition) {
int change = encPositionOld - encPosition;
if (reverseEnc) {
change = change * -1;
}
/*if (((encoderChange > 0) != encoderDirectionOld) && encoderTimeBetweenPulses < 150) { //filter out encoder "jumps". Comented out
encoderChange = 0; //because it seems like sometimes it was preventing normal scroll
} //if it works ok without it delete encoderDirectionOld var altogether
encoderDirectionOld = (encoderChange > 0);*/
//encoder acceleration
if (encoderTimeBetweenPulses < 15) { // <--
encoderBurstCount++;
} else {
encoderBurstCount = 0;
unsigned long ms = encoder.getMillisBetweenRotations();
/*if (encDirectionOld == encDirection && ms < 20) { //encoder acceleration
change = change * 5;
} else if (encDirectionOld == encDirection && ms < 80) {
change = change * 2;
} else */ if (encDirectionOld != encDirection && ms < 200) { //filter out encoder "jumps"
change = 0;
}
if (encoderBurstCount > 3) { // <--
encoderChange = encoderChange * 3; // <-- The three params need to be finetuned to feel natural
}
encDirectionOld = encDirection;
if (displayScreen == 0) {
uint8_t channelCV;
byte channelCV;
if (!insideTab && !shiftBtnPushed) { //Change tab
displayTab = displayTab + encoderChange;
displayTab = displayTab + change;
if (displayTab > 100) { //to address "negative" numbers
displayTab = 0;
} else if (displayTab > (extraChannel ? 7 : 6)) {
displayTab = (extraChannel ? 7 : 6);
} else if (displayTab > 6) {
displayTab = 6;
}
} else if (((!insideTab && shiftBtnPushed)
|| (insideTab && menuItem == 0
&& (menuItemSelected || shiftBtnPushed)))
&& displayTab == 0 && masterClockMode == 0) { //Change BPM
bpm = bpm + encoderChange;
bpm = bpm + change;
if (bpm > MAXBPM) {
bpm = MAXBPM;
} else if (bpm < MINBPM) {
@ -106,13 +130,13 @@ void checkInputs() {
|| (insideTab && menuItem == 0
&& (menuItemSelected || shiftBtnPushed)))
&& displayTab != 0
&& channels[displayTab - 1].mode == Clock) {
channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - encoderChange;
&& channels[displayTab - 1].mode == 0) {
channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - change;
//channels[displayTab - 1].offset = 0;
if (channels[displayTab - 1].subDiv > 100) {
channels[displayTab - 1].subDiv = 0;
} if (channels[displayTab - 1].subDiv > (sizeof(subDivs) / sizeof(subDivs[0])) - 1) {
channels[displayTab - 1].subDiv = (sizeof(subDivs) / sizeof(subDivs[0])) - 1;
} if (channels[displayTab - 1].subDiv > (sizeof(subDivs) / sizeof(int)) - 1) {
channels[displayTab - 1].subDiv = (sizeof(subDivs) / sizeof(int)) - 1;
}
if (!isPlaying) {
calculateCycles();
@ -131,8 +155,8 @@ void checkInputs() {
|| (insideTab && menuItem == 0
&& (menuItemSelected || shiftBtnPushed)))
&& displayTab != 0
&& channels[displayTab - 1].mode == Random) { //Change Random
channels[displayTab - 1].random = channels[displayTab - 1].random + encoderChange;
&& channels[displayTab - 1].mode == 1) { //Change Random
channels[displayTab - 1].random = channels[displayTab - 1].random + change;
if (channels[displayTab - 1].random > 100) {
channels[displayTab - 1].random = 0;
} else if (channels[displayTab - 1].random > 9) {
@ -143,42 +167,16 @@ void checkInputs() {
|| (insideTab && menuItem == 0
&& (menuItemSelected || shiftBtnPushed)))
&& displayTab != 0
&& channels[displayTab - 1].mode == Sequencer) { //Change SEQ pattern
if (channels[displayTab - 1].seqPattern == 0 && encoderChange == -1) {
&& channels[displayTab - 1].mode == 2) { //Change SEQ pattern
channels[displayTab - 1].seqPattern = channels[displayTab - 1].seqPattern + change;
if (channels[displayTab - 1].seqPattern > 100) {
channels[displayTab - 1].seqPattern = 0;
} else if (channels[displayTab - 1].seqPattern == 31 && encoderChange == 1) {
channels[displayTab - 1].seqPattern = 31;
} else {
channels[displayTab - 1].seqPattern = channels[displayTab - 1].seqPattern + encoderChange;
} else if (channels[displayTab - 1].seqPattern > 15) {
channels[displayTab - 1].seqPattern = 15;
}
saveState();
} else if (((!insideTab && shiftBtnPushed)
|| (insideTab && menuItem == 0
&& (menuItemSelected || shiftBtnPushed)))
&& displayTab != 0
&& channels[displayTab - 1].mode == Swing) { //Change SWING
channels[displayTab - 1].swing = channels[displayTab - 1].swing + encoderChange;
if (channels[displayTab - 1].swing > 6) {
channels[displayTab - 1].swing = 0;
} else if (channels[displayTab - 1].swing > 5) {
channels[displayTab - 1].swing = 5;
}
saveState();
} else if (((!insideTab && shiftBtnPushed)
|| (insideTab && menuItem == 0
&& (menuItemSelected || shiftBtnPushed)))
&& displayTab != 0
&& channels[displayTab - 1].mode == Gate) { //Change GATE
channels[displayTab - 1].gate = channels[displayTab - 1].gate + encoderChange;
if (channels[displayTab - 1].gate > 100 || channels[displayTab - 1].gate == 0) {
channels[displayTab - 1].gate = 1;
} else if (channels[displayTab - 1].gate > 99) {
channels[displayTab - 1].gate = 99;
}
calculateGate(displayTab - 1);
saveState();
} else if (insideTab && !shiftBtnPushed && !menuItemSelected) {
menuItem = menuItem + encoderChange;
menuItem = menuItem + change;
if (menuItem > 100) { //for "negative" values
menuItem = 0;
} else if (menuItem > lastMenuItem) {
@ -188,14 +186,14 @@ void checkInputs() {
&& (shiftBtnPushed || menuItemSelected)
&& displayTab == 0
&& menuItem == 1) { //Master Clock Mode
if (masterClockMode == 1) { // && encoderChange == -1) { //Stop when switching from ext to int or to midi
if (masterClockMode == 1) { // && change == -1) { //Stop when switching from ext to int or to midi
isPlaying = false;
}
masterClockMode = masterClockMode + encoderChange;
masterClockMode = masterClockMode + change;
if (masterClockMode > 100) {
masterClockMode = 0;
} else if (masterClockMode > 2) {
} else if (masterClockMode > 2) { //Set to 1 to hide MIDI mode
masterClockMode = 2;
}
saveState();
@ -204,7 +202,7 @@ void checkInputs() {
&& displayTab == 0
&& menuItem == 2
&& masterClockMode == 0) { //Modulation channel
bpmModulationChannel = bpmModulationChannel + encoderChange;
bpmModulationChannel = bpmModulationChannel + change;
if (bpmModulationChannel == 0 || bpmModulationChannel == 1) {
bpmModulationRange = 1;
} else if (bpmModulationChannel > 100) {
@ -219,7 +217,7 @@ void checkInputs() {
&& displayTab == 0
&& menuItem == 2
&& masterClockMode == 1) { //PPQN
extClockPPQN = extClockPPQN + encoderChange;
extClockPPQN = extClockPPQN + change;
if (extClockPPQN > 100) {
extClockPPQN = 0;
} else if (extClockPPQN > 1) {
@ -230,7 +228,7 @@ void checkInputs() {
&& (menuItemSelected || shiftBtnPushed)
&& displayTab == 0
&& menuItem == 3) { //Modulation range
bpmModulationRange = bpmModulationRange + encoderChange;
bpmModulationRange = bpmModulationRange + change;
if (bpmModulationRange == 0) {
bpmModulationRange = 1;
} else if (bpmModulationRange > 100) {
@ -243,11 +241,11 @@ void checkInputs() {
&& (menuItemSelected || shiftBtnPushed)
&& displayTab != 0
&& menuItem == 1) { //Channel Mode
channels[displayTab - 1].mode = channels[displayTab - 1].mode + encoderChange;
if (channels[displayTab - 1].mode == 7) {
channels[displayTab - 1].mode = 4; //to make it cycle through all the modes
} else if (channels[displayTab - 1].mode > 4) {
channels[displayTab - 1].mode = channels[displayTab - 1].mode + change;
if (channels[displayTab - 1].mode > 100) {
channels[displayTab - 1].mode = 0;
} else if (channels[displayTab - 1].mode > 2) {
channels[displayTab - 1].mode = 2;
}
channels[displayTab - 1].CV1Target = 0;
channels[displayTab - 1].CV2Target = 0;
@ -255,8 +253,8 @@ void checkInputs() {
} else if (insideTab
&& (menuItemSelected || shiftBtnPushed)
&& displayTab != 0 && menuItem == 2
&& channels[displayTab - 1].mode == Clock) { //Offset
channels[displayTab - 1].offset = channels[displayTab - 1].offset + encoderChange;
&& channels[displayTab - 1].mode == 0) { //Offset
channels[displayTab - 1].offset = channels[displayTab - 1].offset + change;
if (channels[displayTab - 1].offset == 255) { // 0 - 1 for uint8 is 255
channels[displayTab - 1].offset = 0;
} else if (channels[displayTab - 1].offset > channelPulsesPerCycle[displayTab-1]) {
@ -267,12 +265,12 @@ void checkInputs() {
&& (menuItemSelected || shiftBtnPushed)
&& displayTab != 0
&& menuItem == 2
&& (channels[displayTab - 1].mode == Random || channels[displayTab - 1].mode == Gate)) { //SUBDIV for RANDOM and GATE
channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - encoderChange;
&& channels[displayTab - 1].mode == 1) { //SUBDIV for RANDOM
channels[displayTab - 1].subDiv = channels[displayTab - 1].subDiv - change;
if (channels[displayTab - 1].subDiv > 200) {
channels[displayTab - 1].subDiv = 0;
} else if (channels[displayTab - 1].subDiv > (sizeof(subDivs) / sizeof(subDivs[0])) - 1) {
channels[displayTab - 1].subDiv = (sizeof(subDivs) / sizeof(subDivs[0])) - 1;
} else if (channels[displayTab - 1].subDiv > (sizeof(subDivs) / sizeof(int)) - 1) {
channels[displayTab - 1].subDiv = (sizeof(subDivs) / sizeof(int)) - 1;
}
if (!isPlaying) {
calculateCycles();
@ -282,7 +280,7 @@ void checkInputs() {
&& (menuItemSelected || shiftBtnPushed)
&& displayTab != 0
&& menuItem == 3
&& channels[displayTab - 1].mode == Clock) { //CV for CLK
&& channels[displayTab - 1].mode == 0) { //CV for CLK
if (channels[displayTab - 1].CV1Target == 1 && channels[displayTab - 1].CV2Target == 0) {
channelCV = 1;
} else if (channels[displayTab - 1].CV1Target == 0 && channels[displayTab - 1].CV2Target == 1) {
@ -290,7 +288,7 @@ void checkInputs() {
} else {
channelCV = 0;
}
channelCV = channelCV + encoderChange;
channelCV = channelCV + change;
if (channelCV == 0 || channelCV > 100) {
channelCV = 0;
channels[displayTab - 1].CV1Target = 0;
@ -304,7 +302,7 @@ void checkInputs() {
channels[displayTab - 1].CV2Target = 1;
}
saveState();
} else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 3 && channels[displayTab - 1].mode == Random) { //CV for RND
} else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 3 && channels[displayTab - 1].mode == 1) { //CV for RND
if (channels[displayTab - 1].CV1Target == 2 && channels[displayTab - 1].CV2Target == 0) {
channelCV = 1;
} else if (channels[displayTab - 1].CV1Target == 0 && channels[displayTab - 1].CV2Target == 2) {
@ -312,7 +310,7 @@ void checkInputs() {
} else {
channelCV = 0;
}
channelCV = channelCV + encoderChange;
channelCV = channelCV + change;
if (channelCV == 0 || channelCV > 100) {
channelCV = 0;
channels[displayTab - 1].CV1Target = 0;
@ -326,7 +324,7 @@ void checkInputs() {
channels[displayTab - 1].CV2Target = 2;
}
saveState();
} else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 3 && channels[displayTab - 1].mode == Sequencer) { //CV1 for SEQ
} else if (insideTab && (menuItemSelected || shiftBtnPushed) && displayTab != 0 && menuItem == 3 && channels[displayTab - 1].mode == 2) { //CV1 for SEQ
if (channels[displayTab - 1].CV1Target == 3 && channels[displayTab - 1].CV2Target == 0) {
channelCV = 1;
} else if (channels[displayTab - 1].CV1Target == 0 && channels[displayTab - 1].CV2Target == 3) {
@ -334,7 +332,7 @@ void checkInputs() {
} else {
channelCV = 0;
}
channelCV = channelCV + encoderChange;
channelCV = channelCV + change;
if (channelCV == 0 || channelCV > 100) {
channelCV = 0;
channels[displayTab - 1].CV1Target = 0;
@ -348,21 +346,16 @@ void checkInputs() {
channels[displayTab - 1].CV2Target = 3;
}
saveState();
}
} else if (displayScreen == 1 && !isRecording && !shiftBtnPushed) {
stepNumSelected = stepNumSelected + encoderChange;
if (stepNumSelected < -1 ) {
stepNumSelected = -1;
} else if (stepNumSelected > sequences[channels[displayTab - 1].seqPattern].length && !shiftBtnPushed) {
}
} else if (displayScreen == 1 && !isRecording) {
stepNumSelected = stepNumSelected + change;
if (stepNumSelected > 100) {
stepNumSelected = 15;
} else if (stepNumSelected > 15) {
stepNumSelected = 0;
}
} else if (displayScreen == 1 && !isRecording && stepNumSelected == -1 && shiftBtnPushed) {
if ((sequences[channels[displayTab - 1].seqPattern].length != 31 && encoderChange > 0) ||
(sequences[channels[displayTab - 1].seqPattern].length != 0 && encoderChange < 0)) {
sequences[channels[displayTab - 1].seqPattern].length += encoderChange;
}
}
} else if (displayScreen == 2 && !shiftBtnPushed) {
menuItem = menuItem + encoderChange;
menuItem = menuItem + change;
if (menuItem > 100) { //for "negative" values
menuItem = 0;
} else if (menuItem > lastMenuItem) {
@ -371,11 +364,11 @@ void checkInputs() {
}
updateScreen();
encoderChange = 0;
encPositionOld = encPosition;
}
//play button
if (!digitalRead(START_STOP_BTN_PIN) && !playBtnPushed && !shiftBtnPushed) {
if (!digitalRead(START_STOP_BTN_PIN) && !playBtnPushed) {
if (masterClockMode == 0) {
calculateBPMTiming();
if (!isPlaying) {
@ -394,15 +387,6 @@ void checkInputs() {
playBtnPushed = false;
}
//shift + play = mute channel
if (!digitalRead(START_STOP_BTN_PIN) && !playBtnPushed && shiftBtnPushed) {
channels[displayTab - 1].isMute = !channels[displayTab - 1].isMute;
playBtnPushed = true;
updateScreen(); //to wake up the screen if turned off
} else if (digitalRead(START_STOP_BTN_PIN) && playBtnPushed) {
playBtnPushed = false;
}
//shift button
if (!digitalRead(SHIFT_BTN_PIN) && !shiftBtnPushed) {
shiftBtnPushed = true;
@ -410,22 +394,24 @@ void checkInputs() {
if (isRecording) { //Live triggering
digitalWrite(outsPins[displayTab - 1], HIGH);
}
if (displayScreen == 1 && !isRecording && stepNumSelected <= sequences[patternToEdit].length && stepNumSelected != -1) {
sequences[patternToEdit].sequence = bitFlip(sequences[patternToEdit].sequence, stepNumSelected);
if (displayScreen == 1 && !isRecording) {
patternToEdit[stepNumSelected] = !patternToEdit[stepNumSelected];
} else if (displayScreen == 1 && isRecording && !recordToNextStep) { //Recording
bitSet(sequences[patternToEdit].sequence, currentStep[displayTab - 1]);
patternToEdit[currentStep] = 1;
} else if (displayScreen == 1 && isRecording && recordToNextStep && currentStep != 15) {
bitSet(sequences[patternToEdit].sequence, currentStep[displayTab - 1] + 1);
patternToEdit[currentStep+1] = 1;
} else if (displayScreen == 1 && isRecording && recordToNextStep && currentStep == 15) {
bitSet(sequences[patternToEdit].sequence, 0);
patternToEdit[0] = 1;
}
saveState();
updateScreen();
} else if (digitalRead(SHIFT_BTN_PIN) && shiftBtnPushed) {
shiftBtnPushed = false;
shiftReleasedTime = millis();
if (displayScreen == 1 && shiftReleasedTime - shiftPressedTime > 1000 && !encBtnPushed && stepNumSelected != -1) { //&& shiftReleasedTime - shiftPressedTime < 2000 //Clear the sequence
sequences[patternToEdit].sequence = 0b000000000000000000000000000000000;
if (displayScreen == 1 && shiftReleasedTime - shiftPressedTime > 500 && !encBtnPushed) { //&& shiftReleasedTime - shiftPressedTime < 2000 //Clear the sequence
for (byte i = 0; i < 16; i++) {
patternToEdit[i] = 0;
}
} else if (shiftReleasedTime - shiftPressedTime > 2000 && encBtnPushed) {
displayScreen = 2;
menuItemSelected = 1; //hack to prevent from going back when the encoder is released

View File

@ -2,8 +2,8 @@ void updateScreen() {
u8g2.firstPage();
do {
uint8_t leftOffset;
uint8_t width;
byte leftOffset;
byte width;
String valueStr;
u8g2.setDrawColor(1);
@ -11,7 +11,7 @@ void updateScreen() {
//BPM Tab
if (displayTab == 0) { //BPM
u8g2.setFont(stkS);
u8g2.setFont(velvetscreen);
//Menu items
lastMenuItem = 4;
@ -27,7 +27,7 @@ void updateScreen() {
lastMenuItem = 1;
}
for (uint8_t i = 1; i <= lastMenuItem; i++) {
for (byte i = 1; i <= lastMenuItem; i++) {
if (i == 1) {
valueStr = F("MODE:");
} else if (i == 2 && masterClockMode == 0) {
@ -48,7 +48,7 @@ void updateScreen() {
}
//Values
for (uint8_t i = 1; i <= lastMenuItem; i++) {
for (byte i = 1; i <= lastMenuItem; i++) {
if (i == 1 && masterClockMode == 0) { //Channel mode
valueStr = F("INT");
} else if (i == 1 && masterClockMode == 1) {
@ -91,19 +91,19 @@ void updateScreen() {
if ((!insideTab && !shiftBtnPushed) || (insideTab && menuItem != 0)) { //default view, nothing is selected or editable
u8g2.setFont(stkL);
u8g2.drawButtonUTF8(leftOffset-1, 28, U8G2_BTN_BW0|U8G2_BTN_HCENTER, width, 0, 3, valueStr.c_str() );
u8g2.setFont(stkS);
u8g2.setFont(velvetscreen);
valueStr = F("BPM");
u8g2.drawButtonUTF8(leftOffset, 40, U8G2_BTN_BW0|U8G2_BTN_HCENTER, width, 0, 2, valueStr.c_str() );
} else if ((!insideTab && shiftBtnPushed) || (insideTab && menuItem == 0 && (menuItemSelected || shiftBtnPushed))) { //show value as editable
u8g2.setFont(stkL);
u8g2.drawButtonUTF8(leftOffset-1, 28, U8G2_BTN_BW1|U8G2_BTN_HCENTER, width, 0, 3, valueStr.c_str() );
u8g2.setFont(stkS);
u8g2.setFont(velvetscreen);
valueStr = F("BPM");
u8g2.drawButtonUTF8(leftOffset, 40, U8G2_BTN_BW1|U8G2_BTN_INV|U8G2_BTN_HCENTER, width, 0, 2, valueStr.c_str() );
} else if (insideTab && menuItem == 0 && !menuItemSelected) { //show as selected menu item
u8g2.setFont(stkL);
u8g2.drawButtonUTF8(leftOffset-1, 28, U8G2_BTN_BW1|U8G2_BTN_INV|U8G2_BTN_HCENTER, width, 0, 3, valueStr.c_str() );
u8g2.setFont(stkS);
u8g2.setFont(velvetscreen);
valueStr = F("BPM");
u8g2.drawButtonUTF8(leftOffset, 40, U8G2_BTN_BW1|U8G2_BTN_INV|U8G2_BTN_HCENTER, width, 0, 2, valueStr.c_str() );
}
@ -118,26 +118,18 @@ void updateScreen() {
//Channel Tabs
else {
//Menu items
if (channels[displayTab - 1].mode == Swing) {
lastMenuItem = 1;
} else if (channels[displayTab - 1].mode == Gate) {
lastMenuItem = 3;
} else {
lastMenuItem = 3;
}
lastMenuItem = 3;
width = 32;
leftOffset = 62;
for (uint8_t i = 1; i <= lastMenuItem; i++) {
for (byte i = 1; i <= lastMenuItem; i++) {
if (i == 1) {
valueStr = F("MODE:");
} else if (i == 2 && channels[displayTab - 1].mode == Clock) {
} else if (i == 2 && channels[displayTab - 1].mode == 0) {
valueStr = F("OFFSET:");
} else if (i == 2 && (channels[displayTab - 1].mode == Random || channels[displayTab - 1].mode == Gate)) {
} else if (i == 2 && channels[displayTab - 1].mode == 1) {
valueStr = F("SUBDIV:");
} else if (i == 2 && channels[displayTab - 1].mode == Sequencer) {
} else if (i == 2 && channels[displayTab - 1].mode == 2) {
valueStr = F("EDIT PATTERN");
} else if (i == 3 && channels[displayTab - 1].mode == Gate) {
valueStr = (String(pulsePeriod) + " " + String(channelPulsesPerCycle[displayTab - 1]));
} else if (i == 3) {
valueStr = F("MOD:");
}
@ -149,18 +141,14 @@ void updateScreen() {
}
//Values
for (uint8_t i = 1; i <= lastMenuItem; i++) {
if (i == 1 && channels[displayTab - 1].mode == Clock) { //Channel mode
for (byte i = 1; i <= lastMenuItem; i++) {
if (i == 1 && channels[displayTab - 1].mode == 0) { //Channel mode
valueStr = F("CLOCK");
} else if (i == 1 && channels[displayTab - 1].mode == Random) {
} else if (i == 1 && channels[displayTab - 1].mode == 1) {
valueStr = F("RAND");
} else if (i == 1 && channels[displayTab - 1].mode == Sequencer) {
} else if (i == 1 && channels[displayTab - 1].mode == 2) {
valueStr = F("SEQ");
} else if (i == 1 && channels[displayTab - 1].mode == Swing) {
valueStr = F("SWING");
} else if (i == 1 && channels[displayTab - 1].mode == Gate) {
valueStr = F("GATE");
} else if (i == 2 && channels[displayTab - 1].mode == Clock) { //SubDiv and offset
} else if (i == 2 && channels[displayTab - 1].mode == 0) { //SubDiv and offset
valueStr = String(channels[displayTab - 1].offset) + F("/");
int PulsesPerStep;
if (subDivs[channels[displayTab - 1].subDiv] < 0) {
@ -169,10 +157,10 @@ void updateScreen() {
PulsesPerStep = subDivs[channels[displayTab - 1].subDiv] * PPQN;
}
valueStr = valueStr + String(PulsesPerStep); //(playingModes[i] * PPQN) - 1 //String(channelPulsesPerCycle[displayTab-1]+1)
} else if (i == 2 && (channels[displayTab - 1].mode == Random || channels[displayTab - 1].mode == Gate) && subDivs[channels[displayTab - 1].subDiv] > 0) {
} else if (i == 2 && channels[displayTab - 1].mode == 1 && subDivs[channels[displayTab - 1].subDiv] > 0) {
valueStr = F("/");
valueStr = valueStr + String(subDivs[channels[displayTab - 1].subDiv]);
} else if (i == 2 && (channels[displayTab - 1].mode == Random || channels[displayTab - 1].mode == Gate) && subDivs[channels[displayTab - 1].subDiv] < 0) {
} else if (i == 2 && channels[displayTab - 1].mode == 1 && subDivs[channels[displayTab - 1].subDiv] < 0) {
valueStr = F("x");
valueStr = valueStr + String(abs(subDivs[channels[displayTab - 1].subDiv]));
} else if (i == 3 && channels[displayTab - 1].CV1Target == 0 && channels[displayTab - 1].CV2Target == 0) { //MOD
@ -183,7 +171,7 @@ void updateScreen() {
valueStr = F("CV2");
}
if (i == 2 && channels[displayTab - 1].mode == Sequencer) { //EDIT PATTERN thing
if (i == 2 && channels[displayTab - 1].mode == 2) { //EDIT PATTERN thing
if (menuItem == i && insideTab) {
u8g2.drawBox(leftOffset + 54, ((i-1) * 11), 11, 11);
}
@ -201,52 +189,36 @@ void updateScreen() {
//Main Param
leftOffset = 29;
width = 55;
if (channels[displayTab - 1].mode == Clock) {
if (channels[displayTab - 1].mode == 0) {
valueStr = F("SUBDIVISION");
} else if (channels[displayTab - 1].mode == Random) {
} else if (channels[displayTab - 1].mode == 1) {
valueStr = F("SKIP CHANCE");
} else if (channels[displayTab - 1].mode == Sequencer) {
} else if (channels[displayTab - 1].mode == 2) {
valueStr = F("PATTERN");
} else if (channels[displayTab - 1].mode == Swing) {
valueStr = F("SWING");
} else if (channels[displayTab - 1].mode == Gate) {
valueStr = gateLengthTime[displayTab - 1];
}
}
if ((!insideTab && shiftBtnPushed) || (insideTab && menuItem == 0)) {
u8g2.drawButtonUTF8(leftOffset, 41, U8G2_BTN_BW1|U8G2_BTN_INV|U8G2_BTN_HCENTER, width, 0, 3, valueStr.c_str() );
} else {
u8g2.drawButtonUTF8(leftOffset, 41, U8G2_BTN_BW0|U8G2_BTN_HCENTER, width, 1, 2, valueStr.c_str() );
}
if (channels[displayTab - 1].mode == Clock) {
if (channels[displayTab - 1].mode == 0) {
if (subDivs[channels[displayTab - 1].subDiv] > 0) {
valueStr = F("/");
} else {
valueStr = F("x");
}
valueStr = valueStr + String(abs(subDivs[channels[displayTab - 1].subDiv]));
} else if (channels[displayTab - 1].mode == Random) {
valueStr = String(channels[displayTab - 1].random) + (channels[displayTab - 1].random == 0 ? "%" : "0%");
} else if (channels[displayTab - 1].mode == Sequencer) {
} else if (channels[displayTab - 1].mode == 1) {
valueStr = String(channels[displayTab - 1].random) + "0%";
} else if (channels[displayTab - 1].mode == 2) {
if (channels[displayTab - 1].seqPattern < 8) {
valueStr = F("A");
valueStr = valueStr + String(channels[displayTab - 1].seqPattern + 1);
} else if (channels[displayTab - 1].seqPattern >= 8 && channels[displayTab - 1].seqPattern < 16) {
} else {
valueStr = F("B");
valueStr = valueStr + String(channels[displayTab - 1].seqPattern - 7);
} else if (channels[displayTab - 1].seqPattern >= 16 && channels[displayTab - 1].seqPattern < 24) {
valueStr = F("C");
valueStr = valueStr + String(channels[displayTab - 1].seqPattern - 15);
} else if (channels[displayTab - 1].seqPattern >= 24 && channels[displayTab - 1].seqPattern < 32) {
valueStr = F("D");
valueStr = valueStr + String(channels[displayTab - 1].seqPattern - 23);
}
} else if (channels[displayTab - 1].mode == Swing) {
uint8_t swingVals[6] = {50, 58, 66, 75, 83, 92};
valueStr = String(swingVals[channels[displayTab - 1].swing]) + "%";
} else if (channels[displayTab - 1].mode == Gate) {
valueStr = String(channels[displayTab - 1].gate) + "%";
}
u8g2.setFont(stkL);
if ((!insideTab && shiftBtnPushed) || (insideTab && menuItem == 0 && (menuItemSelected || shiftBtnPushed))) {
@ -260,9 +232,9 @@ void updateScreen() {
//Tabs
u8g2.drawHLine(0, 53, 128);
u8g2.setFont(stkS);
uint8_t yPos = 61;
uint8_t xWidth = 12;
u8g2.setFont(velvetscreen);
byte yPos = 61;
byte xWidth = 12;
valueStr = F("w");
if (displayTab == 0) {
if (insideTab == true || shiftBtnPushed == true) {
@ -274,7 +246,7 @@ void updateScreen() {
u8g2.drawButtonUTF8(xWidth/2, yPos, U8G2_BTN_BW0|U8G2_BTN_HCENTER, xWidth, 0, 2, valueStr.c_str() );
}
for (uint8_t i = 1; i <= (extraChannel ? 7 : 6); i++) {
for (int i = 1; i <= 6; i++) {
valueStr = String(i);
if (displayTab == i) {
if (insideTab == true || shiftBtnPushed == true) {
@ -298,8 +270,8 @@ void updateScreen() {
//Edit Pattern Screen (Sequencer)
else if (displayScreen == 1) {
u8g2.setFont(stkS);
uint8_t pattern = channels[displayTab - 1].seqPattern;
u8g2.setFont(velvetscreen);
byte pattern = channels[displayTab - 1].seqPattern;
if (pattern < 8) {
valueStr = F("PATTERN A");
valueStr = valueStr + String(pattern + 1);
@ -307,31 +279,27 @@ void updateScreen() {
valueStr = F("PATTERN B");
valueStr = valueStr + String(pattern - 7);
}
u8g2.drawUTF8(8, 6, valueStr.c_str() );
valueStr = F("L: ");
//u8g2.drawUTF8(100, 5, valueStr.c_str() );
if (!isRecording && stepNumSelected == -1) {
u8g2.drawButtonUTF8(97, 6, U8G2_BTN_BW1|U8G2_BTN_INV, 5, 1, 2, valueStr.c_str() );
} else {
u8g2.drawButtonUTF8(97, 6, U8G2_BTN_BW0, 5, 1, 2, valueStr.c_str() );
u8g2.drawButtonUTF8(64, 5, U8G2_BTN_BW1|U8G2_BTN_HCENTER, 128, 0, 2, valueStr.c_str() );
for (byte i = 0; i < 8; i++) {
if (patternToEdit[i]) {
u8g2.drawUTF8(19 + i*12, 24, "q");
} else {
u8g2.drawUTF8(19 + i*12, 24, "p");
}
}
valueStr = String(sequences[patternToEdit].length + 1);
//u8g2.drawUTF8(110, 5, valueStr.c_str() );
if (!isRecording && stepNumSelected == -1 && (menuItemSelected || shiftBtnPushed)) {
u8g2.drawButtonUTF8(110, 6, U8G2_BTN_BW1, 8, 1, 2, valueStr.c_str() );
} else if (!isRecording && stepNumSelected == -1 && (!menuItemSelected || !shiftBtnPushed)) {
u8g2.drawButtonUTF8(110, 6, U8G2_BTN_BW1|U8G2_BTN_INV, 8, 1, 2, valueStr.c_str() );
} else {
u8g2.drawButtonUTF8(110, 6, U8G2_BTN_BW0, 8, 1, 2, valueStr.c_str() );
for (byte i = 8; i < 16; i++) {
if (patternToEdit[i]) {
u8g2.drawUTF8(19 + (i-8)*12, 40, "q");
} else {
u8g2.drawUTF8(19 + (i-8)*12, 40, "p");
}
}
u8g2.drawHLine(0, 8, 128);
for (uint8_t i = 0; i <= sequences[patternToEdit].length; i++) {
u8g2.drawUTF8(19 + (i % 8)*12, 33 - ((sequences[patternToEdit].length / 8) * 5) + ((i / 8) * 11), (bitRead(sequences[patternToEdit].sequence, i) ? "q" : "p"));
}
if (!isRecording && stepNumSelected >= 0) {
u8g2.drawFrame(16 + (stepNumSelected % 8)*12, 25 - ((sequences[patternToEdit].length / 8) * 5) + ((stepNumSelected / 8) * 11), 11, 11); //cursor
if (!isRecording) {
if (stepNumSelected < 8 ) {
u8g2.drawFrame(16 + stepNumSelected * 12, 16, 11, 11);
} else {
u8g2.drawFrame(16 + (stepNumSelected-8) * 12, 32, 11, 11);
}
}
if (isRecording) {
@ -346,9 +314,9 @@ void updateScreen() {
u8g2.drawStr(8, 5, valueStr.c_str() );
u8g2.drawStr(122 - (u8g2.getStrWidth(version.c_str())), 5, version.c_str() );
u8g2.drawHLine(0, 8, 128);
lastMenuItem = 4;
uint8_t width = 112;
for (uint8_t i = 0; i <= lastMenuItem; i++) {
lastMenuItem = 3;
byte width = 112;
for (byte i = 0; i <= lastMenuItem; i++) {
switch(i) {
case 0:
valueStr = F("CALIBRATE CV INS");
@ -360,9 +328,6 @@ void updateScreen() {
valueStr = F("REVERSE ENCODER");
break;
case 3:
valueStr = (extraChannel ? F("7TH CHANNEL: ON") : F("7TH CHANNEL: OFF"));
break;
case 4:
valueStr = F("FACTORY RESET");
break;
};

View File

@ -1,40 +0,0 @@
#pragma once
#define PPQN 24
#define PULSE_LENGTH 120 //1/10ms resolution. 12ms was failing at 1ms resolution at higher bpm. 60000/200/24 = 12.5 the max pulse length at 1ms resolution for 200bpm is 11ms
#define MAXBPM 200 //250 at 24ppqn with 5ms pulse will be 50/50 square wave
#define MINBPM 20
#define SCREEN_ADDRESS 0x3C
// Rev 2+ 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 uint8_t clockOutPin = 3;
const uint8_t outsPins[] = { 7, 8, 10, 6, 9, 11, clockOutPin };
bool rotateScreen = false;
bool reverseEnc = false;
/* Rev 1 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 100
#define EXT_INPUT_PIN 2 //needs to be an interrupt pin
#define ANALOGUE_INPUT_1_PIN A2
#define ANALOGUE_INPUT_2_PIN A1
const byte clockOutPin = 13;
const byte outsPins[6] = {6, 11, 7, 10, 8, 9, clockOutPin};
bool rotateScreen = true;
*/
#define bitFlip(value, bit) ((value) ^ (1UL << (bit)))

View File

@ -1,38 +0,0 @@
#pragma once
const PROGMEM uint8_t stkS[437] U8G2_FONT_SECTION("stk-s") =
"\64\0\2\2\3\3\2\3\4\5\5\0\0\5\0\5\0\0\221\0\0\1\230 \4\200\134%\11\255tT"
"R\271RI(\6\252\334T\31)\7\252\134bJ\12+\7\233\345\322J\0,\5\221T\4-\5\213"
"f\6.\5\211T\2/\6\244\354c\33\60\10\254\354T\64\223\2\61\7\353\354\222\254\6\62\11\254l"
"\66J*\217\0\63\11\254l\66J\32\215\4\64\10\254l\242\34\272\0\65\11\254l\206\336h$\0\66"
"\11\254\354T^\61)\0\67\10\254lF\216u\4\70\11\254\354TL*&\5\71\11\254\354TL;"
")\0:\6\231UR\0A\10\254\354T\34S\6B\11\254lV\34)\216\4C\11\254\354T\324\61"
")\0D\10\254lV\64G\2E\10\254l\206\36z\4F\10\254l\206^\71\3G\11\254\354TN"
"\63)\0H\10\254l\242\34S\6I\6\251T\206\0J\10\254\354k\231\24\0K\11\254l\242J\62"
"\225\1L\7\254lr{\4M\11\255t\362ZI\353\0N\11\255t\362TI\356\0O\10\254\354T"
"\64\223\2P\11\254lV\34)g\0Q\10\254\354T\264b\12R\10\254lV\34\251\31S\11\254\354"
"FF\32\215\4T\7\253dVl\1U\10\254l\242\63)\0V\11\255t\262Ne\312\21W\12\255"
"t\262J*\251.\0X\11\254l\242L*\312\0Y\12\255tr\252\63\312(\2Z\7\253df*"
"\7p\10\255\364V\266\323\2q\7\255\364\216\257\5r\10\253d\242\32*\2t\6\255t\376#w\11"
"\255\364V\245FN\13x\6\233dR\7\0\0\0\4\377\377\0";
const PROGMEM uint8_t stkL[592] U8G2_FONT_SECTION("stk-l") =
"\26\0\4\4\4\5\2\1\6\17\27\1\0\27\0\0\0\1\77\0\0\2\63%'\17\37\313\330R#&"
"\32!F\14\211I\310\24!\65\204(MF\21)Cd\304\10\62b\14\215\60Vb\334\20\0/\14"
"\272\336\336d\244\350\263q\343\0\60\37|\377\216!%*\10\35\263\253ChD\30\21bB\14\242S"
"\306lv\210\204\22Ef\0\61\24z\337\322\60R\205\314\234\31\61F\310\270\371\177\224\42\3\62\33|"
"\377\216)\64*\10\35\63\66r\206\304\314`c\252\34\301\221\263|\360\300\0\63\34|\377\216)\64*"
"\10\35\63\66r \71\332YIr\226\306\16\221P\203\312\14\0\64 |\377\226\220AC\306\20\31B"
"f\310\240\21\204F\214\32\61j\304(cv\366\200\305\312\371\0\65\32|\377\206\212-F\316\27\204\224"
"\254\30\65t\344,\215\35\42\241\6\225\31\0\66\33}\17\317\251\64+\206\235\63:/\314,aA\352"
"\234\335\235\42\261&\325\31\0\67\23|\377\302\212\7)\347Crt\70\345\300\221\363\16\0\70 |\377"
"\216)\64*\10\35\263\354\20\11\42d\20\235BC\204\4\241cvv\210\204\32Tf\0\71\32|\377"
"\216)\64*\10\35\263\263C$\226\250I\71_\14\42\241\6\225\31\0A\26}\17S\271Si(\31"
"\65d\324\210q\366\356\301w\366\273\1B$}\17C\42\65KF\221\30\66b\330\210a#\206\215\30"
"Eb\311&\243H\14;g\317\36\204`\261\4\0C\27}\17\317\251\64K\10!\63:\377\247\304F"
"\20\42\261F\21\22\0D\33}\17C\42\65KF\15\31\66b\330\210q\366\77;\66b\24\211%j"
"\22\1E\21|\377\302\7)\347%\42\214F\316/\37<\60I\7so\302\37$M$}\17\203\310"
"r\346N\245Q\263\202E\12)L\224\60Q\302\310\20#C\214\14\61\23\306L\30s\366\335\0T\15"
"}\17\303\7\251\206\316\377\377\12\0X)~\37\303@\203\307H\14\33B\210\14\21RC\206\241\63h"
"\222(I\203\346\220\15\31E\204\14!\42\303F\20;h\341\0x\24\312\336\302 CGH\240\61E"
"\312\14\222)\6Y\64\0\0\0\0\4\377\377\0";