硬汉嵌入式论坛

 找回密码
 立即注册
查看: 5081|回复: 0
收起左侧

[emWin] 分享适用于H7的emWin6.x的ARGB和ABGR两种库的底层驱动

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107144
QQ
发表于 2021-2-3 13:12:44 | 显示全部楼层 |阅读模式


代码:

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : emWin的底层驱动文件
  5. *        文件名称 : LCDConf_Lin_Template.c
  6. *        版    本 : V2.0
  7. *        说    明 : LCD的部分驱动和emWin底层接口都在这个文件实现。
  8. *              使用说明:
  9. *                1. 此驱动自适应安富莱4.3寸,5寸和7寸屏。
  10. *                2. 用户使用emWin前,请先使能STM32的CRC时钟,之后调用GUI_Init()即可使用emWin。
  11. *                3. 不同的显示屏对用的触摸驱动不同,用户自己使用的话,请周期性调用即可。
  12. *                   电阻屏是:TOUCH_Scan(),1ms调用一次。
  13. *                   电容屏是:GT911_OnePiontScan(),GT811_OnePiontScan()或者FT5X06_OnePiontScan(),10ms调用一次。
  14. *              配置说明:
  15. *                1. H7的图层是由背景层,图层1和图层2组成。
  16. *                2. 程序中对每个配置选项都有详细说明。
  17. *              移植说明:
  18. *                  注意以下三点即可:
  19. *                1. 提供函数LCD_SetBackLight,实现背光的开关。
  20. *                2. 定义全局变量g_LcdWidth和g_LcdHeight。
  21. *                3. 修改函数LCD_ConfigLTDC,修改本文件中函数LCD_LL_Init里面的时序参数。
  22. *
  23. *        修改记录 :
  24. *                版本号    日期         作者        说明
  25. *                V1.0    2019-05-25    Eric2013     首发
  26. *                V2.0    2021-01-03    Eric2013     适配ARGB和ABGR两种格式库
  27. *
  28. *
  29. *        Copyright (C), 2021-2030, 安富莱电子 www.armfly.com
  30. *
  31. *********************************************************************************************************
  32. */
  33. #include "bsp.h"
  34. #include "GUI.h"
  35. #include "GUI_Private.h"
  36. #include "GUIDRV_Lin.h"
  37. #include "GUIConf.h"


  38. /*
  39. **********************************************************************************************************
  40.                                                                         结构体变量
  41. **********************************************************************************************************
  42. */
  43. typedef struct
  44. {
  45.   int32_t      address;         
  46.   __IO int32_t      pending_buffer;   
  47.   int32_t      buffer_index;     
  48.   int32_t      xSize;            
  49.   int32_t      ySize;            
  50.   int32_t      BytesPerPixel;
  51.   LCD_API_COLOR_CONV   *pColorConvAPI;
  52. }LCD_LayerPropTypedef;

  53. /*
  54. **********************************************************************************************************
  55.                                                                         用户可以配置的选项
  56. **********************************************************************************************************
  57. */
  58. /* 0 暂时用不到这几个功能 */
  59. #define DrawBitmapA4Enalbe    0
  60. #define ClearCacheHookEnalbe  0
  61. #define DrawAlpha             0
  62. #define UsedDrawBitmap8bpp    0

  63. /*
  64.   1. 显示屏的物理分辨率,驱动已经做了显示屏自适应,支持4.3寸,5寸和7寸屏
  65.      这里填写自适应显示屏中的最大分辨率。
  66. */
  67. #define XSIZE_PHYS       800
  68. #define YSIZE_PHYS       480

  69. /* 2. 旋转方向,暂未使用此选项,直接在工程运行时做旋转即可 */
  70. #define ROTATION_0       0
  71. #define ROTATION_CW      1
  72. #define ROTATION_180     2
  73. #define ROTATION_CCW     3

  74. /*
  75.    3. STM32H7支持的颜色模式。
  76.       (1) 如果打算使用24位色或者32位色,请选择CMS_ARGB8888,如果使用16位色,请选择CMS_RGB565,其它颜色格式不再做支持。
  77.           (2) 如果用户选择了ARGB8888或者RGB888模式,LCD闪烁的话,优先查看是否是此贴的问题:
  78.               http://forum.armfly.com/forum.php?mod=viewthread&tid=16892 (适用于F429和H7系列)
  79.                   如果不是这个问题,再降低LTDC输出时钟即可,在本文件的函数LCD_ConfigLTDC里面   
  80. */
  81. #define CMS_ARGB8888 1
  82. #define CMS_RGB888   2
  83. #define CMS_RGB565   3
  84. #define CMS_ARGB1555 4
  85. #define CMS_ARGB4444 5
  86. #define CMS_L8       6
  87. #define CMS_AL44     7
  88. #define CMS_AL88     8

  89. /* 4. 多缓冲 / 虚拟屏,多缓冲和虚拟屏不可同时使用,emWin不支持 */
  90. #define NUM_BUFFERS      3 /* 定义多缓冲个数,仅可以设置1,2和3,也就是最大支持三缓冲 */
  91. #define NUM_VSCREENS     1 /* 定义虚拟屏个数 */

  92. /*
  93.    5. 重定义图层数,对于STM32H7,用户可以选择一个图层或者两个图层,不支持三图层
  94.       (1). 设置GUI_NUM_LAYERS = 1时,即仅使用图层1时,默认触摸值是发送给图层1的。
  95.           (2). 设置GUI_NUM_LAYERS = 2时,即图层1和图层2都已经使能,此时图层2是顶层,
  96.                用户需要根据自己的使用情况设置如下两个地方。
  97.                    a. 在bsp_touch.c文件中的函数TOUCH_InitHard里面设置参数State.Layer = 1,1就表示
  98.                       给图层2发送触摸值。
  99.                    b. 调用GUI_Init函数后,调用函数GUI_SelectLayer(1), 设置当前操作的是图层2。
  100. */
  101. #undef  GUI_NUM_LAYERS
  102. #define GUI_NUM_LAYERS 1

  103. /*
  104.    6. 设置图层1和图层2对应的显存地址
  105.       (1) EXT_SDRAM_ADDR 是SDRAM的首地址。
  106.       (2) LCD_LAYER0_FRAME_BUFFER 是图层1的显存地址。
  107.           (3) LCD_LAYER1_FRAME_BUFFER 是图层2的显存地址。
  108.           (4) 每个图层的显存大小比较考究,这里进行下简单的说明。
  109.               如果用户选择的颜色模式 = 32位色ARGB8888,显存的大小:
  110.               XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS * NUM_BUFFERS
  111.                   
  112.               颜色模式 = 24位色RGB888,显存的大小:
  113.               XSIZE_PHYS * YSIZE_PHYS * 3 * NUM_VSCREENS * NUM_BUFFERS
  114.                   
  115.               颜色模式 = 16位色RGB566,ARGB1555, ARGB4444,AL88,那么显存的大小就是:
  116.               XSIZE_PHYS * YSIZE_PHYS * 2 * NUM_VSCREENS * NUM_BUFFERS

  117.               颜色模式 = 8位色L8,AL44,那么显存的大小就是:
  118.               XSIZE_PHYS * YSIZE_PHYS * 1 * NUM_VSCREENS * NUM_BUFFERS       
  119.       
  120.       这里为了方便起见,将开发板配套的16MB的SDRAM前8MB分配给LCD显存使用,后8MB用于emWin动态内存。
  121.           对于24位色,16位色,8位色,用户可以对其使能三缓冲,并且使能双图层。但是32位色也使能三缓冲和双
  122.           图层的话会超出8MB,所以用户根据自己的情况做显存和emWin动态内存的分配调整。
  123.             举一个例子,对于800*480分辨率的显示屏,使能32位色,三缓冲,那么最终一个图层需要的大小就是
  124.       800 * 480 * 4 * 3  = 4.394MB的空间,如果是双图层,已经超出8MB的分配范围。

  125.       (5)为了方便起见,图层2的宏定义LCD_LAYER1_FRAME_BUFFER中的参数4是按照32位色设置的,如果用户的图层1
  126.          使用的是8位色,这里填数字1,如果是16位色,这里填2,如果是24位色,这里填3。
  127. */
  128. #define LCD_LAYER0_FRAME_BUFFER  EXT_SDRAM_ADDR
  129. #define LCD_LAYER1_FRAME_BUFFER  (LCD_LAYER0_FRAME_BUFFER + XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS * NUM_BUFFERS)


  130. /* 7. 配置图层1的颜色模式和分辨率大小 */
  131. #define COLOR_MODE_0  CMS_RGB565
  132. #define ORIENTATION_0 ROTATION_0
  133. #define XSIZE_0       XSIZE_PHYS
  134. #define YSIZE_0       YSIZE_PHYS

  135. /* 8. 配置图层2的的颜色模式和分辨率大小 */
  136. #define COLOR_MODE_1  CMS_RGB565
  137. #define ORIENTATION_1 ROTATION_0
  138. #define XSIZE_1       XSIZE_PHYS
  139. #define YSIZE_1       YSIZE_PHYS

  140. /* 9. 没有图层激活时,背景色设置, 暂时未用到 */
  141. #define BK_COLOR      GUI_DARKBLUE


  142. /* 10. 单图层情况下,根据用户选择的颜色模式可自动选择图层1的emWin的颜色模式 */
  143. #if   (COLOR_MODE_0 == CMS_ARGB8888)
  144.   #define COLOR_CONVERSION_0 GUICC_M8888I
  145. #elif (COLOR_MODE_0 == CMS_RGB888)
  146.   #define COLOR_CONVERSION_0 GUICC_M888
  147. #elif (COLOR_MODE_0 == CMS_RGB565)
  148.   #define COLOR_CONVERSION_0 GUICC_M565
  149. #elif (COLOR_MODE_0 == CMS_ARGB1555)
  150.   #define COLOR_CONVERSION_0 GUICC_M1555I
  151. #elif (COLOR_MODE_0 == CMS_ARGB4444)
  152.   #define COLOR_CONVERSION_0 GUICC_M4444I
  153. #elif (COLOR_MODE_0 == CMS_L8)
  154.   #define COLOR_CONVERSION_0 GUICC_8666
  155. #elif (COLOR_MODE_0 == CMS_AL44)
  156.   #define COLOR_CONVERSION_0 GUICC_1616I
  157. #elif (COLOR_MODE_0 == CMS_AL88)
  158.   #define COLOR_CONVERSION_0 GUICC_88666I
  159. #else
  160.   #error Illegal color mode 0!
  161. #endif

  162. /* 11. 单图层情况下,根据用户选择的颜色模式可自动选择图层1的emWin的驱动 */
  163. #if   (COLOR_MODE_0 == CMS_ARGB8888)
  164.   #if   (ORIENTATION_0 == ROTATION_0)
  165.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_32
  166.   #elif (ORIENTATION_0 == ROTATION_CW)
  167.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSX_32
  168.   #elif (ORIENTATION_0 == ROTATION_180)
  169.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OXY_32
  170.   #elif (ORIENTATION_0 == ROTATION_CCW)
  171.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSY_32
  172.   #endif
  173. #elif (COLOR_MODE_0 == CMS_RGB888)
  174.   #if   (ORIENTATION_0 == ROTATION_0)
  175.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_24
  176.   #elif (ORIENTATION_0 == ROTATION_CW)
  177.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSX_24
  178.   #elif (ORIENTATION_0 == ROTATION_180)
  179.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OXY_24
  180.   #elif (ORIENTATION_0 == ROTATION_CCW)
  181.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSY_24
  182.   #endif
  183. #elif (COLOR_MODE_0 == CMS_RGB565)   \
  184.    || (COLOR_MODE_0 == CMS_ARGB1555) \
  185.    || (COLOR_MODE_0 == CMS_ARGB4444) \
  186.    || (COLOR_MODE_0 == CMS_AL88)
  187.   #if   (ORIENTATION_0 == ROTATION_0)
  188.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  189.   #elif (ORIENTATION_0 == ROTATION_CW)
  190.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSX_16
  191.   #elif (ORIENTATION_0 == ROTATION_180)
  192.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OXY_16
  193.   #elif (ORIENTATION_0 == ROTATION_CCW)
  194.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSY_16
  195.   #endif
  196. #elif (COLOR_MODE_0 == CMS_L8)   \
  197.    || (COLOR_MODE_0 == CMS_AL44)
  198.   #if   (ORIENTATION_0 == ROTATION_0)
  199.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  200.   #elif (ORIENTATION_0 == ROTATION_CW)
  201.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSX_8
  202.   #elif (ORIENTATION_0 == ROTATION_180)
  203.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OXY_8
  204.   #elif (ORIENTATION_0 == ROTATION_CCW)
  205.     #define DISPLAY_DRIVER_0   GUIDRV_LIN_OSY_8
  206.   #endif
  207. #endif


  208. /* 12. 双图层情况下,根据用户选择的颜色模式可自动选择图层2的emWin的颜色模式 */
  209. #if (GUI_NUM_LAYERS > 1)
  210. #if   (COLOR_MODE_1 == CMS_ARGB8888)
  211.   #define COLOR_CONVERSION_1 GUICC_M8888I
  212. #elif (COLOR_MODE_1 == CMS_RGB888)
  213.   #define COLOR_CONVERSION_1 GUICC_M888
  214. #elif (COLOR_MODE_1 == CMS_RGB565)
  215.   #define COLOR_CONVERSION_1 GUICC_M565
  216. #elif (COLOR_MODE_1 == CMS_ARGB1555)
  217.   #define COLOR_CONVERSION_1 GUICC_M1555I
  218. #elif (COLOR_MODE_1 == CMS_ARGB4444)
  219.   #define COLOR_CONVERSION_1 GUICC_M4444I
  220. #elif (COLOR_MODE_1 == CMS_L8)
  221.   #define COLOR_CONVERSION_1 GUICC_8666
  222. #elif (COLOR_MODE_1 == CMS_AL44)
  223.   #define COLOR_CONVERSION_1 GUICC_1616I
  224. #elif (COLOR_MODE_1 == CMS_AL88)
  225.   #define COLOR_CONVERSION_1 GUICC_88666I
  226. #else
  227.   #error Illegal color mode 0!
  228. #endif

  229. /* 13. 双图层情况下,根据用户选择的颜色模式可自动选择图层2的emWin的驱动 */
  230. #if   (COLOR_MODE_1 == CMS_ARGB8888)
  231.   #if   (ORIENTATION_1 == ROTATION_0)
  232.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_32
  233.   #elif (ORIENTATION_1 == ROTATION_CW)
  234.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSX_32
  235.   #elif (ORIENTATION_1 == ROTATION_180)
  236.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OXY_32
  237.   #elif (ORIENTATION_1 == ROTATION_CCW)
  238.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSY_32
  239.   #endif
  240. #elif (COLOR_MODE_1 == CMS_RGB888)
  241.   #if   (ORIENTATION_1 == ROTATION_0)
  242.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_24
  243.   #elif (ORIENTATION_1 == ROTATION_CW)
  244.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSX_24
  245.   #elif (ORIENTATION_1 == ROTATION_180)
  246.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OXY_24
  247.   #elif (ORIENTATION_1 == ROTATION_CCW)
  248.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSY_24
  249.   #endif
  250. #elif (COLOR_MODE_1 == CMS_RGB565)   \
  251.    || (COLOR_MODE_1 == CMS_ARGB1555) \
  252.    || (COLOR_MODE_1 == CMS_ARGB4444) \
  253.    || (COLOR_MODE_1 == CMS_AL88)
  254.   #if   (ORIENTATION_1 == ROTATION_0)
  255.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  256.   #elif (ORIENTATION_1 == ROTATION_CW)
  257.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSX_16
  258.   #elif (ORIENTATION_1 == ROTATION_180)
  259.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OXY_16
  260.   #elif (ORIENTATION_1 == ROTATION_CCW)
  261.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSY_16
  262.   #endif
  263. #elif (COLOR_MODE_1 == CMS_L8)   \
  264.    || (COLOR_MODE_1 == CMS_AL44)
  265.   #if   (ORIENTATION_1 == ROTATION_0)
  266.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  267.   #elif (ORIENTATION_1 == ROTATION_CW)
  268.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSX_8
  269.   #elif (ORIENTATION_1 == ROTATION_180)
  270.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OXY_8
  271.   #elif (ORIENTATION_1 == ROTATION_CCW)
  272.     #define DISPLAY_DRIVER_1   GUIDRV_LIN_OSY_8
  273.   #endif
  274. #endif

  275. #else

  276. #undef XSIZE_0
  277. #undef YSIZE_0
  278. #define XSIZE_0 XSIZE_PHYS
  279. #define YSIZE_0 YSIZE_PHYS
  280.      
  281. #endif

  282. /*14. 配置选项检测,防止配置错误或者某些选项没有配置 */
  283. #if NUM_BUFFERS > 3
  284.   #error More than 3 buffers make no sense and are not supported in this configuration file!
  285. #endif
  286. #ifndef   XSIZE_PHYS
  287.   #error Physical X size of display is not defined!
  288. #endif
  289. #ifndef   YSIZE_PHYS
  290.   #error Physical Y size of display is not defined!
  291. #endif
  292. #ifndef   NUM_BUFFERS
  293.   #define NUM_BUFFERS 1
  294. #else
  295.   #if (NUM_BUFFERS <= 0)
  296.     #error At least one buffer needs to be defined!
  297.   #endif
  298. #endif
  299. #ifndef   NUM_VSCREENS
  300.   #define NUM_VSCREENS 1
  301. #else
  302.   #if (NUM_VSCREENS <= 0)
  303.     #error At least one screeen needs to be defined!
  304.   #endif
  305. #endif
  306. #if (NUM_VSCREENS > 1) && (NUM_BUFFERS > 1)
  307.   #error Virtual screens together with multiple buffers are not allowed!
  308. #endif
  309.      
  310. /*
  311. **********************************************************************************************************
  312.                                                                         使用DMA2D重定向颜色的批量转换
  313. **********************************************************************************************************
  314. */
  315. #define DEFINE_DMA2D_COLORCONVERSION(PFIX, PIXELFORMAT)                                                        \
  316. static void _Color2IndexBulk_##PFIX##_DMA2D(LCD_COLOR * pColor, void * pIndex, U32 NumItems, U8 SizeOfIndex) { \
  317.   _DMA_Color2IndexBulk(pColor, pIndex, NumItems, SizeOfIndex, PIXELFORMAT);                                    \
  318. }                                                                                                              \
  319. static void _Index2ColorBulk_##PFIX##_DMA2D(void * pIndex, LCD_COLOR * pColor, U32 NumItems, U8 SizeOfIndex) { \
  320.   _DMA_Index2ColorBulk(pIndex, pColor, NumItems, SizeOfIndex, PIXELFORMAT);                                    \
  321. }

  322. /* 函数声明 */
  323. static void _DMA_Index2ColorBulk(void * pIndex, LCD_COLOR * pColor, U32 NumItems, U8 SizeOfIndex, U32 PixelFormat);
  324. static void _DMA_Color2IndexBulk(LCD_COLOR * pColor, void * pIndex, U32 NumItems, U8 SizeOfIndex, U32 PixelFormat);

  325. /* 颜色转换 */
  326. DEFINE_DMA2D_COLORCONVERSION(M8888I, LTDC_PIXEL_FORMAT_ARGB8888)
  327. DEFINE_DMA2D_COLORCONVERSION(M888,   LTDC_PIXEL_FORMAT_ARGB8888)
  328. DEFINE_DMA2D_COLORCONVERSION(M565,   LTDC_PIXEL_FORMAT_RGB565)
  329. DEFINE_DMA2D_COLORCONVERSION(M1555I, LTDC_PIXEL_FORMAT_ARGB1555)
  330. DEFINE_DMA2D_COLORCONVERSION(M4444I, LTDC_PIXEL_FORMAT_ARGB4444)


  331. static LTDC_HandleTypeDef     hltdc;  
  332. static LCD_LayerPropTypedef   layer_prop[GUI_NUM_LAYERS];
  333. static const U32   _aAddr[]   = {LCD_LAYER0_FRAME_BUFFER, LCD_LAYER1_FRAME_BUFFER};
  334. static int _aPendingBuffer[2] = { -1, -1 };
  335. static int _aBufferIndex[GUI_NUM_LAYERS];
  336. static int _axSize[GUI_NUM_LAYERS];
  337. static int _aySize[GUI_NUM_LAYERS];
  338. static int _aBytesPerPixels[GUI_NUM_LAYERS];

  339. /* 用不上,留作备用 */
  340. #if DrawBitmapA4Enalbe == 1
  341. static U32 _aBuffer[XSIZE_PHYS];
  342. static U32 * _pBuffer_DMA2D = &_aBuffer[0];

  343. /* 加速 A4 bitmaps 显示 */
  344. static const U8 _aMirror[] = {
  345.   0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
  346.   0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
  347.   0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
  348.   0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
  349.   0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
  350.   0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
  351.   0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
  352.   0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
  353.   0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
  354.   0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
  355.   0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
  356.   0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
  357.   0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
  358.   0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
  359.   0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
  360.   0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF,
  361. };
  362. #else
  363. static U32         _pBuffer_DMA2D[XSIZE_PHYS];
  364. //static U32         _pBuffer_FG   [XSIZE_PHYS];
  365. //static U32         _pBuffer_BG   [XSIZE_PHYS];
  366. #endif

  367. /* 颜色转换模式 */
  368. static const LCD_API_COLOR_CONV *_apColorConvAPI[] = {
  369.   COLOR_CONVERSION_0,
  370. #if GUI_NUM_LAYERS > 1
  371.   COLOR_CONVERSION_1,
  372. #endif
  373. };

  374. /* 显示方向 */
  375. static const int _aOrientation[] =
  376. {
  377.   ORIENTATION_0,
  378. #if GUI_NUM_LAYERS > 1
  379.   ORIENTATION_1,
  380. #endif
  381. };

  382. /*
  383. *********************************************************************************************************
  384. *        函 数 名: _ClearCacheHook
  385. *        功能说明: 清Cache
  386. *        形    参: LayerIndex  图层
  387. *        返 回 值: 无
  388. *********************************************************************************************************
  389. */
  390. #if ClearCacheHookEnalbe == 1
  391. static void _ClearCacheHook(U32 LayerMask)
  392. {
  393.         int i;
  394.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  395.         {
  396.                 if (LayerMask & (1 << i))
  397.                 {
  398.                         SCB_CleanDCache_by_Addr ((uint32_t *)_aAddr[i], XSIZE_PHYS * YSIZE_PHYS * sizeof(U32));
  399.                 }
  400.         }
  401. }
  402. #endif

  403. /*
  404. *********************************************************************************************************
  405. *        函 数 名: _GetPixelformat
  406. *        功能说明: 获取图层1或者图层2使用的颜色格式
  407. *        形    参: LayerIndex  图层
  408. *        返 回 值: 颜色格式
  409. *********************************************************************************************************
  410. */
  411. static U32 _GetPixelformat(int LayerIndex)
  412. {
  413.         const LCD_API_COLOR_CONV * pColorConvAPI;

  414.         if (LayerIndex >= GUI_COUNTOF(_apColorConvAPI))
  415.         {
  416.                 return 0;
  417.         }
  418.        
  419.         pColorConvAPI = _apColorConvAPI[LayerIndex];
  420.        
  421.         if (pColorConvAPI == GUICC_M8888I)
  422.         {
  423.                 return LTDC_PIXEL_FORMAT_ARGB8888;
  424.         }
  425.         else if (pColorConvAPI == GUICC_M888)
  426.         {
  427.                 return LTDC_PIXEL_FORMAT_RGB888;
  428.         }
  429.         else if (pColorConvAPI == GUICC_M565)
  430.         {
  431.                 return LTDC_PIXEL_FORMAT_RGB565;
  432.         }
  433.         else if (pColorConvAPI == GUICC_M1555I)
  434.         {
  435.                 return LTDC_PIXEL_FORMAT_ARGB1555;
  436.         }
  437.         else if (pColorConvAPI == GUICC_M4444I)
  438.         {
  439.         return LTDC_PIXEL_FORMAT_ARGB4444;
  440.         }
  441.         else if (pColorConvAPI == GUICC_8666  )
  442.         {
  443.                 return LTDC_PIXEL_FORMAT_L8;
  444.         }
  445.         else if (pColorConvAPI == GUICC_1616I )
  446.         {
  447.                 return LTDC_PIXEL_FORMAT_AL44;
  448.         }
  449.         else if (pColorConvAPI == GUICC_88666I)
  450.         {
  451.                 return LTDC_PIXEL_FORMAT_AL88;
  452.         }
  453.        
  454.         /* 配置错误会进入这里 */
  455.         while (1);
  456. }

  457. /*
  458. *********************************************************************************************************
  459. *        函 数 名: _GetPixelformat
  460. *        功能说明: 获取图层1或者图层2使用的颜色格式
  461. *        形    参: LayerIndex  图层
  462. *        返 回 值: 颜色格式
  463. *********************************************************************************************************
  464. */
  465. static void LCD_LL_LayerInit(U32 LayerIndex)
  466. {  
  467.         LTDC_LayerCfgTypeDef  layer_cfg;  
  468.         static uint32_t       LUT[256];
  469.         uint32_t              i;

  470.         if (LayerIndex < GUI_NUM_LAYERS)
  471.         {
  472.                 /* 窗口显示区设置 */
  473.                 layer_cfg.WindowX0 = 0;
  474.                 layer_cfg.WindowX1 = g_LcdWidth;
  475.                 layer_cfg.WindowY0 = 0;
  476.                 layer_cfg.WindowY1 = g_LcdHeight;
  477.                
  478.                 /* 配置颜色格式 */
  479.                 layer_cfg.PixelFormat = _GetPixelformat(LayerIndex);
  480.                
  481.                 /* 显存地址 */
  482.                 layer_cfg.FBStartAdress = layer_prop[LayerIndex].address;
  483.                
  484.                 /* Alpha常数 (255 表示完全不透明) */
  485.                 layer_cfg.Alpha = 255;
  486.                
  487.                 /* 无背景色 */
  488.                 layer_cfg.Alpha0 = 0;   /* 完全透明 */
  489.                 layer_cfg.Backcolor.Blue = 0;
  490.                 layer_cfg.Backcolor.Green = 0;
  491.                 layer_cfg.Backcolor.Red = 0;
  492.                
  493.                 /* 配置图层混合因数 */
  494.                 layer_cfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
  495.                 layer_cfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;

  496.                 /* 配置行列大小 */
  497.                 layer_cfg.ImageWidth = g_LcdWidth;
  498.                 layer_cfg.ImageHeight = g_LcdHeight;

  499.                 /* 配置图层1 */
  500.                 HAL_LTDC_ConfigLayer(&hltdc, &layer_cfg, LayerIndex);

  501.                 /* 使能LUT */
  502.                 if (LCD_GetBitsPerPixelEx(LayerIndex) <= 8)
  503.                 {
  504.                         HAL_LTDC_EnableCLUT(&hltdc, LayerIndex);
  505.                 }
  506.                 else
  507.                 {
  508.                         /*  AL88模式(16bpp) */
  509.                         if (layer_prop[LayerIndex].pColorConvAPI == GUICC_88666I)
  510.                         {
  511.                                 HAL_LTDC_EnableCLUT(&hltdc, LayerIndex);

  512.                                 for (i = 0; i < 256; i++)
  513.                                 {
  514.                                         LUT[i] = LCD_API_ColorConv_8666.pfIndex2Color(i);
  515.                                 }
  516.                                
  517.                                 HAL_LTDC_ConfigCLUT(&hltdc, LUT, 256, LayerIndex);
  518.                         }
  519.                 }
  520.         }  
  521. }

  522. /*
  523. *********************************************************************************************************
  524. *        函 数 名: LCD_LL_Init
  525. *        功能说明: 配置LTDC
  526. *        形    参: 无
  527. *        返 回 值: 无
  528. *   笔    记:
  529. *       LCD_TFT 同步时序配置(整理自官方做的一个截图,言简意赅):
  530. *       ----------------------------------------------------------------------------
  531. *   
  532. *                                                 Total Width
  533. *                             <--------------------------------------------------->
  534. *                       Hsync width HBP             Active Width                HFP
  535. *                             <---><--><--------------------------------------><-->
  536. *                         ____    ____|_______________________________________|____
  537. *                             |___|   |                                       |    |
  538. *                                     |                                       |    |
  539. *                         __|         |                                       |    |
  540. *            /|\    /|\  |            |                                       |    |
  541. *             | VSYNC|   |            |                                       |    |
  542. *             |Width\|/  |__          |                                       |    |
  543. *             |     /|\     |         |                                       |    |
  544. *             |  VBP |      |         |                                       |    |
  545. *             |     \|/_____|_________|_______________________________________|    |
  546. *             |     /|\     |         | / / / / / / / / / / / / / / / / / / / |    |
  547. *             |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  548. *    Total    |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  549. *    Heigh    |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  550. *             |Active|      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  551. *             |Heigh |      |         |/ / / / / / Active Display Area / / / /|    |
  552. *             |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  553. *             |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  554. *             |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  555. *             |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  556. *             |      |      |         |/ / / / / / / / / / / / / / / / / / / /|    |
  557. *             |     \|/_____|_________|_______________________________________|    |
  558. *             |     /|\     |                                                      |
  559. *             |  VFP |      |                                                      |
  560. *            \|/    \|/_____|______________________________________________________|
  561. *            
  562. *     
  563. *     每个LCD设备都有自己的同步时序值:
  564. *     Horizontal Synchronization (Hsync)
  565. *     Horizontal Back Porch (HBP)      
  566. *     Active Width                     
  567. *     Horizontal Front Porch (HFP)     
  568. *   
  569. *     Vertical Synchronization (Vsync)  
  570. *     Vertical Back Porch (VBP)         
  571. *     Active Heigh                       
  572. *     Vertical Front Porch (VFP)         
  573. *     
  574. *     LCD_TFT 窗口水平和垂直的起始以及结束位置 :
  575. *     ----------------------------------------------------------------
  576. *   
  577. *     HorizontalStart = (Offset_X + Hsync + HBP);
  578. *     HorizontalStop  = (Offset_X + Hsync + HBP + Window_Width - 1);
  579. *     VarticalStart   = (Offset_Y + Vsync + VBP);
  580. *     VerticalStop    = (Offset_Y + Vsync + VBP + Window_Heigh - 1);
  581. *
  582. *********************************************************************************************************
  583. */
  584. static void LCD_LL_Init(void)
  585. {
  586.         /* 配置LCD相关的GPIO */
  587.         {
  588.                 /* GPIOs Configuration */
  589.                 /*
  590.                 +------------------------+-----------------------+----------------------------+
  591.                 +                       LCD pins assignment                                   +
  592.                 +------------------------+-----------------------+----------------------------+
  593.                 |  LCDH7_TFT R0 <-> PI.15  |  LCDH7_TFT G0 <-> PJ.07 |  LCDH7_TFT B0 <-> PJ.12      |
  594.                 |  LCDH7_TFT R1 <-> PJ.00  |  LCDH7_TFT G1 <-> PJ.08 |  LCDH7_TFT B1 <-> PJ.13      |
  595.                 |  LCDH7_TFT R2 <-> PJ.01  |  LCDH7_TFT G2 <-> PJ.09 |  LCDH7_TFT B2 <-> PJ.14      |
  596.                 |  LCDH7_TFT R3 <-> PJ.02  |  LCDH7_TFT G3 <-> PJ.10 |  LCDH7_TFT B3 <-> PJ.15      |
  597.                 |  LCDH7_TFT R4 <-> PJ.03  |  LCDH7_TFT G4 <-> PJ.11 |  LCDH7_TFT B4 <-> PK.03      |
  598.                 |  LCDH7_TFT R5 <-> PJ.04  |  LCDH7_TFT G5 <-> PK.00 |  LCDH7_TFT B5 <-> PK.04      |
  599.                 |  LCDH7_TFT R6 <-> PJ.05  |  LCDH7_TFT G6 <-> PK.01 |  LCDH7_TFT B6 <-> PK.05      |
  600.                 |  LCDH7_TFT R7 <-> PJ.06  |  LCDH7_TFT G7 <-> PK.02 |  LCDH7_TFT B7 <-> PK.06      |
  601.                 -------------------------------------------------------------------------------
  602.                 |  LCDH7_TFT HSYNC <-> PI.12  | LCDTFT VSYNC <->  PI.13 |
  603.                 |  LCDH7_TFT CLK   <-> PI.14  | LCDH7_TFT DE   <->  PK.07 |
  604.                 -----------------------------------------------------
  605.                 */               
  606.                 GPIO_InitTypeDef GPIO_Init_Structure;

  607.                 /*##-1- Enable peripherals and GPIO Clocks #################################*/  
  608.                 /* 使能LTDC和DMA2D时钟 */
  609.                 __HAL_RCC_LTDC_CLK_ENABLE();
  610.                 __HAL_RCC_DMA2D_CLK_ENABLE();  
  611.                
  612.                 /* 使能GPIO时钟 */
  613.                 __HAL_RCC_GPIOI_CLK_ENABLE();
  614.                 __HAL_RCC_GPIOJ_CLK_ENABLE();
  615.                 __HAL_RCC_GPIOK_CLK_ENABLE();

  616.                 /* GPIOI 配置 */
  617.                 GPIO_Init_Structure.Pin       = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
  618.                 GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;
  619.                 GPIO_Init_Structure.Pull      = GPIO_NOPULL;
  620.                 GPIO_Init_Structure.Speed     = GPIO_SPEED_FREQ_HIGH;
  621.                 GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;  
  622.                 HAL_GPIO_Init(GPIOI, &GPIO_Init_Structure);

  623.                 /* GPIOJ 配置 */  
  624.                 GPIO_Init_Structure.Pin       = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
  625.                                                                           GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | \
  626.                                                                           GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | \
  627.                                                                           GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
  628.                 GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;
  629.                 GPIO_Init_Structure.Pull      = GPIO_NOPULL;
  630.                 GPIO_Init_Structure.Speed     = GPIO_SPEED_FREQ_HIGH;
  631.                 GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;  
  632.                 HAL_GPIO_Init(GPIOJ, &GPIO_Init_Structure);  

  633.                 /* GPIOK 配置 */  
  634.                 GPIO_Init_Structure.Pin       = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | \
  635.                                                                           GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
  636.                 GPIO_Init_Structure.Mode      = GPIO_MODE_AF_PP;
  637.                 GPIO_Init_Structure.Pull      = GPIO_NOPULL;
  638.                 GPIO_Init_Structure.Speed     = GPIO_SPEED_FREQ_HIGH;
  639.                 GPIO_Init_Structure.Alternate = GPIO_AF14_LTDC;  
  640.                 HAL_GPIO_Init(GPIOK, &GPIO_Init_Structure);         
  641.         }
  642.        
  643.         /*##-2- LTDC初始化 #############################################################*/  
  644.         {       
  645.                 uint16_t Width, Height, HSYNC_W, HBP, HFP, VSYNC_W, VBP, VFP;
  646.                 RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct = {0};

  647.                 /* 支持6种面板 */
  648.                 switch (g_LcdType)
  649.                 {
  650.                         case LCD_35_480X320:        /* 3.5寸 480 * 320 */       
  651.                                 Width = 480;
  652.                                 Height = 272;
  653.                                 HSYNC_W = 10;
  654.                                 HBP = 20;
  655.                                 HFP = 20;
  656.                                 VSYNC_W = 20;
  657.                                 VBP = 20;
  658.                                 VFP = 20;
  659.                                 break;
  660.                        
  661.                         case LCD_43_480X272:                /* 4.3寸 480 * 272 */                       
  662.                                 Width = 480;
  663.                                 Height = 272;

  664.                                 HSYNC_W = 40;
  665.                                 HBP = 2;
  666.                                 HFP = 2;
  667.                                 VSYNC_W = 9;
  668.                                 VBP = 2;
  669.                                 VFP = 2;
  670.                
  671.                                 /* LCD 时钟配置 */
  672.                                 /* PLL3_VCO Input = HSE_VALUE/PLL3M = 25MHz/5 = 5MHz */
  673.                                 /* PLL3_VCO Output = PLL3_VCO Input * PLL3N = 5MHz * 48 = 240MHz */
  674.                                 /* PLLLCDCLK = PLL3_VCO Output/PLL3R = 240 / 10 = 24MHz */
  675.                                 /* LTDC clock frequency = PLLLCDCLK = 24MHz */
  676.                                 /*
  677.                                         刷新率 = 24MHz /((Width + HSYNC_W  + HBP  + HFP)*(Height + VSYNC_W +  VBP  + VFP))
  678.                                       = 24000000/((480 + 40  + 2  + 2)*(272 + 9 +  2  + 2))
  679.                                        = 24000000/(524*285)
  680.                            = 160Hz       

  681.                                         当前这个配置方便用户使用PLL3Q输出的48MHz时钟供USB使用。
  682.                             */
  683.                                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  684.                                 PeriphClkInitStruct.PLL3.PLL3M = 5;
  685.                                 PeriphClkInitStruct.PLL3.PLL3N = 48;
  686.                                 PeriphClkInitStruct.PLL3.PLL3P = 2;
  687.                                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
  688.                                 PeriphClkInitStruct.PLL3.PLL3R = 10;                               
  689.                                 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);                            
  690.                                 break;
  691.                        
  692.                         case LCD_50_480X272:                /* 5.0寸 480 * 272 */
  693.                                 Width = 480;
  694.                                 Height = 272;
  695.                        
  696.                                 HSYNC_W = 40;
  697.                                 HBP = 2;
  698.                                 HFP = 2;
  699.                                 VSYNC_W = 9;
  700.                                 VBP = 2;
  701.                                 VFP = 2;                       
  702.                                 break;
  703.                        
  704.                         case LCD_50_800X480:                /* 5.0寸 800 * 480 */
  705.                         case LCD_70_800X480:                /* 7.0寸 800 * 480 */                                       
  706.                                 Width = 800;
  707.                                 Height = 480;

  708.                                 HSYNC_W = 96;        /* =10时,显示错位,20时部分屏可以的,80时全部OK */
  709.                                 HBP = 10;
  710.                                 HFP = 10;
  711.                                 VSYNC_W = 2;
  712.                                 VBP = 10;
  713.                                 VFP = 10;                       

  714.                                 /* LCD 时钟配置 */
  715.                                 /* PLL3_VCO Input = HSE_VALUE/PLL3M = 25MHz/5 = 5MHz */
  716.                                 /* PLL3_VCO Output = PLL3_VCO Input * PLL3N = 5MHz * 48 = 240MHz */
  717.                                 /* PLLLCDCLK = PLL3_VCO Output/PLL3R = 240 / 10 = 24MHz */
  718.                                 /* LTDC clock frequency = PLLLCDCLK = 24MHz */
  719.                                 /*
  720.                                         刷新率 = 24MHz /((Width + HSYNC_W  + HBP  + HFP)*(Height + VSYNC_W +  VBP  + VFP))
  721.                                       = 24000000/((800 + 96  + 10  + 10)*(480 + 2 +  10  + 10))
  722.                                        = 24000000/(916*502)
  723.                            = 52Hz       
  724.                        
  725.                                         根据需要可以加大,100Hz刷新率完全没问题,设置PeriphClkInitStruct.PLL3.PLL3N = 100即可
  726.                                         此时的LTDC时钟是50MHz
  727.                                         刷新率 = 50MHz /((Width + HSYNC_W  + HBP  + HFP )*(Height + VSYNC_W +  VBP  +VFP  ))
  728.                                                = 5000000/(916*502)
  729.                                                = 108.7Hz

  730.                                         当前这个配置方便用户使用PLL3Q输出的48MHz时钟供USB使用。
  731.                             */
  732.                                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  733.                                 PeriphClkInitStruct.PLL3.PLL3M = 5;
  734.                                 PeriphClkInitStruct.PLL3.PLL3N = 48;
  735.                                 PeriphClkInitStruct.PLL3.PLL3P = 2;
  736.                                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
  737.                                 PeriphClkInitStruct.PLL3.PLL3R = 10;
  738.                                 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);                            
  739.                                 break;
  740.                        
  741.                         case LCD_70_1024X600:                /* 7.0寸 1024 * 600 */
  742.                                 /* 实测像素时钟 = 53.7M */
  743.                                 Width = 1024;
  744.                                 Height = 600;

  745.                                 HSYNC_W = 2;        /* =10时,显示错位,20时部分屏可以的,80时全部OK */
  746.                                 HBP = 157;
  747.                                 HFP = 160;
  748.                                 VSYNC_W = 2;
  749.                                 VBP = 20;
  750.                                 VFP = 12;               
  751.                        
  752.                                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  753.                                 PeriphClkInitStruct.PLL3.PLL3M = 5;
  754.                                 PeriphClkInitStruct.PLL3.PLL3N = 48;
  755.                                 PeriphClkInitStruct.PLL3.PLL3P = 2;
  756.                                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
  757.                                 PeriphClkInitStruct.PLL3.PLL3R = 10;
  758.                                 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);                        
  759.                                 break;
  760.                        
  761.                         default:
  762.                                 Width = 800;
  763.                                 Height = 480;

  764.                                 HSYNC_W = 80;        /* =10时,显示错位,20时部分屏可以的,80时全部OK */
  765.                                 HBP = 10;
  766.                                 HFP = 10;
  767.                                 VSYNC_W = 10;
  768.                                 VBP = 10;
  769.                                 VFP = 10;               
  770.                        
  771.                                 /* LCD 时钟配置 */
  772.                                 /* PLL3_VCO Input = HSE_VALUE/PLL3M = 25MHz/5 = 5MHz */
  773.                                 /* PLL3_VCO Output = PLL3_VCO Input * PLL3N = 5MHz * 48 = 240MHz */
  774.                                 /* PLLLCDCLK = PLL3_VCO Output/PLL3R = 240 / 10 = 24MHz */
  775.                                 /* LTDC clock frequency = PLLLCDCLK = 24MHz */
  776.                                 /*
  777.                                         刷新率 = 24MHz /((Width + HSYNC_W  + HBP  + HFP)*(Height + VSYNC_W +  VBP  + VFP))
  778.                                       = 24000000/((800 + 96  + 10  + 10)*(480 + 2 +  10  + 10))
  779.                                        = 24000000/(916*502)
  780.                            = 52Hz

  781.                                         根据需要可以加大,100Hz刷新率完全没问题,设置PeriphClkInitStruct.PLL3.PLL3N = 100即可
  782.                                         此时的LTDC时钟是50MHz
  783.                                         刷新率 = 50MHz /((Width + HSYNC_W  + HBP  + HFP )*(Height + VSYNC_W +  VBP  +VFP  ))
  784.                                                = 5000000/(916*502)
  785.                                                = 108.7Hz

  786.                                         当前这个配置方便用户使用PLL3Q输出的48MHz时钟供USB使用。
  787.                             */
  788.                                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  789.                                 PeriphClkInitStruct.PLL3.PLL3M = 5;
  790.                                 PeriphClkInitStruct.PLL3.PLL3N = 48;
  791.                                 PeriphClkInitStruct.PLL3.PLL3P = 2;
  792.                                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
  793.                                 PeriphClkInitStruct.PLL3.PLL3R = 10;  
  794.                                 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);                        
  795.                                 break;
  796.                 }               

  797.                 g_LcdHeight = Height;
  798.                 g_LcdWidth = Width;
  799.                
  800.                 /* 配置信号极性 */       
  801.                 hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;        /* HSYNC 低电平有效 */
  802.                 hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;         /* VSYNC 低电平有效 */
  803.                 hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;         /* DE 低电平有效 */
  804.                 hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

  805.                 /* 时序配置 */   
  806.                 hltdc.Init.HorizontalSync = (HSYNC_W - 1);
  807.                 hltdc.Init.VerticalSync = (VSYNC_W - 1);
  808.                 hltdc.Init.AccumulatedHBP = (HSYNC_W + HBP - 1);
  809.                 hltdc.Init.AccumulatedVBP = (VSYNC_W + VBP - 1);  
  810.                 hltdc.Init.AccumulatedActiveH = (Height + VSYNC_W + VBP - 1);
  811.                 hltdc.Init.AccumulatedActiveW = (Width + HSYNC_W + HBP - 1);
  812.                 hltdc.Init.TotalHeigh = (Height + VSYNC_W + VBP + VFP - 1);
  813.                 hltdc.Init.TotalWidth = (Width + HSYNC_W + HBP + HFP - 1);

  814.                 /* 配置背景层颜色 */
  815.                 hltdc.Init.Backcolor.Blue = 0;
  816.                 hltdc.Init.Backcolor.Green = 0;
  817.                 hltdc.Init.Backcolor.Red = 0;

  818.                 hltdc.Instance = LTDC;

  819.                 /* 配置LTDC  */  
  820.                 if (HAL_LTDC_Init(&hltdc) != HAL_OK)
  821.                 {
  822.                         /* 初始化错误 */
  823.                         Error_Handler(__FILE__, __LINE__);
  824.                 }
  825.         }  

  826.         /* 使能行中断 */
  827.         HAL_LTDC_ProgramLineEvent(&hltdc, 0);
  828.   
  829.     /* 使能Dither */
  830.     //HAL_LTDC_EnableDither(&hltdc);

  831.         /* 使能LTDC中断,并配置其优先级 */
  832.         HAL_NVIC_SetPriority(LTDC_IRQn, 0x2, 0);
  833.         HAL_NVIC_EnableIRQ(LTDC_IRQn);
  834. }

  835. /*
  836. *********************************************************************************************************
  837. *        函 数 名: _DMA_Copy
  838. *        功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
  839. *        形    参: LayerIndex    图层
  840. *             pSrc          颜色数据源地址
  841. *             pDst          颜色数据目的地址
  842. *             xSize         要复制区域的X轴大小,即每行像素数
  843. *             ySize         要复制区域的Y轴大小,即行数
  844. *             OffLineSrc    前景层图像的行偏移
  845. *             OffLineDst    输出的行偏移
  846. *        返 回 值: 无
  847. *********************************************************************************************************
  848. */
  849. static void _DMA_Copy(int LayerIndex, void * pSrc, void * pDst, int xSize, int ySize, int OffLineSrc, int OffLineDst)
  850. {
  851.         U32 PixelFormat;

  852.         /* 获取图层使用的颜色格式 */
  853.         PixelFormat    = _GetPixelformat(LayerIndex);

  854.         /* DMA2D配置 */  
  855.         DMA2D->CR      = 0x00000000UL | (1 << 9);
  856.         DMA2D->FGMAR   = (U32)pSrc;
  857.         DMA2D->OMAR    = (U32)pDst;
  858.         DMA2D->FGOR    = OffLineSrc;
  859.         DMA2D->OOR     = OffLineDst;
  860.         DMA2D->FGPFCCR = PixelFormat;
  861.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  862.         /* 启动传输 */
  863.         DMA2D->CR   |= DMA2D_CR_START;   

  864.         /* 等待DMA2D传输完成 */
  865.         while (DMA2D->CR & DMA2D_CR_START) {}
  866. }

  867. /*
  868. *********************************************************************************************************
  869. *        函 数 名: _DMA_CopyRGB565
  870. *        功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
  871. *        形    参: pSrc          颜色数据源地址
  872. *             pDst          颜色数据目的地址
  873. *             xSize         要复制区域的X轴大小,即每行像素数
  874. *             ySize         要复制区域的Y轴大小,即行数
  875. *             OffLineSrc    前景层图像的行偏移
  876. *             OffLineDst    输出的行偏移
  877. *        返 回 值: 无
  878. *********************************************************************************************************
  879. */
  880. #if GUI_USE_ARGB
  881. static void _DMA_CopyRGB565(const void * pSrc, void * pDst, int xSize, int ySize, int OffLineSrc, int OffLineDst)
  882. {
  883.         /* DMA2D配置 */  
  884.         DMA2D->CR      = 0x00000000UL | (1 << 9);
  885.         DMA2D->FGMAR   = (U32)pSrc;
  886.         DMA2D->OMAR    = (U32)pDst;
  887.         DMA2D->FGOR    = OffLineSrc;
  888.         DMA2D->OOR     = OffLineDst;
  889.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
  890.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  891.         /* 启动传输 */
  892.         DMA2D->CR   |= DMA2D_CR_START;   

  893.         /* 等待DMA2D传输完成 */
  894.         while (DMA2D->CR & DMA2D_CR_START) {}
  895. }
  896. #endif

  897. /*
  898. *********************************************************************************************************
  899. *        函 数 名: _DMA_Fill
  900. *        功能说明: 通过DMA2D对于指定区域进行颜色填充
  901. *        形    参: LayerIndex    图层
  902. *             pDst          颜色数据目的地址
  903. *             xSize         要复制区域的X轴大小,即每行像素数
  904. *             ySize         要复制区域的Y轴大小,即行数
  905. *             OffLine       前景层图像的行偏移
  906. *             ColorIndex    要填充的颜色值
  907. *        返 回 值: 无
  908. *********************************************************************************************************
  909. */
  910. static void _DMA_Fill(int LayerIndex, void * pDst, int xSize, int ySize, int OffLine, U32 ColorIndex)
  911. {
  912.         U32 PixelFormat;

  913.         /* 获取图层使用的颜色格式 */
  914.         PixelFormat = _GetPixelformat(LayerIndex);

  915.         /* DMA2D配置 */  
  916.         DMA2D->CR      = 0x00030000UL | (1 << 9);
  917.         DMA2D->OCOLR   = ColorIndex;
  918.         DMA2D->OMAR    = (U32)pDst;
  919.         DMA2D->OOR     = OffLine;
  920.         DMA2D->OPFCCR  = PixelFormat;
  921.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  922.         /* 启动传输 */
  923.         DMA2D->CR   |= DMA2D_CR_START;   

  924.         /* 等待DMA2D传输完成 */
  925.         while (DMA2D->CR & DMA2D_CR_START) {}
  926. }

  927. /*
  928. *********************************************************************************************************
  929. *        函 数 名: _DMA_DrawBitmapL8
  930. *        功能说明: 绘制L8格式位图
  931. *        形    参: pSrc             源数据地址
  932. *             pDst             目的数据地址
  933. *             OffSrc           源数据行偏移
  934. *             OffDst           目的数据行偏移
  935. *             PixelFormatDst   转换的颜色格式
  936. *             xSize            位图长
  937. *             ySize            位图高
  938. *        返 回 值: 无
  939. *********************************************************************************************************
  940. */
  941. #if UsedDrawBitmap8bpp
  942. static void _DMA_DrawBitmapL8(void * pSrc, void * pDst,  U32 OffSrc, U32 OffDst, U32 PixelFormatDst, U32 xSize, U32 ySize)
  943. {
  944.         /* 配置DMA2D */
  945.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  946.         DMA2D->FGMAR   = (U32)pSrc;
  947.         DMA2D->OMAR    = (U32)pDst;
  948.         DMA2D->FGOR    = OffSrc;
  949.         DMA2D->OOR     = OffDst;
  950.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_L8;
  951.         DMA2D->OPFCCR  = PixelFormatDst;            
  952.                         
  953.         DMA2D->NLR     = (U32)(xSize << 16) | ySize;

  954.         /* 启动传输 */
  955.         DMA2D->CR   |= DMA2D_CR_START;   

  956.         /* 等待DMA2D传输完成 */
  957.         while (DMA2D->CR & DMA2D_CR_START) {}  
  958. }
  959. #endif

  960. #if DrawBitmapA4Enalbe == 1
  961. /*
  962. *********************************************************************************************************
  963. *        函 数 名: _DMA_DrawBitmapA4
  964. *        功能说明: 绘制A4格式位图
  965. *        形    参: pSrc             源数据地址
  966. *             pDst             目的数据地址
  967. *             OffSrc           源数据行偏移
  968. *             OffDst           目的数据行偏移
  969. *             PixelFormatDst   转换的颜色格式
  970. *             xSize            位图长
  971. *             ySize            位图高
  972. *        返 回 值: 0
  973. *********************************************************************************************************
  974. */
  975. static int _DMA_DrawBitmapA4(void * pSrc, void * pDst,  U32 OffSrc, U32 OffDst, U32 PixelFormatDst, U32 xSize, U32 ySize)
  976. {
  977.     U8 * pRD;
  978.     U8 * pWR;
  979.     U32 NumBytes, Color, Index;


  980.     NumBytes = (((xSize + 1) & (U32)~1) * ySize) >> 1;
  981.     if ((NumBytes > sizeof(_aBuffer)) || (NumBytes == 0)) {
  982.     return 1;
  983.     }

  984.     pWR = (U8 *)_aBuffer;
  985.     pRD = (U8 *)pSrc;
  986.     do {
  987.     *pWR++ = _aMirror[*pRD++];
  988.     } while (--NumBytes);


  989.     Index = LCD_GetColorIndex();
  990.     Color = LCD_Index2Color(Index);


  991.     DMA2D->CR = 0x00020000UL | (1 << 9);

  992. #if (GUI_USE_ARGB == 0)
  993.     DMA2D->FGCOLR  = ((Color & 0xFF) << 16)  // Red
  994.                  |  (Color & 0xFF00)       // Green
  995.                  | ((Color >> 16) & 0xFF); // Blue
  996. #else
  997.     DMA2D->FGCOLR  = Color;
  998. #endif
  999.     DMA2D->FGMAR   = (U32)_aBuffer;
  1000.     DMA2D->FGOR    = 0;
  1001.     DMA2D->FGPFCCR = 0xA;                    // A4 bitmap
  1002.     DMA2D->NLR     = (U32)((xSize + OffSrc) << 16) | ySize;
  1003.     DMA2D->BGMAR   = (U32)pDst;
  1004.     DMA2D->BGOR    = OffDst - OffSrc;
  1005.     DMA2D->BGPFCCR = PixelFormatDst;
  1006.     DMA2D->OMAR    = DMA2D->BGMAR;
  1007.     DMA2D->OOR     = DMA2D->BGOR;
  1008.     DMA2D->OPFCCR  = DMA2D->BGPFCCR;

  1009.     /* 启动传输 */
  1010.     DMA2D->CR   |= DMA2D_CR_START;   

  1011.     /* 等待DMA2D传输完成 */
  1012.     while (DMA2D->CR & DMA2D_CR_START) {}

  1013.         return 0;
  1014. }
  1015. #endif

  1016. /*
  1017. *********************************************************************************************************
  1018. *        函 数 名: _DMA_DrawAlphaBitmap
  1019. *        功能说明: 绘制带透明通道的位图
  1020. *        形    参: pSrc             源数据地址
  1021. *             pDst             目的数据地址
  1022. *             xSize            位图长
  1023. *             ySize            位图高
  1024. *             OffLineSrc       源数据行偏移
  1025. *             OffLineDst       目的数据行偏移
  1026. *             PixelFormatDst   转换的颜色格式
  1027. *        返 回 值: 0
  1028. *********************************************************************************************************
  1029. */
  1030. #if  DrawAlpha == 1  
  1031. static void _DMA_DrawAlphaBitmap(void * pDst, const void * pSrc, int xSize, int ySize, int OffLineSrc, int OffLineDst, int PixelFormat)
  1032. {
  1033.         /* 配置*/
  1034.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1035.         DMA2D->FGMAR   = (U32)pSrc;
  1036.         DMA2D->BGMAR   = (U32)pDst;
  1037.         DMA2D->OMAR    = (U32)pDst;
  1038.         DMA2D->FGOR    = OffLineSrc;
  1039.         DMA2D->BGOR    = OffLineDst;
  1040.         DMA2D->OOR     = OffLineDst;
  1041.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1042.         DMA2D->BGPFCCR = PixelFormat;
  1043.         DMA2D->OPFCCR  = PixelFormat;
  1044.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  1045.         /* 启动传输 */
  1046.         DMA2D->CR   |= DMA2D_CR_START;   

  1047.         /* 等待DMA2D传输完成 */
  1048.         while (DMA2D->CR & DMA2D_CR_START) {}
  1049. }
  1050. #endif

  1051. /*
  1052. *********************************************************************************************************
  1053. *        函 数 名: _DMA_LoadLUT
  1054. *        功能说明: 加载颜色表
  1055. *        形    参: pColor     颜色表地址
  1056. *             NumItems   要加载的个数
  1057. *        返 回 值: 0
  1058. *********************************************************************************************************
  1059. */
  1060. static void _DMA_LoadLUT(LCD_COLOR * pColor, U32 NumItems)
  1061. {
  1062.         /* 配置DMA2D */
  1063.         DMA2D->FGCMAR  = (U32)pColor;
  1064.         DMA2D->FGPFCCR  = LTDC_PIXEL_FORMAT_RGB888
  1065.                                   | ((NumItems - 1) & 0xFF) << 8;
  1066.        
  1067.         /* 启动加载 */
  1068.         DMA2D->FGPFCCR |= (1 << 5);
  1069. }

  1070. /*
  1071. *********************************************************************************************************
  1072. *        函 数 名: _DMA_AlphaBlending
  1073. *        功能说明: 前景层和背景层混合输出
  1074. *        形    参: pColorFG    前景层颜色数据地址
  1075. *             pColorBG    背景层颜色数据地址
  1076. *             pColorDst   输出目标区地址
  1077. *             NumItems    转换次数
  1078. *        返 回 值: 无
  1079. *********************************************************************************************************
  1080. */
  1081. static void _DMA_AlphaBlending(LCD_COLOR * pColorFG, LCD_COLOR * pColorBG, LCD_COLOR * pColorDst, U32 NumItems)
  1082. {
  1083. #if (GUI_USE_ARGB)
  1084.     /* DMA2D配置 */   
  1085.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1086.         DMA2D->FGMAR   = (U32)pColorFG;
  1087.         DMA2D->BGMAR   = (U32)pColorBG;
  1088.         DMA2D->OMAR    = (U32)pColorDst;
  1089.         DMA2D->FGOR    = 0;
  1090.         DMA2D->BGOR    = 0;
  1091.         DMA2D->OOR     = 0;
  1092.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1093.         DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1094.         DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;
  1095.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1096.         /* 启动传输 */
  1097.         DMA2D->CR   |= DMA2D_CR_START;   

  1098.         /* 等待DMA2D传输完成 */
  1099.         while (DMA2D->CR & DMA2D_CR_START) {}
  1100. #else
  1101.     /* DMA2D配置 */   
  1102.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1103.         DMA2D->FGMAR   = (U32)pColorFG;
  1104.         DMA2D->BGMAR   = (U32)pColorBG;
  1105.         DMA2D->OMAR    = (U32)pColorDst;
  1106.         DMA2D->FGOR    = 0;
  1107.         DMA2D->BGOR    = 0;
  1108.         DMA2D->OOR     = 0;
  1109.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1110.                      | (DMA2D_INVERTED_ALPHA << 20) ;
  1111.         DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1112.                      | (DMA2D_INVERTED_ALPHA << 20) ;
  1113.         DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888
  1114.                      | (DMA2D_INVERTED_ALPHA << 20) ;
  1115.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1116.         /* 启动传输 */
  1117.         DMA2D->CR   |= DMA2D_CR_START;   

  1118.         /* 等待DMA2D传输完成 */
  1119.         while (DMA2D->CR & DMA2D_CR_START) {}
  1120. #endif
  1121. }

  1122. /*
  1123. *********************************************************************************************************
  1124. *        函 数 名: _DMA_Index2ColorBulk
  1125. *        功能说明: 通过DMA2D,将当前显示屏的颜色数据转换为emWin的32位ARGB颜色数据。
  1126. *        形    参: pIndex       显示屏颜色地址
  1127. *             pColor       转换成适用于emWin的颜色地址
  1128. *             NumItems     转换的颜色数量
  1129. *             SizeOfIndex  未使用
  1130. *             PixelFormat  显示屏当前使用的颜色格式
  1131. *        返 回 值: 无
  1132. *********************************************************************************************************
  1133. */
  1134. static void _DMA_Index2ColorBulk(void * pIndex, LCD_COLOR * pColor, U32 NumItems, U8 SizeOfIndex, U32 PixelFormat)
  1135. {
  1136. #if (GUI_USE_ARGB)
  1137.     uint32_t blkCnt;
  1138.     uint32_t *ptr1 = (uint32_t *)pColor;
  1139.     uint32_t *ptr2 = (uint32_t *)_pBuffer_DMA2D;
  1140.    
  1141.     /* 配置DMA2D */
  1142.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  1143.         DMA2D->FGMAR   = (U32)pIndex;
  1144.         DMA2D->OMAR    = (U32)_pBuffer_DMA2D;
  1145.         DMA2D->FGOR    = 0;
  1146.         DMA2D->OOR     = 0;
  1147.         DMA2D->FGPFCCR = PixelFormat;
  1148.                                            
  1149.     DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;   
  1150.                                              
  1151.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1152.         /* 启动传输 */
  1153.         DMA2D->CR   |= DMA2D_CR_START;

  1154.         /* 等待DMA2D传输完成 */
  1155.         while (DMA2D->CR & DMA2D_CR_START) {}
  1156.    
  1157.     /* 将数据从_pBuffer_DMA2D复制到pColor */
  1158.     blkCnt = NumItems / 0x4U;
  1159.         
  1160.     while (blkCnt > 0U)
  1161.         {
  1162.         *ptr1++ = *ptr2++;
  1163.         *ptr1++ = *ptr2++;
  1164.         *ptr1++ = *ptr2++;
  1165.         *ptr1++ = *ptr2++;
  1166.                 blkCnt--;
  1167.         }
  1168.    
  1169.     blkCnt = NumItems % 0x4U;
  1170.    
  1171.     while (blkCnt > 0U)
  1172.     {
  1173.         *ptr1++ = *ptr2++;
  1174.         blkCnt--;
  1175.     }     
  1176. #else
  1177.     uint32_t blkCnt;
  1178.     uint32_t *ptr1 = (uint32_t *)pColor;
  1179.     uint32_t *ptr2 = (uint32_t *)_pBuffer_DMA2D;
  1180.    
  1181.     /* 配置DMA2D */
  1182.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  1183.         DMA2D->FGMAR   = (U32)pIndex;
  1184.         DMA2D->OMAR    = (U32)_pBuffer_DMA2D;
  1185.         DMA2D->FGOR    = 0;
  1186.         DMA2D->OOR     = 0;
  1187.         DMA2D->FGPFCCR = PixelFormat;
  1188.                                            
  1189.     DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888
  1190.                      | (DMA2D_INVERTED_ALPHA << 20)
  1191.                                          | (DMA2D_RB_SWAP << 21);   
  1192.                                              
  1193.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1194.         /* 启动传输 */
  1195.         DMA2D->CR   |= DMA2D_CR_START;

  1196.         /* 等待DMA2D传输完成 */
  1197.         while (DMA2D->CR & DMA2D_CR_START) {}
  1198.    
  1199.     /* 将数据从_pBuffer_DMA2D复制到pColor */
  1200.     blkCnt = NumItems / 0x4U;
  1201.         
  1202.     while (blkCnt > 0U)
  1203.         {
  1204.         *ptr1++ = *ptr2++;
  1205.         *ptr1++ = *ptr2++;
  1206.         *ptr1++ = *ptr2++;
  1207.         *ptr1++ = *ptr2++;
  1208.                 blkCnt--;
  1209.         }
  1210.    
  1211.     blkCnt = NumItems % 0x4U;
  1212.    
  1213.     while (blkCnt > 0U)
  1214.     {
  1215.         *ptr1++ = *ptr2++;
  1216.         blkCnt--;
  1217.     }   
  1218. #endif
  1219. }

  1220. /*
  1221. *********************************************************************************************************
  1222. *        函 数 名: _DMA_Color2IndexBulk
  1223. *        功能说明: 通过DMA2D,将emWin的32位ARGB颜色数据转换为适用于当前显示屏的颜色数据
  1224. *        形    参: pIndex       显示屏颜色地址
  1225. *             pColor       转换成适用于emWin的颜色地址
  1226. *             NumItems     转换的颜色数量
  1227. *             SizeOfIndex  未使用
  1228. *             PixelFormat  显示屏当前使用的颜色格式
  1229. *        返 回 值: 无
  1230. *********************************************************************************************************
  1231. */
  1232. static void _DMA_Color2IndexBulk(LCD_COLOR * pColor, void * pIndex, U32 NumItems, U8 SizeOfIndex, U32 PixelFormat)
  1233. {
  1234. #if (GUI_USE_ARGB)   
  1235.     /* 配置DMA2D */
  1236.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  1237.         DMA2D->FGMAR   = (U32)pColor;
  1238.         DMA2D->OMAR    = (U32)pIndex;
  1239.         DMA2D->FGOR    = 0;
  1240.         DMA2D->OOR     = 0;
  1241.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1242.         DMA2D->OPFCCR  = PixelFormat;
  1243.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1244.         /* 启动传输 */
  1245.         DMA2D->CR   |= DMA2D_CR_START;   

  1246.         /* 等待DMA2D传输完成 */
  1247.         while (DMA2D->CR & DMA2D_CR_START) {}
  1248. #else
  1249.   /* 配置DMA2D */
  1250.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  1251.         DMA2D->FGMAR   = (U32)pColor;
  1252.         DMA2D->OMAR    = (U32)pIndex;
  1253.         DMA2D->FGOR    = 0;
  1254.         DMA2D->OOR     = 0;
  1255.    
  1256.         DMA2D->FGPFCCR =  LTDC_PIXEL_FORMAT_ARGB8888
  1257.                                          | (DMA2D_INVERTED_ALPHA << 20)
  1258.                                          | (DMA2D_RB_SWAP << 21);
  1259.                       
  1260.     DMA2D->OPFCCR  = PixelFormat;
  1261.                      
  1262.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1263.         /* 启动传输 */
  1264.         DMA2D->CR   |= DMA2D_CR_START;   

  1265.         /* 等待DMA2D传输完成 */
  1266.         while (DMA2D->CR & DMA2D_CR_START) {}   
  1267. #endif
  1268. }

  1269. /*
  1270. *********************************************************************************************************
  1271. *        函 数 名: _DMA_MixColorsBulk
  1272. *        功能说明: 将一块显示区的前景色和背景色进行混合
  1273. *        形    参: pFG   前景色地址
  1274. *             pBG   背景色地址
  1275. *             pDst  混合后颜色存储的地址
  1276. *             OffFG    前景色偏移地址
  1277. *             OffBG    背景色偏移地址
  1278. *             OffDest  混合后偏移地址
  1279. *             xSize    显示区x轴大小
  1280. *             ySize    显示区y轴大小
  1281. *             Intens   即alpha值
  1282. *        返 回 值: 无
  1283. *********************************************************************************************************
  1284. */
  1285. static void _LCD_MixColorsBulk(U32 * pFG, U32 * pBG, U32 * pDst, unsigned OffFG, unsigned OffBG, unsigned OffDest, unsigned xSize, unsigned ySize, U8 Intens)
  1286. {
  1287. #if (GUI_USE_ARGB)  
  1288.         int y;

  1289.         GUI_USE_PARA(OffFG);
  1290.         GUI_USE_PARA(OffDest);

  1291.         for (y = 0; y < ySize; y++)
  1292.         {
  1293.         /* 配置DMA2D */
  1294.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1295.         DMA2D->FGMAR   = (U32)pFG;
  1296.         DMA2D->BGMAR   = (U32)pBG;
  1297.         DMA2D->OMAR    = (U32)pDst;
  1298.    
  1299.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1300.                      | (1UL << 16)
  1301.                      | ((U32)Intens << 24);
  1302.         DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1303.                      | (0UL << 16)
  1304.                      | ((U32)(255 - Intens) << 24);
  1305.         DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;
  1306.         DMA2D->NLR     = (U32)(xSize << 16) | 1;

  1307.         /* 启动传输 */
  1308.         DMA2D->CR   |= DMA2D_CR_START;   

  1309.         /* 等待DMA2D传输完成 */
  1310.         while (DMA2D->CR & DMA2D_CR_START) {}
  1311.         
  1312.                 pFG  += xSize + OffFG;
  1313.                 pBG  += xSize + OffBG;
  1314.                 pDst += xSize + OffDest;
  1315.         }
  1316. #else
  1317.         int y;

  1318.         GUI_USE_PARA(OffFG);
  1319.         GUI_USE_PARA(OffDest);

  1320.         for (y = 0; y < ySize; y++)
  1321.         {
  1322.         /* 配置DMA2D */
  1323.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1324.         DMA2D->FGMAR   = (U32)pFG;
  1325.         DMA2D->BGMAR   = (U32)pBG;
  1326.         DMA2D->OMAR    = (U32)pDst;
  1327.         
  1328.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1329.                       | (DMA2D_INVERTED_ALPHA << 20)
  1330.                       | (1UL << 16)
  1331.                       | ((U32)Intens << 24);
  1332.         
  1333.         DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1334.                      | (DMA2D_INVERTED_ALPHA << 20)
  1335.                      | (0UL << 16)
  1336.                      | ((U32)(255 - Intens) << 24);
  1337.         
  1338.         DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888
  1339.                      | (DMA2D_INVERTED_ALPHA << 20);
  1340.         
  1341.         DMA2D->NLR  = (U32)(xSize << 16) | 1;

  1342.         /* 启动传输 */
  1343.         DMA2D->CR   |= DMA2D_CR_START;   

  1344.         /* 等待DMA2D传输完成 */
  1345.         while (DMA2D->CR & DMA2D_CR_START) {}

  1346.                 pFG  += xSize + OffFG;
  1347.                 pBG  += xSize + OffBG;
  1348.                 pDst += xSize + OffDest;
  1349.         }
  1350.    
  1351. #endif
  1352. }

  1353. /*
  1354. *********************************************************************************************************
  1355. *        函 数 名: _GetBufferSize
  1356. *        功能说明: 获取指定层显存大小
  1357. *        形    参: LayerIndex    图层
  1358. *        返 回 值: 显存大小
  1359. *********************************************************************************************************
  1360. */
  1361. static U32 _GetBufferSize(int LayerIndex)
  1362. {
  1363.         U32 BufferSize;

  1364.         BufferSize = _axSize[LayerIndex] * _aySize[LayerIndex] * _aBytesPerPixels[LayerIndex];

  1365.         return BufferSize;
  1366. }

  1367. /*
  1368. *********************************************************************************************************
  1369. *        函 数 名: _LCD_CopyBuffer
  1370. *        功能说明: 此函数用于多缓冲,将一个缓冲中的所有数据复制到另一个缓冲。
  1371. *        形    参: LayerIndex    图层
  1372. *             IndexSrc      源缓冲序号
  1373. *             IndexDst      目标缓冲序号
  1374. *        返 回 值: 无
  1375. *********************************************************************************************************
  1376. */
  1377. static void _LCD_CopyBuffer(int LayerIndex, int IndexSrc, int IndexDst)
  1378. {
  1379.         U32 BufferSize, AddrSrc, AddrDst;

  1380.         BufferSize = _GetBufferSize(LayerIndex);
  1381.         AddrSrc    = _aAddr[LayerIndex] + BufferSize * IndexSrc;
  1382.         AddrDst    = _aAddr[LayerIndex] + BufferSize * IndexDst;
  1383.         _DMA_Copy(LayerIndex, (void *)AddrSrc, (void *)AddrDst, _axSize[LayerIndex], _aySize[LayerIndex], 0, 0);
  1384.        
  1385.         /* 绘制操作切换到缓冲Buffer[IndexDst] */
  1386.         _aBufferIndex[LayerIndex] = IndexDst;
  1387. }

  1388. /*
  1389. *********************************************************************************************************
  1390. *        函 数 名: _LCD_CopyRect
  1391. *        功能说明: 此函数用于多缓冲,将一个缓冲中指定区域数据复制到另一个缓冲。
  1392. *        形    参: LayerIndex    图层
  1393. *             x0            源缓冲x轴位置
  1394. *             y0            源缓冲y轴位置
  1395. *             x1            目标冲x轴位置
  1396. *             y1            目标冲y轴位置
  1397. *             xSize         要复制的x轴大小
  1398. *             ySize         要复制的y轴大小
  1399. *        返 回 值: 无
  1400. *********************************************************************************************************
  1401. */
  1402. static void _LCD_CopyRect(int LayerIndex, int x0, int y0, int x1, int y1, int xSize, int ySize)
  1403. {
  1404.         U32 BufferSize, AddrSrc, AddrDst;
  1405.         int OffLine;

  1406.         BufferSize = _GetBufferSize(LayerIndex);
  1407.         AddrSrc = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y0 * _axSize[LayerIndex] + x0) * _aBytesPerPixels[LayerIndex];
  1408.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y1 * _axSize[LayerIndex] + x1) * _aBytesPerPixels[LayerIndex];
  1409.         OffLine = _axSize[LayerIndex] - xSize;
  1410.         _DMA_Copy(LayerIndex, (void *)AddrSrc, (void *)AddrDst, xSize, ySize, OffLine, OffLine);
  1411. }

  1412. /*
  1413. *********************************************************************************************************
  1414. *        函 数 名: _LCD_FillRect
  1415. *        功能说明: 对指定的区域进行颜色填充
  1416. *        形    参: LayerIndex    图层
  1417. *             x0            起始x轴位置
  1418. *             y0            起始y轴位置
  1419. *             x1            结束x轴位置
  1420. *             y1            结束y轴位置
  1421. *             PixelIndex    要填充的颜色值
  1422. *        返 回 值: 无
  1423. *********************************************************************************************************
  1424. */
  1425. static void _LCD_FillRect(int LayerIndex, int x0, int y0, int x1, int y1, U32 PixelIndex)
  1426. {
  1427.         U32 BufferSize, AddrDst;
  1428.         int xSize, ySize;

  1429.         if (GUI_GetDrawMode() == GUI_DM_XOR)
  1430.         {
  1431.                 LCD_SetDevFunc(LayerIndex, LCD_DEVFUNC_FILLRECT, NULL);
  1432.                 LCD_FillRect(x0, y0, x1, y1);
  1433.                 LCD_SetDevFunc(LayerIndex, LCD_DEVFUNC_FILLRECT, (void(*)(void))_LCD_FillRect);
  1434.         }
  1435.         else
  1436.         {
  1437.                 xSize = x1 - x0 + 1;
  1438.                 ySize = y1 - y0 + 1;
  1439.                 BufferSize = _GetBufferSize(LayerIndex);
  1440.                 AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y0 * _axSize[LayerIndex] + x0) * _aBytesPerPixels[LayerIndex];
  1441.                 _DMA_Fill(LayerIndex, (void *)AddrDst, xSize, ySize, _axSize[LayerIndex] - xSize, PixelIndex);
  1442.         }
  1443. }

  1444. /*
  1445. *********************************************************************************************************
  1446. *        函 数 名: _LCD_DrawBitmap32bpp
  1447. *        功能说明: 绘制32bpp格式位图
  1448. *        形    参: LayerIndex      图层   
  1449. *             x               X轴起始位置
  1450. *             y               Y轴起始位置
  1451. *             p               源数据地址
  1452. *             xSize           位图长
  1453. *             ySize           位图高
  1454. *             BytesPerLine    每行字节数
  1455. *        返 回 值: 无
  1456. *********************************************************************************************************
  1457. */
  1458. static void _LCD_DrawBitmap32bpp(int LayerIndex, int x, int y, U16 const * p, int xSize, int ySize, int BytesPerLine)
  1459. {
  1460.         U32 BufferSize, AddrDst;
  1461.         int OffLineSrc, OffLineDst;

  1462.         BufferSize = _GetBufferSize(LayerIndex);
  1463.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1464.         OffLineSrc = (BytesPerLine / 4) - xSize;
  1465.         OffLineDst = _axSize[LayerIndex] - xSize;
  1466.         _DMA_Copy(LayerIndex, (void *)p, (void *)AddrDst, xSize, ySize, OffLineSrc, OffLineDst);
  1467. }

  1468. /*
  1469. *********************************************************************************************************
  1470. *        函 数 名: _LCD_DrawBitmap16bpp
  1471. *        功能说明: 绘制16bpp格式位图
  1472. *        形    参: LayerIndex      图层   
  1473. *             x               X轴起始位置
  1474. *             y               Y轴起始位置
  1475. *             p               源数据地址
  1476. *             xSize           位图长
  1477. *             ySize           位图高
  1478. *             BytesPerLine    每行字节数
  1479. *        返 回 值: 无
  1480. *********************************************************************************************************
  1481. */
  1482. void _LCD_DrawBitmap16bpp(int LayerIndex, int x, int y, U16 const * p, int xSize, int ySize, int BytesPerLine)
  1483. {
  1484.         U32 BufferSize, AddrDst;
  1485.         int OffLineSrc, OffLineDst;

  1486.         BufferSize = _GetBufferSize(LayerIndex);
  1487.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1488.         OffLineSrc = (BytesPerLine / 2) - xSize;
  1489.         OffLineDst = _axSize[LayerIndex] - xSize;
  1490.         _DMA_Copy(LayerIndex, (void *)p, (void *)AddrDst, xSize, ySize, OffLineSrc, OffLineDst);
  1491. }

  1492. /*
  1493. *********************************************************************************************************
  1494. *        函 数 名: _LCD_DrawBitmap8bpp
  1495. *        功能说明: 绘制8bpp格式位图
  1496. *        形    参: LayerIndex      图层   
  1497. *             x               X轴起始位置
  1498. *             y               Y轴起始位置
  1499. *             p               源数据地址
  1500. *             xSize           位图长
  1501. *             ySize           位图高
  1502. *             BytesPerLine    每行字节数
  1503. *        返 回 值: 无
  1504. *********************************************************************************************************
  1505. */
  1506. #if UsedDrawBitmap8bpp
  1507. static void _LCD_DrawBitmap8bpp(int LayerIndex, int x, int y, U8 const * p, int xSize, int ySize, int BytesPerLine) {
  1508.         U32 BufferSize, AddrDst;
  1509.         int OffLineSrc, OffLineDst;
  1510.         U32 PixelFormat;

  1511.         PixelFormat = _GetPixelformat(LayerIndex);
  1512.         BufferSize = _GetBufferSize(LayerIndex);
  1513.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1514.         OffLineSrc = BytesPerLine - xSize;
  1515.         OffLineDst = _axSize[LayerIndex] - xSize;
  1516.         _DMA_DrawBitmapL8((void *)p, (void *)AddrDst, OffLineSrc, OffLineDst, PixelFormat, xSize, ySize);
  1517. }
  1518. #endif

  1519. #if DrawBitmapA4Enalbe == 1
  1520. /*
  1521. *********************************************************************************************************
  1522. *        函 数 名: _LCD_DrawBitmap4bpp
  1523. *        功能说明: 绘制4bpp格式位图
  1524. *        形    参: LayerIndex      图层   
  1525. *             x               X轴起始位置
  1526. *             y               Y轴起始位置
  1527. *             p               源数据地址
  1528. *             xSize           位图长
  1529. *             ySize           位图高
  1530. *             BytesPerLine    每行字节数
  1531. *        返 回 值: 无
  1532. *********************************************************************************************************
  1533. */
  1534. static int _LCD_DrawBitmap4bpp(int LayerIndex, int x, int y, U8 const * p, int xSize, int ySize, int BytesPerLine) {
  1535.         U32 BufferSize, AddrDst;
  1536.         int OffLineSrc, OffLineDst;
  1537.         U32 PixelFormat;

  1538.         if (x < 0)
  1539.         {
  1540.                 return 1;
  1541.         }
  1542.        
  1543.         if ((x + xSize) >= _axSize[LayerIndex])
  1544.         {
  1545.                 return 1;
  1546.         }
  1547.        
  1548.         if (y < 0)
  1549.         {
  1550.                 return 1;
  1551.         }
  1552.        
  1553.         if ((y + ySize) >= _aySize[LayerIndex])
  1554.         {
  1555.                 return 1;
  1556.         }
  1557.        
  1558.         PixelFormat = _GetPixelformat(LayerIndex);

  1559.         if (PixelFormat > LTDC_PIXEL_FORMAT_ARGB4444)
  1560.         {
  1561.                 return 1;
  1562.         }
  1563.        
  1564.         BufferSize = _GetBufferSize(LayerIndex);
  1565.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1566.         OffLineSrc = (BytesPerLine * 2) - xSize;
  1567.         OffLineDst = _axSize[LayerIndex] - xSize;
  1568.         return _DMA_DrawBitmapA4((void *)p, (void *)AddrDst, OffLineSrc, OffLineDst, PixelFormat, xSize, ySize);;
  1569. }
  1570. #endif

  1571. /*
  1572. *********************************************************************************************************
  1573. *        函 数 名: _LCD_DrawMemdev16bpp
  1574. *        功能说明: 绘制16bpp存储设备
  1575. *        形    参: pDst               源数据地址   
  1576. *             pSrc               目的数据地址
  1577. *             xSize              存储设备长
  1578. *             ySize              存储设备高
  1579. *             BytesPerLineDst    源数据每行字节数
  1580. *             BytesPerLineSrc    目的数据每行字节数
  1581. *        返 回 值: 无
  1582. *********************************************************************************************************
  1583. */
  1584. #if GUI_USE_ARGB
  1585. static void _LCD_DrawMemdev16bpp(void * pDst, const void * pSrc, int xSize, int ySize, int BytesPerLineDst, int BytesPerLineSrc)
  1586. {
  1587.         int OffLineSrc, OffLineDst;

  1588.         OffLineSrc = (BytesPerLineSrc / 2) - xSize;
  1589.         OffLineDst = (BytesPerLineDst / 2) - xSize;
  1590.         _DMA_CopyRGB565(pSrc, pDst, xSize, ySize, OffLineSrc, OffLineDst);
  1591. }
  1592. #endif

  1593. /*
  1594. *********************************************************************************************************
  1595. *        函 数 名: _LCD_DrawMemdevAlpha
  1596. *        功能说明: 绘制带Alpha通道的存储设备
  1597. *        形    参: pDst               源数据地址   
  1598. *             pSrc               目的数据地址
  1599. *             xSize              存储设备长
  1600. *             ySize              存储设备高
  1601. *             BytesPerLineDst    源数据每行字节数
  1602. *             BytesPerLineSrc    目的数据每行字节数
  1603. *        返 回 值: 无
  1604. *********************************************************************************************************
  1605. */
  1606. #if  DrawAlpha == 1  
  1607. static void _LCD_DrawMemdevAlpha(void * pDst, const void * pSrc, int xSize, int ySize, int BytesPerLineDst, int BytesPerLineSrc)
  1608. {
  1609.         int OffLineSrc, OffLineDst;

  1610.         OffLineSrc = (BytesPerLineSrc / 4) - xSize;
  1611.         OffLineDst = (BytesPerLineDst / 4) - xSize;
  1612.         _DMA_DrawAlphaBitmap(pDst, pSrc, xSize, ySize, OffLineSrc, OffLineDst, LTDC_PIXEL_FORMAT_ARGB8888);
  1613. }
  1614. #endif

  1615. /*
  1616. *********************************************************************************************************
  1617. *        函 数 名: _LCD_DrawBitmapAlpha
  1618. *        功能说明: 绘制带Alpha通道的位图
  1619. *        形    参: LayerIndex      图层   
  1620. *             x               X轴起始位置
  1621. *             y               Y轴起始位置
  1622. *             p               源数据地址
  1623. *             xSize           位图长
  1624. *             ySize           位图高
  1625. *             BytesPerLine    每行字节数
  1626. *        返 回 值: 无
  1627. *********************************************************************************************************
  1628. */
  1629. #if  DrawAlpha == 1  
  1630. static void _LCD_DrawBitmapAlpha(int LayerIndex, int x, int y, const void * p, int xSize, int ySize, int BytesPerLine)
  1631. {
  1632.         U32 BufferSize, AddrDst;
  1633.         int OffLineSrc, OffLineDst;
  1634.         U32 PixelFormat;

  1635.         PixelFormat = _GetPixelformat(LayerIndex);
  1636.         BufferSize = _GetBufferSize(LayerIndex);
  1637.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1638.         OffLineSrc = (BytesPerLine / 4) - xSize;
  1639.         OffLineDst = _axSize[LayerIndex] - xSize;
  1640.         _DMA_DrawAlphaBitmap((void *)AddrDst, p, xSize, ySize, OffLineSrc, OffLineDst, PixelFormat);
  1641. }
  1642. #endif

  1643. /*
  1644. *********************************************************************************************************
  1645. *        函 数 名: _LCD_GetpPalConvTable
  1646. *        功能说明: 转换颜色板以适应控制器设置的颜色格式。
  1647. *        形    参: pLogPal   源颜色板地址
  1648. *             pBitmap   位图地址
  1649. *             LayerIndex  源颜色格式
  1650. *        返 回 值: 转换后的颜色板地址
  1651. *********************************************************************************************************
  1652. */
  1653. static void _InvertAlpha_SwapRB(LCD_COLOR * pColorSrc, LCD_COLOR * pColorDst, U32 NumItems) {
  1654.   U32 Color;
  1655.   do {
  1656.     Color = *pColorSrc++;
  1657.     *pColorDst++ = ((Color & 0x000000FF) << 16)         // Swap red <-> blue
  1658.                  |  (Color & 0x0000FF00)                // Green
  1659.                  | ((Color & 0x00FF0000) >> 16)         // Swap red <-> blue
  1660.                  | ((Color & 0xFF000000) ^ 0xFF000000); // Invert alpha
  1661.   } while (--NumItems);
  1662. }
  1663. static LCD_PIXELINDEX * _LCD_GetpPalConvTable(const LCD_LOGPALETTE GUI_UNI_PTR * pLogPal, const GUI_BITMAP GUI_UNI_PTR * pBitmap, int LayerIndex)
  1664. {
  1665. #if (GUI_USE_ARGB)
  1666.         void (* pFunc)(void);
  1667.         int DoDefault = 0;

  1668.         /* 8bpp */
  1669.         if (pBitmap->BitsPerPixel == 8)
  1670.         {
  1671.                 pFunc = LCD_GetDevFunc(LayerIndex, LCD_DEVFUNC_DRAWBMP_8BPP);
  1672.                 if (pFunc)
  1673.                 {
  1674.                         if (pBitmap->pPal)
  1675.                         {
  1676.                                 if (pBitmap->pPal->HasTrans)
  1677.                                 {
  1678.                                         DoDefault = 1;
  1679.                                 }
  1680.                         }
  1681.                         else
  1682.                         {
  1683.                                 DoDefault = 1;
  1684.                         }
  1685.                 }
  1686.                 else
  1687.                 {
  1688.                         DoDefault = 1;
  1689.                 }
  1690.         }
  1691.         else
  1692.         {
  1693.         DoDefault = 1;
  1694.         }

  1695.         /* 默认颜色板管理 */
  1696.         if (DoDefault)
  1697.         {
  1698.                 /* 返回索引值 */
  1699.                 return LCD_GetpPalConvTable(pLogPal);
  1700.         }

  1701.         /* DMA2D加载LUT */
  1702.         _DMA_LoadLUT((U32 *)pLogPal->pPalEntries, pLogPal->NumEntries);

  1703.         /* 返回非NULL */
  1704.         return _pBuffer_DMA2D;
  1705. #else
  1706.         void (* pFunc)(void);
  1707.         int DoDefault = 0;

  1708.         /* 8bpp */
  1709.         if (pBitmap->BitsPerPixel == 8)
  1710.         {
  1711.                 pFunc = LCD_GetDevFunc(LayerIndex, LCD_DEVFUNC_DRAWBMP_8BPP);
  1712.                 if (pFunc)
  1713.                 {
  1714.                         if (pBitmap->pPal)
  1715.                         {
  1716.                                 if (pBitmap->pPal->HasTrans)
  1717.                                 {
  1718.                                         DoDefault = 1;
  1719.                                 }
  1720.                         }
  1721.                         else
  1722.                         {
  1723.                                 DoDefault = 1;
  1724.                         }
  1725.                 }
  1726.                 else
  1727.                 {
  1728.                         DoDefault = 1;
  1729.                 }
  1730.         }
  1731.         else
  1732.         {
  1733.         DoDefault = 1;
  1734.         }

  1735.         /* 默认颜色板管理 */
  1736.         if (DoDefault)
  1737.         {
  1738.                 /* 返回索引值 */
  1739.                 return LCD_GetpPalConvTable(pLogPal);
  1740.         }
  1741.    
  1742.     _InvertAlpha_SwapRB((U32 *)pLogPal->pPalEntries, _pBuffer_DMA2D, pLogPal->NumEntries);

  1743.         /* DMA2D加载LUT */
  1744.         _DMA_LoadLUT((U32 *)pLogPal->pPalEntries, pLogPal->NumEntries);

  1745.         /* 返回非NULL */
  1746.         return _pBuffer_DMA2D;

  1747. #endif
  1748. }

  1749. /*
  1750. *********************************************************************************************************
  1751. *        函 数 名: LCD_X_DisplayDriver
  1752. *        功能说明: 显示驱动设置
  1753. *        形    参: LayerIndex   图层
  1754. *             Cmd          命令
  1755. *             pData        数据地址
  1756. *        返 回 值: 成功返回0,失败返回-1
  1757. *********************************************************************************************************
  1758. */
  1759. int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData)
  1760. {
  1761.         int r = 0;
  1762.         U32 addr;

  1763.         switch (Cmd)
  1764.         {
  1765.                 case LCD_X_INITCONTROLLER:
  1766.                 {
  1767.                         /* 驱动初始化 */
  1768.                         LCD_LL_LayerInit(LayerIndex);
  1769.                         break;
  1770.                 }
  1771.                
  1772.                 case LCD_X_SETORG:
  1773.                 {
  1774.                         /* 设置显存地址 */
  1775.                         LCD_X_SETORG_INFO * p;

  1776.                         p = (LCD_X_SETORG_INFO *)pData;
  1777.                         addr = _aAddr[LayerIndex] + p->yPos * _axSize[LayerIndex] * _aBytesPerPixels[LayerIndex];
  1778.                         HAL_LTDC_SetAddress(&hltdc, addr, LayerIndex);
  1779.                         break;
  1780.                 }
  1781.                
  1782.                 case LCD_X_SHOWBUFFER:
  1783.                 {
  1784.                         /* 用于多缓冲,参数Index用于指示使用的那个缓冲 */
  1785.                         LCD_X_SHOWBUFFER_INFO * p;

  1786.                         p = (LCD_X_SHOWBUFFER_INFO *)pData;
  1787.                         _aPendingBuffer[LayerIndex] = p->Index;
  1788.                         break;
  1789.                 }
  1790.                
  1791.                 case LCD_X_SETLUTENTRY:
  1792.                 {
  1793.                         /* 颜色查找表设置 */
  1794.                         LCD_X_SETLUTENTRY_INFO * p;

  1795.                         p = (LCD_X_SETLUTENTRY_INFO *)pData;
  1796.                         HAL_LTDC_ConfigCLUT(&hltdc, (uint32_t*)p->Color, p->Pos, LayerIndex);
  1797.                         break;
  1798.                 }
  1799.                
  1800.                 case LCD_X_ON:
  1801.                 {
  1802.                         /* 使能LTDC  */
  1803.                         __HAL_LTDC_ENABLE(&hltdc);
  1804.                         break;
  1805.                 }
  1806.                
  1807.                 case LCD_X_OFF:
  1808.                 {
  1809.                         /* 关闭LTDC */
  1810.                         __HAL_LTDC_DISABLE(&hltdc);
  1811.                         break;
  1812.                 }
  1813.                
  1814.                 case LCD_X_SETVIS:
  1815.                 {
  1816.                         /* 图层的开关 */
  1817.                         LCD_X_SETVIS_INFO * p;

  1818.                         p = (LCD_X_SETVIS_INFO *)pData;
  1819.                         if(p->OnOff == ENABLE )
  1820.                         {
  1821.                                 __HAL_LTDC_LAYER_ENABLE(&hltdc, LayerIndex);
  1822.                         }
  1823.                         else
  1824.                         {
  1825.                                 __HAL_LTDC_LAYER_DISABLE(&hltdc, LayerIndex);
  1826.                         }
  1827.                        
  1828.                         __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc);
  1829.                         break;
  1830.                 }
  1831.                
  1832.                 case LCD_X_SETPOS:
  1833.                 {
  1834.                         /* 设置图层显示位置 */
  1835.                         LCD_X_SETPOS_INFO * p;

  1836.                         p = (LCD_X_SETPOS_INFO *)pData;   
  1837.                         HAL_LTDC_SetWindowPosition(&hltdc, p->xPos, p->yPos, LayerIndex);
  1838.                         break;
  1839.                 }
  1840.                
  1841.                 case LCD_X_SETSIZE:
  1842.                 {
  1843.                         /* 设置图层大小 */
  1844.                         LCD_X_SETSIZE_INFO * p;
  1845.                         int xPos, yPos;

  1846.                         GUI_GetLayerPosEx(LayerIndex, &xPos, &yPos);
  1847.                         p = (LCD_X_SETSIZE_INFO *)pData;
  1848.                         if (LCD_GetSwapXYEx(LayerIndex))
  1849.                         {
  1850.                                 _axSize[LayerIndex] = p->ySize;
  1851.                                 _aySize[LayerIndex] = p->xSize;
  1852.                         }
  1853.                         else
  1854.                         {
  1855.                                 _axSize[LayerIndex] = p->xSize;
  1856.                                 _aySize[LayerIndex] = p->ySize;
  1857.                         }
  1858.                        
  1859.                         HAL_LTDC_SetWindowPosition(&hltdc, xPos, yPos, LayerIndex);
  1860.                         break;
  1861.                 }
  1862.                
  1863.                 case LCD_X_SETALPHA:
  1864.                 {
  1865.                         /* 设置透明 */
  1866.                         LCD_X_SETALPHA_INFO * p;

  1867.                         p = (LCD_X_SETALPHA_INFO *)pData;
  1868.          #if (GUI_USE_ARGB)
  1869.                         HAL_LTDC_SetAlpha(&hltdc, p->Alpha, LayerIndex);
  1870.          #else
  1871.             HAL_LTDC_SetAlpha(&hltdc, 255-p->Alpha, LayerIndex);
  1872.          #endif
  1873.                         break;
  1874.                 }
  1875.                
  1876.                 case LCD_X_SETCHROMAMODE:
  1877.                 {
  1878.                         /* 使能或禁止扣色 */
  1879.                         LCD_X_SETCHROMAMODE_INFO * p;

  1880.                         p = (LCD_X_SETCHROMAMODE_INFO *)pData;
  1881.                         if(p->ChromaMode != 0)
  1882.                         {
  1883.                                 HAL_LTDC_EnableColorKeying(&hltdc, LayerIndex);
  1884.                         }
  1885.                         else
  1886.                         {
  1887.                                 HAL_LTDC_DisableColorKeying(&hltdc, LayerIndex);      
  1888.                         }
  1889.                         break;
  1890.                 }
  1891.                
  1892.                 case LCD_X_SETCHROMA:
  1893.                 {
  1894.                         /* 设置扣色 */
  1895.                         LCD_X_SETCHROMA_INFO * p;
  1896.                         U32 Color;

  1897.                         p = (LCD_X_SETCHROMA_INFO *)pData;
  1898.                         Color = ((p->ChromaMin & 0xFF0000) >> 16) | (p->ChromaMin & 0x00FF00) | ((p->ChromaMin & 0x0000FF) << 16);
  1899.                         HAL_LTDC_ConfigColorKeying(&hltdc, Color, LayerIndex);
  1900.                         break;
  1901.                 }
  1902.                
  1903.                 default:
  1904.                         r = -1;
  1905.                         break;
  1906.         }

  1907.         return r;
  1908. }

  1909. /*
  1910. *********************************************************************************************************
  1911. *        函 数 名: LCD_X_DisplayDriver
  1912. *        功能说明: 初始化配置
  1913. *        形    参: 无
  1914. *        返 回 值: 无
  1915. *********************************************************************************************************
  1916. */
  1917. void LCD_X_Config(void)
  1918. {
  1919.         int i;
  1920.         U32 PixelFormat;

  1921.         /* 底层初始化 */
  1922.         LCD_LL_Init ();

  1923. #if ClearCacheHookEnalbe == 1
  1924.         GUI_DCACHE_SetClearCacheHook(_ClearCacheHook);
  1925. #endif

  1926.         /* 初始化多缓冲 */
  1927. #if (NUM_BUFFERS > 1)
  1928.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  1929.         {
  1930.                 GUI_MULTIBUF_ConfigEx(i, NUM_BUFFERS);
  1931.         }
  1932. #endif

  1933.         /* 设置显示驱动和颜色格式转换 */
  1934.         GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER_0, COLOR_CONVERSION_0, 0, 0);

  1935.         /* 设置图层1 */
  1936.         if (LCD_GetSwapXYEx(0))
  1937.         {
  1938.                 LCD_SetSizeEx (0,  g_LcdHeight, g_LcdWidth);
  1939.                 LCD_SetVSizeEx(0,  g_LcdHeight * NUM_VSCREENS, g_LcdWidth);
  1940.         }
  1941.         else
  1942.         {
  1943.                 LCD_SetSizeEx (0, g_LcdWidth, g_LcdHeight);
  1944.                 LCD_SetVSizeEx(0, g_LcdWidth, g_LcdHeight * NUM_VSCREENS);
  1945.         }
  1946.        
  1947. #if (GUI_NUM_LAYERS > 1)
  1948.         /* 设置显示驱动和颜色格式转换 */
  1949.         GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER_1, COLOR_CONVERSION_1, 0, 1);

  1950.         /* 设置图层2 */
  1951.         if (LCD_GetSwapXYEx(1))
  1952.         {
  1953.                 LCD_SetSizeEx (1, g_LcdHeight, g_LcdWidth);
  1954.                 LCD_SetVSizeEx(1,  g_LcdHeight * NUM_VSCREENS, g_LcdWidth);
  1955.         }
  1956.         else
  1957.         {
  1958.                 LCD_SetSizeEx (1, g_LcdWidth, g_LcdHeight);
  1959.                 LCD_SetVSizeEx(1, g_LcdWidth, g_LcdHeight * NUM_VSCREENS);
  1960.         }
  1961. #endif
  1962.        
  1963.         /* 设置RAM地址和每个像素的字节数 */
  1964.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  1965.         {
  1966.                 /* 设置RAM地址 */
  1967.                 LCD_SetVRAMAddrEx(i, (void *)(_aAddr[i]));
  1968.                
  1969.                 /* 每个像素的字节数 */
  1970.                 _aBytesPerPixels[i] = LCD_GetBitsPerPixelEx(i) >> 3;
  1971.         }
  1972.        
  1973.         /* 设置函数重定向 */
  1974.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  1975.         {
  1976.                 PixelFormat = _GetPixelformat(i);
  1977.                
  1978.                 /* CopyBuffer重定向,多缓冲使用 */
  1979.                 LCD_SetDevFunc(i, LCD_DEVFUNC_COPYBUFFER, (void(*)(void))_LCD_CopyBuffer);

  1980.                 if (PixelFormat <= LTDC_PIXEL_FORMAT_ARGB4444)
  1981.                 {
  1982.                         /* 填充使用 */
  1983.                         LCD_SetDevFunc(i, LCD_DEVFUNC_FILLRECT, (void(*)(void))_LCD_FillRect);
  1984.                 }

  1985.                 if (_aOrientation[i] == ROTATION_0)
  1986.                 {
  1987.                         /* CopyRect重定向 */
  1988.                         LCD_SetDevFunc(i, LCD_DEVFUNC_COPYRECT, (void(*)(void))_LCD_CopyRect);

  1989.                         /* 8bpp重定向 */
  1990.                         if (PixelFormat <= LTDC_PIXEL_FORMAT_ARGB4444)
  1991.                         {
  1992.                 #if UsedDrawBitmap8bpp
  1993.                                  LCD_SetDevFunc(i, LCD_DEVFUNC_DRAWBMP_8BPP, (void(*)(void))_LCD_DrawBitmap8bpp);
  1994.                 #endif
  1995.                         }

  1996.                         /* 16bpp重定向 */
  1997.                         if (PixelFormat == LTDC_PIXEL_FORMAT_RGB565)
  1998.                         {
  1999.                                 LCD_SetDevFunc(i, LCD_DEVFUNC_DRAWBMP_16BPP, (void(*)(void))_LCD_DrawBitmap16bpp);
  2000.                         }

  2001.                         /* 32bpp重定向 */
  2002.                         if (PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
  2003.                         {
  2004.                                 LCD_SetDevFunc(i, LCD_DEVFUNC_DRAWBMP_32BPP, (void(*)(void))_LCD_DrawBitmap32bpp);
  2005.                         }
  2006.                 }
  2007.         }

  2008.         /* DMA2D for ARGB1555 */
  2009.         GUICC_M1555I_SetCustColorConv(_Color2IndexBulk_M1555I_DMA2D, _Index2ColorBulk_M1555I_DMA2D);

  2010.         /* DMA2D for RGB565 */  
  2011.         GUICC_M565_SetCustColorConv  (_Color2IndexBulk_M565_DMA2D,   _Index2ColorBulk_M565_DMA2D);

  2012.         /* DMA2D for ARGB4444 */
  2013.         GUICC_M4444I_SetCustColorConv(_Color2IndexBulk_M4444I_DMA2D, _Index2ColorBulk_M4444I_DMA2D);

  2014.         /* DMA2D for RGB888 */
  2015.         GUICC_M888_SetCustColorConv  (_Color2IndexBulk_M888_DMA2D,   _Index2ColorBulk_M888_DMA2D);

  2016.         /* DMA2D for ARGB8888 */
  2017.         GUICC_M8888I_SetCustColorConv(_Color2IndexBulk_M8888I_DMA2D, _Index2ColorBulk_M8888I_DMA2D);

  2018.         /* Alpha混合重定向 */
  2019.         GUI_SetFuncAlphaBlending(_DMA_AlphaBlending);

  2020.         GUI_SetFuncGetpPalConvTable(_LCD_GetpPalConvTable);

  2021.         /* 颜色混合重定向 */
  2022.         GUI_SetFuncMixColorsBulk(_LCD_MixColorsBulk);

  2023. #if DrawBitmapA4Enalbe == 1
  2024.         GUI_AA_SetpfDrawCharAA4(_LCD_DrawBitmap4bpp); /* 这个函数有问题,未使用 */
  2025. #endif

  2026.         /* 16bpp存储设备重定向 */
  2027. #if GUI_USE_ARGB == 1
  2028.         GUI_MEMDEV_SetDrawMemdev16bppFunc(_LCD_DrawMemdev16bpp);
  2029. #endif

  2030. #if  DrawAlpha == 1   
  2031.         /* Alpha绘制重定向 */
  2032.         GUI_SetFuncDrawAlpha(_LCD_DrawMemdevAlpha, _LCD_DrawBitmapAlpha);
  2033. #endif
  2034. }

  2035. #if 1
  2036. /*
  2037. *********************************************************************************************************
  2038. *        函 数 名: LTDC_IRQHandler
  2039. *        功能说明: 初始化配置
  2040. *        形    参: 无
  2041. *        返 回 值: 无
  2042. *********************************************************************************************************
  2043. */
  2044. void LTDC_IRQHandler(void)
  2045. {
  2046.         U32 Addr;
  2047.         int i;

  2048.         LTDC->ICR = (U32)LTDC_IER_LIE;
  2049.        
  2050.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  2051.         {
  2052.                 if (_aPendingBuffer[i] >= 0)
  2053.                 {
  2054.                         /* 计算缓冲地址 */
  2055.                         Addr = _aAddr[i] + _axSize[i] * _aySize[i] * _aPendingBuffer[i] * _aBytesPerPixels[i];

  2056.                         /* 更新LTDC寄存器 */          
  2057.                         __HAL_LTDC_LAYER(&hltdc, i)->CFBAR = Addr;     
  2058.                         __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc);   

  2059.                         /* 告诉emWin使用的缓冲 */
  2060.                         GUI_MULTIBUF_ConfirmEx(i, _aPendingBuffer[i]);

  2061.                         /* 清除标志 */
  2062.                         _aPendingBuffer[i] = -1;
  2063.                 }
  2064.         }
  2065. }

  2066. #else
  2067. /*
  2068. *********************************************************************************************************
  2069. *        函 数 名: LTDC_IRQHandler
  2070. *        功能说明: 初始化配置
  2071. *        形    参: 无
  2072. *        返 回 值: 无
  2073. *********************************************************************************************************
  2074. */
  2075. void LTDC_IRQHandler(void)
  2076. {
  2077.         HAL_LTDC_IRQHandler(&hltdc);
  2078. }

  2079. void HAL_LTDC_LineEvenCallback(LTDC_HandleTypeDef *hltdc)
  2080. {
  2081.         U32 Addr;
  2082.         int i;

  2083.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  2084.         {
  2085.                 if (_aPendingBuffer[i] >= 0)
  2086.                 {
  2087.                         /* 计算缓冲地址 */
  2088.                         Addr = _aAddr[i] + _axSize[i] * _aySize[i] * _aPendingBuffer[i] * _aBytesPerPixels[i];

  2089.                         /* 更新LTDC寄存器 */          
  2090.                         __HAL_LTDC_LAYER(hltdc, i)->CFBAR = Addr;     
  2091.                         __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(hltdc);   

  2092.                         /* 告诉emWin使用的缓冲 */
  2093.                         GUI_MULTIBUF_ConfirmEx(i, _aPendingBuffer[i]);

  2094.                         /* 清除标志 */
  2095.                         _aPendingBuffer[i] = -1;
  2096.                 }
  2097.         }

  2098.         /* 重新开启行中断,因为函数HAL_LTDC_IRQHandler里面会关闭 */
  2099.         HAL_LTDC_ProgramLineEvent(hltdc, 0);
  2100. }

  2101. #endif

  2102. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-20 11:06 , Processed in 0.190538 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表