#include "graphics.h" #include "font_ubuntu.h" #include "utf8.h" #include 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; }