Skip to content

Commit

Permalink
Update Firmware for new EncoderButton library (#23)
Browse files Browse the repository at this point in the history
* Initial commit of Euclidean Rhythm mvp.

* small optimizations and cleanup

* Updated script to replace SimpleRotary with EncoderButton in experimental version of libModulove. Also fixed formatting.

* Added padding functionality

* Added ability to save state between power cycling the module.

* Updated module UI docs.

* Only call updatePattern() when chage actually modifies the pattern. Apply formatting.

* Update documentation to include Euclidean firmware.

* Update TimeBandit firmware for new EncoderButton lib.

* Update Uncertainty for new EncoderButton lib.

* Update BitGarden firmware for new EncoderButton lib.
  • Loading branch information
awonak authored Jan 22, 2025
1 parent c87ccd4 commit d4a7061
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 108 deletions.
98 changes: 42 additions & 56 deletions A-RYTH-MATIK/BitGarden/BitGarden.ino
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ void setup() {
hw.config.ReverseEncoder = true;
#endif

hw.eb.setClickHandler(HandleShortPress);
hw.eb.setLongPressHandler(HandleLongPress);
hw.eb.setEncoderHandler(HandleRotate);

// Initialize the A-RYTH-MATIK peripherials.
hw.Init();

Expand Down Expand Up @@ -175,24 +179,6 @@ void loop() {
}
}

// Read the encoder button press event.
Encoder::PressType press = hw.encoder.Pressed();

// Short button press. Change editable parameter.
if (press == Encoder::PRESS_SHORT) {
HandleShortPress();
}
// Long button press. Change menu page.
else if (press == Encoder::PRESS_LONG) {
HandleLongPress();
}

// Read encoder for a change in direction and update the selected page or
// parameter.
(page_select)
? UpdatePage(hw.encoder.Rotate())
: UpdateParameter(hw.encoder.Rotate());

// Render any new UI changes to the OLED display.
UpdateDisplay();
}
Expand Down Expand Up @@ -253,7 +239,7 @@ void Reset() {
}

// Short press handler.
void HandleShortPress() {
void HandleShortPress(EncoderButton &eb) {
// If we are in page select mode, set current page.
if (page_select) {
page_select = false;
Expand Down Expand Up @@ -293,7 +279,7 @@ void HandleShortPress() {

// Long press handler will toggle between page select mode and parameter edit
// mode for the current page.
void HandleLongPress() {
void HandleLongPress(EncoderButton &eb) {
// Toggle between menu page select mode.
if (!page_select) {
page_select = true;
Expand All @@ -308,19 +294,29 @@ void HandleLongPress() {
update_display = true;
}

void HandleRotate(EncoderButton &eb) {
// Read encoder for a change in direction and update the selected page or
// parameter.
int dir = eb.increment();
(page_select)
? UpdatePage(dir)
: UpdateParameter(dir);
}

// When in select page mode, scroll through menu pages.
void UpdatePage(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_UNCHANGED)
return;
else if (dir == Encoder::DIRECTION_INCREMENT && selected_page < PAGE_LAST - 1)
void UpdatePage(int dir) {
if (dir == 1 && selected_page < PAGE_LAST - 1) {
selected_page = static_cast<MenuPage>((selected_page + 1) % PAGE_LAST);
else if (dir == Encoder::DIRECTION_DECREMENT && selected_page > PAGE_MAIN)
update_display = true;
}
else if (dir == -1 && selected_page > PAGE_MAIN) {
selected_page = static_cast<MenuPage>((selected_page - 1) % PAGE_LAST);
update_display = true;
update_display = true;
}
}

// Update the current selected parameter with the current movement of the encoder.
void UpdateParameter(Encoder::Direction dir) {
void UpdateParameter(int dir) {
if (selected_page == PAGE_MAIN) {
if (selected_param == PARAM_SEED) UpdateSeed(dir);
if (selected_param == PARAM_LENGTH) UpdateLength(dir);
Expand All @@ -334,34 +330,27 @@ void UpdateParameter(Encoder::Direction dir) {
}

// Select seed from the previous seeds in the packet or add new random seed to packet.
void UpdateSeed(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_UNCHANGED)
return;
else if (dir == Encoder::DIRECTION_INCREMENT)
packet.NextSeed();
else if (dir == Encoder::DIRECTION_DECREMENT)
packet.PrevSeed();
void UpdateSeed(int dir) {
if (dir == 1) packet.NextSeed();
else if (dir == -1) packet.PrevSeed();
update_display = true;
state_changed = true;
}

// Adjust the step length for the given input direction (1=increment, 2=decrement).
void UpdateLength(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_INCREMENT && state.step_length <= MAX_LENGTH) {
void UpdateLength(int dir) {
if (dir == 1 && state.step_length <= MAX_LENGTH) {
SetLength(++state.step_length);
} else if (dir == Encoder::DIRECTION_DECREMENT && state.step_length >= MIN_LENGTH) {
} else if (dir == -1 && state.step_length >= MIN_LENGTH) {
SetLength(--state.step_length);
}
}

// Change the current output mode selection.
void UpdateMode(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_UNCHANGED) return;

if (dir == Encoder::DIRECTION_INCREMENT && state.mode < MODE_LAST - 1) {
void UpdateMode(int dir) {
if (dir == 1 && state.mode < MODE_LAST - 1) {
state.mode = static_cast<Mode>(state.mode + 1);

} else if (dir == Encoder::DIRECTION_DECREMENT && state.mode > 0) {
} else if (dir == -1 && state.mode > 0) {
state.mode = static_cast<Mode>(state.mode - 1);
}
// Update the mode for all outputs.
Expand All @@ -372,31 +361,28 @@ void UpdateMode(Encoder::Direction dir) {
state_changed = true;
}

void UpdateProbability(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_UNCHANGED) return;
void UpdateProbability(int dir) {
if (prob_param == PROB_OUTPUT) UpdateOutput(dir);
if (prob_param == PROB_PERCENTAGE) UpdatePercentage(dir);
}

void UpdateOutput(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_INCREMENT && selected_out < OUTPUT_COUNT - 1)
void UpdateOutput(int dir) {
if (dir == 1 && selected_out < OUTPUT_COUNT - 1)
selected_out++;
if (dir == Encoder::DIRECTION_DECREMENT && selected_out > 0)
if (dir == -1 && selected_out > 0)
selected_out--;
update_display = true;
}

void UpdatePercentage(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_INCREMENT) outputs[selected_out].IncProb();
if (dir == Encoder::DIRECTION_DECREMENT) outputs[selected_out].DecProb();
void UpdatePercentage(int dir) {
if (dir == 1) outputs[selected_out].IncProb();
if (dir == -1) outputs[selected_out].DecProb();
update_display = true;
state_changed = true;
}

// Edit the current seed.
void EditSeed(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_UNCHANGED) return;

void EditSeed(int dir) {
int change;
if (seed_index == 0)
change = 0x1000;
Expand All @@ -407,9 +393,9 @@ void EditSeed(Encoder::Direction dir) {
else if (seed_index == 3)
change = 0x0001;

if (dir == Encoder::DIRECTION_INCREMENT)
if (dir == 1)
temp_seed += change;
else if (dir == Encoder::DIRECTION_DECREMENT)
else if (dir == -1)
temp_seed -= change;

packet.UpdateSeed(temp_seed);
Expand Down
32 changes: 16 additions & 16 deletions A-RYTH-MATIK/TimeBandit/TimeBandit.ino
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ void setup() {
// Initialize the A-RYTH-MATIK peripherials.
hw.Init();

// Set up encoder parameters
hw.eb.setEncoderHandler(UpdateRotate);
hw.eb.setClickHandler(UpdatePress);

// Define each of the fixed clock divisions.
// NOTE: This is binary value, clock divisions are bit shifted left by one.
clockDiv[0] = {hw.outputs[0], 1};
Expand Down Expand Up @@ -99,28 +103,24 @@ void loop() {
counter = 0;
}

// Read the encoder button press event.
Encoder::PressType press = hw.encoder.Pressed();

// Short button press. Change mode.
if (press == Encoder::PRESS_SHORT) {
// Next param on Main page.
selected_mode = static_cast<Mode>((selected_mode + 1) % MODE_LAST);
update_display = true;
}

UpdateParameter(hw.encoder.Rotate());
UpdateDisplay();
}

void UpdateParameter(Encoder::Direction dir) {
void UpdatePress(EncoderButton &eb) {
// Next param on Main page.
selected_mode = static_cast<Mode>((selected_mode + 1) % MODE_LAST);
update_display = true;
}

void UpdateRotate(EncoderButton &eb) {
int dir = eb.increment() > 0 ? 1 : -1;
if (selected_mode == MODE_SELECT) {
switch (dir) {
case Encoder::DIRECTION_DECREMENT:
case -1:
if (selected_out > 0) --selected_out;
update_display = true;
break;
case Encoder::DIRECTION_INCREMENT:
case 1:
if (selected_out < OUTPUT_COUNT - 1) ++selected_out;
update_display = true;
break;
Expand All @@ -129,14 +129,14 @@ void UpdateParameter(Encoder::Direction dir) {
if (selected_mode == MODE_EDIT) {
int division = clockDiv[selected_out].division;
switch (dir) {
case Encoder::DIRECTION_DECREMENT:
case -1:
if (division > 1) {
clockDiv[selected_out].division = division >> 1;
counter = 0;
update_display = true;
}
break;
case Encoder::DIRECTION_INCREMENT:
case 1:
if (division < 4096) {
clockDiv[selected_out].division = division << 1;
counter = 0;
Expand Down
72 changes: 36 additions & 36 deletions A-RYTH-MATIK/Uncertainty/Uncertainty.ino
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ void setup() {
Serial.begin(9600);
#endif

hw.eb.setClickHandler(ShortPress);
hw.eb.setLongPressHandler(LongPress);
hw.eb.setEncoderHandler(UpdateParameter);

// Initialize the A-RYTH-MATIK peripherials.
hw.Init();

Expand Down Expand Up @@ -96,66 +100,62 @@ void loop() {
}
}

// Read the encoder button press event.
Encoder::PressType press = hw.encoder.Pressed();
// Render any new UI changes to the OLED display.
UpdateDisplay();
}

// Short button press. Change editable parameter.
if (press == Encoder::PRESS_SHORT) {
// Next param on Main page.
if (selected_page == PAGE_MAIN)
selected_param = ++selected_param % PARAM_COUNT;
// Short button press. Change editable parameter.
void ShortPress(EncoderButton &eb) {
// Next param on Main page.
if (selected_page == PAGE_MAIN)
selected_param = ++selected_param % PARAM_COUNT;

update_display = true;
}
update_display = true;
}

// Long button press. Change menu page.
if (press == Encoder::PRESS_LONG) {
if (selected_page == PAGE_MAIN) {
selected_page = PAGE_MODE;
selected_param = 2;
} else {
selected_page = PAGE_MAIN;
selected_param = 0;
}
update_display = true;
// Long button press. Change menu page.
void LongPress(EncoderButton &eb) {
if (selected_page == PAGE_MAIN) {
selected_page = PAGE_MODE;
selected_param = 2;
} else {
selected_page = PAGE_MAIN;
selected_param = 0;
}

// Read encoder for a change in direction and update the selected parameter.
UpdateParameter(hw.encoder.Rotate());

// Render any new UI changes to the OLED display.
UpdateDisplay();
update_display = true;
}

void UpdateParameter(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_UNCHANGED) return;
// Read encoder for a change in direction and update the selected parameter.
void UpdateParameter(EncoderButton &eb) {
int dir = eb.increment();
if (selected_param == 0) UpdateOutput(dir);
if (selected_param == 1) UpdateProb(dir);
if (selected_param == 2) UpdateMode(dir);
update_display = true;
}

void UpdateOutput(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_INCREMENT && selected_out < OUTPUT_COUNT - 1)
void UpdateOutput(int dir) {
if (dir == 1 && selected_out < OUTPUT_COUNT - 1)
selected_out++;
if (dir == Encoder::DIRECTION_DECREMENT && selected_out > 0)
if (dir == -1 && selected_out > 0)
selected_out--;
update_display = true;
}

void UpdateMode(Encoder::Direction dir) {
void UpdateMode(int dir) {
Mode newMode;
if (dir == Encoder::DIRECTION_INCREMENT) newMode = Mode::FLIP;
if (dir == Encoder::DIRECTION_DECREMENT) newMode = Mode::TRIGGER;
if (dir == 1) newMode = Mode::FLIP;
if (dir == -1) newMode = Mode::TRIGGER;
// Update the mode for all outputs.
for (int i = 0; i < OUTPUT_COUNT; i++) {
outputs[i].SetMode(newMode);
}
update_display = true;
}

void UpdateProb(Encoder::Direction dir) {
if (dir == Encoder::DIRECTION_INCREMENT) outputs[selected_out].IncProb();
if (dir == Encoder::DIRECTION_DECREMENT) outputs[selected_out].DecProb();
void UpdateProb(int dir) {
if (dir == 1) outputs[selected_out].IncProb();
if (dir == -1) outputs[selected_out].DecProb();
update_display = true;
}

Expand Down

0 comments on commit d4a7061

Please sign in to comment.