Самописную. Там всего пару сотен строк кода надо: lcd.h
/**
* @file lcd.h
* @brief Драйвер дисплея ET022003DMU
*/
#ifndef LCD_H
#define LCD_H
#include <stdint.h>
#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 */
lcd.c
/**
* @file lcd.c
* @brief Драйвер дисплея ET022003DMU
*/
#include "lcd.h"
#include "timer.h"
#include "stm32f2regs.h"
#include <string.h>
#include <assert.h>
#include <intrinsics.h>
#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)
{
while (len-- > 0)
{
LCD_WRITE8(*src++);
}
}
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 */
| ( 1 << 0); /* address setup: 1 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;
GPIOA_BSRR = (1 << 4); /* backlight on */
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 */
}
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++;
}
}
}
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้