Rotary encoder
This commit is contained in:
parent
d30bac7ec5
commit
59b48c1ab3
@ -17,12 +17,6 @@ const int16_t AMPLITUDE = 16383; // Use a lower amplitude to avoid clipping (max
|
|||||||
I2S i2s(OUTPUT);
|
I2S i2s(OUTPUT);
|
||||||
|
|
||||||
// --- Synthesizer State ---
|
// --- Synthesizer State ---
|
||||||
// Frequencies for a C-Major scale to pick from
|
|
||||||
const float NOTE_FREQUENCIES[] = {
|
|
||||||
261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25
|
|
||||||
};
|
|
||||||
const int NUM_NOTES = sizeof(NOTE_FREQUENCIES) / sizeof(NOTE_FREQUENCIES[0]);
|
|
||||||
|
|
||||||
float currentFrequency = 440.0f;
|
float currentFrequency = 440.0f;
|
||||||
double phase = 0.0;
|
double phase = 0.0;
|
||||||
unsigned long lastNoteChangeTime = 0;
|
unsigned long lastNoteChangeTime = 0;
|
||||||
@ -50,8 +44,8 @@ void loopAudio() {
|
|||||||
// Every 500ms, pick a new random note to play
|
// Every 500ms, pick a new random note to play
|
||||||
if (now - lastNoteChangeTime > 500) {
|
if (now - lastNoteChangeTime > 500) {
|
||||||
lastNoteChangeTime = now;
|
lastNoteChangeTime = now;
|
||||||
int noteIndex = random(0, NUM_NOTES);
|
int noteIndex = random(0, SCALES[currentScaleIndex].numNotes);
|
||||||
currentFrequency = NOTE_FREQUENCIES[noteIndex];
|
currentFrequency = SCALES[currentScaleIndex].frequencies[noteIndex];
|
||||||
Serial.println("Playing note: " + String(currentFrequency) + " Hz");
|
Serial.println("Playing note: " + String(currentFrequency) + " Hz");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,3 +3,12 @@
|
|||||||
volatile unsigned long lastLoop0Time = 0;
|
volatile unsigned long lastLoop0Time = 0;
|
||||||
volatile unsigned long lastLoop1Time = 0;
|
volatile unsigned long lastLoop1Time = 0;
|
||||||
volatile bool watchdogActive = false;
|
volatile bool watchdogActive = false;
|
||||||
|
|
||||||
|
const Scale SCALES[] = {
|
||||||
|
{ "C Major", { 261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25 }, 8 },
|
||||||
|
{ "C Minor", { 261.63, 293.66, 311.13, 349.23, 392.00, 415.30, 466.16, 523.25 }, 8 },
|
||||||
|
{ "Pentatonic", { 261.63, 293.66, 329.63, 392.00, 440.00, 523.25, 587.33, 659.25 }, 8 },
|
||||||
|
{ "Blues", { 261.63, 311.13, 349.23, 369.99, 392.00, 466.16, 523.25, 587.33 }, 8 }
|
||||||
|
};
|
||||||
|
const int NUM_SCALES = sizeof(SCALES) / sizeof(SCALES[0]);
|
||||||
|
volatile int currentScaleIndex = 0;
|
||||||
@ -7,4 +7,14 @@ extern volatile unsigned long lastLoop0Time;
|
|||||||
extern volatile unsigned long lastLoop1Time;
|
extern volatile unsigned long lastLoop1Time;
|
||||||
extern volatile bool watchdogActive;
|
extern volatile bool watchdogActive;
|
||||||
|
|
||||||
|
struct Scale {
|
||||||
|
const char* name;
|
||||||
|
const float frequencies[8];
|
||||||
|
int numNotes;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const Scale SCALES[];
|
||||||
|
extern const int NUM_SCALES;
|
||||||
|
extern volatile int currentScaleIndex;
|
||||||
|
|
||||||
#endif // SHAREDSTATE_H
|
#endif // SHAREDSTATE_H
|
||||||
67
UIThread.cpp
67
UIThread.cpp
@ -14,13 +14,45 @@
|
|||||||
#define PIN_SDA 4
|
#define PIN_SDA 4
|
||||||
#define PIN_SCL 5
|
#define PIN_SCL 5
|
||||||
|
|
||||||
|
// Encoder Pins
|
||||||
|
#define PIN_ENC_CLK 12
|
||||||
|
#define PIN_ENC_DT 13
|
||||||
|
|
||||||
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
|
||||||
|
|
||||||
|
volatile int8_t encoderDelta = 0;
|
||||||
|
static uint8_t prevNextCode = 0;
|
||||||
|
static uint16_t store = 0;
|
||||||
|
|
||||||
|
// --- ENCODER INTERRUPT ---
|
||||||
|
// Robust Rotary Encoder reading
|
||||||
|
void readEncoder() {
|
||||||
|
static int8_t rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};
|
||||||
|
|
||||||
|
prevNextCode <<= 2;
|
||||||
|
if (digitalRead(PIN_ENC_DT)) prevNextCode |= 0x02;
|
||||||
|
if (digitalRead(PIN_ENC_CLK)) prevNextCode |= 0x01;
|
||||||
|
prevNextCode &= 0x0f;
|
||||||
|
|
||||||
|
// If valid state
|
||||||
|
if (rot_enc_table[prevNextCode]) {
|
||||||
|
store <<= 4;
|
||||||
|
store |= prevNextCode;
|
||||||
|
if ((store & 0xff) == 0x2b) encoderDelta--;
|
||||||
|
if ((store & 0xff) == 0x17) encoderDelta++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setupUI() {
|
void setupUI() {
|
||||||
Wire.setSDA(PIN_SDA);
|
Wire.setSDA(PIN_SDA);
|
||||||
Wire.setSCL(PIN_SCL);
|
Wire.setSCL(PIN_SCL);
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
|
|
||||||
|
pinMode(PIN_ENC_CLK, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_ENC_DT, INPUT_PULLUP);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_ENC_CLK), readEncoder, CHANGE);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_ENC_DT), readEncoder, CHANGE);
|
||||||
|
|
||||||
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
|
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
|
||||||
Serial.println(F("SSD1306 allocation failed"));
|
Serial.println(F("SSD1306 allocation failed"));
|
||||||
for(;;);
|
for(;;);
|
||||||
@ -34,7 +66,36 @@ void setupUI() {
|
|||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loopUI() {
|
void handleInput() {
|
||||||
// The loop on core 0 is responsible for updating the UI.
|
// Handle Encoder Rotation
|
||||||
delay(100);
|
int rotation = 0;
|
||||||
|
noInterrupts();
|
||||||
|
rotation = encoderDelta;
|
||||||
|
encoderDelta = 0;
|
||||||
|
interrupts();
|
||||||
|
|
||||||
|
if (rotation != 0) {
|
||||||
|
currentScaleIndex += rotation;
|
||||||
|
while (currentScaleIndex < 0) currentScaleIndex += NUM_SCALES;
|
||||||
|
while (currentScaleIndex >= NUM_SCALES) currentScaleIndex -= NUM_SCALES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loopUI() {
|
||||||
|
// sleep to avoid thread starvation
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
handleInput();
|
||||||
|
// The loop on core 0 is responsible for updating the UI.
|
||||||
|
static unsigned long lastUpdate = 0;
|
||||||
|
if (millis() - lastUpdate < 100) return;
|
||||||
|
lastUpdate = millis();
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setCursor(0, 0);
|
||||||
|
display.setTextSize(1);
|
||||||
|
display.println(F("Current Scale:"));
|
||||||
|
display.setTextSize(2);
|
||||||
|
display.println(SCALES[currentScaleIndex].name);
|
||||||
|
display.display();
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user