examples
This commit is contained in:
+286
@@ -0,0 +1,286 @@
|
||||
//______________________/\\\\\__________________________/\\\______________________________/\\\__________________________________________________________
|
||||
// ____________________/\\\///__________________________\/\\\_____________________________\/\\\__________________________________________________________
|
||||
// ___________________/\\\______________________________\/\\\_____________________________\/\\\_____/\\\__/\\\_______________________________/\\\\\\\\___
|
||||
// _____/\\\\\\\\__/\\\\\\\\\_______/\\\\\______________\/\\\____________/\\\\\___________\/\\\____\//\\\/\\\___/\\\\\\\\\\_____/\\\\\\\\___/\\\////\\\__
|
||||
// ___/\\\//////__\////\\\//______/\\\///\\\____________\/\\\\\\\\\____/\\\///\\\____/\\\\\\\\\_____\//\\\\\___\/\\\//////____/\\\/////\\\_\//\\\\\\\\\__
|
||||
// __/\\\____________\/\\\_______/\\\__\//\\\___________\/\\\////\\\__/\\\__\//\\\__/\\\////\\\______\//\\\____\/\\\\\\\\\\__/\\\\\\\\\\\___\///////\\\__
|
||||
// _\//\\\___________\/\\\______\//\\\__/\\\____________\/\\\__\/\\\_\//\\\__/\\\__\/\\\__\/\\\___/\\_/\\\_____\////////\\\_\//\\///////__________\/\\\__
|
||||
// __\///\\\\\\\\____\/\\\_______\///\\\\\/_____________\/\\\\\\\\\___\///\\\\\/___\//\\\\\\\/\\_\//\\\\/_______/\\\\\\\\\\__\//\\\\\\\\\\________\/\\\\_
|
||||
// ____\////////_____\///__________\/////_______________\/////////______\/////______\///////\//___\////________\//////////____\//////////_________\////__
|
||||
// CFO BODYSEQ sequencer, 3 button version, reworked interaction, http://www.vsionhairies.info/
|
||||
|
||||
#define MIDI_CHANNEL 1
|
||||
#include <spi4teensy3.h>
|
||||
#include <EEPROM.h>
|
||||
#include <CFO_BODYSEQ.h>
|
||||
|
||||
#define NUM_TRACKS 8
|
||||
#define NUM_STEPS 8
|
||||
#define NUM_SAMPLES 8
|
||||
#define NUM_LEDS 8
|
||||
|
||||
int mode;
|
||||
unsigned long debounceTime = 100;
|
||||
unsigned long debounceTimeDefault = 100;
|
||||
unsigned long debounceTimeLong = 500;
|
||||
|
||||
int _bpm;
|
||||
|
||||
int trackPlaying = 0 ;
|
||||
int trackSelected = 0;
|
||||
int sampleSelected = 0;
|
||||
int stepSelected = 0;
|
||||
int trackChained = -1;
|
||||
|
||||
int s1;
|
||||
int indx = 0;
|
||||
int indxLED;
|
||||
uint8_t sample[NUM_TRACKS][NUM_SAMPLES][NUM_STEPS];
|
||||
|
||||
int leds;
|
||||
int chainedLedState = 0;
|
||||
unsigned long ledNow;
|
||||
unsigned long ledTime = 0;
|
||||
unsigned long ledPulse = 100;
|
||||
|
||||
bool inStartupMode = true;
|
||||
|
||||
|
||||
// old stuff
|
||||
const int seqLed[] = {3,4,5,6,7,8,9,10};
|
||||
const int statusLed1 = 13;
|
||||
//boolean debug = true;
|
||||
|
||||
/////////////
|
||||
// BUTTONS //
|
||||
/////////////
|
||||
#define NUM_BUTTONS 3
|
||||
const int buttonPin [] = {11,12,2};
|
||||
int buttonIndex = 0;
|
||||
int buttonRead = 0;
|
||||
int buttonChange = 0;
|
||||
int buttonState[] = {0, 0, 0};
|
||||
unsigned long buttonNow = 0;
|
||||
unsigned long buttonTime[] = {0, 0, 0};
|
||||
int machineState = 0;
|
||||
|
||||
//////////
|
||||
// KEYS //
|
||||
//////////
|
||||
#define NUM_KEYS 8
|
||||
#define KEY_THRESHOLD 15
|
||||
const int keyPin[] = {A2,A3,A4,A5,A6,A7,A8,A9};
|
||||
int keyIndex = 0;
|
||||
int keyRead = 0;
|
||||
int keyValue = 0;
|
||||
int keyChange = 0;
|
||||
int keyState[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
unsigned long keyNow = 0;
|
||||
unsigned long keyTime[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int keys;
|
||||
|
||||
|
||||
void setup() {
|
||||
Music.init();
|
||||
Music.setSampler(true);
|
||||
Music.setSynth(false);
|
||||
usbMIDI.setHandleNoteOff(OnNoteOff);
|
||||
usbMIDI.setHandleNoteOn(OnNoteOn);
|
||||
usbMIDI.setHandleControlChange(OnControlChange);
|
||||
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
|
||||
analogReadAveraging(32);
|
||||
Sequencer.init(120);
|
||||
// Sequencer.setInternalClock(true);
|
||||
s1 = Sequencer.newSequence(NOTE_16, &s1cb);
|
||||
// resetMemory();
|
||||
loadSequences();
|
||||
initInterface();
|
||||
Sequencer.startSequence(s1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
Sequencer.update();
|
||||
usbMIDI.read();
|
||||
Midi.checkSerialMidi();
|
||||
readButtons();
|
||||
readKeys();
|
||||
checkBPM();
|
||||
checkBitcrush();
|
||||
|
||||
switch(machineState) {
|
||||
case 0:
|
||||
playTrack();
|
||||
break;
|
||||
case 1:
|
||||
selectStep();
|
||||
break;
|
||||
case 2:
|
||||
selectSample();
|
||||
break;
|
||||
case 3:
|
||||
selectTrack();
|
||||
break;
|
||||
case 4:
|
||||
selectTrack();
|
||||
break;
|
||||
case 5: // nothing
|
||||
chainTrack();
|
||||
break;
|
||||
case 6:
|
||||
copyTrack();
|
||||
break;
|
||||
case 7:
|
||||
clearTrack();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateLEDs();
|
||||
}
|
||||
|
||||
|
||||
void playTrack() {
|
||||
if(keyChange && keys) {
|
||||
Serial.println("PLAY TRACK");
|
||||
for(int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keys & (1 << i)) {
|
||||
if(trackPlaying == i) trackChained = -1;
|
||||
if(trackChained < 0) trackPlaying = i;
|
||||
else trackChained = i;
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void selectStep() {
|
||||
if(keyChange) {
|
||||
Serial.println("SELECT STEP");
|
||||
for(int k = 0; k < NUM_KEYS; k++) {
|
||||
if(keys & (1 << k)) {
|
||||
stepSelected = k;
|
||||
int j = sampleSelected;
|
||||
int i = trackSelected;
|
||||
sample[i][j][k] ^= 1;
|
||||
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), sample[i][j][k]);
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void selectSample() {
|
||||
if(keyChange) {
|
||||
Serial.println("SELECT SAMPLE");
|
||||
for(int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keys & (1 << i)) {
|
||||
sampleSelected = i;
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void selectTrack() {
|
||||
if(keyChange) {
|
||||
Serial.println("SELECT TRACK");
|
||||
for(int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keys & (1 << i)) {
|
||||
trackSelected = i;
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void chainTrack() {
|
||||
if(keyChange) {
|
||||
Serial.println("SELECT TRACK");
|
||||
for(int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keys & (1 << i)) {
|
||||
if(i == trackChained) trackChained = -1;
|
||||
else trackChained = i;
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void copyTrack() {
|
||||
if(keyChange) {
|
||||
debounceTime = debounceTimeLong;
|
||||
Serial.println("COPY TRACK");
|
||||
for(int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keys & (1 << i)) {
|
||||
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||
for(int k=0; k<NUM_STEPS; k++) {
|
||||
sample[i][j][k] = sample[trackSelected][j][k];
|
||||
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), sample[i][j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
debounceTime = debounceTimeDefault;
|
||||
}
|
||||
}
|
||||
|
||||
void clearTrack() {
|
||||
if(keyChange) {
|
||||
Serial.println("CLEAR TRACK");
|
||||
for(int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keys & (1 << i)) {
|
||||
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||
for(int k=0; k<NUM_STEPS; k++) {
|
||||
sample[i][j][k] = 0;
|
||||
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
keyChange = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void resetMemory() {
|
||||
for(int i=0; i<NUM_TRACKS; i++) {
|
||||
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||
for(int k=0; k<NUM_STEPS; k++) {
|
||||
EEPROM.write(k + NUM_SAMPLES * (j + i * NUM_TRACKS), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadSequences() {
|
||||
for(int i=0; i<NUM_TRACKS; i++) {
|
||||
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||
for(int k=0; k<NUM_STEPS; k++) {
|
||||
sample[i][j][k] = EEPROM.read(k + NUM_SAMPLES * (j + i * NUM_TRACKS));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void s1cb() {
|
||||
indxLED = indx;
|
||||
for(int i=0; i<NUM_SAMPLES; i++) {
|
||||
if(sample[trackPlaying][i][indx]) Music.noteOnSample(i);
|
||||
}
|
||||
indx++;
|
||||
if(indx >= NUM_STEPS) {
|
||||
indx = 0;
|
||||
if(trackChained < 0);
|
||||
else {
|
||||
int t = trackPlaying;
|
||||
trackPlaying = trackChained;
|
||||
trackChained = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+201
@@ -0,0 +1,201 @@
|
||||
/////////////
|
||||
// BUTTONS //
|
||||
/////////////
|
||||
void readButtons() {
|
||||
// buttons are active low
|
||||
for(int i = 0; i < NUM_BUTTONS; i++) {
|
||||
// int i = buttonIndex++;
|
||||
// if(buttonIndex >= NUM_BUTTONS) buttonIndex = 0;
|
||||
buttonNow = millis();
|
||||
if((buttonNow - buttonTime[i]) > debounceTime) {
|
||||
buttonRead = digitalRead(buttonPin[i]);
|
||||
if(buttonRead != buttonState[i]) {
|
||||
buttonState[i] = buttonRead;
|
||||
buttonChange |= 1<<i;
|
||||
buttonTime[i] = buttonNow;
|
||||
machineState = 7 - buttonState[0] - buttonState[1] * 2 - buttonState[2] * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////
|
||||
// KEYS //
|
||||
//////////
|
||||
void readKeys() {
|
||||
int keyr = 0;
|
||||
int keyv = 0;
|
||||
for (int i = 0; i < NUM_KEYS; i++) {
|
||||
keyNow = millis();
|
||||
if((keyNow - keyTime[i]) > debounceTime) {
|
||||
keyRead = analogRead(keyPin[i]);
|
||||
if(keyRead > KEY_THRESHOLD) {
|
||||
keyValue = 1;
|
||||
} else {
|
||||
keyValue = 0;
|
||||
}
|
||||
if(i == 0) {
|
||||
keyr = keyRead;
|
||||
keyv = keyValue;
|
||||
}
|
||||
// keyValue = (keyRead > KEY_THRESHOLD) ? 1 : 0 ;
|
||||
if(keyState[i] != keyValue) {
|
||||
keyState[i] = keyValue;
|
||||
keyChange |= 1<<i;
|
||||
keyTime[i] = keyNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < NUM_KEYS; i++) {
|
||||
if(keyState[i] == 1) {
|
||||
keys |= (1<<i);
|
||||
} else if(keyState[i] == 0) {
|
||||
keys &= ~(1<<i);
|
||||
}
|
||||
}
|
||||
// Serial.printf("keyTime[0]=%10ld, keyr=%i, keyv=%i - keyState is %i%i%i%i%i%i%i%i, keys is %X \n", keyTime[0], keyr, keyv, keyState[0], keyState[1], keyState[2], keyState[3], keyState[4], keyState[5], keyState[6], keyState[7], keys);
|
||||
}
|
||||
|
||||
|
||||
//////////
|
||||
// POTS //
|
||||
//////////
|
||||
void checkBPM() {
|
||||
int bpm = analogRead(A0)>>2;
|
||||
if(bpm != _bpm) {
|
||||
_bpm = bpm;
|
||||
Serial.print("BPM set to ");
|
||||
Serial.println(_bpm);
|
||||
Sequencer.setbpm(_bpm);
|
||||
if(_bpm == 0) {
|
||||
Midi.setMidiIn(true);
|
||||
Midi.setMidiThru(true);
|
||||
Midi.setMidiOut(true);
|
||||
Midi.setMidiClockIn(true);
|
||||
Midi.setMidiClockThru(true);
|
||||
Midi.setMidiClockOut(true);
|
||||
Sequencer.setInternalClock(false);
|
||||
} else {
|
||||
Midi.setMidiIn(false);
|
||||
Midi.setMidiThru(false);
|
||||
Midi.setMidiOut(false);
|
||||
Midi.setMidiClockIn(false);
|
||||
Midi.setMidiClockThru(false);
|
||||
Midi.setMidiClockOut(false);
|
||||
Sequencer.setInternalClock(true);
|
||||
// Sequencer.sequencerContinue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkBitcrush() {
|
||||
int bc = (1024 - analogRead(A1)) >> 7;
|
||||
Music.setBitcrush(bc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void initInterface() {
|
||||
pinMode(buttonPin[0], INPUT_PULLUP);
|
||||
pinMode(buttonPin[1], INPUT_PULLUP);
|
||||
pinMode(buttonPin[2], INPUT_PULLUP);
|
||||
pinMode(statusLed1,OUTPUT);
|
||||
for (int i = 0; i<8; i++) {
|
||||
pinMode(seqLed[i], OUTPUT);
|
||||
}
|
||||
startupAnimation();
|
||||
}
|
||||
|
||||
|
||||
void updateLEDs() {
|
||||
ledNow = millis();
|
||||
int t = trackSelected;
|
||||
int s = sampleSelected;
|
||||
leds = 0;
|
||||
switch(machineState) {
|
||||
case 0: // PLAY TRACK
|
||||
leds |= (1 << trackPlaying);
|
||||
if(trackChained >= 0) {
|
||||
if((ledNow - ledTime) > ledPulse) {
|
||||
chainedLedState ^= 1;
|
||||
ledTime = ledNow;
|
||||
}
|
||||
leds |= (chainedLedState << trackChained);
|
||||
}
|
||||
break;
|
||||
case 1: // SELECT STEP
|
||||
// leds = 0;
|
||||
for(int i=0; i<NUM_STEPS; i++) {
|
||||
leds |= (sample[t][s][i] << i);
|
||||
}
|
||||
break;
|
||||
case 2: // SELECT SAMPLE
|
||||
leds |= (1 << sampleSelected);
|
||||
break;
|
||||
case 3: // SELECT TRACK
|
||||
leds |= (1 << trackSelected);
|
||||
break;
|
||||
case 4: // SELECT TRACK
|
||||
leds |= (1 << trackSelected);
|
||||
break;
|
||||
case 5: // CHAIN TRACKS PLAYING
|
||||
leds |= (1 << trackPlaying);
|
||||
if(trackChained >= 0) {
|
||||
if((ledNow - ledTime) > ledPulse) {
|
||||
chainedLedState ^= 1;
|
||||
ledTime = ledNow;
|
||||
}
|
||||
leds |= (chainedLedState << trackChained);
|
||||
}
|
||||
break;
|
||||
case 6: // COPY TRACK
|
||||
leds |= (1 << trackSelected);
|
||||
break;
|
||||
case 7: // CLEAR TRACK
|
||||
for(int i=0; i<NUM_KEYS; i++) {
|
||||
for(int j=0; j<NUM_SAMPLES; j++) {
|
||||
for(int k=0; k<NUM_STEPS; k++) {
|
||||
leds |= (sample[i][j][k] << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i<8; i++) {
|
||||
leds |= (1 << indxLED);
|
||||
digitalWrite(seqLed[i], leds & (1 << i));
|
||||
// leds ^= (1 << indxLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void startupAnimation() {
|
||||
digitalWrite(statusLed1, HIGH);
|
||||
|
||||
for (int i = 0; i<8; i++) {
|
||||
digitalWrite(seqLed[i],HIGH);
|
||||
delay(30);
|
||||
}
|
||||
for (int i = 0; i<8; i++) {
|
||||
digitalWrite(seqLed[i],LOW);
|
||||
delay(30);
|
||||
}
|
||||
|
||||
for (int i = 0; i<8; i++) {
|
||||
digitalWrite(seqLed[7-i],HIGH);
|
||||
delay(30);
|
||||
}
|
||||
for (int i = 0; i<8; i++) {
|
||||
digitalWrite(seqLed[7-i],LOW);
|
||||
delay(30);
|
||||
}
|
||||
|
||||
digitalWrite(statusLed1, LOW);
|
||||
|
||||
delay(100);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user