11/* *
22 * @file SCOPE.ino
3- * @author Modulove & friends (https://github.com/modulove/)
4- * @brief Eurorack scope / OLED Display (new config menu (≥3s))
3+ * @author Modulove
4+ * @brief Eurorack scope + OLED flip
55 * @version 1.1
6- * @date 2025-10-15
6+ * @date 2025-11-29
77 */
88
99#include < EEPROM.h>
1717#include < string.h>
1818#include < stdlib.h>
1919
20- // ---------------- Display configuration ----------------
20+ // ---------------- Display ----------------
2121#define SCREEN_WIDTH 128
2222#define SCREEN_HEIGHT 64
2323#define OLED_MOSI 9
@@ -39,21 +39,21 @@ Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_
3939
4040Encoder encoder (ENCODER_PIN_A , ENCODER_PIN_B );
4141
42- // ---------------- EEPROM map ----------------
43- // add OLED rotation.
44- #define ENCODER_DIR_ADDR 0 // int8_t (1 or -1)
45- #define OLED_ROT_ADDR 1 // uint8_t (0 or 2)
46- #define MENUTIMER_DIR_ADDR 2 // uint8_t (1..60)
47- const int EEPROM_MODE_ADDR = 4 ; // uint8_t
48- const int EEPROM_PARAM_SELECT_ADDR = 5 ; // per-mode bank starts here (5..16 used for 4 modes)
42+ // ---------------- EEPROM ----------------
43+ // OLED rotation.
44+ #define ENCODER_DIR_ADDR 0
45+ #define OLED_ROT_ADDR 1
46+ #define MENUTIMER_DIR_ADDR 2
47+ const int EEPROM_MODE_ADDR = 4 ;
48+ const int EEPROM_PARAM_SELECT_ADDR = 5 ;
4949
5050// ---------------- Modes ----------------
5151#define MODE_LFO 1
5252#define MODE_WAVE 2
5353#define MODE_SHOT 3
5454#define MODE_SPECTRUM 4
5555
56- // ---------------- Boot logo ----------------
56+ // ---------------- Boot logo (PROGMEM) ----------------
5757const unsigned char Modulove_Logo [] PROGMEM = {
5858 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xc0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
5959 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0xc0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
@@ -110,7 +110,7 @@ int rfrs = 0;
110110float oldPosition = -999 ;
111111float newPosition = -999 ;
112112
113- // Secret menu
113+ // config menu
114114bool encoderPressed = false ;
115115bool secretMenuActive = false ;
116116unsigned long enterPressStartTime = 0 ;
@@ -127,9 +127,8 @@ union {
127127} buffer;
128128
129129// ------------- Optional: WebScope flag -------------
130- volatile bool webscopeEnabled = false ; // set by serial command later
130+ volatile bool webscopeEnabled = false ;
131131
132- // ---------------- Prototypes ----------------
133132void drawBootAnimation ();
134133void setupMode (uint8_t mode);
135134void runLFOMode (bool showParams);
@@ -167,7 +166,7 @@ void setup() {
167166 display.setTextColor (WHITE );
168167
169168 drawBootAnimation ();
170- delay (1000 );
169+ delay (800 );
171170
172171 // I/O
173172 pinMode (OFFSET_PIN , OUTPUT );
@@ -182,7 +181,7 @@ void setup() {
182181 loadSettings ();
183182 setupMode (mode);
184183
185- // (Optional) Serial for WebSerial features
184+ // (Optional) WebSerial features
186185 // Serial.begin(115200);
187186}
188187
@@ -229,7 +228,7 @@ void loop() {
229228 // ---------- Normal operation ----------
230229 newPosition = encoderDirection * encoder.read ();
231230
232- // Button: cycle through parameter “slots” like original
231+ // Button: cycle through parameter “slots”
233232 if (old_SW == 0 && SW == 1 && param_select == param) { param_select = 0 ; hideTimer = millis (); }
234233 else if (old_SW == 0 && SW == 1 && (param >= 1 && param <= 3 )) { param_select = param; hideTimer = millis (); }
235234
@@ -276,7 +275,7 @@ void loop() {
276275
277276 display.display ();
278277
279- // (Optional) web scope streaming could go here if enabled
278+ // (Optional) web scope streaming
280279 // if (webscopeEnabled) { /* stream a decimated frame over Serial */ }
281280}
282281
@@ -301,7 +300,7 @@ void setupMode(uint8_t m) {
301300 switch (m) {
302301 case MODE_LFO :
303302 param1 = (saved_param1 >= 1 && saved_param1 <= 8 ) ? saved_param1 : 4 ; // Time
304- param2 = (saved_param2 >= 1 && saved_param2 <= 8 ) ? saved_param2 : 1 ; // Offset
303+ param2 = (saved_param2 >= - 6 && saved_param2 <= 10 ) ? saved_param2 : 1 ; // Offset
305304 pinMode (FILTER_PIN , INPUT );
306305 analogWrite (OFFSET_PIN , 0 );
307306 ADCSRA = (ADCSRA & 0xF8 ) | 0x04 ; // prescaler /16 (fast)
@@ -341,11 +340,11 @@ void setupMode(uint8_t m) {
341340void runLFOMode (bool showParams) {
342341 param = constrain (param, 1 , 3 );
343342 param1 = constrain (param1, 1 , 8 ); // Time scale
344- param2 = constrain (param2, 1 , 8 ); // Vertical offset
343+ param2 = constrain (param2, - 6 , 10 ); // Vertical offset
345344
346345 uint8_t currentSample = analogRead (ANALOG_INPUT_PIN ) >> 4 ; // 0..63
347346
348- // Scroll waveform (faster than for-loop)
347+ // Scroll waveform
349348 memmove (&buffer.waveform [1 ], &buffer.waveform [0 ], 127 );
350349 buffer.waveform [0 ] = currentSample;
351350
@@ -354,8 +353,8 @@ void runLFOMode(bool showParams) {
354353 lastDraw = millis ();
355354 display.clearDisplay ();
356355
357- int step = (9 - param1); // 8..1
358- int voff = (param2 - 1 ) * 4 ; // 0..28
356+ int step = (9 - param1);
357+ int voff = (param2 - 1 ) * 6 ;
359358 int segments = 126 / step;
360359
361360 for (int i = 0 ; i < segments; i++) {
@@ -523,7 +522,7 @@ void drawParameterBar(bool showParams) {
523522 }
524523}
525524
526- // ---------------- config menu (incl OLED rotation) ----------------
525+ // ---------------- config menu (new: OLED rotation) ----------------
527526void secretMenu () {
528527 int newDirection = encoderDirection;
529528 newPosition = encoder.read ();
@@ -598,34 +597,35 @@ void secretMenu() {
598597 display.setCursor (0 , 0 );
599598 display.setTextColor (WHITE );
600599 display.println (F (" GLOBAL SETTINGS" ));
600+ display.println ();
601601
602602 // 1) Encoder direction
603603 display.setTextColor (secretMenuOption == 1 ? BLACK : WHITE , secretMenuOption == 1 ? WHITE : BLACK );
604- display.println (F (" Encoder Direction: " ));
604+ display.print (F (" Encoder: " ));
605605 display.setTextColor (WHITE );
606- display.println (encoderDirection == 1 ? F ( " Normal" ) : F ( " Reversed" ));
606+ display.print (encoderDirection == 1 ? ( " Normal" ) : ( " Reversed" ));
607607 display.println ();
608608
609609 // 2) Menu timer
610610 display.setTextColor (secretMenuOption == 2 ? BLACK : WHITE , secretMenuOption == 2 ? WHITE : BLACK );
611- display.println (F (" Menu Timer:" ));
611+ display.print (F (" Timer: " ));
612612 display.setTextColor (WHITE );
613- display.print (menuTimer); display.println ( F (" s" ));
613+ display.print (menuTimer); display.print ( (" s" ));
614614 display.println ();
615615
616616 // 3) OLED Rotation
617617 display.setTextColor (secretMenuOption == 3 ? BLACK : WHITE , secretMenuOption == 3 ? WHITE : BLACK );
618- display.println (F (" OLED Rotation: " ));
618+ display.print (F (" OLED: " ));
619619 display.setTextColor (WHITE );
620- display.println (oledRotation == 0 ? F ( " 0 deg" ) : F ( " 180 deg" ));
620+ display.print (oledRotation == 0 ? ( " 0 deg" ) : ( " 180 deg" ));
621621
622622 // Exit bar
623623 if (exitProgress > 0 ) {
624- display.drawRect (0 , 56 , 128 , 8 , WHITE );
625- display.fillRect (2 , 58 , (exitProgress * 124 ) / 100 , 4 , WHITE );
626- display.setCursor (0 , 48 ); display.print (F (" Hold to save & exit" ));
624+ display.drawRect (0 , 54 , 128 , 8 , WHITE );
625+ display.fillRect (2 , 56 , (exitProgress * 124 ) / 100 , 4 , WHITE );
626+ display.setCursor (4 , 44 ); display.print (F (" Hold to save & exit" ));
627627 } else {
628- display.setCursor (0 , 56 ); display.print (F (" Hold button to exit" ));
628+ display.setCursor (4 , 52 ); display.print (F (" Hold button to exit" ));
629629 }
630630 display.display ();
631631}
0 commit comments