Что-то типа такого:
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้
Самолепные форматы шрифтов и растровых изображений с RLE. Самолепные утилитки для их импортирования и преобразования в сишники для вставки в дерево исходников для сборки. Форматы подсмотрены в чужих софтах, на первом этапе целесообразно просто позаимствовать готовые подходящие форматы и утилиты.
#ifndef LCD_H #define LCD_H #include .. #define LCD_WIDTH 320 #define LCD_HEIGHT 240 #define LCD_BLACK 0x000000 #define LCD_WHITE 0xFFFFFF #define LCD_RED 0x0000FF #define LCD_GREEN 0x00FF00 #define LCD_BLUE 0xFF0000 #define LCD_YELLOW 0x00FFFF typedef uint32_t lcd_color; enum text_align { ALIGN_RIGHT, ALIGN_LEFT }; struct font_char { uint32_t width : 8; uint32_t index : 24; }; struct font { uint8_t height; uint8_t first; const struct font_char* chars; const uint32_t* bitstream; }; struct bitmap { uint16_t width; uint16_t height; const uint32_t* palette; const uint8_t* bitstream; }; extern void lcd_init(void); extern void lcd_fillrect(int left, int top, int right, int bottom, lcd_color rgb); extern void lcd_settextattr(const struct font* font, lcd_color fgrgb, lcd_color bgrgb, enum text_align align); extern int lcd_getcharwidth(char c); extern int lcd_gettextwidth(const char* str); extern void lcd_outputchar(char c, int x, int y); extern void lcd_outputtext(const char* str, int x, int y); extern void lcd_drawbitmap(const struct bitmap* bitmap, int x, int y); #endif /* LCD_H */
#include "lcd.h" #include "timer.h" #include "stm32f2regs.h" #include .. #define LCD_BASE 0x60000000 #define LCD_CMDOFS 0x00100000 #define LCD_CMD(n) do (*(uint8_t volatile*)LCD_BASE = (n)); while (0) #define LCD_WRITE8(x) do (*(uint8_t volatile*)(LCD_BASE + LCD_CMDOFS) = (x)); while (0) #define LCD_WRLE16(x) do (*(uint16_t volatile*)(LCD_BASE + LCD_CMDOFS) = (x)); while (0) #define LCD_WRLE32(x) do (*(uint32_t volatile*)(LCD_BASE + LCD_CMDOFS) = (x)); while (0) #define LCD_WRBE16(x) do (*(uint16_t volatile*)(LCD_BASE + LCD_CMDOFS) = __REV16(x)); while (0) #define LCD_WRBE32(x) do (*(uint32_t volatile*)(LCD_BASE + LCD_CMDOFS) = __REV(x)); while (0) static enum text_align align; static const struct font* font; static lcd_color shades[8]; static void write_array(int len, const uint8_t *src) { timer_delay(TIMER_TPS / 1000000); while (len-- > 0) { LCD_WRITE8(*src++); timer_delay(TIMER_TPS / 1000000); } } void lcd_init(void) { /* enable clocking of PORT A, B, D, E */ RCC_AHB1ENR |= 0x0000001B; /* enable clocking of FSMC */ REGBIT(RCC_AHB3ENR, 0) = 1; FSMC_BWTR1 = ( 0 << 28) /* access mode A */ | ( 1 << 20) /* max. CLK out freq., don't care */ | ( 8 << 8) /* data phase: 8 HCLK cycles */ | ( 0 << 4) /* address hold: 0 HCLK cycles */ | ( 7 << 0); /* address setup: 7 HCLK cycle */ FSMC_BTR1 = ( 0 << 28) /* access mode A */ | ( 1 << 20) /* max. CLK out freq., don't care */ | (11 << 16) /* delay of 11 HCLK cycles between consecutive reads */ | (42 << 8) /* data phase: 42 HCLK cycles */ | ( 0 << 4) /* address hold: 0 HCLK cycles */ | ( 1 << 0); /* address setup: 1 HCLK cycle */ FSMC_BCR1 = ( 1 << 14) /* enable FSMC_BTWR register */ | ( 1 << 12) /* enable write operations */ | ( 1 << 6) /* access enable */ | ( 0 << 4) /* memory width: 8 bits */ | ( 0 << 2) /* memory type: SRAM, ROM */ | ( 0 << 1) /* non-multiplexed */ | ( 1 << 0); /* bank enable */ GPIOD_BSRR = (1 << 7); /* set CS high */ GPIOD_AFRL |= 0x00CC00CC; GPIOD_AFRH |= 0xCC000000; GPIOE_AFRL |= 0xC00C0000; GPIOE_AFRH |= 0xC0000CCC; /* configure PD0,1,4,5,14,15 as AF, PD7 as GP output */ GPIOD_MODER |= 0xA0004A0A; /* configure PE4,7,8,9,10 as AF */ GPIOE_MODER |= 0x002A8200; /* configure PB7 as GP output */ GPIOB_MODER |= 0x00004000; timer_delay(TIMER_TPS / 100000); /* 10 us reset puls */ /* set RESET high */ GPIOB_BSRR = (1 << 7); timer_delay(TIMER_TPS / 200); /* 5 ms delay */ /* set CS low */ GPIOD_BSRR = (0x10000u << 7); /* configure PA4 as GP output */ GPIOA_MODER |= 0x00000100; LCD_CMD(0x11); /* Sleep Out */ LCD_CMD(0xF3); /* Power Control */ write_array(5, "\x01\xFF\x1F\x00\x03"); LCD_CMD(0xF2); /* Display Control */ write_array(17, "\x28\x78\x7F\x08\x08\x00\x00\x15\x48\x00\x07\x01\x00\x00\x94\x08\x08"); LCD_CMD(0xF4); /* Power Control */ write_array(20, "\x09\x00\x00\x00\x21\x47\x01\x02\x2A\x69\x03\x2A\x00\x03\x00\x00\x00\x00\x00\x00"); LCD_CMD(0xF5); /* VCOM Control */ write_array(12, "\x00\x34\x56\x00\x00\x12\x00\x00\x0D\x01\x00\x00"); LCD_CMD(0xF6); /* Source Control */ write_array(8, "\x01\x01\x07\x00\x02\x0C\x02\x08"); LCD_WRITE8(0x03); LCD_CMD(0xF7); /* Interface Control */ write_array(4, "\x01\x00\x10\x00"); LCD_CMD(0xF8); /* Panel Control */ write_array(3, "\x99\x00\x00"); LCD_CMD(0xF9); /* Gamma Selection */ LCD_WRITE8(0x01); LCD_CMD(0xFA); /* Positive Gamma Control */ write_array(12, "\x00\x17\x0C\x18\x23\x36\x2B\x2C\x2A\x28\x25\x00\x00\x00\x00\x00"); LCD_CMD(0xFB); /* Negative Gamma Control */ write_array(12, "\x00\x0A\x26\x23\x23\x26\x1A\x3B\x27\x1E\x0D\x00\x00\x00\x00\x00"); LCD_CMD(0x36); /* Memory Data Access Control */ LCD_WRITE8(0x28); lcd_fillrect(0, 0, 319, 239, LCD_BLACK); LCD_CMD(0x29); /* Display ON */ timer_delay(TIMER_TPS / 10); GPIOA_BSRR = (1 << 4); /* backlight on */ } static void putpixel(lcd_color rgb) { LCD_WRLE16(rgb & 0xFFFF); LCD_WRITE8(rgb >> 16); } void lcd_fillrect(int left, int top, int right, int bottom, lcd_color rgb) { int i; uint32_t pdata[3]; LCD_CMD(0x2A); LCD_WRBE16(left); LCD_WRBE16(right); LCD_CMD(0x2B); LCD_WRBE16(top); LCD_WRBE16(bottom); pdata[0] = (rgb << 24) | rgb; pdata[1] = (rgb << 16) | (rgb >> 8); pdata[2] = (rgb << 8) | (rgb >> 16); LCD_CMD(0x2C); for (i = (right - left + 1) * (bottom - top + 1); i > 0; i -= 4) { LCD_WRLE32(pdata[0]); LCD_WRLE32(pdata[1]); LCD_WRLE32(pdata[2]); } } void lcd_settextattr(const struct font* font_arg, lcd_color fgrgb_arg, lcd_color bgrgb_arg, enum text_align align_arg) { int i; font = font_arg; memset(shades, 0, sizeof(shades)); /* Calculate 8 shades between BG and FG colors for each of R, G, B */ shades[0] = bgrgb_arg; for (i = 0; i < 24; i += 8) { int j; uint32_t diff; diff = (((fgrgb_arg - bgrgb_arg) >> i << 8) & 0xFFFF) / 7; for (j = 1; j < 8; j++) { shades[j] += shades[0] + ((j * diff) >> 8 << i); } } align = align_arg; } void lcd_outputchar(char c, int x, int y) { char buf[2]; buf[0] = c; buf[1] = 0; lcd_outputtext(buf, x, y); } void lcd_outputtext(const char* str, int x, int y) { const struct font_char* firstchar; int h; switch (align) { case ALIGN_LEFT: break; case ALIGN_RIGHT: x -= lcd_gettextwidth(str); break; default: assert(0); } firstchar = font->chars; h = font->height; LCD_CMD(0x2B); LCD_WRBE16(y); LCD_WRBE16(y + h - 1); while (*str != 0) { const struct font_char* pchar; const uint32_t* bitstream; int idx, left; pchar = firstchar + ((uint8_t)*str - font->first); str++; LCD_CMD(0x2A); LCD_WRBE16(x); x += pchar->width - 1; LCD_WRBE16(x); x++; bitstream = font->bitstream; idx = pchar->index; LCD_CMD(0x2C); left = pchar->width * h; while (left > 0) { uint8_t c; c = (bitstream[idx >> 3] >> ((idx & 7) << 2)) & 0xF; idx++; if ((c & 8) == 0) { putpixel(shades[c]); left--; } else { int n; n = (bitstream[idx >> 3] >> ((idx & 7) << 2)) & 0xF; idx++; n += 1; c &= 7; left -= n; while (n > 0) { putpixel(shades[c]); n--; } } } } } int lcd_getcharwidth(char c) { return font->chars[(uint8_t)c - font->first].width; } int lcd_gettextwidth(const char* str) { int sum = 0; while (*str != 0) { sum += lcd_getcharwidth(*str); str++; } return sum; } void lcd_drawbitmap(const struct bitmap* bitmap, int x, int y) { const uint32_t* palette; const uint8_t* bitstream; int n; palette = bitmap->palette; bitstream = bitmap->bitstream; n = bitmap->width * bitmap->height; LCD_CMD(0x2A); LCD_WRBE16(x); x += bitmap->width - 1; LCD_WRBE16(x); LCD_CMD(0x2B); LCD_WRBE16(y); LCD_WRBE16(y + bitmap->height - 1); LCD_CMD(0x2C); while (n > 0) { int len; if (*bitstream == 0) { bitstream++; len = *bitstream; bitstream++; n -= len; do { putpixel(palette[*bitstream]); bitstream++; len--; } while (len > 0); } else { len = *bitstream; bitstream++; n -= len; do { putpixel(palette[*bitstream]); len--; } while (len > 0); bitstream++; } } }