diff --git a/README.md b/README.md index 58d0e58..aac097a 100644 --- a/README.md +++ b/README.md @@ -111,4 +111,3 @@ void UpdateDisplay() { gravity.display.display(); } ``` - diff --git a/encoder_dir.h b/encoder_dir.h index dbc3c56..2a55bf8 100644 --- a/encoder_dir.h +++ b/encoder_dir.h @@ -33,8 +33,11 @@ class EncoderDir { Direction dir; public: - EncoderDir() : encoder_(ENCODER_PIN1, ENCODER_PIN2, RotaryEncoder::LatchMode::FOUR3), - button_(ENCODER_SW_PIN) {} + EncoderDir() { + encoder_ = new RotaryEncoder(ENCODER_PIN1, ENCODER_PIN2, RotaryEncoder::LatchMode::FOUR3); + button_ = new Button(ENCODER_SW_PIN); + } + ~EncoderDir() {} // Set to true if the encoder read direction should be reversed. @@ -55,15 +58,15 @@ class EncoderDir { // Parse EncoderButton increment direction. Direction RotateDirection() { - int dir = (int)(encoder_.getDirection()); + int dir = (int)(encoder_->getDirection()); return rotate_(dir, reversed_); } void Process() { // Get encoder position change amount. int encoder_rotated = _rotate_change() != 0; - bool button_pressed = button_.On(); - button_.Process(); + bool button_pressed = button_->On(); + button_->Process(); // Handle encoder position change and button press. if (button_pressed && encoder_rotated) { @@ -71,32 +74,32 @@ class EncoderDir { if (on_press_rotate != NULL) on_press_rotate(dir, change); } else if (!button_pressed && encoder_rotated) { if (on_rotate != NULL) on_rotate(dir, change); - } else if (button_.Change() == Button::CHANGE_RELEASED && !rotated_while_held_) { + } else if (button_->Change() == Button::CHANGE_RELEASED && !rotated_while_held_) { if (on_press != NULL) on_press(); } // Reset rotate while held state. - if (button_.Change() == Button::CHANGE_RELEASED && rotated_while_held_) { + if (button_->Change() == Button::CHANGE_RELEASED && rotated_while_held_) { rotated_while_held_ = false; } } // Read the encoder state and update the read position. void UpdateEncoder() { - encoder_.tick(); + encoder_->tick(); } private: int previous_pos_; bool rotated_while_held_; bool reversed_ = true; - RotaryEncoder encoder_; - Button button_; + RotaryEncoder * encoder_ = nullptr; + Button * button_ = nullptr; // Return the number of ticks change since last polled. int _rotate_change() { - int position = encoder_.getPosition(); - unsigned long ms = encoder_.getMillisBetweenRotations(); + int position = encoder_->getPosition(); + unsigned long ms = encoder_->getMillisBetweenRotations(); // Validation (TODO: add debounce check). if (previous_pos_ == position) { diff --git a/examples/clock_mod/clock_mod.ino b/examples/clock_mod/clock_mod.ino index fa6979a..3a45299 100644 --- a/examples/clock_mod/clock_mod.ino +++ b/examples/clock_mod/clock_mod.ino @@ -61,16 +61,16 @@ void setup() { gravity.Init(); // Clock handlers. - gravity.clock.AttachExtHandler(ExtClock); - gravity.clock.AttachIntHandler(IntClock); + gravity.clock->AttachExtHandler(ExtClock); + gravity.clock->AttachIntHandler(IntClock); // Encoder rotate and press handlers. - gravity.encoder.AttachPressHandler(HandleEncoderPressed); - gravity.encoder.AttachRotateHandler(HandleRotate); - gravity.encoder.AttachPressRotateHandler(HandlePressedRotate); + gravity.encoder->AttachPressHandler(HandleEncoderPressed); + gravity.encoder->AttachRotateHandler(HandleRotate); + gravity.encoder->AttachPressRotateHandler(HandlePressedRotate); // Button press handlers. - gravity.play_button.AttachPressHandler(HandlePlayPressed); + gravity.play_button->AttachPressHandler(HandlePlayPressed); } void loop() { @@ -88,8 +88,8 @@ void loop() { // void ExtClock() { - if (gravity.clock.ExternalSource()) { - gravity.clock.Tick(); + if (gravity.clock->ExternalSource()) { + gravity.clock->Tick(); app.refresh_screen = true; } } @@ -98,7 +98,7 @@ void IntClock(uint32_t tick) { for (int i = 0; i < OUTPUT_COUNT; i++) { const auto& channel = app.channel[i]; auto& output = gravity.outputs[i]; - + const uint32_t mod_pulses = clock_mod_pulses[channel.clock_mod_index]; const uint32_t current_tick_offset = tick + channel.offset_pulses; @@ -119,8 +119,8 @@ void IntClock(uint32_t tick) { } void HandlePlayPressed() { - gravity.clock.Pause(); - if (gravity.clock.IsPaused()) { + gravity.clock->Pause(); + if (gravity.clock->IsPaused()) { for (int i = 0; i < OUTPUT_COUNT; i++) { gravity.outputs[i].Low(); } @@ -149,21 +149,21 @@ void HandleRotate(Direction dir, int val) { if (app.selected_channel == 0) { switch (app.selected_param) { case 0: - if (gravity.clock.ExternalSource()) { + if (gravity.clock->ExternalSource()) { break; } - gravity.clock.SetTempo(gravity.clock.Tempo() + val); + gravity.clock->SetTempo(gravity.clock->Tempo() + val); app.refresh_screen = true; break; - case 1: + case 1: if (static_cast(app.selected_source) == 0 && val < 0) { app.selected_source = static_cast(SOURCE_LAST - 1); } else { app.selected_source = static_cast((app.selected_source + val) % SOURCE_LAST); } - gravity.clock.SetSource(app.selected_source); + gravity.clock->SetSource(app.selected_source); app.refresh_screen = true; break; } @@ -222,7 +222,7 @@ Channel& GetSelectedChannel() { void UpdateDisplay() { app.refresh_screen = false; - gravity.display.clearDisplay(); + gravity.display->clearDisplay(); if (app.selected_channel == 0) { DisplayMainPage(); @@ -231,83 +231,82 @@ void UpdateDisplay() { } // Show selected param indicator - gravity.display.drawChar(0, app.selected_param * 10, 0x10, 1, 0, 1); + gravity.display->drawChar(0, app.selected_param * 10, 0x10, 1, 0, 1); // Global channel select UI. DisplaySelectedChannel(); - gravity.display.display(); + gravity.display->display(); } void DisplaySelectedChannel() { - gravity.display.drawLine(1, 52, 126, 52, 1); + gravity.display->drawLine(1, 52, 126, 52, 1); for (int i = 0; i < 7; i++) { (app.selected_channel == i) - ? gravity.display.fillRect(i * 18, 52, 18, 12, 1) - : gravity.display.drawLine(i * 18, 52, i * 18, 64, 1); + ? gravity.display->fillRect(i * 18, 52, 18, 12, 1) + : gravity.display->drawLine(i * 18, 52, i * 18, 64, 1); int selected = app.selected_channel == i; if (i == 0) { - char icon = gravity.clock.IsPaused() ? CHAR_PAUSE : CHAR_PLAY; - gravity.display.drawChar((i * 18) + 7, 55, icon, !selected, selected, 1); + char icon = gravity.clock->IsPaused() ? CHAR_PAUSE : CHAR_PLAY; + gravity.display->drawChar((i * 18) + 7, 55, icon, !selected, selected, 1); } else { - gravity.display.drawChar((i * 18) + 7, 55, i + 48, !selected, selected, 1); + gravity.display->drawChar((i * 18) + 7, 55, i + 48, !selected, selected, 1); } } - gravity.display.drawLine(126, 52, 126, 64, 1); + gravity.display->drawLine(126, 52, 126, 64, 1); } void DisplayMainPage() { - gravity.display.setCursor(10, 0); - gravity.display.print(F("Tempo: ")); - gravity.display.print(gravity.clock.Tempo()); + gravity.display->setCursor(10, 0); + gravity.display->print(F("Tempo: ")); + gravity.display->print(gravity.clock->Tempo()); - gravity.display.setCursor(10, 10); - gravity.display.print(F("Source: ")); - switch (app.selected_source) - { - case SOURCE_INTERNAL: - gravity.display.print(F("INT")); - break; - case SOURCE_EXTERNAL_PPQN_24: - gravity.display.print(F("EXT 24 PPQN")); - break; - case SOURCE_EXTERNAL_PPQN_4: - gravity.display.print(F("EXT 4 PPQN")); - break; - // case SOURCE_EXTERNAL_MIDI: - // gravity.display.print(F("EXT MIDI")); - // break; - default: - break; + gravity.display->setCursor(10, 10); + gravity.display->print(F("Source: ")); + switch (app.selected_source) { + case SOURCE_INTERNAL: + gravity.display->print(F("INT")); + break; + case SOURCE_EXTERNAL_PPQN_24: + gravity.display->print(F("EXT 24 PPQN")); + break; + case SOURCE_EXTERNAL_PPQN_4: + gravity.display->print(F("EXT 4 PPQN")); + break; + // case SOURCE_EXTERNAL_MIDI: + // gravity.display->print(F("EXT MIDI")); + // break; + default: + break; } } void DisplayChannelPage() { auto& ch = GetSelectedChannel(); - gravity.display.setCursor(10, 0); - gravity.display.print(F("Mod: ")); + gravity.display->setCursor(10, 0); + gravity.display->print(F("Mod: ")); if (clock_mod[ch.clock_mod_index] > 1) { - gravity.display.print(F("/ ")); - gravity.display.print(clock_mod[ch.clock_mod_index]); + gravity.display->print(F("/ ")); + gravity.display->print(clock_mod[ch.clock_mod_index]); } else { - gravity.display.print(F("X ")); - gravity.display.print(abs(clock_mod[ch.clock_mod_index])); + gravity.display->print(F("X ")); + gravity.display->print(abs(clock_mod[ch.clock_mod_index])); } - gravity.display.setCursor(10, 10); - gravity.display.print(F("Probability: ")); - gravity.display.print(ch.probability); - gravity.display.print(F("%")); + gravity.display->setCursor(10, 10); + gravity.display->print(F("Probability: ")); + gravity.display->print(ch.probability); + gravity.display->print(F("%")); - gravity.display.setCursor(10, 20); - gravity.display.print(F("Duty Cycle: ")); - gravity.display.print(ch.duty_cycle); - gravity.display.print(F("%")); + gravity.display->setCursor(10, 20); + gravity.display->print(F("Duty Cycle: ")); + gravity.display->print(ch.duty_cycle); + gravity.display->print(F("%")); - gravity.display.setCursor(10, 30); - gravity.display.print(F("Offset: ")); - gravity.display.print(ch.offset); - gravity.display.print(F("%")); + gravity.display->setCursor(10, 30); + gravity.display->print(F("Offset: ")); + gravity.display->print(ch.offset); + gravity.display->print(F("%")); } \ No newline at end of file diff --git a/gravity.cpp b/gravity.cpp index 2cfbb8b..6ba4a36 100644 --- a/gravity.cpp +++ b/gravity.cpp @@ -19,15 +19,22 @@ void Gravity::Init() { } void Gravity::InitClock() { - clock.Init(); + clock = new Clock(); + clock->Init(); } void Gravity::InitInputs() { - shift_button.Init(SHIFT_BTN_PIN); - play_button.Init(PLAY_BTN_PIN); + shift_button = new Button(); + play_button = new Button(); + shift_button->Init(SHIFT_BTN_PIN); + play_button->Init(PLAY_BTN_PIN); - cv1.Init(CV1_PIN); - cv2.Init(CV2_PIN); + cv1 = new AnalogInput(); + cv2 = new AnalogInput(); + cv1->Init(CV1_PIN); + cv2->Init(CV2_PIN); + + encoder = new EncoderDir(); // Pin Change Interrupts for Encoder. // Thanks to https://dronebotworkshop.com/interrupts/ @@ -50,23 +57,25 @@ void Gravity::InitOutputs() { outputs[5].Init(OUT_CH6); } void Gravity::InitDisplay() { + display = new Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + // OLED Display configuration. - display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS); + display->begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS); delay(1000); - display.setRotation(2); // rotates text on OLED 1=90 degrees, 2=180 degrees - display.clearDisplay(); - display.setTextSize(1); - display.setTextColor(WHITE); - display.display(); + display->setRotation(2); // rotates text on OLED 1=90 degrees, 2=180 degrees + display->clearDisplay(); + display->setTextSize(1); + display->setTextColor(WHITE); + display->display(); } void Gravity::Process() { // Read peripherials for changes. - shift_button.Process(); - play_button.Process(); - encoder.Process(); - cv1.Process(); - cv2.Process(); + shift_button->Process(); + play_button->Process(); + encoder->Process(); + cv1->Process(); + cv2->Process(); // Update Output states. for (int i; i < OUTPUT_COUNT; i++) { @@ -75,7 +84,7 @@ void Gravity::Process() { } void ReadEncoder() { - gravity.encoder.UpdateEncoder(); + gravity.encoder->UpdateEncoder(); } // Define Encoder pin ISR. diff --git a/gravity.h b/gravity.h index 698ebcb..2d8909d 100644 --- a/gravity.h +++ b/gravity.h @@ -16,8 +16,7 @@ class Gravity { public: // Constructor - Gravity() - : display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1) {} + Gravity() {} // Deconstructor ~Gravity() {} @@ -28,14 +27,14 @@ class Gravity { // Polling check for state change of inputs and outputs. void Process(); - Adafruit_SSD1306 display; // OLED display object. - Clock clock; // Clock source wrapper. + Adafruit_SSD1306 * display = nullptr; // OLED display object. + Clock * clock = nullptr; // Clock source wrapper. DigitalOutput outputs[OUTPUT_COUNT]; // An array containing each Output object. - EncoderDir encoder; // Rotary encoder with button instance - Button shift_button; - Button play_button; - AnalogInput cv1; - AnalogInput cv2; + EncoderDir * encoder = nullptr; // Rotary encoder with button instance + Button * shift_button = nullptr; + Button * play_button = nullptr; + AnalogInput * cv1 = nullptr; + AnalogInput * cv2 = nullptr; private: void InitClock(); diff --git a/peripherials.h b/peripherials.h index 5ec0539..1b2abbb 100644 --- a/peripherials.h +++ b/peripherials.h @@ -15,6 +15,7 @@ #define OLED_ADDRESS 0x3C #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 +#define OLED_RESET -1 // Peripheral input pins #define ENCODER_PIN1 17 // A3