226 lines
6.7 KiB
C
226 lines
6.7 KiB
C
#include "graphics.h"
|
|
#include "font_ubuntu.h"
|
|
#include "utf8.h"
|
|
#include <pico/stdlib.h>
|
|
|
|
void lcd_draw_horizontal_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
uint16_t y1 = y + 8;
|
|
uint16_t x0 = x + 7;
|
|
uint16_t w = 32;
|
|
for (int i = y; i < y1; ++i, w += 2, --x0) {
|
|
_draw_h_strip(x0, i, w, color);
|
|
}
|
|
x0 += 2;
|
|
w -= 4;
|
|
y = y1;
|
|
y1 = y + 7;
|
|
for (int i = y; i < y1; ++i, w -= 2, ++x0) {
|
|
_draw_h_strip(x0, i, w, color);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_vertical_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
uint16_t x1 = x + 8;
|
|
uint16_t y0 = y + 7;
|
|
uint16_t h = 32;
|
|
for (int i = x; i < x1; ++i, h += 2, --y0) {
|
|
_draw_v_strip(i, y0, h, color);
|
|
}
|
|
y0 += 2;
|
|
h -= 4;
|
|
x = x1;
|
|
x1 = x + 7;
|
|
for (int i = x; i < x1; ++i, h -= 2, ++y0) {
|
|
_draw_v_strip(i, y0, h, color);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_horizontal_small_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
uint16_t y1 = y + 6;
|
|
uint16_t x0 = x + 5;
|
|
uint16_t w = 24;
|
|
for (int i = y; i < y1; ++i, w += 2, --x0) {
|
|
_draw_h_strip(x0, i, w, color);
|
|
}
|
|
x0 += 2;
|
|
w -= 4;
|
|
y = y1;
|
|
y1 = y + 5;
|
|
for (int i = y; i < y1; ++i, w -= 2, ++x0) {
|
|
_draw_h_strip(x0, i, w, color);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_vertical_small_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
uint16_t x1 = x + 6;
|
|
uint16_t y0 = y + 5;
|
|
uint16_t h = 24;
|
|
for (int i = x; i < x1; ++i, h += 2, --y0) {
|
|
_draw_v_strip(i, y0, h, color);
|
|
}
|
|
y0 += 2;
|
|
h -= 4;
|
|
x = x1;
|
|
x1 = x + 5;
|
|
for (int i = x; i < x1; ++i, h -= 2, ++y0) {
|
|
_draw_v_strip(i, y0, h, color);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_horizontal_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
uint16_t y1 = y + 4;
|
|
uint16_t x0 = x + 3;
|
|
uint16_t w = 16;
|
|
for (int i = y; i < y1; ++i, w += 2, --x0) {
|
|
_draw_h_strip(x0, i, w, color);
|
|
}
|
|
x0 += 2;
|
|
w -= 4;
|
|
y = y1;
|
|
y1 = y + 3;
|
|
for (int i = y; i < y1; ++i, w -= 2, ++x0) {
|
|
_draw_h_strip(x0, i, w, color);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_vertical_xsmall_digit_segment(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
uint16_t x1 = x + 4;
|
|
uint16_t y0 = y + 3;
|
|
uint16_t h = 16;
|
|
for (int i = x; i < x1; ++i, h += 2, --y0) {
|
|
_draw_v_strip(i, y0, h, color);
|
|
}
|
|
y0 += 2;
|
|
h -= 4;
|
|
x = x1;
|
|
x1 = x + 3;
|
|
for (int i = x; i < x1; ++i, h -= 2, ++y0) {
|
|
_draw_v_strip(i, y0, h, color);
|
|
}
|
|
}
|
|
|
|
static const uint8_t DIGIT_MASKS[10] = {0b1110111, 0b0100100, 0b1011101, 0b1101101, 0b0101110,
|
|
0b1101011, 0b1111011, 0b0100101, 0b1111111, 0b1101111};
|
|
|
|
void lcd_draw_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
|
const uint16_t SEGMENT_OFFSETS[7][2] = {{9, 0}, {0, 9}, {49, 9}, {9, 49}, {0, 58}, {49, 58}, {9, 99}};
|
|
for (int seg = 0; seg < 7; ++seg) {
|
|
uint16_t segColor = ((DIGIT_MASKS[digit] >> seg) & 1) ? color : bgColor;
|
|
if (seg == 0 || seg == 3 || seg == 6)
|
|
lcd_draw_horizontal_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
|
else
|
|
lcd_draw_vertical_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_small_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
|
const uint16_t SEGMENT_OFFSETS[7][2] = {{7, 0}, {0, 7}, {37, 7}, {7, 37}, {0, 44}, {37, 44}, {7, 74}};
|
|
for (int seg = 0; seg < 7; ++seg) {
|
|
uint16_t segColor = ((DIGIT_MASKS[digit] >> seg) & 1) ? color : bgColor;
|
|
if (seg == 0 || seg == 3 || seg == 6)
|
|
lcd_draw_horizontal_small_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
|
else
|
|
lcd_draw_vertical_small_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_xsmall_digit(uint8_t digit, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
|
const uint16_t SEGMENT_OFFSETS[7][2] = {{4, 0}, {0, 4}, {23, 4}, {4, 23}, {0, 27}, {23, 27}, {4, 46}};
|
|
for (int seg = 0; seg < 7; ++seg) {
|
|
uint16_t segColor = ((DIGIT_MASKS[digit] >> seg) & 1) ? color : bgColor;
|
|
if (seg == 0 || seg == 3 || seg == 6)
|
|
lcd_draw_horizontal_xsmall_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
|
else
|
|
lcd_draw_vertical_xsmall_digit_segment(x + SEGMENT_OFFSETS[seg][0], y + SEGMENT_OFFSETS[seg][1], segColor);
|
|
}
|
|
}
|
|
|
|
void lcd_draw_decimal_point(uint16_t x, uint16_t y, uint16_t color) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
for (int i = 0; i < 5; ++i) {
|
|
_draw_h_strip(x + 4 - i, y + i, 8 + i, color);
|
|
}
|
|
for (int i = 5; i < 9; ++i) {
|
|
_draw_h_strip(x, y + i, 12, color);
|
|
}
|
|
for (int i = 9; i < 13; ++i) {
|
|
_draw_h_strip(x, y + i, 20 - i, color);
|
|
}
|
|
}
|
|
|
|
void lcd_write_string(const char *string, uint16_t x, uint16_t y, uint16_t color, uint16_t bgColor) {
|
|
x += LCD_OFFSET_X;
|
|
y += LCD_OFFSET_Y;
|
|
static uint16_t glyphPixels[24 * 24];
|
|
while (*string) {
|
|
int character = decode_code_point(&string);
|
|
if (character != 32) {
|
|
int glyphIndex = glyph_index_for_code_point(character);
|
|
const uint8_t *glyph;
|
|
int8_t glyphWidth;
|
|
if (glyphIndex != -1) {
|
|
glyph = GLYPH_ADDR[glyphIndex];
|
|
glyphWidth = GLYPH_WIDTH[glyphIndex];
|
|
} else {
|
|
glyph = GLYPH_MISSING;
|
|
glyphWidth = 12;
|
|
}
|
|
int row = 0, col = 0;
|
|
for (int byte = 0; byte < glyphWidth * 3; ++byte) {
|
|
int rem = glyph[byte];
|
|
for (int bit = 0; bit < 8; ++bit) {
|
|
glyphPixels[(row * 8 + bit) * (glyphWidth + LETTER_SPACING) + col] = (rem & 1) ? color : bgColor;
|
|
rem >>= 1;
|
|
}
|
|
if (++col == glyphWidth) {
|
|
col = 0;
|
|
++row;
|
|
}
|
|
}
|
|
for (int j = 0; j < 24; ++j) {
|
|
for (int i = 0; i < LETTER_SPACING; ++i)
|
|
glyphPixels[j * (glyphWidth + LETTER_SPACING) + glyphWidth + i] = 0;
|
|
}
|
|
st7789_caset(x, x + glyphWidth + LETTER_SPACING - 1);
|
|
st7789_raset(y, y + 24 - 1);
|
|
st7789_write(glyphPixels, 24 * (glyphWidth + LETTER_SPACING) * sizeof(uint16_t));
|
|
x += glyphWidth + LETTER_SPACING;
|
|
} else {
|
|
_fill_rectangle(x, y, 12, 24, bgColor);
|
|
x += 12;
|
|
}
|
|
}
|
|
}
|
|
|
|
int lcd_string_width(const char *string) {
|
|
int width = 0;
|
|
while (*string) {
|
|
int character = decode_code_point(&string);
|
|
if (character == 32) {
|
|
width += 12;
|
|
continue;
|
|
} else {
|
|
int glyphIndex = glyph_index_for_code_point(character);
|
|
if (glyphIndex != -1) {
|
|
width += GLYPH_WIDTH[glyphIndex] + LETTER_SPACING;
|
|
} else {
|
|
width += 12;
|
|
}
|
|
}
|
|
}
|
|
return width;
|
|
}
|