Seedbox v0.1 + firmware, generic kit/synth, ROOT/SCALE pages
Some checks failed
check / check (push) Has been cancelled
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:
91
firmware/drivers/pcd8544.c
Normal file
91
firmware/drivers/pcd8544.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user