Skip to content

Commit

Permalink
Allow editing of binary clock divisions.
Browse files Browse the repository at this point in the history
  • Loading branch information
awonak committed Jan 30, 2024
1 parent 2edd2ae commit 2787fb1
Showing 1 changed file with 108 additions and 28 deletions.
136 changes: 108 additions & 28 deletions A-RYTH-MATIK/TimeBandit/TimeBandit.ino
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* @file TimeBandit.ino
* @author Adam Wonak (https://github.com/awonak/)
* @brief Fixed binary clock divider and sub oscillator.
* @version 0.1
* @date 2023-10-29
* @version 0.2
* @date 2024-01-29
*
* @copyright Copyright (c) 2023
*
Expand All @@ -12,7 +12,8 @@
* clock divider or provide sub octaves of the incoming audio rate signal.
* Each output is one octave lower than the previous.
*
* ENCODER: Unused.
* ENCODER: Select which division to edit. Single press to edit the selected
* output. Single press again to leave edit mode.
*
* CLK: Clock input used to derrive fixed binary divisions.
*
Expand All @@ -21,6 +22,13 @@
*/
#include "src/libmodulove/arythmatik.h"

// Flag for enabling debug print to serial monitoring output.
// Note: this affects performance and locks LED 4 & 5 on HIGH.
// #define DEBUG

// Flag for reversing the encoder direction.
// #define ENCODER_REVERSED

using namespace modulove;
using namespace arythmatik;

Expand All @@ -35,8 +43,26 @@ struct ClockDivision {
Arythmatik hw;
ClockDivision clockDiv[OUTPUT_COUNT];
byte counter;
byte mode; // Normal, Select Output, Edit.
byte selected_out = 0;
bool update_display = true;

// Enum constants for script behavior mode.
enum Mode {
MODE_DEFAULT,
MODE_SELECT,
MODE_EDIT,
MODE_LAST,
};
Mode selected_mode = MODE_DEFAULT;

void setup() {
// Only enable Serial monitoring if DEBUG is defined.
// Note: this affects performance and locks LED 4 & 5 on HIGH.
#ifdef DEBUG
Serial.begin(57600);
#endif

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

Expand All @@ -50,31 +76,7 @@ void setup() {
clockDiv[5] = {hw.outputs[5], 32};

// Display each clock division on the OLED.
hw.display.clearDisplay();

// Draw page title.
hw.display.setTextSize(0);
hw.display.setCursor(36, 0);
hw.display.println("Time Bandit");
hw.display.drawFastHLine(0, 10, SCREEN_WIDTH, WHITE);

// Draw each clock division.
double ymod = SCREEN_HEIGHT * 0.25;
double xmod = SCREEN_WIDTH * 0.6;
int ypos = 4;
int xpos = 6;
int count;
for (int i = 0; i < 2; i++) { // columns
for (int j = 0; j < 3; j++) { // rows
ypos += ymod;
hw.display.setCursor(xpos, ypos);
hw.display.println("CLK /" + String(clockDiv[count].division<<1));
count++;
}
xpos += xmod;
ypos = 4;
}
hw.display.display();
UpdateDisplay();
}

void loop() {
Expand All @@ -96,4 +98,82 @@ void loop() {
if (hw.rst.State() == DigitalInput::STATE_RISING) {
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) {
if (selected_mode == MODE_SELECT) {
switch (dir) {
case Encoder::DIRECTION_DECREMENT:
if (selected_out > 0) --selected_out;
update_display = true;
break;
case Encoder::DIRECTION_INCREMENT:
if (selected_out < OUTPUT_COUNT - 1) ++selected_out;
update_display = true;
break;
}
}
if (selected_mode == MODE_EDIT) {
int division = clockDiv[selected_out].division;
switch (dir) {
case Encoder::DIRECTION_DECREMENT:
if (division > 1) clockDiv[selected_out].division = division >> 1;
update_display = true;
break;
case Encoder::DIRECTION_INCREMENT:
if (division < 4096) clockDiv[selected_out].division = division << 1;
update_display = true;
break;
}
}
}

void UpdateDisplay() {
if (!update_display) return;
update_display = false;
hw.display.clearDisplay();

// Draw page title.
hw.display.setTextSize(0);
hw.display.setCursor(36, 0);
hw.display.println("TIME BANDIT");
hw.display.drawFastHLine(0, 10, SCREEN_WIDTH, WHITE);

// Draw each clock division.
double ymod = SCREEN_HEIGHT / 4;
double xmod = SCREEN_WIDTH / 2;
int ypos = 4;
int xpos = 6;
int count;
String label = "CLK /";
for (int i = 0; i < 2; i++) { // columns
for (int j = 0; j < 3; j++) { // rows
ypos += ymod;
hw.display.setCursor(xpos, ypos);
if (selected_mode != MODE_DEFAULT) {
label = (selected_out == count) ? "EDIT/" : "CLK /";
}
if (selected_mode == MODE_EDIT && selected_out == count) {
hw.display.drawRect(xpos - 4, ypos - 4, SCREEN_WIDTH / 2 - 4, 16, 1);
}
hw.display.println(label + String(clockDiv[count].division << 1));
count++;
}
xpos += xmod;
ypos = 4;
}
hw.display.display();
}

0 comments on commit 2787fb1

Please sign in to comment.