1
0
Fork 0

Compare commits

...

5 Commits

Author SHA1 Message Date
radex 805c7b8420
update readme 2024-06-23 20:57:05 +02:00
radex 11340358d2
add bitmap font rendering (untested) 2024-06-20 17:40:49 +02:00
radex 47019ac5c2
pcb/main board: add errata 2024-06-20 17:40:17 +02:00
radex d1e4912330
SD: try bumping to 24mhz 2024-06-20 17:40:10 +02:00
radex c114007ddb
integration hell 2024-06-20 17:39:46 +02:00
10 changed files with 1068 additions and 25 deletions

View File

@ -20,14 +20,14 @@ The microcontroller board was optimized for JLC PCBA to a lesser extent -- I use
The display is capable of:
- 8 bit (TODO, 5-bit demonstrated) red color
- 8 bit red color
- 60fps (TODO, 30fps demonstrated)
Additionally, the MCU board can:
- Read multiple "videos" (specially encoded for this firmware) from an SD card
- Pipe in 8-bit 44kHz audio (TODO, lower quality demonstrated due to SD performance issues)
- do CAN (TODO)
- Pipe in 8-bit 44kHz audio
- Transmit and receive CAN messages
## v2

View File

@ -0,0 +1,169 @@
// https://github.com/petabyt/font3x3
#ifndef FONT3X3_H
#define FONT3X3_H
struct Font3x3 {
const char letter;
const char code[3][4];
};
struct Font3x3 font[] = {
{'A', {
" # ",
"###",
"# #"}},
{'B', {
"## ",
"###",
"###"}},
{'C', {
"###",
"# ",
"###"}},
{'D', {
"## ",
"# #",
"## "}},
{'E', {
"###",
"## ",
"###"}},
{'F', {
"###",
"## ",
"# "}},
{'G', {
"## ",
"# #",
"###"}},
{'H', {
"# #",
"###",
"# #"}},
{'I', {
"###",
" # ",
"###"}},
{'J', {
" #",
"# #",
"###"}},
{'K', {
"# #",
"## ",
"# #"}},
{'L', {
"# ",
"# ",
"###"}},
{'M', {
"###",
"###",
"# #"}},
{'N', {
"###",
"# #",
"# #"}},
{'O', {
"###",
"# #",
"###"}},
{'P', {
"###",
"###",
"# "}},
{'Q', {
"###",
"###",
" #"}},
{'R', {
"###",
"# ",
"# "}},
{'S', {
" ##",
" # ",
"## "}},
{'T', {
"###",
" # ",
" # "}},
{'U', {
"# #",
"# #",
"###"}},
{'V', {
"# #",
"# #",
" # "}},
{'W', {
"# #",
"###",
"###"}},
{'X', {
"# #",
" # ",
"# #"}},
{'Y', {
"# #",
" # ",
" # "}},
{'Z', {
"## ",
" # ",
" ##"}},
{'!', {
"# ",
" ",
"# "}},
{'>', {
"# ",
" # ",
"# "}},
{'<', {
" # ",
"# ",
" # "}},
{'%', {
" #",
"###",
"# "}},
{'*', {
" # ",
"## ",
" "}},
{'+', {
" # ",
"###",
" # "}},
{'-', {
" ",
"###",
" "}},
{'.', {
" ",
" ",
"# "}},
{',', {
" ",
"# ",
"# "}},
{'$', {
"###",
" # ",
"###"}},
{'|', {
"# ",
"# ",
"# "}},
{'?', {
"###",
" ##",
" # "}},
{'^', {
" # ",
"# #",
" "}}
};
#endif

View File

@ -0,0 +1,761 @@
// https://github.com/petabyt/font
/*
"font.h", Written by Daniel C. MIT License.
This file is C89.
Compiler/preprocessor configs (optional):
-D NO_LOWERCASE
-D NO_SYMBOL
-D NO_NUMBERS
In case you are limited in space :)
*/
#ifndef FONT_H
#define FONT_H
struct Font {
char letter;
char code[7][5];
};
struct Font font[] = {
{' ', { /* Processor should ignore this */
" ",
" ",
" ",
" ",
" ",
" ",
" "}},
{'A', {
" ### ",
"# #",
"# #",
"# #",
"#####",
"# #",
"# #"}},
{'B', {
"#### ",
"# #",
"# #",
"#### ",
"# #",
"# #",
"#### "}},
{'C', {
" ####",
"# ",
"# ",
"# ",
"# ",
"# ",
" ####"}},
{'D', {
"#### ",
"# #",
"# #",
"# #",
"# #",
"# #",
"#### "}},
{'E', {
"#####",
"# ",
"# ",
"#####",
"# ",
"# ",
"#####"}},
{'F', {
"#####",
"# ",
"# ",
"#####",
"# ",
"# ",
"# "}},
{'G', {
" ####",
"# ",
"# ",
"# ##",
"# #",
"# #",
" ####"}},
{'H', {
"# #",
"# #",
"# #",
"#####",
"# #",
"# #",
"# #"}},
{'I', {
"# ",
"# ",
"# ",
"# ",
"# ",
"# ",
"# "}},
{'J', {
" #",
" #",
" #",
" #",
" #",
" #",
"#### "}},
{'K', {
"# #",
"# # ",
"# # ",
"## ",
"# # ",
"# # ",
"# #"}},
{'L', {
"# ",
"# ",
"# ",
"# ",
"# ",
"# ",
"#####"}},
{'M', {
"# #",
"## ##",
"# # #",
"# #",
"# #",
"# #",
"# #"}},
{'N', {
"# #",
"## #",
"# # #",
"# ##",
"# #",
"# #",
"# #"}},
{'O', {
" ### ",
"# #",
"# #",
"# #",
"# #",
"# #",
" ### "}},
{'P', {
"#### ",
"# #",
"# #",
"#### ",
"# ",
"# ",
"# "}},
{'Q', {
" ### ",
"# #",
"# #",
"# #",
"# #",
"# ##",
" ####"}},
{'R', {
"#### ",
"# #",
"# #",
"# #",
"#### ",
"# #",
"# #"}},
{'S', {
" ####",
"# ",
"# ",
" ### ",
" #",
" #",
"#### "}},
{'T', {
"#####",
" # ",
" # ",
" # ",
" # ",
" # ",
" # "}},
{'U', {
"# #",
"# #",
"# #",
"# #",
"# #",
"# #",
" ### "}},
{'V', {
"# #",
"# #",
"# #",
"# #",
"# #",
" # # ",
" # "}},
{'W', {
"# #",
"# #",
"# #",
"# #",
"# # #",
"## ##",
"# #"}},
{'X', {
"# #",
"# #",
" # # ",
" # ",
" # # ",
"# #",
"# #"}},
{'Y', {
"# #",
"# #",
"# #",
" ### ",
" # ",
" # ",
" # "}},
{'Z', {
"#####",
" #",
" # ",
" # ",
" # ",
"# ",
"#####"}},
#ifndef NO_LOWERCASE
{'a', {
" ",
" ",
" ### ",
" #",
" ####",
"# #",
" ####"}},
{'b', {
"# ",
"# ",
"#### ",
"# #",
"# #",
"# #",
"#### "}},
{'c', {
" ",
" ",
" ### ",
"# #",
"# ",
"# #",
" ### "}},
{'d', {
" #",
" #",
" ####",
"# #",
"# #",
"# #",
" ####"}},
{'e', {
" ",
" ",
" ### ",
"# #",
"#####",
"# ",
" ####"}},
{'f', {
" ## ",
" # #",
" # ",
"### ",
" # ",
" # ",
" # "}},
{'g', {
" ",
" ####",
"# #",
"# #",
" ####",
" #",
"#### "}},
{'h', {
"# ",
"# ",
"#### ",
"# #",
"# #",
"# #",
"# #"}},
{'i', {
"# ",
" ",
"# ",
"# ",
"# ",
"# ",
"# "}},
{'j', {
" #",
" ",
" ##",
" #",
" #",
"# #",
" ### "}},
{'k', {
"# ",
"# ",
"# #",
"# # ",
"### ",
"# # ",
"# #"}},
{'l', {
"# ",
"# ",
"# ",
"# ",
"# ",
"# ",
"## "}},
{'m', {
" ",
" ",
"#### ",
"# # #",
"# # #",
"# # #",
"# # #"}},
{'n', {
" ",
" ",
"#### ",
"# #",
"# #",
"# #",
"# #"}},
{'o', {
" ",
" ",
" ### ",
"# #",
"# #",
"# #",
" ### "}},
{'p', {
" ",
" ### ",
" # #",
" # #",
" ### ",
" # ",
" # "}},
{'q', {
" ",
" ",
" ###",
" # #",
" ###",
" #",
" #"}},
{'r', {
" ",
" ",
"# ###",
"## ",
"# ",
"# ",
"# "}},
{'s', {
" ",
" ",
" ####",
"# ",
" ### ",
" #",
"#### "}},
{'t', {
" # ",
" # ",
"### ",
" # ",
" # ",
" # ",
" ## "}},
{'u', {
" ",
" ",
"# #",
"# #",
"# #",
"# #",
" ### "}},
{'v', {
" ",
" ",
"# #",
"# #",
"# #",
" # # ",
" # "}},
{'w', {
" ",
" ",
"# #",
"# #",
"# # #",
"# # #",
" # # "}},
{'x', {
" ",
" ",
"# #",
" # # ",
" # ",
" # # ",
"# #"}},
{'y', {
" ",
" ",
"# #",
"# #",
" ####",
" #",
"#### "}},
{'z', {
" ",
" ",
"#####",
" # ",
" # ",
" # ",
"#####"}},
#endif
#ifndef NO_NUMBERS
{'0', {
" ### ",
"# #",
"# ##",
"# # #",
"## #",
"# #",
" ### "}},
{'1', {
"## ",
" # ",
" # ",
" # ",
" # ",
" # ",
" # "}},
{'2', {
" ### ",
"# #",
" #",
" ## ",
" # ",
"# ",
"#####"}},
{'3', {
"#### ",
" #",
" #",
" ### ",
" #",
" #",
"#### "}},
{'4', {
"# #",
"# #",
"# #",
"#####",
" #",
" #",
" #"}},
{'5', {
"#####",
"# ",
"# ",
"#### ",
" #",
" #",
"#### "}},
{'6', {
" ####",
"# ",
"# ",
" ### ",
"# #",
"# #",
" ### "}},
{'7', {
"#####",
" #",
" #",
" ## ",
" # ",
" # ",
" # "}},
{'8', {
" ### ",
"# #",
"# #",
" ### ",
"# #",
"# #",
" ### "}},
{'9', {
" ### ",
"# #",
"# #",
" ####",
" #",
" #",
" ### "}},
#endif
#ifndef NO_SYMBOLS
{'!', {
"# ",
"# ",
"# ",
"# ",
"# ",
" ",
"# "}},
{'.', {
" ",
" ",
" ",
" ",
" ",
" ",
"# "}},
{',', {
" ",
" ",
" ",
" ",
" ",
" # ",
" # "}},
{'?', {
" ## ",
"# # ",
" # ",
" # ",
" # ",
" ",
" # "}},
{1, {
" ",
" # # ",
" # # ",
" ",
" # ",
"# #",
" ### "}},
{'%', {
" #",
" # #",
" # ",
" # ",
" # ",
"# # ",
"# "}},
{'#', {
" # # ",
" # # ",
"#####",
" # # ",
"#####",
" # # ",
" # # "}},
{'_', {
" ",
" ",
" ",
" ",
" ",
" ",
"#####"}},
{'-', {
" ",
" ",
" ",
" ### ",
" ",
" ",
" "}},
{';', {
" ",
" # ",
" ",
" # ",
" # ",
"# ",
" "}},
{'`', {
" # ",
" # ",
" ",
" ",
" ",
" ",
" "}},
{'=', {
" ",
"#####",
" ",
" ",
"#####",
" ",
" "}},
{'_', {
" ",
" ",
" ",
" ",
" ",
" ",
"#####"}},
{':', {
" ",
" # ",
" ",
" ",
" # ",
" ",
" "}},
{'<', {
" # ",
" # ",
" # ",
"# ",
" # ",
" # ",
" # "}},
{'>', {
" # ",
" # ",
" # ",
" #",
" # ",
" # ",
" # "}},
{'~', {
" ",
" ",
"# # #",
" # # ",
" ",
" ",
" "}},
{'*', {
" # ",
" ### ",
" # ",
" # # ",
" ",
" ",
" "}},
{'/', {
" #",
" #",
" # ",
" # ",
" # ",
" # ",
"# "}},
{'\'', {
"# ",
"# ",
"# ",
" ",
" ",
" ",
" "}},
{'"', {
"# # ",
"# # ",
"# # ",
" ",
" ",
" ",
" "}},
{'(', {
" # ",
" # ",
"# ",
"# ",
"# ",
" # ",
" # "}},
{')', {
"# ",
" # ",
" # ",
" # ",
" # ",
" # ",
"# "}},
{'}', {
"# ",
" # ",
" # ",
" # ",
" # ",
" # ",
"# "}},
{'{', {
" # ",
" # ",
" # ",
"# ",
" # ",
" # ",
" # "}},
{'+', {
" ",
" ",
" # ",
" # ",
"#####",
" # ",
" # "}},
{'-', {
" ",
" ",
" ",
" ",
"#####",
" ",
" "}},
#endif
/* Fallback/end Char. If you don't know the
font size, use this as the "null terminator" */
{0, {
"#####",
"#####",
"#####",
"#####",
"#####",
"#####",
"#####"}},
};
#endif

View File

@ -34,22 +34,22 @@
// #define COMMON_SER 21
// #define COMMON_RCLK 23
#define COMMON_SRCLR 25
// #define COMMON_SRCLR 25
#define COL_SER 21
#define COL_OE 22
#define COL_RCLK 23
#define COL_SRCLK 24
// #define COL_SRCLR 25
#define COL_SER 22 // orig: 21
#define COL_OE 21 // orig: 22
#define COL_RCLK 23 // orig: 23
#define COL_SRCLK 24 // orig: 24
#define COL_SRCLR 25 // orig: 25
#define ROW_SER 14
#define ROW_OE 19
#define ROW_RCLK 20
#define ROW_SRCLK 18
// #define ROW_SRCLR 15
#define ROW_SRCLR 15
#define COL_SER_INVERTED true
#define COL_OE_INVERTED true
#define COL_SER_INVERTED false
#define COL_OE_INVERTED false
#define COL_RCLK_INVERTED true
#define COL_SRCLK_INVERTED true
#define COL_SRCLR_INVERTED false
@ -75,7 +75,7 @@
// --- other settings ---
#define CPU_CLOCK_HZ 133000000.0f
#define SD_CARD_BAUD_RATE 12 * 1000 * 1000
#define SD_CARD_BAUD_RATE 24 * 1000 * 1000
#define REFERENCE_VOLTAGE 3.3f // for ADC
#define CAN_BITRATE 500000

View File

@ -3,12 +3,12 @@
.define public irq_rclk_sync 2
.define public irq_did_latch 3
.define public rclk_1_delay 6
.define public rclk_1_delay 3
.program leds_px_pusher
.side_set 1 opt
.define public srclk_0_delay 3
.define public srclk_1_delay 5
.define public srclk_0_delay 2
.define public srclk_1_delay 3
entry_point:
.wrap_target
; get 32 bits from fifo (not required with autopull, useful for debug)

View File

@ -12,7 +12,7 @@
#define irq_px_pushed 1
#define irq_rclk_sync 2
#define irq_did_latch 3
#define rclk_1_delay 6
#define rclk_1_delay 3
// -------------- //
// leds_px_pusher //
@ -21,20 +21,20 @@
#define leds_px_pusher_wrap_target 0
#define leds_px_pusher_wrap 9
#define leds_px_pusher_srclk_0_delay 3
#define leds_px_pusher_srclk_1_delay 5
#define leds_px_pusher_srclk_0_delay 2
#define leds_px_pusher_srclk_1_delay 3
static const uint16_t leds_px_pusher_program_instructions[] = {
// .wrap_target
0xf037, // 0: set x, 23 side 0
0x7301, // 1: out pins, 1 side 0 [3]
0x1d41, // 2: jmp x--, 1 side 1 [5]
0x7201, // 1: out pins, 1 side 0 [2]
0x1b41, // 2: jmp x--, 1 side 1 [3]
0x7028, // 3: out x, 8 side 0
0x0020, // 4: jmp !x, 0
0xc001, // 5: irq nowait 1
0x2040, // 6: wait 0 irq, 0
0x20c2, // 7: wait 1 irq, 2
0xe601, // 8: set pins, 1 [6]
0xe301, // 8: set pins, 1 [3]
0xe000, // 9: set pins, 0
// .wrap
};
@ -73,7 +73,7 @@ static const uint16_t leds_row_selector_program_instructions[] = {
0xb003, // 4: mov pins, null side 0
0x0043, // 5: jmp x--, 3
0xc022, // 6: irq wait 2
0xe601, // 7: set pins, 1 [6]
0xe301, // 7: set pins, 1 [3]
0xe000, // 8: set pins, 0
0xc003, // 9: irq nowait 3
// .wrap

View File

@ -18,13 +18,14 @@ void setup() {
Serial.begin(115200);
Serial.println("Hello worldd!");
init_audio();
leds_initRenderer();
if (CPU_CLOCK_HZ != rp2040.f_cpu()) {
Serial.println("CPU clock speed is not set correctly!");
while (true) {}
}
init_audio();
leds_initRenderer();
#if CAN_ENABLED
canbus_setup();
#endif

85
firmware/src/text.cpp Normal file
View File

@ -0,0 +1,85 @@
#include <assert.h>
#include "text.h"
#include "font3x3.h"
#define FONT_WIDTH 3
#define FONT_HEIGHT 3
uint8_t cx = 0;
uint8_t cy = 0;
void text_setCursor(uint8_t x, uint8_t y) {
assert(x < COL_COUNT);
assert(y < ROW_COUNT);
cx = x;
cy = y;
}
uint8_t text_charIdx(char c) {
// change to uppercase
if (c >= 'a' && c <= 'z') {
c += ('A' - 'a');
}
// find character
for (int i = 0; i < sizeof(font); i++) {
if (font[i].letter == c) {
return i;
}
}
// if not found, use `?` as placeholder
return text_charIdx('?');
}
inline void text_newline() {
cx = 0;
cy += (FONT_HEIGHT + 1);
}
void text_next() {
cx += (FONT_WIDTH + 1);
if (cx >= COL_COUNT) {
text_newline();
}
}
bool text_printChar(uint8_t framebuffer[ROW_COUNT * COL_COUNT], char c) {
// check if there is space
if (cy + FONT_HEIGHT >= ROW_COUNT) {
return false;
}
// special cases - space, newline
if (c == '\n') {
text_newline();
return true;
} else if (c == ' ') {
text_next();
return true;
}
// draw pixels
uint8_t letterIdx = text_charIdx(c);
for (int i = 0; i < FONT_HEIGHT; i++) {
for (int j = 0; j < FONT_WIDTH; j++) {
if (font[letterIdx].code[i][j] == '#') {
framebuffer[(i + cy) * COL_COUNT + (j + cx)] = 255;
}
}
}
// move cursor
text_next();
return true;
}
bool text_printStr(uint8_t framebuffer[ROW_COUNT * COL_COUNT], char *string) {
for (int i = 0; string[i] != 0; i++) {
if (!text_printChar(framebuffer, string[i])) {
return false;
}
}
return true;
}

10
firmware/src/text.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _text_h
#define _text_h
#include <stdint.h>
#include "config.h"
bool text_printChar(uint8_t framebuffer[ROW_COUNT * COL_COUNT], char c);
bool text_printStr(uint8_t framebuffer[ROW_COUNT * COL_COUNT], char *string);
#endif

17
pcb/MainBoard/README.md Normal file
View File

@ -0,0 +1,17 @@
# Main Board
50x50mm microcontroller module, driving LedArrayMux modules. Contains an RP2040 microcontroller, a CAN transceiver, PWM audio output, current sensing, and level shifters to work around LedArrayMux bugs.
## Revisions
### Rev A
Errata:
1. Level shifters are too slow to be useful
- Workaround: decrease pullup values to obnoxiously low ones (100-180Ω); do not use level shifters; increase PIO delays until functional
2. CAN receive signal is not level shifted, which exposes RP2040 to a 5V signal
- Workaround: Do nothing; replace with a 3v3 CAN transceiver
3. The 431 shunt voltage reference does not work correctly
- Workaround: use main 3v3 regulator for vref
4. PWM audio signal filter is suspected to be responsible for poor quality audio