1
0
Fork 0

add bitmap font rendering (untested)

main
radex 2024-06-20 17:40:49 +02:00
parent 47019ac5c2
commit 11340358d2
Signed by: radex
SSH Key Fingerprint: SHA256:hvqRXAGG1h89yqnS+cyFTLKQbzjWD4uXIqw7Y+0ws30
4 changed files with 1025 additions and 0 deletions

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

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