Seedbox v0.1 + firmware, generic kit/synth, ROOT/SCALE pages
Some checks failed
check / check (push) Has been cancelled

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>
This commit is contained in:
2026-10-11 20:39:36 +03:00
commit 2196633ed5
77 changed files with 52207 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
#include "pcd8544.h"
#include "hardware/gpio.h"
#include "hardware/spi.h"
#include "pico/time.h"
#include <string.h>
#define PIN_CE 17
#define PIN_SCK 18
#define PIN_MOSI 19
#define PIN_DC 20
#define PIN_RST 21
#define LCD_SPI spi0
#define LCD_HZ 4000000
static uint8_t fb[LCD_W * LCD_H / 8]; /* PCD8544 layout: 6 banks of 8 rows, LSB at the top */
static void write(int data, const uint8_t *b, size_t n){
gpio_put(PIN_DC, data);
gpio_put(PIN_CE, 0);
spi_write_blocking(LCD_SPI, b, n); /* returns once the bytes are shifted out */
gpio_put(PIN_CE, 1);
}
static void cmd(uint8_t c){ write(0, &c, 1); }
void lcd_set_vop(int vop){
cmd(0x21); /* extended instruction set */
cmd((uint8_t)(0x80 | (vop & 0x7F)));
cmd(0x20);
}
void lcd_init(int vop){
spi_init(LCD_SPI, LCD_HZ);
spi_set_format(LCD_SPI, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
gpio_init(PIN_CE); gpio_set_dir(PIN_CE, GPIO_OUT); gpio_put(PIN_CE, 1);
gpio_init(PIN_DC); gpio_set_dir(PIN_DC, GPIO_OUT); gpio_put(PIN_DC, 0);
gpio_init(PIN_RST); gpio_set_dir(PIN_RST, GPIO_OUT);
gpio_put(PIN_RST, 0); sleep_ms(10); gpio_put(PIN_RST, 1); sleep_ms(10);
cmd(0x21); /* extended */
cmd((uint8_t)(0x80 | (vop & 0x7F)));/* Vop */
cmd(0x04); /* temperature coefficient 0 */
cmd(0x13); /* bias 1:48 */
cmd(0x20); /* basic, horizontal addressing */
cmd(0x0C); /* normal display */
lcd_clear(); lcd_flush();
}
void lcd_clear(void){ memset(fb, 0, sizeof fb); }
void lcd_px(int x, int y, int on){
if(x < 0 || x >= LCD_W || y < 0 || y >= LCD_H) return;
if(on) fb[(y >> 3) * LCD_W + x] |= (uint8_t)(1u << (y & 7));
else fb[(y >> 3) * LCD_W + x] &= (uint8_t)~(1u << (y & 7));
}
void lcd_fill(int x, int y, int w, int h, int on){ int i, j; for(j = y; j < y + h; j++) for(i = x; i < x + w; i++) lcd_px(i, j, on); }
/* The 5 × 7 font from sim/app.js (FONT): five column bytes per glyph, bit 0 at the top. */
typedef struct { char c; uint8_t col[5]; } glyph_t;
static const glyph_t FONT[] = {
{' ',{0,0,0,0,0}},{'+',{8,8,62,8,8}},{'-',{8,8,8,8,8}},{'.',{0,96,96,0,0}},{'/',{32,16,8,4,2}},{':',{0,54,54,0,0}},
{'#',{20,127,20,127,20}},{'*',{20,8,62,8,20}},{'>',{0,65,34,20,8}},{'?',{2,1,81,9,6}},{'!',{0,0,95,0,0}},
{'0',{62,81,73,69,62}},{'1',{0,66,127,64,0}},{'2',{66,97,81,73,70}},{'3',{33,65,69,75,49}},{'4',{24,20,18,127,16}},
{'5',{39,69,69,69,57}},{'6',{60,74,73,73,48}},{'7',{1,113,9,5,3}},{'8',{54,73,73,73,54}},{'9',{6,73,73,41,30}},
{'A',{126,17,17,17,126}},{'B',{127,73,73,73,54}},{'C',{62,65,65,65,34}},{'D',{127,65,65,34,28}},{'E',{127,73,73,73,65}},
{'F',{127,9,9,9,1}},{'G',{62,65,73,73,122}},{'H',{127,8,8,8,127}},{'I',{0,65,127,65,0}},{'J',{32,64,65,63,1}},
{'K',{127,8,20,34,65}},{'L',{127,64,64,64,64}},{'M',{127,2,12,2,127}},{'N',{127,4,8,16,127}},{'O',{62,65,65,65,62}},
{'P',{127,9,9,9,6}},{'Q',{62,65,81,33,94}},{'R',{127,9,25,41,70}},{'S',{70,73,73,73,49}},{'T',{1,1,127,1,1}},
{'U',{63,64,64,64,63}},{'V',{31,32,64,32,31}},{'W',{63,64,56,64,63}},{'X',{99,20,8,20,99}},{'Y',{7,8,112,8,7}},
{'Z',{97,81,73,69,67}}
};
static const glyph_t *glyph(char c){
size_t i;
if(c >= 'a' && c <= 'z') c = (char)(c - 32);
for(i = 0; i < sizeof FONT / sizeof FONT[0]; i++) if(FONT[i].c == c) return &FONT[i];
return glyph('?');
}
void lcd_text_v(int x, int y, const char *s, int on){
for(; *s; s++, x += 6){
const glyph_t *g = glyph(*s);
int col, row;
for(col = 0; col < 5; col++) for(row = 0; row < 7; row++) if((g->col[col] >> row) & 1) lcd_px(x + col, y + row, on);
}
}
void lcd_text(int x, int y, const char *s){ lcd_text_v(x, y, s, 1); }
void lcd_box(int x, int y, int w, int h){ lcd_fill(x, y, w, 1, 1); lcd_fill(x, y + h - 1, w, 1, 1); lcd_fill(x, y, 1, h, 1); lcd_fill(x + w - 1, y, 1, h, 1); }
void lcd_flush(void){
cmd(0x80); cmd(0x40); /* X = 0, Y = 0 */
write(1, fb, sizeof fb);
}