sorry, this code is very messy as I have not yet learned how to work with classes.
the problem is, I have 10 presets, and they work fine within a power cycle.
all my changes are saved and loaded correctly.
however, if I reboot the daisy, presets are empty.
thanks in advance, this mistake must be very small,
I have a version of this with a single preset which is saved with a button and loads when the device starts up, and it works absolutely perfect
#include "daisysp.h"
#include <stdio.h>
#include <string.h>
#include "daisy_seed.h"
#include "dev/oled_ssd130x.h"
#include "dev/mpr121.h"
#include "Utility/dsp.h"
using namespace daisysp;
using namespace daisy;
using MyOledDisplay = OledDisplay<SSD130xI2c128x64Driver>;
dsy_gpio ledR_1_pin, ledG_1_pin, ledB_1_pin;
dsy_gpio muxpin, muxbpin, muxcpin;
uint16_t currTouched;
uint16_t lastTouched;
DaisySeed hw;
MyOledDisplay display;
Mpr121I2C mpr121;
Encoder encoder;
Switch button;
Switch buttonP;
Switch buttonsave;
// Define display dimensions
const int DISPLAY_WIDTH = 128;
const int DISPLAY_HEIGHT = 64;
// Define display buffer size
const int DISPLAY_BUFFER_SIZE = (DISPLAY_WIDTH * DISPLAY_HEIGHT) / 8;
// Define display buffer
uint8_t displayBuffer[DISPLAY_BUFFER_SIZE];
// Number of presets
const int NUM_PRESETS = 10;
//Setting Struct containing parameters we want to save to flash
struct Settings {
int p1[8]; // Sequence Pitch
int p2[8]; // Beat
int p3[8]; // Sequence Pitch
int p4[8]; // Beat
int p5; //lfoFenv
int p6; //lfoFamt
int p7; //lfoAenv
int p8; //lfoAamt
int p9; //osc2pv
int p10; //scale
//Overloading the != operator
//This is necessary as this operator is used in the PersistentStorage source code
bool operator!=(const Settings& a) const {
for (int i = 0; i < 8; ++i) {
if (p1[i] != a.p1[i] || p2[i] != a.p2[i] || p3[i] != a.p3[i] || p4[i] != a.p4[i]) {
return true;
}
}
return p5 != a.p5 || p6 != a.p6 || p7 != a.p7 || p8 != a.p8 || p9 != a.p9 || p10 != a.p10;
}
};
Settings presets[NUM_PRESETS];
int current_preset = 0;
static Oscillator osc;
static Oscillator osc2;
static Oscillator lfo;
static Svf filt;
static Metro clock;
static Adsr env;
static Adsr envM;
float osc2F=24;
float gate;
float envout;
float oscF=24;
int seqF;
float Dseq;
float trig;
float sig;
int decO=0;
int trigo = 0;
float keyF=0;
int ctfO=0;
int beat[8] {1, 1, 1, 1, 1, 1, 1, 1};
int beato[8] {0, 0, 0, 0, 0 ,0 ,0 ,0};
int seqP[8] {0, 0, 0, 0, 0, 0, 0, 0};
float seqD[8] {0, 0, 0, 0, 0, 0, 0, 0};
float seDc[8] {0, 0, 0, 0, 0, 0, 0, 0};
int Pval=0;//enc parameter select
int Pval2=0;
int step = 0;
int cnt = 0;
int stepped = 0;
int steppedO = 0;
int oct=0;
int seqlen = 8;
float sDec = 0;
int pg=0;
int pgtrig=0;
int pgtrigO=0;
int lfoFenv=0;
int lfoAenv=0;
int lfoFamt=0;
int lfoAamt=0;
int osc2seq=0;
int subP=0;
float lfo_=0;
float lfoF_=0;
float lfoA_=0;
int osc2pv=0;
int scale=0;
int sub2=0;
int output_value = 0;
// Buffer to store the previous state of the display
uint8_t prevDisplayBuffer[128 * 64 / 8];
uint8_t currentDisplayBuffer[128 * 64 / 8];
// Function to update only the changed pixels
void updateDisplay(uint8_t* currentBuffer) {
// Compare the current buffer with the previous buffer
for (int i = 0; i < 128 * 64 / 8; i++) {
if (currentBuffer[i] != prevDisplayBuffer[i]) {
// Calculate the x, y position of the changed pixel
int x = (i % 128);
int y = (i / 128);
// Update the pixel on the display
display.DrawPixel(x, y, currentBuffer[i]);
// Update the corresponding pixel in the previous buffer
prevDisplayBuffer[i] = currentBuffer[i];
}
}
// Send the updated pixels to the display
display.Update();
}
//Persistent Storage Declaration. Using type Settings and passed the devices qspi handle
// Erstelle eine Instanz der PersistentStorage-Klasse fĂźr deine Presets
daisy::PersistentStorage<Settings> SavedSettings(hw.qspi);
// Create an array of settings to hold multiple presets
bool use_preset = false;
bool trigger_save = false;
void LoadPreset(int preset_index) {
// Ensure SavedSettings.Init() has been called before Load()
if (preset_index < 0 || preset_index >= NUM_PRESETS) return; // Invalid preset index
const Settings& preset = presets[preset_index];
for (int i = 0; i < 8; i++) {
seqP[i] = preset.p1[i];
beat[i] = preset.p2[i];
seqD[i] = preset.p3[i];
seDc[i] = preset.p4[i];
}
lfoFenv = preset.p5;
lfoFamt = preset.p6;
lfoAenv = preset.p7;
lfoAamt = preset.p8;
osc2pv = preset.p9;
scale = preset.p10;
}
void SavePreset(int preset_index) {
if (preset_index < 0 || preset_index >= NUM_PRESETS) return; // Invalid preset index
Settings& preset = presets[preset_index];
for (int i = 0; i < 8; i++) {
preset.p1[i] = seqP[i];
preset.p2[i] = beat[i];
preset.p3[i] = seqD[i];
preset.p4[i] = seDc[i];
}
preset.p5 = lfoFenv;
preset.p6 = lfoFamt;
preset.p7 = lfoAenv;
preset.p8 = lfoAamt;
preset.p9 = osc2pv;
preset.p10 = scale;
trigger_save = true;
}
// P R E S E T
void ProcessControls() {
int increment3 = encoder.Increment();
buttonsave.Debounce();
buttonP.Debounce();
if(buttonP.RisingEdge() && pg==0)
{
output_value += 1;
output_value %= 8;
}
if(buttonP.RisingEdge() && pg==1)
{
subP += 1;
subP %= 2;
}
if(buttonP.RisingEdge() && pg==2)
{
sub2 += 1;
sub2 %= 2;
}
if (pg == 2) {
if (increment3 > 0) {
current_preset = (current_preset + 1) % NUM_PRESETS;
} else if (increment3 < 0) {
current_preset = (current_preset - 1 + NUM_PRESETS) % NUM_PRESETS;
}
if (encoder.RisingEdge()) {
if(sub2==0){
LoadPreset(current_preset);
display.Fill(false);
display.SetCursor(38, 24);
display.WriteString("Loaded", Font_11x18, true);
updateDisplay(currentDisplayBuffer);
}
else if(sub2==1){
SavePreset(current_preset);
display.Fill(false);
display.SetCursor(38, 24);
display.WriteString("Saved", Font_11x18, true);
updateDisplay(currentDisplayBuffer);
}
}
}
if(encoder.FallingEdge() || encoder.Increment() || button.FallingEdge()|| buttonP.FallingEdge() ||
(encoder.TimeHeldMs() > 200) || hw.adc.GetFloat(4)> 0.5)
{
if(pg==0){
display.Fill(false);
//display.SetCursor(2, 0);
//display.WriteString("Gate & P & Mod-Dec", Font_7x10, true);
display.DrawCircle(10, 56, beat[0] *2+1, true);
display.DrawCircle(25, 56, beat[1] *2+1, true);
display.DrawCircle(40, 56, beat[2] *2+1, true);
display.DrawCircle(55, 56, beat[3] *2+1, true);
display.DrawCircle(70, 56, beat[4] *2+1, true);
display.DrawCircle(85, 56, beat[5] *2+1, true);
display.DrawCircle(100, 56, beat[6] *2+1, true);
display.DrawCircle(115, 56, beat[7] *2+1, true);
display.DrawLine(128, 36-Pval*18, 128, 36-Pval*18+12, true);
display.DrawLine(output_value*15 + 4, 63, output_value*15+16, 63, true);
display.DrawArc(10, 42, 6, 90, seqP[0]*-14, true);
display.DrawArc(25, 42, 6, 90, seqP[1]*-14, true);
display.DrawArc(40, 42, 6, 90, seqP[2]*-14, true);
display.DrawArc(55, 42, 6, 90, seqP[3]*-14, true);
display.DrawArc(70, 42, 6, 90, seqP[4]*-14, true);
display.DrawArc(85, 42, 6, 90, seqP[5]*-14, true);
display.DrawArc(100, 42, 6, 90, seqP[6]*-14, true);
display.DrawArc(115, 42, 6, 90, seqP[7]*-14, true);
display.DrawArc(10, 24, 6, 90, seqD[0]*-12, true);
display.DrawArc(25, 24, 6, 90, seqD[1]*-12, true);
display.DrawArc(40, 24, 6, 90, seqD[2]*-12, true);
display.DrawArc(55, 24, 6, 90, seqD[3]*-12, true);
display.DrawArc(70, 24, 6, 90, seqD[4]*-12, true);
display.DrawArc(85, 24, 6, 90, seqD[5]*-12, true);
display.DrawArc(100, 24, 6, 90, seqD[6]*-12, true);
display.DrawArc(115, 24, 6, 90, seqD[7]*-12, true);
display.DrawArc(10, 6, 6, 90, seDc[0]*-12, true);
display.DrawArc(25, 6, 6, 90, seDc[1]*-12, true);
display.DrawArc(40, 6, 6, 90, seDc[2]*-12, true);
display.DrawArc(55, 6, 6, 90, seDc[3]*-12, true);
display.DrawArc(70, 6, 6, 90, seDc[4]*-12, true);
display.DrawArc(85, 6, 6, 90, seDc[5]*-12, true);
display.DrawArc(100, 6, 6, 90, seDc[6]*-12, true);
display.DrawArc(115, 6, 6, 90, seDc[7]*-12, true);
}
else if (pg==1){
display.Fill(false);
display.DrawLine(128, Pval2*16, 128, Pval2*16+14, true);
display.DrawLine(subP*36 + 54, 63, subP*36 + 54 + 32, 63, true);
display.SetCursor(2, 4);
display.WriteString("LFO F", Font_7x10, true);
display.DrawArc(114, 8, 6, 90, lfoFamt*-12, true);
switch(lfoFenv){
case 0: display.SetCursor(54, 4);
display.WriteString("Off", Font_7x10, true); break;
case 1: display.SetCursor(54, 4);
display.WriteString("Env 1", Font_7x10, true); break;
case 2: display.SetCursor(54, 4);
display.WriteString("Env 2", Font_7x10, true); break;
default: 0; break;
}
display.SetCursor(2, 20);
display.WriteString("LFO A", Font_7x10, true);
display.DrawArc(114, 24, 6, 90, lfoAamt*-12, true);
switch(lfoAenv){
case 0: display.SetCursor(54, 20);
display.WriteString("Off", Font_7x10, true); break;
case 1: display.SetCursor(54, 20);
display.WriteString("Env 1", Font_7x10, true); break;
case 2: display.SetCursor(54, 20);
display.WriteString("Env 2", Font_7x10, true); break;
default: 0; break;
}
display.SetCursor(2, 36);
display.WriteString("Osc2 F", Font_7x10, true);
display.DrawArc(114, 40, 1, 90, 360, true);
switch(osc2pv){
case 0: display.SetCursor(54, 36);
display.WriteString("Key+Seq", Font_7x10, true); break;
case 1: display.SetCursor(54, 36);
display.WriteString("Key Only", Font_7x10, true); break;
case 2: display.SetCursor(54, 36);
display.WriteString("None", Font_7x10, true); break;
default: 0; break;
}
display.SetCursor(2, 52);
display.WriteString("Scale", Font_7x10, true);
display.DrawArc(114, 56, 1, 90, 360, true);
switch(scale){
case 0: display.SetCursor(54, 52);
display.WriteString("Chroma", Font_7x10, true); break;
case 1: display.SetCursor(54, 52);
display.WriteString("Major", Font_7x10, true); break;
case 2: display.SetCursor(54, 52);
display.WriteString("Minor", Font_7x10, true); break;
case 3: display.SetCursor(54, 52);
display.WriteString("Penta", Font_7x10, true); break;
default: 0; break;
}
}
if(pg==2){
display.Fill(false);
display.SetCursor(40, 2);
display.WriteString("Preset", Font_7x10, true);
display.SetCursor(50, 22);
FixedCapStr<16> str("");
str.AppendInt(current_preset);
display.WriteString(str, Font_11x18, true);
display.SetCursor(20, 50);
display.WriteString("Load", Font_7x10, true);
display.SetCursor(80, 50);
display.WriteString("Save", Font_7x10, true);
display.DrawLine(sub2*36 + 20, 63, sub2*36 + 20 + 40, 63, true);
}
// Update only the changed pixels
updateDisplay(currentDisplayBuffer);
//display.Update();
//System :: Delay(1);
}
}
static void AudioCallback(AudioHandle::InterleavingInputBuffer in,
AudioHandle::InterleavingOutputBuffer out,
size_t size)
{
for(size_t i = 0; i < size; i += 2)
{
// Use envelope to control the amplitude of the oscillator.
envout = env.Process(trig && gate);
osc.SetAmp(envout*.5);
osc2.SetAmp(envout*.5);
sig = osc.Process() + osc2.Process();
filt.Process(sig);
// left out
out[i] = filt.Low();
// right out
out[i + 1] = filt.Low();
}
}
int main(void)
{
// Initialize the previous display buffer to all zeros
memset(prevDisplayBuffer, 0, sizeof(prevDisplayBuffer));
// initialize seed hardware and oscillator daisysp module
float sample_rate = 96000;
hw.Configure();
hw.Init();
hw.SetAudioBlockSize(2);
hw.SetAudioSampleRate(SaiHandle::Config::SampleRate::SAI_96KHZ);
sample_rate = hw.AudioSampleRate();
// Initialize PersistentStorage with default settings
Settings DefaultSettings = {{12, 24, 48, 24, 12, 0, 0, 0}, {0, 1, 0, 1, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},0,0,0,0,0,0};
SavedSettings.Init(DefaultSettings);
// Load settings on boot
LoadPreset(0);
//Set button to pin 28, to be updated at a 1kHz samplerate
button.Init(hw.GetPin(9), 100);
buttonP.Init(hw.GetPin(10), 100);
buttonsave.Init(hw.GetPin(26), 100);
osc.Init(sample_rate);
osc2.Init(sample_rate);
lfo.Init(sample_rate);
//init metro object
clock.Init(2, sample_rate);
clock.SetFreq (200);
//Set envelope parameters
env.Init(sample_rate);
env.SetTime(ADSR_SEG_ATTACK, .1);
env.SetTime(ADSR_SEG_DECAY, .5);
env.SetTime(ADSR_SEG_RELEASE, .5);
env.SetSustainLevel(.5);
//Mod>Env Init
envM.Init(sample_rate);
envM.SetTime(ADSR_SEG_ATTACK, .1);
envM.SetTime(ADSR_SEG_DECAY, .5);
envM.SetTime(ADSR_SEG_RELEASE, .5);
envM.SetSustainLevel(.5);
// Set parameters for oscillator
osc.SetWaveform(4);
osc.SetFreq(220);
osc.SetAmp(0.5);
// Set parameters for oscillator
osc2.SetWaveform(4);
osc2.SetFreq(220);
osc2.SetAmp(0.5);
lfo.SetWaveform(0);
lfo.SetFreq(.5);
// Initialize Filter, and set parameters.
filt.Init(sample_rate);
filt.SetFreq(500.0);
filt.SetRes(0.85);
filt.SetDrive(0.8);
// R 1 on pin 27
ledR_1_pin.pin = hw.GetPin(28);
ledR_1_pin.mode = DSY_GPIO_MODE_OUTPUT_PP;
ledR_1_pin.pull = DSY_GPIO_NOPULL;
dsy_gpio_init(&ledR_1_pin);
dsy_gpio_write(&ledR_1_pin, true);
// R 1 on pin 27
ledG_1_pin.pin = hw.GetPin(29);
ledG_1_pin.mode = DSY_GPIO_MODE_OUTPUT_PP;
ledG_1_pin.pull = DSY_GPIO_NOPULL;
dsy_gpio_init(&ledG_1_pin);
dsy_gpio_write(&ledG_1_pin, true);
// R 1 on pin 27
ledB_1_pin.pin = hw.GetPin(30);
ledB_1_pin.mode = DSY_GPIO_MODE_OUTPUT_PP;
ledB_1_pin.pull = DSY_GPIO_NOPULL;
dsy_gpio_init(&ledB_1_pin);
dsy_gpio_write(&ledB_1_pin, true);
// muxing out
muxpin.pin = hw.GetPin(13);
muxpin.mode = DSY_GPIO_MODE_OUTPUT_PP;
muxpin.pull = DSY_GPIO_NOPULL;
dsy_gpio_init(&muxpin);
dsy_gpio_write(&muxpin, false);
muxbpin.pin = hw.GetPin(14);
muxbpin.mode = DSY_GPIO_MODE_OUTPUT_PP;
muxbpin.pull = DSY_GPIO_NOPULL;
dsy_gpio_init(&muxbpin);
dsy_gpio_write(&muxbpin, false);
muxcpin.pin = hw.GetPin(27);
muxcpin.mode = DSY_GPIO_MODE_OUTPUT_PP;
muxcpin.pull = DSY_GPIO_NOPULL;
dsy_gpio_init(&muxcpin);
dsy_gpio_write(&muxcpin, false);
//Configure pin 21 as an ADC input. This is where we'll read the knob.
// Create an array of two AdcChannelConfig objects
const int num_adc_channels = 11;
AdcChannelConfig my_adc_config[num_adc_channels];
// Initialize the first one connected to A0
my_adc_config[0].InitSingle(hw.GetPin(21));
my_adc_config[1].InitSingle(hw.GetPin(20));
my_adc_config[2].InitSingle(hw.GetPin(19));
my_adc_config[3].InitSingle(hw.GetPin(18));
my_adc_config[4].InitSingle(hw.GetPin(17));
my_adc_config[5].InitSingle(hw.GetPin(16));
my_adc_config[6].InitSingle(hw.GetPin(22));
my_adc_config[7].InitSingle(hw.GetPin(23));
my_adc_config[8].InitSingle(hw.GetPin(24));
my_adc_config[9].InitMux(hw.GetPin(15), 8, seed::D3, seed::D4, seed::D5);
my_adc_config[10].InitMux(hw.GetPin(25), 8, seed::D0, seed::D1, seed::D2);
//Initialize the adc with the config we just made
hw.adc.Init(my_adc_config, num_adc_channels);
//Start reading values
hw.adc.Start();
/** Initialize our Encoder */
encoder.Init(seed::D6, seed::D7, seed::D8);
// start callback
hw.StartAudio(AudioCallback);
// touch works
// Initialize MPR121 with I2C configuration
Mpr121I2C::Config mprConfig;
mprConfig.transport_config.periph = I2CHandle::Config::Peripheral::I2C_1;
mprConfig.transport_config.speed = I2CHandle::Config::Speed::I2C_400KHZ;
mprConfig.transport_config.mode = I2CHandle::Config::Mode::I2C_MASTER;
mprConfig.transport_config.scl = Pin(PORTB,8); // Replace with your SCL pin
mprConfig.transport_config.sda = Pin(PORTB,9); // Replace with your SDA pin
// Set additional MPR121 configuration if needed
mprConfig.touch_threshold = 12;
mprConfig.release_threshold = 6;
if(mpr121.Init(mprConfig) != Mpr121I2C::OK)
{
// Handle initialization error
while(1)
{
// Error handling code (blinking LED, etc.)
}
}
// Setup to print
hw.StartLog();
/** Create a variable to store the value we'll print out to USB */
// oled
// Configure the Display
MyOledDisplay::Config disp_cfg;
disp_cfg.driver_config.transport_config.i2c_address = 0x3C;
disp_cfg.driver_config.transport_config.i2c_config.periph = I2CHandle::Config::Peripheral::I2C_1;
disp_cfg.driver_config.transport_config.i2c_config.speed = I2CHandle::Config::Speed::I2C_1MHZ;
disp_cfg.driver_config.transport_config.i2c_config.mode = I2CHandle::Config::Mode::I2C_MASTER;
disp_cfg.driver_config.transport_config.i2c_config.pin_config.scl = {DSY_GPIOB, 8};
disp_cfg.driver_config.transport_config.i2c_config.pin_config.sda = {DSY_GPIOB, 9};
// And Initialize
display.Init(disp_cfg);
display.Fill(false);
display.SetCursor(20, 10);
display.WriteString("MONOFONK", Font_11x18, true);
display.SetCursor(2, 42);
display.WriteString("Pointless Innovations", Font_6x8, true);
display.Update();
while(1) {
if(trigger_save) {
SavedSettings.Save(); // Writing locally stored settings to the external flash
trigger_save = false;
}
ProcessControls();
//E N C O D E R
encoder.Debounce();
//Pager
if(hw.adc.GetFloat(4) > .5f)
{
hw.SetLed(true);
pgtrig=1;
if(pgtrigO!=pgtrig){
pg++;
pg %= 3;
}
}
else {pgtrig=0;}
pgtrigO=pgtrig;
if(pg ==0){
if(encoder.FallingEdge() && pg==0){Pval++;
if (Pval>2) {Pval=0;}}
int increment = encoder.Increment();
button.Debounce();
if(button.RisingEdge() && pg==0){
if (beat[output_value] == 1)
{
beat[output_value] = 0;
}
else
{
beat[output_value] = 1;
}
}
if((Pval==0) && (increment > 0) && pg==0)
{
seqP[output_value] += 1;
hw.PrintLine("Pitch:\t%d", seqP[output_value]);
}
else if((Pval==0) && (increment < 0))
{
seqP[output_value] -= 1;
hw.PrintLine("Pitch:\t%d", seqP[output_value]);
}
if((Pval==1) && (increment > 0) && pg==0)
{
seqD[output_value] += 1;
}
else if((Pval==1) && (increment < 0) && pg==0)
{
seqD[output_value] -= 1;
}
if((Pval==2) && (increment > 0) && pg==0)
{
seDc[output_value] += 1;
}
else if((Pval==2) && (increment < 0) && pg==0)
{
seDc[output_value] -= 1;
}
if ((encoder.TimeHeldMs() > 200) && pg==0)
{
seqP[output_value] = 0;
seqD[output_value] = 0;
beat[output_value] = 1;
seDc[output_value] = 0;
}
}
// PAGE 1
if(pg == 1){
if(encoder.FallingEdge()) {Pval2++; Pval2 %= 4;}
int increment2 = encoder.Increment();
if((subP==0) && (Pval2==0)&&(increment2 > 0) )
{
lfoFenv += 1;
lfoFenv %= 3;
}
else if((subP==0) && (Pval2==0) && (increment2 < 0))
{
lfoFenv -= 1;
if(lfoFenv < 0){lfoFenv = 2;}
}
if((subP==1) && (Pval2==0) && (increment2 > 0) )
{
lfoFamt += 1;
}
else if((subP==1) && (Pval2==0) && (increment2 < 0) )
{
lfoFamt -= 1;
}
if((subP==0) && (Pval2==1) && (increment2 > 0) )
{
lfoAenv += 1;
lfoAenv %= 3;
}
else if((subP==0) && (Pval2==1) && (increment2 < 0) )
{
lfoAenv -= 1;
if(lfoAenv < 0){lfoAenv = 2;}
}
if((subP==1) && (Pval2==1) && (increment2 > 0) )
{
lfoAamt += 1;
}
else if((subP==1) && (Pval2==1) && (increment2 < 0) )
{
lfoAamt -= 1;
}
if((subP==0) && (Pval2==2) && (increment2 > 0) )
{
osc2pv += 1;
osc2pv %= 3;
}
else if((subP==0) && (Pval2==2) && (increment2 < 0) )
{
osc2pv -= 1;
if(osc2pv < 0){osc2pv = 2;}
}
if((subP==0) && (Pval2==3) && (increment2 > 0) )
{
scale += 1;
scale %= 4;
}
else if((subP==0) && (Pval2==3) && (increment2 < 0) )
{
scale -= 1;
if(scale < 0){scale = 3;}
}
}
// Read touch status
currTouched = mpr121.Touched();
// Process the touch status as needed
for(int i = 0; i < 12; i++)
{
if((currTouched & (1 << i)) && !(lastTouched& (1 << i)))
{
// Channel i is touched, print the channel number
hw.PrintLine("Channel %d touched", i);
keyF = i;
trig = 1;
}
if(!(currTouched & (1 << i)) && (lastTouched& (1 << i)))
{
// Channel i is released, print the channel number
hw.PrintLine("Channel %d released", i);
trig = 0;
}
}
lastTouched = currTouched;
//Sequencer
if (hw.adc.GetFloat(6) > 0)
{
if (trig != trigo){
step=0 ;
cnt=0;
clock.Reset();
}
if (trig > 0){
clock.SetFreq(hw.adc.GetFloat(5) * 400);
if (clock.Process()){
cnt++;
cnt %= 4;
if(cnt == 0) {
gate = 1;
step++;
step %= 8;
}
} else if(cnt == 3) {
gate = 0;
}
if(beat[step] > 0)
{
stepped = step;}
else{stepped = steppedO;}
steppedO=stepped;
trigo=trig;
}
gate = beat[step] * gate;
seqF = seqP[stepped];
Dseq = seqD[stepped];
sDec = seDc[stepped];
int muxa = (step) % 2;
int muxb = (int) (.5f * step) % 2;
int muxc = (int) (.25f * step) % 2;
dsy_gpio_write(&muxpin, muxa);
dsy_gpio_write(&muxbpin, muxb);
dsy_gpio_write(&muxcpin, muxc);
}
else
{
gate = 1;
seqF = 0;
Dseq = 0;
sDec = 0;
dsy_gpio_write(&muxpin, false);
dsy_gpio_write(&muxbpin, false);
dsy_gpio_write(&muxcpin, false);
}
float lfoF = hw.adc.GetMuxFloat(9, 0);
switch(lfoFenv){
case 0: lfoF_=(lfoF * lfoF * 299.99 + .01); break;
case 1: lfoF_=(lfoF * lfoF * 299.99 + .01)*env.Process(trig&&gate)*(1-lfoFamt)/24; break;
case 2: lfoF_=(lfoF * lfoF * 299.99 + .01)*envM.Process(trig&&gate)*(1-lfoFamt)/24; break;
default: 0; break;
}
lfo.SetFreq(lfoF_);
switch(lfoAenv){
case 0: lfoA_= lfo.Process(); break;
case 1: lfoA_= lfo.Process() * env.Process(trig && gate) * (1-lfoAamt)/24; break;
case 2: lfoA_= lfo.Process() * envM.Process(trig && gate) * (1-lfoAamt)/24; break;
default: 0; break;
}
float Menv = envM.Process(trig && gate);
float peak = (hw.adc.GetMuxFloat(10, 5) * 96 + Dseq*2) * Menv;
float Cut = hw.adc.GetMuxFloat(10, 4) * 127;
float lfoamt = lfoA_ * hw.adc.GetMuxFloat(9, 1) * 60;
filt.SetFreq(mtof(Cut + peak+ lfoamt + 27));
filt.SetRes(hw.adc.GetMuxFloat(10, 6) * 1.1f);
int rawct=0;
rawct=hw.adc.GetFloat(2) * 4 - 2;
oct = rawct * 12;
int owav = (static_cast<int>(hw.adc.GetMuxFloat(10, 7) * 3 + .7));
switch (owav)
{
case 0: osc.SetWaveform(0); osc2.SetWaveform(0); break;
case 1: osc.SetWaveform(5); osc2.SetWaveform(5); break;
case 2: osc.SetWaveform(6); osc2.SetWaveform(6); break;
case 3: osc.SetWaveform(7); osc2.SetWaveform(7); break;
default: osc.SetWaveform(0); osc2.SetWaveform(0); break;
}
oscF= hw.adc.GetFloat(0) * 96 + 24;
osc2F = hw.adc.GetFloat(1) * 96 + 24;
float lfopamt = lfoA_ * hw.adc.GetMuxFloat(9, 2) * 48;
float Menvpamt = Menv * hw.adc.GetMuxFloat(9, 7) * 60;
float lfopwamt(lfoA_ * hw.adc.GetFloat(7) * .5);
//Scale
int Major[7]{0,2,4,5,7,9,11};
int Minor[7]{0,2,3,5,8,9,10};
int Penta[5]{0,3,5,8,10};
int keyFsc=0;
int keysc=0;
int scoct=0;
switch(scale)
{
case 0: keysc=keyF+seqF; break;
case 1: keyFsc= static_cast<int>(keyF + seqF) % 7;
scoct = static_cast<int>((keyF + seqF)/7)*12;
keysc = Major[keyFsc] + scoct; break;
case 2: keyFsc= static_cast<int>(keyF + seqF) % 7;
scoct = static_cast<int>((keyF + seqF)/7)*12;
keysc= Minor[keyFsc] + scoct; break;
case 3: keyFsc= static_cast<int>(keyF + seqF) % 5;
scoct = static_cast<int>((keyF + seqF)/5)*12;
keysc = Penta[keyFsc] + scoct; break;
default: 0; break;
}
osc.SetFreq(mtof(Menvpamt + lfopamt + keysc + oscF + oct));
float pwm = hw.adc.GetFloat(8) * .9 + lfopwamt;
if (pwm > .99){pwm = .99;}
else if (pwm < .01){pwm = .01;}
osc.SetPw(pwm);
if(osc2pv==0){
osc2.SetFreq((mtof(Menvpamt + lfopamt + keysc + osc2F + oct)));
}
else if(osc2pv==1){
switch(scale)
{
case 0: keysc=keyF; break;
case 1: keyFsc= static_cast<int>(keyF) % 7;
scoct = static_cast<int>(keyF/7)*12;
keysc = Major[keyFsc] + scoct; break;
case 2: keyFsc= static_cast<int>(keyF) % 7;
scoct = static_cast<int>(keyF/7)*12;
keysc= Minor[keyFsc] + scoct; break;
case 3: keyFsc= static_cast<int>(keyF) % 5;
scoct = static_cast<int>(keyF/5)*12;
keysc = Penta[keyFsc] + scoct; break;
default: 0; break;
}
osc2.SetFreq((mtof(Menvpamt + lfopamt + keysc + osc2F + oct)));
}
else if(osc2pv==2){
osc2.SetFreq((mtof(Menvpamt + lfopamt + osc2F + oct)));
}
osc2.SetPw(pwm);
clock.SetFreq(4 * (hw.adc.GetFloat(6) * 1.9f + .1f));
//Set envelope parameters
env.SetTime(ADSR_SEG_ATTACK, hw.adc.GetMuxFloat(10, 0));
float dec = hw.adc.GetMuxFloat(10, 1);
env.SetTime(ADSR_SEG_DECAY, (dec * dec) + (sDec/256));
env.SetTime(ADSR_SEG_RELEASE, hw.adc.GetMuxFloat(10, 3));
env.SetSustainLevel(trig * hw.adc.GetMuxFloat(10, 2));
//Set Mod envelope parameters
envM.SetTime(ADSR_SEG_ATTACK, hw.adc.GetMuxFloat(9, 3));
float decM = hw.adc.GetMuxFloat(9, 4);
envM.SetTime(ADSR_SEG_DECAY, (decM * decM) + (sDec/256));
envM.SetTime(ADSR_SEG_RELEASE, hw.adc.GetMuxFloat(9, 6));
envM.SetSustainLevel(trig * hw.adc.GetMuxFloat(9, 5));
//OlED Stuff
/*fonepole(Cutfone, Cut, .000001);
int newcut = Cutfone * 10000000;
if (newcut != ctfO){
display.SetCursor(40, 2);
display.WriteString("Cutoff", Font_6x8, true);
display.SetCursor(50, 22);
/
FixedCapStr<16> str("");
str.AppendInt(newcut);
display.WriteString(str, Font_11x18, true);
display.Update();
}*/
//false is true
if ((Pval==0) && (cnt < 3) && (hw.adc.GetFloat(6) > 0)){
dsy_gpio_write(&ledR_1_pin, false );
dsy_gpio_write(&ledG_1_pin, false );
dsy_gpio_write(&ledB_1_pin, true );
}
else if ((Pval==1) && (cnt < 3) && (hw.adc.GetFloat(6) > 0)){
dsy_gpio_write(&ledR_1_pin, false );
dsy_gpio_write(&ledG_1_pin, true );
dsy_gpio_write(&ledB_1_pin, false );
}
else if ((Pval==2) && (cnt < 3) && (hw.adc.GetFloat(6) > 0)){
dsy_gpio_write(&ledR_1_pin, true );
dsy_gpio_write(&ledG_1_pin, false );
dsy_gpio_write(&ledB_1_pin, false );
}
else if (trig>0 && (hw.adc.GetFloat(6) < .5))
{dsy_gpio_write(&ledR_1_pin, false );
dsy_gpio_write(&ledG_1_pin, false );
dsy_gpio_write(&ledB_1_pin, false );}
else
{dsy_gpio_write(&ledR_1_pin, true );
dsy_gpio_write(&ledG_1_pin, true );
dsy_gpio_write(&ledB_1_pin, true );}
//decO = newdec;
//ctfO = newcut;
}
}