Files
seedbox/firmware/drivers/encoder.c
Gee 2196633ed5
Some checks failed
check / check (push) Has been cancelled
Seedbox v0.1 + firmware, generic kit/synth, ROOT/SCALE pages
First commit of the repo. Contents beyond the v0.1 simulator and layout:

- Full Pico 2 W firmware (firmware/app, drivers, engine port, host test).
- BANK page and 404 mode A/B removed; learned pads play exactly what was learned.
- 404/MiniFreak renamed to KIT/SYNTH throughout (jacks, code, sim, docs,
  layout labels; wiring rebuilt).
- ROLL returns to page select after a re-roll; a freshly learned track turns on.
- LCD contrast 66.
- ROOT and SCALE pages: 21 scales, AUTO = the seed picks; global and sticky.

Intended music change: the scale table grew from 8 to 21 and AUTO picks from
all of them, so every seed's scale changed. Vectors regenerated with
npm run vectors, plus new key-override cases. Flash record is now version 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:39:36 +03:00

46 lines
1.6 KiB
C

#include "encoder.h"
#include "hardware/gpio.h"
#define PIN_A 10
#define PIN_B 11
#define REST 3 /* A = B = 1: both contacts open at a detent */
#define DIR -1 /* as wired on the bench, the raw count runs down clockwise */
static volatile int32_t steps, clicks;
static volatile int8_t acc; /* edges since the last rest */
static volatile uint8_t prev;
/* index = previous AB << 2 | current AB; invalid (bounce) transitions count 0 */
static const int8_t TABLE[16] = { 0,-1, 1, 0, 1, 0, 0,-1, -1, 0, 0, 1, 0, 1,-1, 0 };
static uint8_t read_ab(void){ return (uint8_t)((gpio_get(PIN_A) << 1) | gpio_get(PIN_B)); }
static void on_edge(uint gpio, uint32_t events){
uint8_t cur;
int8_t d;
(void)events;
if(gpio != PIN_A && gpio != PIN_B) return;
cur = read_ab();
d = TABLE[(prev << 2) | cur];
steps += d; acc = (int8_t)(acc + d);
prev = cur;
if(cur == REST){
/* a full click is 4 edges; accept 2 or more in case bounce hid some, ignore wiggles of 1 */
if(acc >= 2) clicks += DIR;
else if(acc <= -2) clicks -= DIR;
acc = 0;
}
}
void encoder_init(void){
gpio_init(PIN_A); gpio_set_dir(PIN_A, GPIO_IN); gpio_pull_up(PIN_A);
gpio_init(PIN_B); gpio_set_dir(PIN_B, GPIO_IN); gpio_pull_up(PIN_B);
prev = read_ab();
gpio_set_irq_enabled_with_callback(PIN_A, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, on_edge);
gpio_set_irq_enabled(PIN_B, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
}
int32_t encoder_count(void){ return clicks; }
int32_t encoder_steps(void){ return DIR * steps; }
int encoder_ab(void){ return read_ab(); }