embox
209 строк · 4.8 Кб
1/**
2* @file
3*
4* @date Oct 18, 2021
5* @author Anton Bondarev
6*/
7
8#include <errno.h>9#include <assert.h>10#include <stdint.h>11#include <string.h>12#include <sys/mman.h>13
14#include <drivers/video/fb.h>15#include <mem/page.h>16#include <util/binalign.h>17#include <util/log.h>18#include <kernel/irq.h>19
20#include <embox/unit.h>21
22#include <stm32f746xx.h>23#include "stm32cube_custom_lcd.h"24
25EMBOX_UNIT_INIT(stm32cube_lcd_init);26
27#define LTDC_IRQ OPTION_GET(NUMBER,ltdc_irq)28static_assert(LTDC_IRQ == LTDC_IRQn, "");29
30#define USE_FB_SECTION OPTION_GET(BOOLEAN,use_fb_section)31
32#if USE_FB_SECTION33#define STM32_FB_SECTION_START OPTION_GET(STRING,fb_section_start)34extern char STM32_FB_SECTION_START;35#else36#define STM32_FB_START OPTION_GET(NUMBER, fb_base)37#endif38
39#define STM32_LCD_HEIGHT OPTION_GET(NUMBER, height)40#define STM32_LCD_WIDTH OPTION_GET(NUMBER, width)41#define STM32_LCD_BPP OPTION_GET(NUMBER, bpp)42
43static_assert(STM32_LCD_BPP == 16 || STM32_LCD_BPP == 32, "");44
45/* Initialize layer 0 as active for all F7 boards. */
46#undef LTDC_ACTIVE_LAYER47#define LTDC_ACTIVE_LAYER 048
49
50extern LTDC_HandleTypeDef hLtdcHandler;51#define hltdc_handler hLtdcHandler52
53static int stm32cube_lcd_set_var(struct fb_info *info,54struct fb_var_screeninfo const *var) {55return 0;56}
57
58static int stm32cube_lcd_get_var(struct fb_info *info,59struct fb_var_screeninfo *var) {60memset(var, 0, sizeof(*var));61
62var->xres = bsp_lcd_getxsize();63var->yres = bsp_lcd_getysize();64var->xres_virtual = var->xres;65var->yres_virtual = var->yres;66var->bits_per_pixel = STM32_LCD_BPP;67
68switch (STM32_LCD_BPP) {69case 16:70var->fmt = BGR565;71break;72case 32:73var->fmt = BGRA8888;74break;75default:76log_error("unknown BPP = %d\n", STM32_LCD_BPP);77return -1;78}79
80return 0;81}
82
83static void stm32cube_lcd_fillrect(struct fb_info *info,84const struct fb_fillrect *rect) {85
86bsp_lcd_settextcolor(rect->color | 0xff000000);87bsp_lcd_fillrect(rect->dx, rect->dy, rect->width, rect->height);88}
89
90static uint32_t stm32cube_get_image_color(const struct fb_image *image, int num) {91switch (image->depth) {92case 1:93if (image->data[num / 8] & (1 << (8 - num % 8))) {94return image->fg_color;95} else {96return image->bg_color;97}98case 16:99return ((uint16_t *) image->data)[num];100case 32:101return ((uint32_t *) image->data)[num];102default:103log_error("Unsupported color depth: %d\n", image->depth);104return image->bg_color;105}106}
107
108static void stm32cube_lcd_imageblit(struct fb_info *info,109const struct fb_image *image) {110int dy = image->dy, dx = image->dx;111int height = image->height, width = image->width;112int n = 0;113
114for (int j = dy; j < dy + height; j++) {115for (int i = dx; i < dx + width; i++) {116bsp_lcd_drawpixel(i, j, stm32cube_get_image_color(image, n));117}118}119}
120
121static void ltdc_layer_init(uint16_t LayerIndex, uint32_t FB_Address, int bpp) {122LCD_LayerCfgTypeDef Layercfg;123
124assert(bpp == 16 || bpp == 32);125
126switch (bpp) {127case 16:128Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;129break;130case 32:131Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;132break;133default:134return;135}136
137/* Layer Init */138Layercfg.WindowX0 = 0;139Layercfg.WindowX1 = bsp_lcd_getxsize();140Layercfg.WindowY0 = 0;141Layercfg.WindowY1 = bsp_lcd_getysize();142Layercfg.FBStartAdress = FB_Address;143Layercfg.Alpha = 255;144Layercfg.Alpha0 = 0;145Layercfg.Backcolor.Blue = 0;146Layercfg.Backcolor.Green = 0;147Layercfg.Backcolor.Red = 0;148Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;149Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;150Layercfg.ImageWidth = bsp_lcd_getxsize();151Layercfg.ImageHeight = bsp_lcd_getysize();152
153HAL_LTDC_ConfigLayer(&hltdc_handler, &Layercfg, LayerIndex);154}
155
156static irq_return_t ltdc_irq_handler(unsigned int irq_num, void *dev_id) {157HAL_LTDC_IRQHandler(&hltdc_handler);158
159return IRQ_HANDLED;160}
161
162STATIC_IRQ_ATTACH(LTDC_IRQ, ltdc_irq_handler, NULL);163
164static struct fb_ops stm32cube_lcd_ops = {165.fb_set_var = stm32cube_lcd_set_var,166.fb_get_var = stm32cube_lcd_get_var,167.fb_fillrect = stm32cube_lcd_fillrect,168.fb_imageblit = stm32cube_lcd_imageblit,169};170
171static int stm32cube_lcd_init(void) {172char *mmap_base;173
174if (bsp_lcd_init(STM32_LCD_HEIGHT, STM32_LCD_WIDTH) != LCD_OK) {175log_error("Failed to init LCD!");176return -1;177}178
179#if USE_FB_SECTION180mmap_base = (char *) &STM32_FB_SECTION_START;181#else182mmap_base = (char *) STM32_FB_START;183#endif184
185ltdc_layer_init(LTDC_ACTIVE_LAYER, (unsigned int) mmap_base, STM32_LCD_BPP);186
187bsp_lcd_setxsize(STM32_LCD_WIDTH);188bsp_lcd_setysize(STM32_LCD_HEIGHT);189
190bsp_lcd_setbackcolor(LCD_COLOR_WHITE);191bsp_lcd_settextcolor(LCD_COLOR_BLACK);192
193bsp_lcd_selectlayer(LTDC_ACTIVE_LAYER);194
195bsp_lcd_clear(LCD_COLOR_BLACK);196
197if (0 > irq_attach(LTDC_IRQ, ltdc_irq_handler, 0, NULL, "LTDC")) {198log_error("irq_attach failed");199return -1;200}201
202fb_create(&stm32cube_lcd_ops,203mmap_base,204STM32_LCD_WIDTH *205STM32_LCD_HEIGHT /2068 * STM32_LCD_BPP);207
208return 0;209}
210