1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2024-11-30 16:14:28 +01:00

Font goes to res and text drawing goes to gfx

This commit is contained in:
whowechina 2024-06-17 10:28:10 +08:00
parent 74331e88ef
commit 579c493911
10 changed files with 189 additions and 181 deletions

View File

@ -50,7 +50,7 @@ void gfx_anima_mix(const anima_t *ani, int x, int y, int frame, uint16_t color)
for (int j = 0; j < ani->height; j++) { for (int j = 0; j < ani->height; j++) {
for (int i = 0; i < ani->width; i++) { for (int i = 0; i < ani->width; i++) {
uint8_t value = rle_get_uint4(&rle); uint8_t value = rle_get_uint4(&rle);
st7789_pixel(x + i, y + j, color, value); st7789_pixel(x + i, y + j, color, value, 4);
} }
} }
} }
@ -69,7 +69,12 @@ void gfx_img_draw(int x, int y, const image_t *img)
for (int i = 0; i < img->height; i++) { for (int i = 0; i < img->height; i++) {
for (int j = 0; j < img->width; j++) { for (int j = 0; j < img->width; j++) {
uint32_t pixel = rle_get(&pixels_rle); uint32_t pixel = rle_get(&pixels_rle);
uint32_t mix = img->alpha.input ? rle_get(&alpha_rle) : 0xff; uint32_t mix = 0xff;
uint32_t mixbits = 8;
if (img->alpha.input) {
mix = rle_get(&alpha_rle);
mixbits = img->alpha.bits;
}
if (img->pallete) { if (img->pallete) {
pixel = img->pallete[pixel]; pixel = img->pallete[pixel];
@ -78,7 +83,108 @@ void gfx_img_draw(int x, int y, const image_t *img)
} }
} }
st7789_pixel(x + j, y + i, pixel, mix); st7789_pixel(x + j, y + i, pixel, mix, mixbits);
} }
} }
} }
void gfx_char_draw(int x, int y, char c, const lv_font_t *font, uint16_t color)
{
if (c < font->range_start || c >= font->range_start + font->range_length) {
return;
}
const lv_font_dsc_t *dsc = font->dsc + c - font->range_start;
const uint8_t *bitmap = font->bitmap + dsc->bitmap_index;
uint8_t bpp = font->bit_per_pixel;
uint8_t mask = (1L << bpp) - 1;
uint8_t off_y = font->line_height - font->base_line - dsc->box_h - dsc->ofs_y;
int crop_w = st7789_get_crop_width();
int crop_h = st7789_get_crop_height();
for (int i = 0; i < dsc->box_h; i++) {
int dot_y = y + off_y + i;
if ((dot_y < 0) || (dot_y > crop_h)) {
continue;
}
for (int j = 0; j < dsc->box_w; j++) {
int dot_x = x + dsc->ofs_x + j;
if ((dot_x < 0) || (dot_x > crop_w)) {
break;
}
uint16_t bits = (i * dsc->box_w + j) * bpp;
uint8_t mix = (bitmap[bits / 8] >> ((8 - bpp) - (bits % 8))) & mask;
st7789_pixel(dot_x, dot_y, color, mix, bpp);
}
}
}
static int spacing_x = 1, spacing_y = 1;
void gfx_text_spacing(int dx, int dy)
{
spacing_x = dx;
spacing_y = dy;
}
static uint16_t text_width(const char *text, const lv_font_t *font)
{
uint16_t width = 0;
for (; *text && (*text != '\n'); text++) {
if (*text == '\x01') {
text += 3;
continue;
} else if (*text == '\x02' || *text == '\x03') {
continue;
}
if (*text - font->range_start < font->range_length) {
width += (font->dsc[*text - font->range_start].adv_w >> 4) + spacing_x;
}
}
return width;
}
void gfx_text_draw(int x, int y, const char *text,
const lv_font_t *font, uint16_t color, alignment_t align)
{
uint16_t old_color = color;
uint16_t curr_color = color;
bool newline = true;
int pos_x = x;
for (; *text; text++) {
if (*text == '\x01') { // set color
old_color = curr_color;
curr_color = st7789_rgb565(st7789_rgb32(text[1], text[2], text[3]));
text += 3;
continue;
} else if (*text == '\x02') { // back to previous color
uint16_t tmp = curr_color;
curr_color = old_color;
old_color = tmp;
continue;
} else if (*text == '\x03') { // reset to default color
old_color = curr_color;
curr_color = color;
continue;
} else if (*text == '\n') { // line wrap
newline = true;
pos_x = x;;
y += font->line_height + spacing_y;
continue;
}
if (newline) {
int width = text_width(text, font);
if (align == ALIGN_CENTER) {
pos_x -= width / 2;
} else if (align == ALIGN_RIGHT) {
pos_x -= width;
}
newline = false;
}
gfx_char_draw(pos_x, y, *text, font, curr_color);
pos_x += (font->dsc[*text - font->range_start].adv_w >> 4) + spacing_x;
}
}

View File

@ -28,4 +28,49 @@ void gfx_anima_mix(const anima_t *ani, int x, int y, int frame, uint16_t color);
void gfx_img_draw(int x, int y, const image_t *img); void gfx_img_draw(int x, int y, const image_t *img);
/* LV Font is Simplified from LVGL (https://lvgl.io/) Font Structure */
typedef struct {
uint32_t bitmap_index; /**< Start index of the bitmap. A font can be max 4 GB.*/
uint32_t adv_w; /**< Draw the next glyph after this width. 28.4 format (real_value * 16 is stored).*/
uint16_t box_w; /**< Width of the glyph's bounding box*/
uint16_t box_h; /**< Height of the glyph's bounding box*/
int16_t ofs_x; /**< x offset of the bounding box*/
int16_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/
} lv_font_dsc_t;
typedef struct {
uint8_t range_start;
uint8_t range_length;
uint8_t bit_per_pixel;
uint16_t line_height;
uint16_t base_line;
const lv_font_dsc_t *dsc;
const uint8_t *bitmap;
} lv_font_t;
/* char and text out only supports 1/2/4/8 bit-per-pixel */
void gfx_char_draw(int x, int y, char c, const lv_font_t *font, uint16_t color);
typedef enum {
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT
} alignment_t;
void gfx_text_spacing(int dx, int dy);
/* Color escape scheme:
"\x01\xRR\xGG\xBB" set color;
"\x02" back to previous color;
"\x03" reset to default color;
*/
#define SET_COLOR(rgb) "\x01" #rgb
#define PREV_COLOR "\x02"
#define RESET_COLOR "\x03"
void gfx_text_draw(int x, int y, const char *text, const lv_font_t *font,
uint16_t color, alignment_t align);
#endif #endif

View File

@ -25,12 +25,8 @@
#include "st7789.h" #include "st7789.h"
#include "cst816t.h" #include "cst816t.h"
#include "conthrax.h"
#include "upheaval.h"
#include "ltsaeada.h"
#include "res/resource.h" #include "res/resource.h"
#include "gfx.h"
#include "gui.h" #include "gui.h"
void gui_init() void gui_init()
@ -90,8 +86,8 @@ static void draw_home_keypad()
glow_frame[key]++; glow_frame[key]++;
} }
char c = signs_text[row * 3 + col]; char c = signs_text[row * 3 + col];
st7789_char(x + 2, y + 2, c, &lv_conthrax, st7789_rgb565(0x101010)); gfx_char_draw(x + 2, y + 2, c, &lv_conthrax, st7789_rgb565(0x101010));
st7789_char(x, y, c, &lv_conthrax, st7789_rgb565(color)); gfx_char_draw(x, y, c, &lv_conthrax, st7789_rgb565(color));
} }
} }
} }
@ -180,25 +176,25 @@ static bool proc_home(cst816t_report_t touch)
static void status_title(int x, int y, const char *title, uint16_t color) static void status_title(int x, int y, const char *title, uint16_t color)
{ {
st7789_text(x + 1, y + 1, title, &lv_lts16, 0x0000, ALIGN_CENTER); gfx_text_draw(x + 1, y + 1, title, &lv_lts16, 0x0000, ALIGN_CENTER);
st7789_text(x, y, title, &lv_lts16, color, ALIGN_CENTER); gfx_text_draw(x, y, title, &lv_lts16, color, ALIGN_CENTER);
} }
static void draw_status() static void draw_status()
{ {
st7789_spacing(1, 0); gfx_text_spacing(1, 0);
char buf[32]; char buf[32];
status_title(120, 3, "Serial Number", st7789_rgb565(0x00c000)); status_title(120, 3, "Serial Number", st7789_rgb565(0x00c000));
sprintf(buf, "%016llx", board_id_64()); sprintf(buf, "%016llx", board_id_64());
st7789_text(120, 22, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER); gfx_text_draw(120, 22, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER);
status_title(120, 46, "Firmware Timestamp", st7789_rgb565(0x00c000)); status_title(120, 46, "Firmware Timestamp", st7789_rgb565(0x00c000));
st7789_text(120, 66, built_time, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER); gfx_text_draw(120, 66, built_time, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER);
status_title(120, 89, "NFC Module", st7789_rgb565(0x00c000)); status_title(120, 89, "NFC Module", st7789_rgb565(0x00c000));
sprintf(buf, "%s (%s)", nfc_module_name(), nfc_module_version()); sprintf(buf, "%s (%s)", nfc_module_name(), nfc_module_version());
st7789_text(120, 105, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER); gfx_text_draw(120, 105, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER);
status_title(120, 132, "Light", st7789_rgb565(0x00c000)); status_title(120, 132, "Light", st7789_rgb565(0x00c000));
if (aic_cfg->light.rgb) { if (aic_cfg->light.rgb) {
@ -206,11 +202,11 @@ static void draw_status()
} else { } else {
sprintf(buf, "RGB: OFF"); sprintf(buf, "RGB: OFF");
} }
st7789_text(120, 148, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER); gfx_text_draw(120, 148, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER);
status_title(120, 175, "LCD", st7789_rgb565(0x00c000)); status_title(120, 175, "LCD", st7789_rgb565(0x00c000));
sprintf(buf, "Backlight: %d", aic_cfg->lcd.backlight); sprintf(buf, "Backlight: %d", aic_cfg->lcd.backlight);
st7789_text(120, 191, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER); gfx_text_draw(120, 191, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER);
status_title(120, 218, "Reader", st7789_rgb565(0x00c000)); status_title(120, 218, "Reader", st7789_rgb565(0x00c000));
int len = sprintf(buf, "Virtual AIC: %s\nMode: %s", int len = sprintf(buf, "Virtual AIC: %s\nMode: %s",
@ -219,7 +215,7 @@ static void draw_status()
if (aic_cfg->reader.mode == MODE_AUTO) { if (aic_cfg->reader.mode == MODE_AUTO) {
sprintf(buf + len, " (%s)", mode_name(aic_runtime.mode)); sprintf(buf + len, " (%s)", mode_name(aic_runtime.mode));
} }
st7789_text(120, 234, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER); gfx_text_draw(120, 234, buf, &lv_lts18, st7789_rgb565(0xc0c0c0), ALIGN_CENTER);
} }
static void draw_credits() static void draw_credits()
@ -236,7 +232,7 @@ static void draw_credits()
"JLCPCB Raspberry\n\n" "JLCPCB Raspberry\n\n"
SET_COLOR(\x90\x90\x90) "and more..."; SET_COLOR(\x90\x90\x90) "and more...";
st7789_text(120, 30, credits, &lv_lts14, st7789_rgb565(0xc0c060), ALIGN_CENTER); gfx_text_draw(120, 30, credits, &lv_lts14, st7789_rgb565(0xc0c060), ALIGN_CENTER);
} }

View File

@ -1,30 +0,0 @@
/*
* Simplified LVGL Font Structure
* Modified from LVGL project: https://lvgl.io/
*/
#ifndef LV_FONT_H
#define LV_FONT_H
#include <stdint.h>
typedef struct {
uint32_t bitmap_index; /**< Start index of the bitmap. A font can be max 4 GB.*/
uint32_t adv_w; /**< Draw the next glyph after this width. 28.4 format (real_value * 16 is stored).*/
uint16_t box_w; /**< Width of the glyph's bounding box*/
uint16_t box_h; /**< Height of the glyph's bounding box*/
int16_t ofs_x; /**< x offset of the bounding box*/
int16_t ofs_y; /**< y offset of the bounding box. Measured from the top of the line*/
} lv_font_dsc_t;
typedef struct {
uint8_t range_start;
uint8_t range_length;
uint8_t bit_per_pixel;
uint16_t line_height;
uint16_t base_line;
const lv_font_dsc_t *dsc;
const uint8_t *bitmap;
} lv_font_t;
#endif

View File

@ -6,7 +6,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "lvgl_font.h" #include "../gfx.h"
static const uint8_t conthrax_bitmap[] = { static const uint8_t conthrax_bitmap[] = {
/* U+0030 "0" */ /* U+0030 "0" */

View File

@ -6,7 +6,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "lvgl_font.h" #include "../gfx.h"
static const uint8_t lts13_bitmap[] = { static const uint8_t lts13_bitmap[] = {
/* U+0020 " " */ /* U+0020 " " */

View File

@ -6,7 +6,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "lvgl_font.h" #include "../gfx.h"
/*Store the image of the glyphs*/ /*Store the image of the glyphs*/
static const uint8_t upheaval_bitmap[] = { static const uint8_t upheaval_bitmap[] = {

View File

@ -12,4 +12,8 @@
#include "image_aic_sega.h" #include "image_aic_sega.h"
#include "image_aic_nesica.h" #include "image_aic_nesica.h"
#include "font_conthrax.h"
#include "font_ltsaeada.h"
#include "font_upheaval.h"
#endif #endif

View File

@ -18,8 +18,6 @@
#include "hardware/dma.h" #include "hardware/dma.h"
#include "hardware/pwm.h" #include "hardware/pwm.h"
#include "lvgl_font.h"
#include "st7789.h" #include "st7789.h"
#define WIDTH 240 #define WIDTH 240
@ -178,6 +176,16 @@ void st7789_crop(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool absolute)
update_addr(); update_addr();
} }
uint16_t st7789_get_crop_width()
{
return crop.w;
}
uint16_t st7789_get_crop_height()
{
return crop.h;
}
void st7789_dimmer(uint8_t level) void st7789_dimmer(uint8_t level)
{ {
pwm_set_gpio_level(ctx.ledk, level); pwm_set_gpio_level(ctx.ledk, level);
@ -313,9 +321,9 @@ void st7789_pixel_raw(int x, int y, uint16_t color)
vram[y * crop.w + x] = color; vram[y * crop.w + x] = color;
} }
void st7789_pixel(int x, int y, uint16_t color, uint8_t mix) void st7789_pixel(int x, int y, uint16_t color, uint8_t mix, uint8_t bits)
{ {
mix_pixel(x, y, color, mix, 8); mix_pixel(x, y, color, mix, bits);
} }
void st7789_hline(int x, int y, uint16_t w, uint16_t color, uint8_t mix) void st7789_hline(int x, int y, uint16_t w, uint16_t color, uint8_t mix)
@ -364,103 +372,6 @@ void st7789_line(int x0, int y0, int x1, int y1, uint16_t color, uint8_t mix)
} }
} }
void st7789_char(int x, int y, char c, const lv_font_t *font, uint16_t color)
{
if (c < font->range_start || c >= font->range_start + font->range_length) {
return;
}
const lv_font_dsc_t *dsc = font->dsc + c - font->range_start;
const uint8_t *bitmap = font->bitmap + dsc->bitmap_index;
uint8_t bpp = font->bit_per_pixel;
uint8_t mask = (1L << bpp) - 1;
uint8_t off_y = font->line_height - font->base_line - dsc->box_h - dsc->ofs_y;
for (int i = 0; i < dsc->box_h; i++) {
int dot_y = y + off_y + i;
if ((dot_y < 0) || (dot_y > crop.h)) {
continue;
}
for (int j = 0; j < dsc->box_w; j++) {
int dot_x = x + dsc->ofs_x + j;
if ((dot_x < 0) || (dot_x > crop.w)) {
break;
}
uint16_t bits = (i * dsc->box_w + j) * bpp;
uint8_t mix = (bitmap[bits / 8] >> ((8 - bpp) - (bits % 8))) & mask;
mix_pixel(dot_x, dot_y, color, mix, bpp);
}
}
}
static int spacing_x = 1, spacing_y = 1;
void st7789_spacing(int dx, int dy)
{
spacing_x = dx;
spacing_y = dy;
}
static uint16_t text_width(const char *text, const lv_font_t *font)
{
uint16_t width = 0;
for (; *text && (*text != '\n'); text++) {
if (*text == '\x01') {
text += 3;
continue;
} else if (*text == '\x02' || *text == '\x03') {
continue;
}
if (*text - font->range_start < font->range_length) {
width += (font->dsc[*text - font->range_start].adv_w >> 4) + spacing_x;
}
}
return width;
}
void st7789_text(int x, int y, const char *text,
const lv_font_t *font, uint16_t color, alignment_t align)
{
uint16_t old_color = color;
uint16_t curr_color = color;
bool newline = true;
int pos_x = x;
for (; *text; text++) {
if (*text == '\x01') { // set color
old_color = curr_color;
curr_color = st7789_rgb565(st7789_rgb32(text[1], text[2], text[3]));
text += 3;
continue;
} else if (*text == '\x02') { // back to previous color
uint16_t tmp = curr_color;
curr_color = old_color;
old_color = tmp;
continue;
} else if (*text == '\x03') { // reset to default color
old_color = curr_color;
curr_color = color;
continue;
} else if (*text == '\n') { // line wrap
newline = true;
pos_x = x;;
y += font->line_height + spacing_y;
continue;
}
if (newline) {
int width = text_width(text, font);
if (align == ALIGN_CENTER) {
pos_x -= width / 2;
} else if (align == ALIGN_RIGHT) {
pos_x -= width;
}
newline = false;
}
st7789_char(pos_x, y, *text, font, curr_color);
pos_x += (font->dsc[*text - font->range_start].adv_w >> 4) + spacing_x;
}
}
uint16_t *st7789_vram(uint16_t x, uint16_t y) uint16_t *st7789_vram(uint16_t x, uint16_t y)
{ {
return &vram[y * crop.w + x]; return &vram[y * crop.w + x];

View File

@ -10,12 +10,12 @@
#include "hardware/spi.h" #include "hardware/spi.h"
#include "lvgl_font.h"
void st7789_reset(); void st7789_reset();
void st7789_init_spi(spi_inst_t *port, uint8_t sck, uint8_t tx, uint8_t csn); void st7789_init_spi(spi_inst_t *port, uint8_t sck, uint8_t tx, uint8_t csn);
void st7789_init(spi_inst_t *port, uint8_t dc, uint8_t rst, uint8_t ledk); void st7789_init(spi_inst_t *port, uint8_t dc, uint8_t rst, uint8_t ledk);
void st7789_crop(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool absolute); void st7789_crop(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool absolute);
uint16_t st7789_get_crop_width();
uint16_t st7789_get_crop_height();
void st7789_dimmer(uint8_t level); void st7789_dimmer(uint8_t level);
void st7789_vsync(); void st7789_vsync();
void st7789_render(bool vsync); void st7789_render(bool vsync);
@ -29,34 +29,10 @@ void st7789_fill(uint16_t *pattern, size_t size, bool raw);
uint16_t *st7789_vram(uint16_t x, uint16_t y); uint16_t *st7789_vram(uint16_t x, uint16_t y);
void st7789_vramcpy(uint32_t offset, const void *src, size_t count); void st7789_vramcpy(uint32_t offset, const void *src, size_t count);
void st7789_pixel_raw(int x, int y, uint16_t color); void st7789_pixel_raw(int x, int y, uint16_t color);
void st7789_pixel(int x, int y, uint16_t color, uint8_t mix); void st7789_pixel(int x, int y, uint16_t color, uint8_t mix, uint8_t bits);
void st7789_hline(int x, int y, uint16_t w, uint16_t color, uint8_t mix); void st7789_hline(int x, int y, uint16_t w, uint16_t color, uint8_t mix);
void st7789_vline(int x, int y, uint16_t h, uint16_t color, uint8_t mix); void st7789_vline(int x, int y, uint16_t h, uint16_t color, uint8_t mix);
void st7789_bar(int x, int y, uint16_t w, uint16_t h, uint16_t color, uint8_t mix); void st7789_bar(int x, int y, uint16_t w, uint16_t h, uint16_t color, uint8_t mix);
void st7789_line(int x0, int y0, int x1, int y1, uint16_t color, uint8_t mix); void st7789_line(int x0, int y0, int x1, int y1, uint16_t color, uint8_t mix);
void st7789_scroll(int dx, int dy); void st7789_scroll(int dx, int dy);
/* char and text out only supports 1/2/4/8 bit-per-pixel */
void st7789_char(int x, int y, char c, const lv_font_t *font, uint16_t color);
typedef enum {
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT
} alignment_t;
void st7789_spacing(int dx, int dy);
/* Color escape scheme:
"\x01\xRR\xGG\xBB" set color;
"\x02" back to previous color;
"\x03" reset to default color;
*/
#define SET_COLOR(rgb) "\x01" #rgb
#define PREV_COLOR "\x02"
#define RESET_COLOR "\x03"
void st7789_text(int x, int y, const char *text, const lv_font_t *font,
uint16_t color, alignment_t align);