Files
seedbox/firmware/drivers/pcd8544.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

92 lines
4.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
}