ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
26 апреля
1112795 Топик полностью
SciFi (28.06.2021 12:57, просмотров: 280) ответил Make_Pic на хотелось понять - подсмотреть как пишется такая софтина - вывод примитивов, а писать все равно свое под UC1604C
Что-то типа такого: 

Самолепные форматы шрифтов и растровых изображений с 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++;
                }
        }
}
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้