Отчего все так боятся графическую библиотеку? Вот вам пример (всего-то 400 строк, поддерживает 2 дисплея - HX8346 и S6D04H0):
/**
* @file lcd.h
*/
#ifndef LCD_H
#define LCD_H
#include <stdint.h>
#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 */
/**
* @file lcd.c
*/
#include "lcd.h"
#include "timer.h"
#include "stm32f2regs.h"
#include <string.h>
#include <stdbool.h>
#define HTONS(x) (__builtin_constant_p(x) ? ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) : rev16(x))
#define HTONL(x) __builtin_bswap32(x)
#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) = HTONS(x); while (0)
#define LCD_WRBE32(x) do *(uint32_t volatile*)(LCD_BASE + LCD_CMDOFS) = HTONL(x); while (0)
#define LCD_REG(n, x) do { LCD_CMD(n); LCD_WRITE8(x); } while (0)
#define LCD_IDX(n) LCD_CMD(n)
#define LCD_READ8() (*(uint8_t volatile*)(LCD_BASE + LCD_CMDOFS))
enum lcd_type
{
LCD_SAMSUNG, LCD_HIMAX
};
static enum text_align align;
static const struct font* font;
static lcd_color shades[8];
static enum lcd_type type;
static int rev16(int x)
{
__asm("rev16 %0, %1" : "=r" (x) : "r" (x));
return x;
}
static void
write_array(int len, const char *src)
{
timer_delay(TIMER_TPS / 1000000);
while (len-- > 0)
{
LCD_WRITE8(*src++);
timer_delay(TIMER_TPS / 1000000);
}
}
static bool
init_samsung(void)
{
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(9, "\x01\x01\x07\x00\x02\x0C\x02\x08\x03");
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_CMD(0x29); /* Display ON */
LCD_CMD(0x0A); /* read power status */
(void)LCD_READ8(); /* dummy read */
return (0x1C == (0x7F & LCD_READ8()));
}
static void
init_himax(void)
{
LCD_REG(0x26, 0x00);
LCD_REG(0x1B, 0x08);
LCD_REG(0x43, 0x00); /* Set VCOMG */
timer_delay(TIMER_TPS / 100);
LCD_REG(0x1C, 0x06); /* Set AP[2-0] */
LCD_REG(0x1B, 0x10);
timer_delay(TIMER_TPS / 25);
LCD_REG(0x43, 0x80); /* Set VCOMG */
LCD_REG(0x01, 0x06); /* Display Mode */
LCD_REG(0x16, 0x60); /* MX, MY, MV, BGR */
LCD_REG(0x46, 0x94); /* Gamma */
LCD_REG(0x47, 0x41); /* Gamma */
LCD_REG(0x48, 0x00); /* Gamma */
LCD_REG(0x49, 0x33); /* Gamma */
LCD_REG(0x4A, 0x23); /* Gamma */
LCD_REG(0x4B, 0x45); /* Gamma */
LCD_REG(0x4C, 0x44); /* Gamma */
LCD_REG(0x4D, 0x77); /* Gamma */
LCD_REG(0x4E, 0x12); /* Gamma */
LCD_REG(0x4F, 0xCC); /* Gamma */
LCD_REG(0x50, 0x46); /* Gamma */
LCD_REG(0x51, 0x82); /* Gamma */
LCD_REG(0x06, 0x00);
LCD_REG(0x08, 0x00);
timer_delay(TIMER_TPS / 16);
LCD_REG(0x26, 0x04);
timer_delay(TIMER_TPS / 100);
LCD_REG(0x26, 0x24);
LCD_REG(0x26, 0x2C);
timer_delay(TIMER_TPS / 100);
LCD_REG(0x26, 0x3C);
}
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 pulse */
/* 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;
if (init_samsung())
{
type = LCD_SAMSUNG;
lcd_fillrect(0, 0, 319, 239, LCD_BLACK);
timer_delay(TIMER_TPS / 10);
}
else
{
type = LCD_HIMAX;
init_himax();
timer_delay(TIMER_TPS / 20);
}
GPIOA_BSRR = (1 << 4); /* backlight on */
}
static void
putpixel(lcd_color rgb)
{
switch (type)
{
case LCD_SAMSUNG:
LCD_WRLE16(rgb & 0xFFFF);
LCD_WRITE8(rgb >> 16);
break;
case LCD_HIMAX:
LCD_WRITE8(rgb >> 16);
LCD_WRBE16(rgb & 0xFFFF);
break;
}
}
void
lcd_fillrect(int left, int top, int right, int bottom, lcd_color rgb)
{
int i;
uint32_t pdata[3];
switch (type)
{
case LCD_SAMSUNG:
LCD_CMD(0x2A);
LCD_WRBE16(left);
LCD_WRBE16(right);
LCD_CMD(0x2B);
LCD_WRBE16(top);
LCD_WRBE16(bottom);
LCD_CMD(0x2C);
break;
case LCD_HIMAX:
rgb = HTONL(rgb) >> 8;
LCD_REG(0x02, left >> 8);
LCD_REG(0x03, left & 0xFF);
LCD_REG(0x04, right >> 8);
LCD_REG(0x05, right & 0xFF);
LCD_REG(0x07, top);
LCD_REG(0x09, bottom);
LCD_IDX(0x22);
break;
}
pdata[0] = (rgb << 24) | rgb;
pdata[1] = (rgb << 16) | (rgb >> 8);
pdata[2] = (rgb << 8) | (rgb >> 16);
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 mask, j, diff;
mask = 0xFF << i;
diff = (((int)fgrgb_arg & mask) - ((int)bgrgb_arg & mask)) >> i;
diff *= 128;
diff /= 7;
for (j = 1; j < 8; j++)
{
int tmp;
tmp = j * diff;
tmp /= 128;
tmp <<= i;
tmp += bgrgb_arg;
shades[j] |= (tmp & mask);
}
}
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;
}
firstchar = font->chars;
h = font->height;
switch (type)
{
case LCD_SAMSUNG:
LCD_CMD(0x2B);
LCD_WRBE16(y);
LCD_WRBE16(y + h - 1);
break;
case LCD_HIMAX:
LCD_REG(0x07, y);
LCD_REG(0x09, y + h - 1);
break;
}
while (*str != 0)
{
const struct font_char* pchar;
int idx, left;
pchar = firstchar + ((uint8_t)*str - font->first);
str++;
switch (type)
{
case LCD_SAMSUNG:
LCD_CMD(0x2A);
LCD_WRBE16(x);
LCD_WRBE16(x + pchar->width - 1);
LCD_CMD(0x2C);
break;
case LCD_HIMAX:
LCD_REG(0x02, x >> 8);
LCD_REG(0x03, x & 0xFF);
LCD_REG(0x04, (x + pchar->width - 1) >> 8);
LCD_REG(0x05, (x + pchar->width - 1) & 0xFF);
LCD_IDX(0x22);
break;
}
x += pchar->width;
idx = pchar->index;
left = pchar->width * h;
while (left > 0)
{
uint8_t c;
c = (font->bitstream[idx >> 3] >> ((idx & 7) << 2)) & 0xF;
idx++;
if ((c & 8) == 0)
{
putpixel(shades[c]);
left--;
}
else
{
int n;
n = (font->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;
switch (type)
{
case LCD_SAMSUNG:
LCD_CMD(0x2A);
LCD_WRBE16(x);
LCD_WRBE16(x + bitmap->width - 1);
LCD_CMD(0x2B);
LCD_WRBE16(y);
LCD_WRBE16(y + bitmap->height - 1);
LCD_CMD(0x2C);
break;
case LCD_HIMAX:
LCD_REG(0x02, x >> 8);
LCD_REG(0x03, x & 0xFF);
LCD_REG(0x04, (x + bitmap->width - 1) >> 8);
LCD_REG(0x05, (x + bitmap->width - 1) & 0xFF);
LCD_REG(0x07, y);
LCD_REG(0x09, y + bitmap->height - 1);
LCD_IDX(0x22);
break;
}
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++;
}
}
}
Если интересно, выложу проги для импорта шрифтов и картинок.
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้