diff --git a/encoder_dir.h b/encoder.h similarity index 72% rename from encoder_dir.h rename to encoder.h index 5375b57..e9a8635 100644 --- a/encoder_dir.h +++ b/encoder.h @@ -16,28 +16,21 @@ #include "button.h" #include "peripherials.h" -enum Direction { - DIRECTION_UNCHANGED, - DIRECTION_INCREMENT, - DIRECTION_DECREMENT, -}; - -class EncoderDir { +class Encoder { protected: typedef void (*CallbackFunction)(void); - typedef void (*RotateCallbackFunction)(Direction dir, int val); + typedef void (*RotateCallbackFunction)(int val); CallbackFunction on_press; RotateCallbackFunction on_press_rotate; RotateCallbackFunction on_rotate; int change; - Direction dir; public: - EncoderDir() : encoder_(ENCODER_PIN1, ENCODER_PIN2, RotaryEncoder::LatchMode::FOUR3), + Encoder() : encoder_(ENCODER_PIN1, ENCODER_PIN2, RotaryEncoder::LatchMode::FOUR3), button_(ENCODER_SW_PIN) { _instance = this; } - ~EncoderDir() {} + ~Encoder() {} // Set to true if the encoder read direction should be reversed. void SetReverseDirection(bool reversed) { @@ -55,12 +48,6 @@ class EncoderDir { on_press_rotate = f; } - // Parse EncoderButton increment direction. - Direction RotateDirection() { - int dir = (int)(encoder_.getDirection()); - return rotate_(dir, reversed_); - } - void Process() { // Get encoder position change amount. int encoder_rotated = _rotate_change() != 0; @@ -70,9 +57,9 @@ class EncoderDir { // Handle encoder position change and button press. if (button_pressed && encoder_rotated) { rotated_while_held_ = true; - if (on_press_rotate != NULL) on_press_rotate(dir, change); + if (on_press_rotate != NULL) on_press_rotate(change); } else if (!button_pressed && encoder_rotated) { - if (on_rotate != NULL) on_rotate(dir, change); + if (on_rotate != NULL) on_rotate(change); } else if (button_.Change() == Button::CHANGE_RELEASED && !rotated_while_held_) { if (on_press != NULL) on_press(); } @@ -91,7 +78,7 @@ class EncoderDir { } private: - static EncoderDir* _instance; + static Encoder* _instance; int previous_pos_; bool rotated_while_held_; @@ -112,7 +99,6 @@ class EncoderDir { // Update state variables. change = position - previous_pos_; previous_pos_ = position; - dir = RotateDirection(); // Encoder rotate acceleration. if (ms < 16) { @@ -126,17 +112,6 @@ class EncoderDir { } return change; } - - inline Direction rotate_(int dir, bool reversed) { - switch (dir) { - case 1: - return (reversed) ? DIRECTION_DECREMENT : DIRECTION_INCREMENT; - case -1: - return (reversed) ? DIRECTION_INCREMENT : DIRECTION_DECREMENT; - default: - return DIRECTION_UNCHANGED; - } - } }; #endif \ No newline at end of file diff --git a/examples/Gravity/Gravity.ino b/examples/Gravity/Gravity.ino index 61da3f8..03edfb9 100644 --- a/examples/Gravity/Gravity.ino +++ b/examples/Gravity/Gravity.ino @@ -142,7 +142,7 @@ void HandleEncoderPressed() { app.refresh_screen = true; } -void HandleRotate(Direction dir, int val) { +void HandleRotate(int val) { if (!app.editing_param) { // Navigation Mode const int max_param = (app.selected_channel == 0) ? PARAM_MAIN_LAST : PARAM_CH_LAST; @@ -158,12 +158,8 @@ void HandleRotate(Direction dir, int val) { app.refresh_screen = true; } -void HandlePressedRotate(Direction dir, int val) { - if (dir == DIRECTION_INCREMENT && app.selected_channel < Gravity::OUTPUT_COUNT) { - app.selected_channel++; - } else if (dir == DIRECTION_DECREMENT && app.selected_channel > 0) { - app.selected_channel--; - } +void HandlePressedRotate(int val) { + updateSelection(app.selected_channel, val, Gravity::OUTPUT_COUNT + 1); app.selected_param = 0; stateManager.markDirty(); app.refresh_screen = true; @@ -180,7 +176,7 @@ void editMainParameter(int val) { break; case PARAM_MAIN_SOURCE: { - int source = static_cast(app.selected_source); + byte source = static_cast(app.selected_source); updateSelection(source, val, Clock::SOURCE_LAST); app.selected_source = static_cast(source); gravity.clock.SetSource(app.selected_source); @@ -220,13 +216,13 @@ void editChannelParameter(int val) { ch.setHits(ch.getHits() + val); break; case PARAM_CH_CV_SRC: { - int source = static_cast(ch.getCvSource()); + byte source = static_cast(ch.getCvSource()); updateSelection(source, val, CV_LAST); ch.setCvSource(static_cast(source)); break; } case PARAM_CH_CV_DEST: { - int dest = static_cast(ch.getCvDestination()); + byte dest = static_cast(ch.getCvDestination()); updateSelection(dest, val, CV_DEST_LAST); ch.setCvDestination(static_cast(dest)); break; @@ -234,12 +230,17 @@ void editChannelParameter(int val) { } } -void updateSelection(int& param, int change, int maxValue) { +// Changes the param by the value provided. +void updateSelection(byte& param, int change, int maxValue) { + // Do not apply acceleration if max value is less than 25. + if (maxValue < 25) { + change = change > 0 ? 1 : -1; + } param = constrain(param + change, 0, maxValue - 1); } // -// Helper functions. +// App Helper functions. // void InitAppState(AppState& app) { diff --git a/examples/Gravity/app_state.h b/examples/Gravity/app_state.h index efedc2a..201ac72 100644 --- a/examples/Gravity/app_state.h +++ b/examples/Gravity/app_state.h @@ -11,8 +11,8 @@ struct AppState { bool encoder_reversed = false; bool refresh_screen = true; bool editing_param = false; - int selected_param = 0; - int selected_sub_param = 0; + byte selected_param = 0; + byte selected_sub_param = 0; byte selected_channel = 0; // 0=tempo, 1-6=output channel byte selected_shuffle = 0; Clock::Source selected_source = Clock::SOURCE_INTERNAL; diff --git a/examples/Gravity/display.h b/examples/Gravity/display.h index 382d34e..73769b9 100644 --- a/examples/Gravity/display.h +++ b/examples/Gravity/display.h @@ -9,7 +9,7 @@ // UI Display functions for drawing the UI to the OLED display. // -const PROGMEM uint8_t TEXT_FONT[437] U8G2_FONT_SECTION("velvetscreen") = +const uint8_t TEXT_FONT[437] U8G2_FONT_SECTION("velvetscreen") PROGMEM = "\64\0\2\2\3\3\2\3\4\5\5\0\0\5\0\5\0\0\221\0\0\1\230 \4\200\134%\11\255tT" "R\271RI(\6\252\334T\31)\7\252\134bJ\12+\7\233\345\322J\0,\5\221T\4-\5\213" "f\6.\5\211T\2/\6\244\354c\33\60\10\254\354T\64\223\2\61\7\353\354\222\254\6\62\11\254l" @@ -25,7 +25,7 @@ const PROGMEM uint8_t TEXT_FONT[437] U8G2_FONT_SECTION("velvetscreen") = "\7p\10\255\364V\266\323\2q\7\255\364\216\257\5r\10\253d\242\32*\2t\6\255t\376#w\11" "\255\364V\245FN\13x\6\233dR\7\0\0\0\4\377\377\0"; -const PROGMEM uint8_t LARGE_FONT[916] U8G2_FONT_SECTION("stk-l") = +const uint8_t LARGE_FONT[916] U8G2_FONT_SECTION("stk-l") PROGMEM = "#\0\4\4\4\5\2\1\6\17\30\1\0\27\0\0\0\1\77\0\0\3w%'\17\37\313\330R#&" "\32!F\14\211I\310\24!\65\204(MF\21)Cd\304\10\62b\14\215\60Vb\334\20\0/\14" "\272\336\336d\244\350\263q\343\0\60\37|\377\216!%*\10\35\263\253ChD\30\21bB\14\242S" @@ -58,11 +58,11 @@ const PROGMEM uint8_t LARGE_FONT[916] U8G2_FONT_SECTION("stk-l") = #define play_icon_width 14 #define play_icon_height 14 -static const unsigned char play_icon[] PROGMEM = { +static const unsigned char play_icon[28] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x7C, 0x00, 0xFC, 0x00, 0xFC, 0x03, 0xFC, 0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0xFC, 0x00, 0x7C, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00}; -static const unsigned char pause_icon[] PROGMEM = { +static const unsigned char pause_icon[28] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x38, 0x0E, 0x00, 0x00}; @@ -278,8 +278,8 @@ void DisplayChannelPage() { subText = "EUCLID HITS"; break; case PARAM_CH_CV_SRC: { + mainText = F("SRC"); switch (ch.getCvSource()) { - mainText = F("SRC"); case CV_NONE: subText = F("NONE"); break; @@ -293,8 +293,8 @@ void DisplayChannelPage() { break; } case PARAM_CH_CV_DEST: { + mainText = F("DEST"); switch (ch.getCvDestination()) { - mainText = F("DEST"); case CV_DEST_NONE: subText = F("NONE"); break; diff --git a/gravity.cpp b/gravity.cpp index 159dc6f..658a960 100644 --- a/gravity.cpp +++ b/gravity.cpp @@ -13,7 +13,7 @@ // Initialize the static pointer for the EncoderDir class to null. We want to // have a static pointer to decouple the ISR from the global gravity object. -EncoderDir* EncoderDir::_instance = nullptr; +Encoder* Encoder::_instance = nullptr; void Gravity::Init() { initClock(); @@ -74,11 +74,11 @@ void Gravity::Process() { // Pin Change Interrupt on Port D (D4). ISR(PCINT2_vect) { - EncoderDir::isr(); + Encoder::isr(); }; // Pin Change Interrupt on Port C (D17/A3). ISR(PCINT1_vect) { - EncoderDir::isr(); + Encoder::isr(); }; // Global instance diff --git a/gravity.h b/gravity.h index 2002616..1cc424b 100644 --- a/gravity.h +++ b/gravity.h @@ -8,7 +8,7 @@ #include "button.h" #include "clock.h" #include "digital_output.h" -#include "encoder_dir.h" +#include "encoder.h" #include "peripherials.h" // Hardware abstraction wrapper for the Gravity module. @@ -32,7 +32,7 @@ class Gravity { U8G2_SSD1306_128X64_NONAME_1_HW_I2C display; // OLED display object. Clock clock; // Clock source wrapper. DigitalOutput outputs[OUTPUT_COUNT]; // An array containing each Output object. - EncoderDir encoder; // Rotary encoder with button instance + Encoder encoder; // Rotary encoder with button instance Button shift_button; Button play_button; AnalogInput cv1;