硬汉嵌入式论坛

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

分享适用于STM32F429的emWin6.x的ARGB和ABGR两种库的底层驱动

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107145
QQ
发表于 2021-2-6 11:44:13 | 显示全部楼层 |阅读模式
代码:

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : emWin的底层驱动文件
  5. *        文件名称 : LCDConf_Lin_Template.c
  6. *        版    本 : V1.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. STM32F429的图层是由背景层,图层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    2021-01-03    Eric2013     适配ARGB和ABGR两种格式库
  26. *
  27. *
  28. *        Copyright (C), 2021-2030, 安富莱电子 www.armfly.com
  29. *
  30. *********************************************************************************************************
  31. */
  32. #include "bsp.h"
  33. #include "GUI.h"
  34. #include "GUI_Private.h"
  35. #include "GUIDRV_Lin.h"
  36. #include "GUIConf.h"


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

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

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

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

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

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

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

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

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

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


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

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

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


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

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


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

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

  274. #else

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  665.                                 HSYNC_W = 40;
  666.                                 HBP = 2;
  667.                                 HFP = 2;
  668.                                 VSYNC_W = 9;
  669.                                 VBP = 2;
  670.                                 VFP = 2;
  671.                
  672.                                 /* LCD 时钟配置 */
  673.                                 /*
  674.                                         PLLSAI_VCO Input = HSE_VALUE / PLL_M = 8M / 8 = 1MHz
  675.                                         PLLSAI_VCO Output  = PLLSAI_VCO Input * PLLSAI_N = 1 * 420 = 420MHz
  676.                                         PLLLCDCLK = PLLSAI_VCO Output / PLLSAI_R = 420 / 7 = 60MHz
  677.                                         LTDC 时钟 = PLLLCDCLK / RCC_PLLSAIDivR = 60 / 4 = 15MHz
  678.                                 */
  679.                                 /*
  680.                                         刷新率 = 15MHz /((Width + HSYNC_W  + HBP  + HFP)*(Height + VSYNC_W +  VBP  + VFP))
  681.                                       = 15000000/((480 + 40  + 2  + 2)*(272 + 9 +  2  + 2))
  682.                                        = 15000000/(524*285)
  683.                            = 100Hz       
  684.                                        
  685.                             */
  686.                                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  687.                                 PeriphClkInitStruct.PLLSAI.PLLSAIN = 420;
  688.                                 PeriphClkInitStruct.PLLSAI.PLLSAIR = 7;
  689.                                 PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_4;
  690.                                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  691.                                 {
  692.                                         Error_Handler(__FILE__, __LINE__);
  693.                                 }                            
  694.                                 break;
  695.                        
  696.                         case LCD_50_800X480:                /* 5.0寸 800 * 480 */
  697.                         case LCD_70_800X480:                /* 7.0寸 800 * 480 */                                       
  698.                                 Width = 800;
  699.                                 Height = 480;

  700.                                 HSYNC_W = 96;       
  701.                                 HBP = 10;
  702.                                 HFP = 10;
  703.                                 VSYNC_W = 2;
  704.                                 VBP = 10;
  705.                                 VFP = 10;                       

  706.                                 /* LCD 时钟配置 */
  707.                                 /*
  708.                                         PLLSAI_VCO Input = HSE_VALUE / PLL_M = 8M / 8 = 1MHz
  709.                                         PLLSAI_VCO Output  = PLLSAI_VCO Input * PLLSAI_N = 1 * 420 = 420MHz
  710.                                         PLLLCDCLK = PLLSAI_VCO Output / PLLSAI_R = 420 / 7 = 60MHz
  711.                                         LTDC 时钟 = PLLLCDCLK / RCC_PLLSAIDivR = 60 / 4 = 15MHz
  712.                                 */
  713.                                 /*
  714.                                         刷新率 = 15MHz /((Width + HSYNC_W  + HBP  + HFP)*(Height + VSYNC_W +  VBP  + VFP))
  715.                                       = 15000000/((800 + 96  + 10  + 10)*(480 + 2 +  10  + 10))
  716.                                        = 15000000/(916*502)
  717.                            = 32Hz       
  718.                                                   
  719.                                         24位或者32位色选择LTDC输出15MHz,16位或者8位30MHz
  720.                             */
  721.                                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  722.                                 PeriphClkInitStruct.PLLSAI.PLLSAIN = 420;
  723.                                 PeriphClkInitStruct.PLLSAI.PLLSAIR = 7;
  724.                                 PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
  725.                                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  726.                                 {
  727.                                         Error_Handler(__FILE__, __LINE__);
  728.                                 }
  729.                                 break;
  730.                        
  731.                         case LCD_70_1024X600:        /* 7.0寸 1024 * 600,未使用 */
  732.                                 Width = 1024;
  733.                                 Height = 600;

  734.                                 HSYNC_W = 2;       
  735.                                 HBP = 157;
  736.                                 HFP = 160;
  737.                                 VSYNC_W = 2;
  738.                                 VBP = 20;
  739.                                 VFP = 12;               
  740.                                                        
  741.                                 break;
  742.                        
  743.                         default:                 /* 未使用 */
  744.                                 Width = 800;
  745.                                 Height = 480;

  746.                                 HSYNC_W = 80;
  747.                                 HBP = 10;
  748.                                 HFP = 10;
  749.                                 VSYNC_W = 10;
  750.                                 VBP = 10;
  751.                                 VFP = 10;               
  752.                                
  753.                                 break;
  754.                 }               

  755.                 g_LcdHeight = Height;
  756.                 g_LcdWidth = Width;
  757.                
  758.                 /* 配置信号极性 */       
  759.                 hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;        /* HSYNC 低电平有效 */
  760.                 hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;         /* VSYNC 低电平有效 */
  761.                 hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;         /* DE 低电平有效 */
  762.                 hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

  763.                 /* 时序配置 */   
  764.                 hltdc.Init.HorizontalSync = (HSYNC_W - 1);
  765.                 hltdc.Init.VerticalSync = (VSYNC_W - 1);
  766.                 hltdc.Init.AccumulatedHBP = (HSYNC_W + HBP - 1);
  767.                 hltdc.Init.AccumulatedVBP = (VSYNC_W + VBP - 1);  
  768.                 hltdc.Init.AccumulatedActiveH = (Height + VSYNC_W + VBP - 1);
  769.                 hltdc.Init.AccumulatedActiveW = (Width + HSYNC_W + HBP - 1);
  770.                 hltdc.Init.TotalHeigh = (Height + VSYNC_W + VBP + VFP - 1);
  771.                 hltdc.Init.TotalWidth = (Width + HSYNC_W + HBP + HFP - 1);

  772.                 /* 配置背景层颜色 */
  773.                 hltdc.Init.Backcolor.Blue = 0;
  774.                 hltdc.Init.Backcolor.Green = 0;
  775.                 hltdc.Init.Backcolor.Red = 0;

  776.                 hltdc.Instance = LTDC;

  777.                 /* 配置LTDC  */  
  778.                 if (HAL_LTDC_Init(&hltdc) != HAL_OK)
  779.                 {
  780.                         /* 初始化错误 */
  781.                         Error_Handler(__FILE__, __LINE__);
  782.                 }        
  783.         }

  784.     /* 使能行中断 */
  785.         HAL_LTDC_ProgramLineEvent(&hltdc, 0);
  786.   
  787.         /* 使能LTDC中断,并配置其优先级 */
  788.         HAL_NVIC_SetPriority(LTDC_IRQn, 0x2, 0);
  789.         HAL_NVIC_EnableIRQ(LTDC_IRQn);
  790. }

  791. /*
  792. *********************************************************************************************************
  793. *        函 数 名: _DMA_Copy
  794. *        功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
  795. *        形    参: LayerIndex    图层
  796. *             pSrc          颜色数据源地址
  797. *             pDst          颜色数据目的地址
  798. *             xSize         要复制区域的X轴大小,即每行像素数
  799. *             ySize         要复制区域的Y轴大小,即行数
  800. *             OffLineSrc    前景层图像的行偏移
  801. *             OffLineDst    输出的行偏移
  802. *        返 回 值: 无
  803. *********************************************************************************************************
  804. */
  805. static void _DMA_Copy(int LayerIndex, void * pSrc, void * pDst, int xSize, int ySize, int OffLineSrc, int OffLineDst)
  806. {
  807.         U32 PixelFormat;

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

  810.         /* DMA2D配置 */  
  811.         DMA2D->CR      = 0x00000000UL | (1 << 9);
  812.         DMA2D->FGMAR   = (U32)pSrc;
  813.         DMA2D->OMAR    = (U32)pDst;
  814.         DMA2D->FGOR    = OffLineSrc;
  815.         DMA2D->OOR     = OffLineDst;
  816.         DMA2D->FGPFCCR = PixelFormat;
  817.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  818.         /* 启动传输 */
  819.         DMA2D->CR   |= DMA2D_CR_START;   

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

  823. /*
  824. *********************************************************************************************************
  825. *        函 数 名: _DMA_CopyRGB565
  826. *        功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
  827. *        形    参: pSrc          颜色数据源地址
  828. *             pDst          颜色数据目的地址
  829. *             xSize         要复制区域的X轴大小,即每行像素数
  830. *             ySize         要复制区域的Y轴大小,即行数
  831. *             OffLineSrc    前景层图像的行偏移
  832. *             OffLineDst    输出的行偏移
  833. *        返 回 值: 无
  834. *********************************************************************************************************
  835. */
  836. #if GUI_USE_ARGB
  837. static void _DMA_CopyRGB565(const void * pSrc, void * pDst, int xSize, int ySize, int OffLineSrc, int OffLineDst)
  838. {
  839.         /* DMA2D配置 */  
  840.         DMA2D->CR      = 0x00000000UL | (1 << 9);
  841.         DMA2D->FGMAR   = (U32)pSrc;
  842.         DMA2D->OMAR    = (U32)pDst;
  843.         DMA2D->FGOR    = OffLineSrc;
  844.         DMA2D->OOR     = OffLineDst;
  845.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
  846.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  847.         /* 启动传输 */
  848.         DMA2D->CR   |= DMA2D_CR_START;   

  849.         /* 等待DMA2D传输完成 */
  850.         while (DMA2D->CR & DMA2D_CR_START) {}
  851. }
  852. #endif

  853. /*
  854. *********************************************************************************************************
  855. *        函 数 名: _DMA_Fill
  856. *        功能说明: 通过DMA2D对于指定区域进行颜色填充
  857. *        形    参: LayerIndex    图层
  858. *             pDst          颜色数据目的地址
  859. *             xSize         要复制区域的X轴大小,即每行像素数
  860. *             ySize         要复制区域的Y轴大小,即行数
  861. *             OffLine       前景层图像的行偏移
  862. *             ColorIndex    要填充的颜色值
  863. *        返 回 值: 无
  864. *********************************************************************************************************
  865. */
  866. static void _DMA_Fill(int LayerIndex, void * pDst, int xSize, int ySize, int OffLine, U32 ColorIndex)
  867. {
  868.         U32 PixelFormat;

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

  871.         /* DMA2D配置 */  
  872.         DMA2D->CR      = 0x00030000UL | (1 << 9);
  873.         DMA2D->OCOLR   = ColorIndex;
  874.         DMA2D->OMAR    = (U32)pDst;
  875.         DMA2D->OOR     = OffLine;
  876.         DMA2D->OPFCCR  = PixelFormat;
  877.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  878.         /* 启动传输 */
  879.         DMA2D->CR   |= DMA2D_CR_START;   

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

  883. /*
  884. *********************************************************************************************************
  885. *        函 数 名: _DMA_DrawBitmapL8
  886. *        功能说明: 绘制L8格式位图
  887. *        形    参: pSrc             源数据地址
  888. *             pDst             目的数据地址
  889. *             OffSrc           源数据行偏移
  890. *             OffDst           目的数据行偏移
  891. *             PixelFormatDst   转换的颜色格式
  892. *             xSize            位图长
  893. *             ySize            位图高
  894. *        返 回 值: 无
  895. *********************************************************************************************************
  896. */
  897. #if UsedDrawBitmap8bpp
  898. static void _DMA_DrawBitmapL8(void * pSrc, void * pDst,  U32 OffSrc, U32 OffDst, U32 PixelFormatDst, U32 xSize, U32 ySize)
  899. {
  900.         /* 配置DMA2D */
  901.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  902.         DMA2D->FGMAR   = (U32)pSrc;
  903.         DMA2D->OMAR    = (U32)pDst;
  904.         DMA2D->FGOR    = OffSrc;
  905.         DMA2D->OOR     = OffDst;
  906.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_L8;
  907.         DMA2D->OPFCCR  = PixelFormatDst;            
  908.                         
  909.         DMA2D->NLR     = (U32)(xSize << 16) | ySize;

  910.         /* 启动传输 */
  911.         DMA2D->CR   |= DMA2D_CR_START;   

  912.         /* 等待DMA2D传输完成 */
  913.         while (DMA2D->CR & DMA2D_CR_START) {}  
  914. }
  915. #endif

  916. #if DrawBitmapA4Enalbe == 1
  917. /*
  918. *********************************************************************************************************
  919. *        函 数 名: _DMA_DrawBitmapA4
  920. *        功能说明: 绘制A4格式位图
  921. *        形    参: pSrc             源数据地址
  922. *             pDst             目的数据地址
  923. *             OffSrc           源数据行偏移
  924. *             OffDst           目的数据行偏移
  925. *             PixelFormatDst   转换的颜色格式
  926. *             xSize            位图长
  927. *             ySize            位图高
  928. *        返 回 值: 0
  929. *********************************************************************************************************
  930. */
  931. static int _DMA_DrawBitmapA4(void * pSrc, void * pDst,  U32 OffSrc, U32 OffDst, U32 PixelFormatDst, U32 xSize, U32 ySize)
  932. {
  933.     U8 * pRD;
  934.     U8 * pWR;
  935.     U32 NumBytes, Color, Index;


  936.     NumBytes = (((xSize + 1) & (U32)~1) * ySize) >> 1;
  937.     if ((NumBytes > sizeof(_aBuffer)) || (NumBytes == 0)) {
  938.     return 1;
  939.     }

  940.     pWR = (U8 *)_aBuffer;
  941.     pRD = (U8 *)pSrc;
  942.     do {
  943.     *pWR++ = _aMirror[*pRD++];
  944.     } while (--NumBytes);


  945.     Index = LCD_GetColorIndex();
  946.     Color = LCD_Index2Color(Index);


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

  948. #if (GUI_USE_ARGB == 0)
  949.     DMA2D->FGCOLR  = ((Color & 0xFF) << 16)  // Red
  950.                  |  (Color & 0xFF00)       // Green
  951.                  | ((Color >> 16) & 0xFF); // Blue
  952. #else
  953.     DMA2D->FGCOLR  = Color;
  954. #endif
  955.     DMA2D->FGMAR   = (U32)_aBuffer;
  956.     DMA2D->FGOR    = 0;
  957.     DMA2D->FGPFCCR = 0xA;                    // A4 bitmap
  958.     DMA2D->NLR     = (U32)((xSize + OffSrc) << 16) | ySize;
  959.     DMA2D->BGMAR   = (U32)pDst;
  960.     DMA2D->BGOR    = OffDst - OffSrc;
  961.     DMA2D->BGPFCCR = PixelFormatDst;
  962.     DMA2D->OMAR    = DMA2D->BGMAR;
  963.     DMA2D->OOR     = DMA2D->BGOR;
  964.     DMA2D->OPFCCR  = DMA2D->BGPFCCR;

  965.     /* 启动传输 */
  966.     DMA2D->CR   |= DMA2D_CR_START;   

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

  969.         return 0;
  970. }
  971. #endif

  972. /*
  973. *********************************************************************************************************
  974. *        函 数 名: _DMA_DrawAlphaBitmap
  975. *        功能说明: 绘制带透明通道的位图
  976. *        形    参: pSrc             源数据地址
  977. *             pDst             目的数据地址
  978. *             xSize            位图长
  979. *             ySize            位图高
  980. *             OffLineSrc       源数据行偏移
  981. *             OffLineDst       目的数据行偏移
  982. *             PixelFormatDst   转换的颜色格式
  983. *        返 回 值: 0
  984. *********************************************************************************************************
  985. */
  986. #if  DrawAlpha == 1  
  987. static void _DMA_DrawAlphaBitmap(void * pDst, const void * pSrc, int xSize, int ySize, int OffLineSrc, int OffLineDst, int PixelFormat)
  988. {
  989.         /* 配置*/
  990.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  991.         DMA2D->FGMAR   = (U32)pSrc;
  992.         DMA2D->BGMAR   = (U32)pDst;
  993.         DMA2D->OMAR    = (U32)pDst;
  994.         DMA2D->FGOR    = OffLineSrc;
  995.         DMA2D->BGOR    = OffLineDst;
  996.         DMA2D->OOR     = OffLineDst;
  997.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  998.         DMA2D->BGPFCCR = PixelFormat;
  999.         DMA2D->OPFCCR  = PixelFormat;
  1000.         DMA2D->NLR     = (U32)(xSize << 16) | (U16)ySize;

  1001.         /* 启动传输 */
  1002.         DMA2D->CR   |= DMA2D_CR_START;   

  1003.         /* 等待DMA2D传输完成 */
  1004.         while (DMA2D->CR & DMA2D_CR_START) {}
  1005. }
  1006. #endif

  1007. /*
  1008. *********************************************************************************************************
  1009. *        函 数 名: _DMA_LoadLUT
  1010. *        功能说明: 加载颜色表
  1011. *        形    参: pColor     颜色表地址
  1012. *             NumItems   要加载的个数
  1013. *        返 回 值: 0
  1014. *********************************************************************************************************
  1015. */
  1016. static void _DMA_LoadLUT(LCD_COLOR * pColor, U32 NumItems)
  1017. {
  1018.         /* 配置DMA2D */
  1019.         DMA2D->FGCMAR  = (U32)pColor;
  1020.         DMA2D->FGPFCCR  = LTDC_PIXEL_FORMAT_RGB888
  1021.                                   | ((NumItems - 1) & 0xFF) << 8;
  1022.        
  1023.         /* 启动加载 */
  1024.         DMA2D->FGPFCCR |= (1 << 5);
  1025. }

  1026. /*
  1027. *********************************************************************************************************
  1028. *        函 数 名: _InvertAlpha_SwapRB
  1029. *        功能说明: emWin的颜色格式跟DMA2D的颜色格式不同,DMA2D的颜色格式要转换为
  1030. *             emWin的颜色格式,需要以下两点:
  1031. *             1. 交换R和B的位置。
  1032. *             2. 翻转alpha通道。
  1033. *             此函数就完成这两个工作,反之亦然。
  1034. *        形    参: pColorSrc  DMA2D格式颜色地址,即原始颜色
  1035. *             pColorDst  emWin格式颜色地址,即转换后颜色
  1036. *             NumItems   要转换的颜色个数
  1037. *        返 回 值: 无
  1038. *********************************************************************************************************
  1039. */
  1040. static void _InvertAlpha_SwapRB(LCD_COLOR * pColorSrc, LCD_COLOR * pColorDst, U32 NumItems) {
  1041.   U32 Color;
  1042.   do {
  1043.     Color = *pColorSrc++;
  1044.     *pColorDst++ = ((Color & 0x000000FF) << 16)         // Swap red <-> blue
  1045.                  |  (Color & 0x0000FF00)                // Green
  1046.                  | ((Color & 0x00FF0000) >> 16)         // Swap red <-> blue
  1047.                  | ((Color & 0xFF000000) ^ 0xFF000000); // Invert alpha
  1048.   } while (--NumItems);
  1049. }

  1050. /*
  1051. *********************************************************************************************************
  1052. *        函 数 名: _InvertAlpha
  1053. *        功能说明: emWin的颜色格式跟DMA2D的颜色格式不同,DMA2D的颜色格式要转换为
  1054. *             emWin的颜色格式,需要以下两点:
  1055. *             1. 交换R和B的位置。
  1056. *             2. 翻转alpha通道。
  1057. *             此函数就完成第二工作,反之亦然。
  1058. *        形    参: pColorSrc  DMA2D格式颜色地址,即原始颜色
  1059. *             pColorDst  emWin格式颜色地址,即转换后颜色
  1060. *             NumItems   要转换的颜色个数
  1061. *        返 回 值: 无
  1062. *********************************************************************************************************
  1063. */
  1064. static void _InvertAlpha(LCD_COLOR * pColorSrc, LCD_COLOR * pColorDst, U32 NumItems) {
  1065.   U32 Color;

  1066.   do {
  1067.     Color = *pColorSrc++;
  1068.     *pColorDst++ = Color ^ 0xFF000000; // Invert alpha
  1069.   } while (--NumItems);
  1070. }

  1071. /*
  1072. *********************************************************************************************************
  1073. *        函 数 名: _DMA_AlphaBlendingBulk
  1074. *        功能说明: 实现批量的颜色混合转换,获取前景色和背景色后执行PFC(像素格式转换器),DMA2D方式选择存储器到存储器并执行混合。
  1075. *        形    参: pColorFG   前景色地址
  1076. *             pColorBG   背景色地址
  1077. *             pColorDst  转换后颜色存储
  1078. *             NumItems   要转换的颜色个数
  1079. *        返 回 值: 无
  1080. *********************************************************************************************************
  1081. */
  1082. static void _DMA_AlphaBlendingBulk(LCD_COLOR * pColorFG, LCD_COLOR * pColorBG, LCD_COLOR * pColorDst, U32 NumItems) {
  1083.     //
  1084.     // Set up mode
  1085.     //
  1086.     DMA2D->CR      = 0x00020000UL | (1 << 9);         // Control Register (Memory to memory with blending of FG and BG and TCIE)
  1087.     //
  1088.     // Set up pointers
  1089.     //
  1090.     DMA2D->FGMAR   = (U32)pColorFG;                   // Foreground Memory Address Register
  1091.     DMA2D->BGMAR   = (U32)pColorBG;                   // Background Memory Address Register
  1092.     DMA2D->OMAR    = (U32)pColorDst;                  // Output Memory Address Register (Destination address)
  1093.     //
  1094.     // Set up offsets
  1095.     //
  1096.     DMA2D->FGOR    = 0;                               // Foreground Offset Register
  1097.     DMA2D->BGOR    = 0;                               // Background Offset Register
  1098.     DMA2D->OOR     = 0;                               // Output Offset Register
  1099.     //
  1100.     // Set up pixel format
  1101.     //
  1102.     DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;       // Foreground PFC Control Register (Defines the FG pixel format)
  1103.     DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;       // Background PFC Control Register (Defines the BG pixel format)
  1104.     DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;       // Output     PFC Control Register (Defines the output pixel format)
  1105.     //
  1106.     // Set up size
  1107.     //
  1108.     DMA2D->NLR     = (U32)(NumItems << 16) | 1;       // Number of Line Register (Size configuration of area to be transfered)
  1109.     //
  1110.     // Execute operation
  1111.     //

  1112.     DMA2D->CR     |= 1;  

  1113.     while (DMA2D->CR & DMA2D_CR_START) {
  1114.     //__WFI();                                      // Sleep until next interrupt
  1115.     }
  1116. }

  1117. /*
  1118. *********************************************************************************************************
  1119. *        函 数 名: _DMA_AlphaBlending
  1120. *        功能说明: 前景层和背景层混合输出
  1121. *        形    参: pColorFG    前景层颜色数据地址
  1122. *             pColorBG    背景层颜色数据地址
  1123. *             pColorDst   输出目标区地址
  1124. *             NumItems    转换次数
  1125. *        返 回 值: 无
  1126. *********************************************************************************************************
  1127. */
  1128. static void _DMA_AlphaBlending(LCD_COLOR * pColorFG, LCD_COLOR * pColorBG, LCD_COLOR * pColorDst, U32 NumItems)
  1129. {
  1130. #if (GUI_USE_ARGB)
  1131.     /* DMA2D配置 */   
  1132.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1133.         DMA2D->FGMAR   = (U32)pColorFG;
  1134.         DMA2D->BGMAR   = (U32)pColorBG;
  1135.         DMA2D->OMAR    = (U32)pColorDst;
  1136.         DMA2D->FGOR    = 0;
  1137.         DMA2D->BGOR    = 0;
  1138.         DMA2D->OOR     = 0;
  1139.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1140.         DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1141.         DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;
  1142.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1143.         /* 启动传输 */
  1144.         DMA2D->CR   |= DMA2D_CR_START;   

  1145.         /* 等待DMA2D传输完成 */
  1146.         while (DMA2D->CR & DMA2D_CR_START) {}
  1147. #else
  1148.   //
  1149.   // Invert alpha values
  1150.   //
  1151.   _InvertAlpha(pColorFG, _pBuffer_FG, NumItems);
  1152.   _InvertAlpha(pColorBG, _pBuffer_BG, NumItems);
  1153.   //
  1154.   // Use DMA2D for mixing
  1155.   //
  1156.   _DMA_AlphaBlendingBulk(_pBuffer_FG, _pBuffer_BG, _pBuffer_DMA2D, NumItems);
  1157.   //
  1158.   // Invert alpha values
  1159.   //
  1160.   _InvertAlpha(_pBuffer_DMA2D, pColorDst, NumItems);
  1161. #endif
  1162. }

  1163. /*
  1164. *********************************************************************************************************
  1165. *        函 数 名: _DMA_ConvertColor
  1166. *        功能说明: 颜色转换,从一个颜色格式转换到另一种颜色格式
  1167. *        形    参: pSrc   源颜色地址
  1168. *             pDst   转换后颜色存储地址
  1169. *             PixelFormatSrc  源颜色格式
  1170. *             PixelFormatDst  转换后颜色格式
  1171. *             NumItems        要转换的颜色个数
  1172. *        返 回 值: 无
  1173. *********************************************************************************************************
  1174. */
  1175. static void _DMA_ConvertColor(void * pSrc, void * pDst,  U32 PixelFormatSrc, U32 PixelFormatDst, U32 NumItems) {
  1176.   //
  1177.   // Set up mode
  1178.   //
  1179.   DMA2D->CR      = 0x00010000UL | (1 << 9);         // Control Register (Memory to memory with pixel format conversion and TCIE)
  1180.   //
  1181.   // Set up pointers
  1182.   //
  1183.   DMA2D->FGMAR   = (U32)pSrc;                       // Foreground Memory Address Register (Source address)
  1184.   DMA2D->OMAR    = (U32)pDst;                       // Output Memory Address Register (Destination address)
  1185.   //
  1186.   // Set up offsets
  1187.   //
  1188.   DMA2D->FGOR    = 0;                               // Foreground Offset Register (Source line offset)
  1189.   DMA2D->OOR     = 0;                               // Output Offset Register (Destination line offset)
  1190.   //
  1191.   // Set up pixel format
  1192.   //
  1193.   DMA2D->FGPFCCR = PixelFormatSrc;                  // Foreground PFC Control Register (Defines the input pixel format)
  1194.   DMA2D->OPFCCR  = PixelFormatDst;                  // Output PFC Control Register (Defines the output pixel format)
  1195.   //
  1196.   // Set up size
  1197.   //
  1198.   DMA2D->NLR     = (U32)(NumItems << 16) | 1;       // Number of Line Register (Size configuration of area to be transfered)
  1199.   //
  1200.   // Execute operation
  1201.   //
  1202.   DMA2D->CR     |= 1;  
  1203.    
  1204.   while (DMA2D->CR & DMA2D_CR_START) {
  1205.     //__WFI();                                        // Sleep until next interrupt
  1206.   }
  1207. }

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

  1238.         /* 启动传输 */
  1239.         DMA2D->CR   |= DMA2D_CR_START;

  1240.         /* 等待DMA2D传输完成 */
  1241.         while (DMA2D->CR & DMA2D_CR_START) {}
  1242.    
  1243.     /* 将数据从_pBuffer_DMA2D复制到pColor */
  1244.     blkCnt = NumItems / 0x4U;
  1245.         
  1246.     while (blkCnt > 0U)
  1247.         {
  1248.         *ptr1++ = *ptr2++;
  1249.         *ptr1++ = *ptr2++;
  1250.         *ptr1++ = *ptr2++;
  1251.         *ptr1++ = *ptr2++;
  1252.                 blkCnt--;
  1253.         }
  1254.    
  1255.     blkCnt = NumItems % 0x4U;
  1256.    
  1257.     while (blkCnt > 0U)
  1258.     {
  1259.         *ptr1++ = *ptr2++;
  1260.         blkCnt--;
  1261.     }     
  1262. #else
  1263.   //
  1264.   // Use DMA2D for the conversion
  1265.   //
  1266.   _DMA_ConvertColor(pIndex, _pBuffer_DMA2D, PixelFormat, LTDC_PIXEL_FORMAT_ARGB8888, NumItems);
  1267.   //
  1268.   // Convert colors from ARGB to ABGR and invert alpha values
  1269.   //
  1270.   _InvertAlpha_SwapRB(_pBuffer_DMA2D, pColor, NumItems);
  1271. #endif
  1272. }

  1273. /*
  1274. *********************************************************************************************************
  1275. *        函 数 名: _DMA_Color2IndexBulk
  1276. *        功能说明: 通过DMA2D,将emWin的32位ARGB颜色数据转换为适用于当前显示屏的颜色数据
  1277. *        形    参: pIndex       显示屏颜色地址
  1278. *             pColor       转换成适用于emWin的颜色地址
  1279. *             NumItems     转换的颜色数量
  1280. *             SizeOfIndex  未使用
  1281. *             PixelFormat  显示屏当前使用的颜色格式
  1282. *        返 回 值: 无
  1283. *********************************************************************************************************
  1284. */
  1285. static void _DMA_Color2IndexBulk(LCD_COLOR * pColor, void * pIndex, U32 NumItems, U8 SizeOfIndex, U32 PixelFormat)
  1286. {
  1287. #if (GUI_USE_ARGB)   
  1288.     /* 配置DMA2D */
  1289.         DMA2D->CR      = 0x00010000UL | (1 << 9);
  1290.         DMA2D->FGMAR   = (U32)pColor;
  1291.         DMA2D->OMAR    = (U32)pIndex;
  1292.         DMA2D->FGOR    = 0;
  1293.         DMA2D->OOR     = 0;
  1294.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
  1295.         DMA2D->OPFCCR  = PixelFormat;
  1296.         DMA2D->NLR     = (U32)(NumItems << 16) | 1;

  1297.         /* 启动传输 */
  1298.         DMA2D->CR   |= DMA2D_CR_START;   

  1299.         /* 等待DMA2D传输完成 */
  1300.         while (DMA2D->CR & DMA2D_CR_START) {}
  1301. #else
  1302.     //
  1303.     // Convert colors from ABGR to ARGB and invert alpha values
  1304.     //
  1305.     _InvertAlpha_SwapRB(pColor, _pBuffer_DMA2D, NumItems);
  1306.     //
  1307.     // Use DMA2D for the conversion
  1308.     //
  1309.     _DMA_ConvertColor(_pBuffer_DMA2D, pIndex, LTDC_PIXEL_FORMAT_ARGB8888, PixelFormat, NumItems);
  1310. #endif
  1311. }

  1312. /*
  1313. *********************************************************************************************************
  1314. *        函 数 名: _DMA_MixColorsBulk
  1315. *        功能说明: 通过给定的alpha值,实现两种颜色的批量混合
  1316. *        形    参: pColorFG   前景色地址
  1317. *             pColorBG   背景色地址
  1318. *             pColorDst  混合后颜色存储的地址
  1319. *             Intens     即alpha值
  1320. *             NumItems   转换的颜色数量
  1321. *        返 回 值: 无
  1322. *********************************************************************************************************
  1323. */
  1324. static void _DMA_MixColorsBulk(LCD_COLOR * pColorFG, LCD_COLOR * pColorBG, LCD_COLOR * pColorDst, U8 Intens, U32 NumItems) {
  1325.   //
  1326.   // Set up mode
  1327.   //
  1328.   DMA2D->CR      = 0x00020000UL | (1 << 9);         // Control Register (Memory to memory with blending of FG and BG and TCIE)
  1329.   //
  1330.   // Set up pointers
  1331.   //
  1332.   DMA2D->FGMAR   = (U32)pColorFG;                   // Foreground Memory Address Register
  1333.   DMA2D->BGMAR   = (U32)pColorBG;                   // Background Memory Address Register
  1334.   DMA2D->OMAR    = (U32)pColorDst;                  // Output Memory Address Register (Destination address)
  1335.   //
  1336.   // Set up pixel format
  1337.   //
  1338.   DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1339.                  | (1UL << 16)
  1340.                  | ((U32)Intens << 24);
  1341.   DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1342.                  | (0UL << 16)
  1343.                  | ((U32)(255 - Intens) << 24);
  1344.   DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;
  1345.   //
  1346.   // Set up size
  1347.   //
  1348.   DMA2D->NLR     = (U32)(NumItems << 16) | 1;              // Number of Line Register (Size configuration of area to be transfered)
  1349.   //
  1350.   // Execute operation
  1351.   //
  1352.   DMA2D->CR     |= 1;  
  1353.    
  1354.   while (DMA2D->CR & DMA2D_CR_START) {
  1355.     //__WFI();                                        // Sleep until next interrupt
  1356.   }
  1357. }

  1358. /*
  1359. *********************************************************************************************************
  1360. *        函 数 名: _DMA_MixColorsBulk
  1361. *        功能说明: 将一块显示区的前景色和背景色进行混合
  1362. *        形    参: pFG   前景色地址
  1363. *             pBG   背景色地址
  1364. *             pDst  混合后颜色存储的地址
  1365. *             OffFG    前景色偏移地址
  1366. *             OffBG    背景色偏移地址
  1367. *             OffDest  混合后偏移地址
  1368. *             xSize    显示区x轴大小
  1369. *             ySize    显示区y轴大小
  1370. *             Intens   即alpha值
  1371. *        返 回 值: 无
  1372. *********************************************************************************************************
  1373. */
  1374. static void _LCD_MixColorsBulk(U32 * pFG, U32 * pBG, U32 * pDst, unsigned OffFG, unsigned OffBG, unsigned OffDest, unsigned xSize, unsigned ySize, U8 Intens)
  1375. {
  1376. #if (GUI_USE_ARGB)  
  1377.         int y;

  1378.         GUI_USE_PARA(OffFG);
  1379.         GUI_USE_PARA(OffDest);

  1380.         for (y = 0; y < ySize; y++)
  1381.         {
  1382.         /* 配置DMA2D */
  1383.         DMA2D->CR      = 0x00020000UL | (1 << 9);
  1384.         DMA2D->FGMAR   = (U32)pFG;
  1385.         DMA2D->BGMAR   = (U32)pBG;
  1386.         DMA2D->OMAR    = (U32)pDst;
  1387.    
  1388.         DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1389.                      | (1UL << 16)
  1390.                      | ((U32)Intens << 24);
  1391.         DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888
  1392.                      | (0UL << 16)
  1393.                      | ((U32)(255 - Intens) << 24);
  1394.         DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;
  1395.         DMA2D->NLR     = (U32)(xSize << 16) | 1;

  1396.         /* 启动传输 */
  1397.         DMA2D->CR   |= DMA2D_CR_START;   

  1398.         /* 等待DMA2D传输完成 */
  1399.         while (DMA2D->CR & DMA2D_CR_START) {}
  1400.         
  1401.                 pFG  += xSize + OffFG;
  1402.                 pBG  += xSize + OffBG;
  1403.                 pDst += xSize + OffDest;
  1404.         }
  1405. #else
  1406.     int y;

  1407.     GUI_USE_PARA(OffFG);
  1408.     GUI_USE_PARA(OffDest);
  1409.     for (y = 0; y < ySize; y++) {
  1410.         //
  1411.         // Invert alpha values
  1412.         //
  1413.         _InvertAlpha(pFG, _pBuffer_FG, xSize);
  1414.         _InvertAlpha(pBG, _pBuffer_BG, xSize);
  1415.         //
  1416.         //
  1417.         //
  1418.         _DMA_MixColorsBulk(_pBuffer_FG, _pBuffer_BG, _pBuffer_DMA2D, Intens, xSize);
  1419.         //
  1420.         //
  1421.         //
  1422.         _InvertAlpha(_pBuffer_DMA2D, pDst, xSize);
  1423.         pFG  += xSize + OffFG;
  1424.         pBG  += xSize + OffBG;
  1425.         pDst += xSize + OffDest;
  1426.     }
  1427.    
  1428. #endif
  1429. }

  1430. /*
  1431. *********************************************************************************************************
  1432. *        函 数 名: _GetBufferSize
  1433. *        功能说明: 获取指定层显存大小
  1434. *        形    参: LayerIndex    图层
  1435. *        返 回 值: 显存大小
  1436. *********************************************************************************************************
  1437. */
  1438. static U32 _GetBufferSize(int LayerIndex)
  1439. {
  1440.         U32 BufferSize;

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

  1442.         return BufferSize;
  1443. }

  1444. /*
  1445. *********************************************************************************************************
  1446. *        函 数 名: _LCD_CopyBuffer
  1447. *        功能说明: 此函数用于多缓冲,将一个缓冲中的所有数据复制到另一个缓冲。
  1448. *        形    参: LayerIndex    图层
  1449. *             IndexSrc      源缓冲序号
  1450. *             IndexDst      目标缓冲序号
  1451. *        返 回 值: 无
  1452. *********************************************************************************************************
  1453. */
  1454. static void _LCD_CopyBuffer(int LayerIndex, int IndexSrc, int IndexDst)
  1455. {
  1456.         U32 BufferSize, AddrSrc, AddrDst;

  1457.         BufferSize = _GetBufferSize(LayerIndex);
  1458.         AddrSrc    = _aAddr[LayerIndex] + BufferSize * IndexSrc;
  1459.         AddrDst    = _aAddr[LayerIndex] + BufferSize * IndexDst;
  1460.         _DMA_Copy(LayerIndex, (void *)AddrSrc, (void *)AddrDst, _axSize[LayerIndex], _aySize[LayerIndex], 0, 0);
  1461.        
  1462.         /* 绘制操作切换到缓冲Buffer[IndexDst] */
  1463.         _aBufferIndex[LayerIndex] = IndexDst;
  1464. }

  1465. /*
  1466. *********************************************************************************************************
  1467. *        函 数 名: _LCD_CopyRect
  1468. *        功能说明: 此函数用于多缓冲,将一个缓冲中指定区域数据复制到另一个缓冲。
  1469. *        形    参: LayerIndex    图层
  1470. *             x0            源缓冲x轴位置
  1471. *             y0            源缓冲y轴位置
  1472. *             x1            目标冲x轴位置
  1473. *             y1            目标冲y轴位置
  1474. *             xSize         要复制的x轴大小
  1475. *             ySize         要复制的y轴大小
  1476. *        返 回 值: 无
  1477. *********************************************************************************************************
  1478. */
  1479. static void _LCD_CopyRect(int LayerIndex, int x0, int y0, int x1, int y1, int xSize, int ySize)
  1480. {
  1481.         U32 BufferSize, AddrSrc, AddrDst;
  1482.         int OffLine;

  1483.         BufferSize = _GetBufferSize(LayerIndex);
  1484.         AddrSrc = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y0 * _axSize[LayerIndex] + x0) * _aBytesPerPixels[LayerIndex];
  1485.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y1 * _axSize[LayerIndex] + x1) * _aBytesPerPixels[LayerIndex];
  1486.         OffLine = _axSize[LayerIndex] - xSize;
  1487.         _DMA_Copy(LayerIndex, (void *)AddrSrc, (void *)AddrDst, xSize, ySize, OffLine, OffLine);
  1488. }

  1489. /*
  1490. *********************************************************************************************************
  1491. *        函 数 名: _LCD_FillRect
  1492. *        功能说明: 对指定的区域进行颜色填充
  1493. *        形    参: LayerIndex    图层
  1494. *             x0            起始x轴位置
  1495. *             y0            起始y轴位置
  1496. *             x1            结束x轴位置
  1497. *             y1            结束y轴位置
  1498. *             PixelIndex    要填充的颜色值
  1499. *        返 回 值: 无
  1500. *********************************************************************************************************
  1501. */
  1502. static void _LCD_FillRect(int LayerIndex, int x0, int y0, int x1, int y1, U32 PixelIndex)
  1503. {
  1504.         U32 BufferSize, AddrDst;
  1505.         int xSize, ySize;

  1506.         if (GUI_GetDrawMode() == GUI_DM_XOR)
  1507.         {
  1508.                 LCD_SetDevFunc(LayerIndex, LCD_DEVFUNC_FILLRECT, NULL);
  1509.                 LCD_FillRect(x0, y0, x1, y1);
  1510.                 LCD_SetDevFunc(LayerIndex, LCD_DEVFUNC_FILLRECT, (void(*)(void))_LCD_FillRect);
  1511.         }
  1512.         else
  1513.         {
  1514.                 xSize = x1 - x0 + 1;
  1515.                 ySize = y1 - y0 + 1;
  1516.                 BufferSize = _GetBufferSize(LayerIndex);
  1517.                 AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y0 * _axSize[LayerIndex] + x0) * _aBytesPerPixels[LayerIndex];
  1518.                 _DMA_Fill(LayerIndex, (void *)AddrDst, xSize, ySize, _axSize[LayerIndex] - xSize, PixelIndex);
  1519.         }
  1520. }

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

  1539.         BufferSize = _GetBufferSize(LayerIndex);
  1540.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1541.         OffLineSrc = (BytesPerLine / 4) - xSize;
  1542.         OffLineDst = _axSize[LayerIndex] - xSize;
  1543.         _DMA_Copy(LayerIndex, (void *)p, (void *)AddrDst, xSize, ySize, OffLineSrc, OffLineDst);
  1544. }

  1545. /*
  1546. *********************************************************************************************************
  1547. *        函 数 名: _LCD_DrawBitmap16bpp
  1548. *        功能说明: 绘制16bpp格式位图
  1549. *        形    参: LayerIndex      图层   
  1550. *             x               X轴起始位置
  1551. *             y               Y轴起始位置
  1552. *             p               源数据地址
  1553. *             xSize           位图长
  1554. *             ySize           位图高
  1555. *             BytesPerLine    每行字节数
  1556. *        返 回 值: 无
  1557. *********************************************************************************************************
  1558. */
  1559. void _LCD_DrawBitmap16bpp(int LayerIndex, int x, int y, U16 const * p, int xSize, int ySize, int BytesPerLine)
  1560. {
  1561.         U32 BufferSize, AddrDst;
  1562.         int OffLineSrc, OffLineDst;

  1563.         BufferSize = _GetBufferSize(LayerIndex);
  1564.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1565.         OffLineSrc = (BytesPerLine / 2) - xSize;
  1566.         OffLineDst = _axSize[LayerIndex] - xSize;
  1567.         _DMA_Copy(LayerIndex, (void *)p, (void *)AddrDst, xSize, ySize, OffLineSrc, OffLineDst);
  1568. }

  1569. /*
  1570. *********************************************************************************************************
  1571. *        函 数 名: _LCD_DrawBitmap8bpp
  1572. *        功能说明: 绘制8bpp格式位图
  1573. *        形    参: LayerIndex      图层   
  1574. *             x               X轴起始位置
  1575. *             y               Y轴起始位置
  1576. *             p               源数据地址
  1577. *             xSize           位图长
  1578. *             ySize           位图高
  1579. *             BytesPerLine    每行字节数
  1580. *        返 回 值: 无
  1581. *********************************************************************************************************
  1582. */
  1583. #if UsedDrawBitmap8bpp
  1584. static void _LCD_DrawBitmap8bpp(int LayerIndex, int x, int y, U8 const * p, int xSize, int ySize, int BytesPerLine) {
  1585.         U32 BufferSize, AddrDst;
  1586.         int OffLineSrc, OffLineDst;
  1587.         U32 PixelFormat;

  1588.         PixelFormat = _GetPixelformat(LayerIndex);
  1589.         BufferSize = _GetBufferSize(LayerIndex);
  1590.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1591.         OffLineSrc = BytesPerLine - xSize;
  1592.         OffLineDst = _axSize[LayerIndex] - xSize;
  1593.         _DMA_DrawBitmapL8((void *)p, (void *)AddrDst, OffLineSrc, OffLineDst, PixelFormat, xSize, ySize);
  1594. }
  1595. #endif

  1596. #if DrawBitmapA4Enalbe == 1
  1597. /*
  1598. *********************************************************************************************************
  1599. *        函 数 名: _LCD_DrawBitmap4bpp
  1600. *        功能说明: 绘制4bpp格式位图
  1601. *        形    参: LayerIndex      图层   
  1602. *             x               X轴起始位置
  1603. *             y               Y轴起始位置
  1604. *             p               源数据地址
  1605. *             xSize           位图长
  1606. *             ySize           位图高
  1607. *             BytesPerLine    每行字节数
  1608. *        返 回 值: 无
  1609. *********************************************************************************************************
  1610. */
  1611. static int _LCD_DrawBitmap4bpp(int LayerIndex, int x, int y, U8 const * p, int xSize, int ySize, int BytesPerLine) {
  1612.         U32 BufferSize, AddrDst;
  1613.         int OffLineSrc, OffLineDst;
  1614.         U32 PixelFormat;

  1615.         if (x < 0)
  1616.         {
  1617.                 return 1;
  1618.         }
  1619.        
  1620.         if ((x + xSize) >= _axSize[LayerIndex])
  1621.         {
  1622.                 return 1;
  1623.         }
  1624.        
  1625.         if (y < 0)
  1626.         {
  1627.                 return 1;
  1628.         }
  1629.        
  1630.         if ((y + ySize) >= _aySize[LayerIndex])
  1631.         {
  1632.                 return 1;
  1633.         }
  1634.        
  1635.         PixelFormat = _GetPixelformat(LayerIndex);

  1636.         if (PixelFormat > LTDC_PIXEL_FORMAT_ARGB4444)
  1637.         {
  1638.                 return 1;
  1639.         }
  1640.        
  1641.         BufferSize = _GetBufferSize(LayerIndex);
  1642.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1643.         OffLineSrc = (BytesPerLine * 2) - xSize;
  1644.         OffLineDst = _axSize[LayerIndex] - xSize;
  1645.         return _DMA_DrawBitmapA4((void *)p, (void *)AddrDst, OffLineSrc, OffLineDst, PixelFormat, xSize, ySize);;
  1646. }
  1647. #endif

  1648. /*
  1649. *********************************************************************************************************
  1650. *        函 数 名: _LCD_DrawMemdev16bpp
  1651. *        功能说明: 绘制16bpp存储设备
  1652. *        形    参: pDst               源数据地址   
  1653. *             pSrc               目的数据地址
  1654. *             xSize              存储设备长
  1655. *             ySize              存储设备高
  1656. *             BytesPerLineDst    源数据每行字节数
  1657. *             BytesPerLineSrc    目的数据每行字节数
  1658. *        返 回 值: 无
  1659. *********************************************************************************************************
  1660. */
  1661. #if GUI_USE_ARGB
  1662. static void _LCD_DrawMemdev16bpp(void * pDst, const void * pSrc, int xSize, int ySize, int BytesPerLineDst, int BytesPerLineSrc)
  1663. {
  1664.         int OffLineSrc, OffLineDst;

  1665.         OffLineSrc = (BytesPerLineSrc / 2) - xSize;
  1666.         OffLineDst = (BytesPerLineDst / 2) - xSize;
  1667.         _DMA_CopyRGB565(pSrc, pDst, xSize, ySize, OffLineSrc, OffLineDst);
  1668. }
  1669. #endif

  1670. /*
  1671. *********************************************************************************************************
  1672. *        函 数 名: _LCD_DrawMemdevAlpha
  1673. *        功能说明: 绘制带Alpha通道的存储设备
  1674. *        形    参: pDst               源数据地址   
  1675. *             pSrc               目的数据地址
  1676. *             xSize              存储设备长
  1677. *             ySize              存储设备高
  1678. *             BytesPerLineDst    源数据每行字节数
  1679. *             BytesPerLineSrc    目的数据每行字节数
  1680. *        返 回 值: 无
  1681. *********************************************************************************************************
  1682. */
  1683. #if  DrawAlpha == 1  
  1684. static void _LCD_DrawMemdevAlpha(void * pDst, const void * pSrc, int xSize, int ySize, int BytesPerLineDst, int BytesPerLineSrc)
  1685. {
  1686.         int OffLineSrc, OffLineDst;

  1687.         OffLineSrc = (BytesPerLineSrc / 4) - xSize;
  1688.         OffLineDst = (BytesPerLineDst / 4) - xSize;
  1689.         _DMA_DrawAlphaBitmap(pDst, pSrc, xSize, ySize, OffLineSrc, OffLineDst, LTDC_PIXEL_FORMAT_ARGB8888);
  1690. }
  1691. #endif

  1692. /*
  1693. *********************************************************************************************************
  1694. *        函 数 名: _LCD_DrawBitmapAlpha
  1695. *        功能说明: 绘制带Alpha通道的位图
  1696. *        形    参: LayerIndex      图层   
  1697. *             x               X轴起始位置
  1698. *             y               Y轴起始位置
  1699. *             p               源数据地址
  1700. *             xSize           位图长
  1701. *             ySize           位图高
  1702. *             BytesPerLine    每行字节数
  1703. *        返 回 值: 无
  1704. *********************************************************************************************************
  1705. */
  1706. #if  DrawAlpha == 1  
  1707. static void _LCD_DrawBitmapAlpha(int LayerIndex, int x, int y, const void * p, int xSize, int ySize, int BytesPerLine)
  1708. {
  1709.         U32 BufferSize, AddrDst;
  1710.         int OffLineSrc, OffLineDst;
  1711.         U32 PixelFormat;

  1712.         PixelFormat = _GetPixelformat(LayerIndex);
  1713.         BufferSize = _GetBufferSize(LayerIndex);
  1714.         AddrDst = _aAddr[LayerIndex] + BufferSize * _aBufferIndex[LayerIndex] + (y * _axSize[LayerIndex] + x) * _aBytesPerPixels[LayerIndex];
  1715.         OffLineSrc = (BytesPerLine / 4) - xSize;
  1716.         OffLineDst = _axSize[LayerIndex] - xSize;
  1717.         _DMA_DrawAlphaBitmap((void *)AddrDst, p, xSize, ySize, OffLineSrc, OffLineDst, PixelFormat);
  1718. }
  1719. #endif

  1720. /*
  1721. *********************************************************************************************************
  1722. *        函 数 名: _LCD_GetpPalConvTable
  1723. *        功能说明: 转换颜色板以适应控制器设置的颜色格式。
  1724. *        形    参: pLogPal   源颜色板地址
  1725. *             pBitmap   位图地址
  1726. *             LayerIndex  源颜色格式
  1727. *        返 回 值: 转换后的颜色板地址
  1728. *********************************************************************************************************
  1729. */
  1730. static LCD_PIXELINDEX * _LCD_GetpPalConvTable(const LCD_LOGPALETTE GUI_UNI_PTR * pLogPal, const GUI_BITMAP GUI_UNI_PTR * pBitmap, int LayerIndex)
  1731. {
  1732. #if (GUI_USE_ARGB)
  1733.         void (* pFunc)(void);
  1734.         int DoDefault = 0;

  1735.         /* 8bpp */
  1736.         if (pBitmap->BitsPerPixel == 8)
  1737.         {
  1738.                 pFunc = LCD_GetDevFunc(LayerIndex, LCD_DEVFUNC_DRAWBMP_8BPP);
  1739.                 if (pFunc)
  1740.                 {
  1741.                         if (pBitmap->pPal)
  1742.                         {
  1743.                                 if (pBitmap->pPal->HasTrans)
  1744.                                 {
  1745.                                         DoDefault = 1;
  1746.                                 }
  1747.                         }
  1748.                         else
  1749.                         {
  1750.                                 DoDefault = 1;
  1751.                         }
  1752.                 }
  1753.                 else
  1754.                 {
  1755.                         DoDefault = 1;
  1756.                 }
  1757.         }
  1758.         else
  1759.         {
  1760.         DoDefault = 1;
  1761.         }

  1762.         /* 默认颜色板管理 */
  1763.         if (DoDefault)
  1764.         {
  1765.                 /* 返回索引值 */
  1766.                 return LCD_GetpPalConvTable(pLogPal);
  1767.         }

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

  1770.         /* 返回非NULL */
  1771.         return _pBuffer_DMA2D;
  1772. #else
  1773.         void (* pFunc)(void);
  1774.         int DoDefault = 0;

  1775.         /* 8bpp */
  1776.         if (pBitmap->BitsPerPixel == 8)
  1777.         {
  1778.                 pFunc = LCD_GetDevFunc(LayerIndex, LCD_DEVFUNC_DRAWBMP_8BPP);
  1779.                 if (pFunc)
  1780.                 {
  1781.                         if (pBitmap->pPal)
  1782.                         {
  1783.                                 if (pBitmap->pPal->HasTrans)
  1784.                                 {
  1785.                                         DoDefault = 1;
  1786.                                 }
  1787.                         }
  1788.                         else
  1789.                         {
  1790.                                 DoDefault = 1;
  1791.                         }
  1792.                 }
  1793.                 else
  1794.                 {
  1795.                         DoDefault = 1;
  1796.                 }
  1797.         }
  1798.         else
  1799.         {
  1800.         DoDefault = 1;
  1801.         }

  1802.         /* 默认颜色板管理 */
  1803.         if (DoDefault)
  1804.         {
  1805.                 /* 返回索引值 */
  1806.                 return LCD_GetpPalConvTable(pLogPal);
  1807.         }
  1808.    
  1809.     _InvertAlpha_SwapRB((U32 *)pLogPal->pPalEntries, _pBuffer_DMA2D, pLogPal->NumEntries);

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

  1812.         /* 返回非NULL */
  1813.         return _pBuffer_DMA2D;

  1814. #endif
  1815. }

  1816. /*
  1817. *********************************************************************************************************
  1818. *        函 数 名: LCD_X_DisplayDriver
  1819. *        功能说明: 显示驱动设置
  1820. *        形    参: LayerIndex   图层
  1821. *             Cmd          命令
  1822. *             pData        数据地址
  1823. *        返 回 值: 成功返回0,失败返回-1
  1824. *********************************************************************************************************
  1825. */
  1826. int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData)
  1827. {
  1828.         int r = 0;
  1829.         U32 addr;

  1830.         switch (Cmd)
  1831.         {
  1832.                 case LCD_X_INITCONTROLLER:
  1833.                 {
  1834.                         /* 驱动初始化 */
  1835.                         LCD_LL_LayerInit(LayerIndex);
  1836.                         break;
  1837.                 }
  1838.                
  1839.                 case LCD_X_SETORG:
  1840.                 {
  1841.                         /* 设置显存地址 */
  1842.                         LCD_X_SETORG_INFO * p;

  1843.                         p = (LCD_X_SETORG_INFO *)pData;
  1844.                         addr = _aAddr[LayerIndex] + p->yPos * _axSize[LayerIndex] * _aBytesPerPixels[LayerIndex];
  1845.                         HAL_LTDC_SetAddress(&hltdc, addr, LayerIndex);
  1846.                         break;
  1847.                 }
  1848.                
  1849.                 case LCD_X_SHOWBUFFER:
  1850.                 {
  1851.                         /* 用于多缓冲,参数Index用于指示使用的那个缓冲 */
  1852.                         LCD_X_SHOWBUFFER_INFO * p;

  1853.                         p = (LCD_X_SHOWBUFFER_INFO *)pData;
  1854.                         _aPendingBuffer[LayerIndex] = p->Index;
  1855.                         break;
  1856.                 }
  1857.                
  1858.                 case LCD_X_SETLUTENTRY:
  1859.                 {
  1860.                         /* 颜色查找表设置 */
  1861.                         LCD_X_SETLUTENTRY_INFO * p;

  1862.                         p = (LCD_X_SETLUTENTRY_INFO *)pData;
  1863.                         HAL_LTDC_ConfigCLUT(&hltdc, (uint32_t*)p->Color, p->Pos, LayerIndex);
  1864.                         break;
  1865.                 }
  1866.                
  1867.                 case LCD_X_ON:
  1868.                 {
  1869.                         /* 使能LTDC  */
  1870.                         __HAL_LTDC_ENABLE(&hltdc);
  1871.                         break;
  1872.                 }
  1873.                
  1874.                 case LCD_X_OFF:
  1875.                 {
  1876.                         /* 关闭LTDC */
  1877.                         __HAL_LTDC_DISABLE(&hltdc);
  1878.                         break;
  1879.                 }
  1880.                
  1881.                 case LCD_X_SETVIS:
  1882.                 {
  1883.                         /* 图层的开关 */
  1884.                         LCD_X_SETVIS_INFO * p;

  1885.                         p = (LCD_X_SETVIS_INFO *)pData;
  1886.                         if(p->OnOff == ENABLE )
  1887.                         {
  1888.                                 __HAL_LTDC_LAYER_ENABLE(&hltdc, LayerIndex);
  1889.                         }
  1890.                         else
  1891.                         {
  1892.                                 __HAL_LTDC_LAYER_DISABLE(&hltdc, LayerIndex);
  1893.                         }
  1894.                        
  1895.                         __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc);
  1896.                         break;
  1897.                 }
  1898.                
  1899.                 case LCD_X_SETPOS:
  1900.                 {
  1901.                         /* 设置图层显示位置 */
  1902.                         LCD_X_SETPOS_INFO * p;

  1903.                         p = (LCD_X_SETPOS_INFO *)pData;   
  1904.                         HAL_LTDC_SetWindowPosition(&hltdc, p->xPos, p->yPos, LayerIndex);
  1905.                         break;
  1906.                 }
  1907.                
  1908.                 case LCD_X_SETSIZE:
  1909.                 {
  1910.                         /* 设置图层大小 */
  1911.                         LCD_X_SETSIZE_INFO * p;
  1912.                         int xPos, yPos;

  1913.                         GUI_GetLayerPosEx(LayerIndex, &xPos, &yPos);
  1914.                         p = (LCD_X_SETSIZE_INFO *)pData;
  1915.                         if (LCD_GetSwapXYEx(LayerIndex))
  1916.                         {
  1917.                                 _axSize[LayerIndex] = p->ySize;
  1918.                                 _aySize[LayerIndex] = p->xSize;
  1919.                         }
  1920.                         else
  1921.                         {
  1922.                                 _axSize[LayerIndex] = p->xSize;
  1923.                                 _aySize[LayerIndex] = p->ySize;
  1924.                         }
  1925.                        
  1926.                         HAL_LTDC_SetWindowPosition(&hltdc, xPos, yPos, LayerIndex);
  1927.                         break;
  1928.                 }
  1929.                
  1930.                 case LCD_X_SETALPHA:
  1931.                 {
  1932.                         /* 设置透明 */
  1933.                         LCD_X_SETALPHA_INFO * p;

  1934.                         p = (LCD_X_SETALPHA_INFO *)pData;
  1935.          #if (GUI_USE_ARGB)
  1936.                         HAL_LTDC_SetAlpha(&hltdc, p->Alpha, LayerIndex);
  1937.          #else
  1938.             HAL_LTDC_SetAlpha(&hltdc, 255-p->Alpha, LayerIndex);
  1939.          #endif
  1940.                         break;
  1941.                 }
  1942.                
  1943.                 case LCD_X_SETCHROMAMODE:
  1944.                 {
  1945.                         /* 使能或禁止扣色 */
  1946.                         LCD_X_SETCHROMAMODE_INFO * p;

  1947.                         p = (LCD_X_SETCHROMAMODE_INFO *)pData;
  1948.                         if(p->ChromaMode != 0)
  1949.                         {
  1950.                                 HAL_LTDC_EnableColorKeying(&hltdc, LayerIndex);
  1951.                         }
  1952.                         else
  1953.                         {
  1954.                                 HAL_LTDC_DisableColorKeying(&hltdc, LayerIndex);      
  1955.                         }
  1956.                         break;
  1957.                 }
  1958.                
  1959.                 case LCD_X_SETCHROMA:
  1960.                 {
  1961.                         /* 设置扣色 */
  1962.                         LCD_X_SETCHROMA_INFO * p;
  1963.                         U32 Color;

  1964.                         p = (LCD_X_SETCHROMA_INFO *)pData;
  1965.                         Color = ((p->ChromaMin & 0xFF0000) >> 16) | (p->ChromaMin & 0x00FF00) | ((p->ChromaMin & 0x0000FF) << 16);
  1966.                         HAL_LTDC_ConfigColorKeying(&hltdc, Color, LayerIndex);
  1967.                         break;
  1968.                 }
  1969.                
  1970.                 default:
  1971.                         r = -1;
  1972.                         break;
  1973.         }

  1974.         return r;
  1975. }

  1976. /*
  1977. *********************************************************************************************************
  1978. *        函 数 名: LCD_X_DisplayDriver
  1979. *        功能说明: 初始化配置
  1980. *        形    参: 无
  1981. *        返 回 值: 无
  1982. *********************************************************************************************************
  1983. */
  1984. void LCD_X_Config(void)
  1985. {
  1986.         int i;
  1987.         U32 PixelFormat;

  1988.         /* 底层初始化 */
  1989.         LCD_LL_Init ();

  1990. #if ClearCacheHookEnalbe == 1
  1991.         GUI_DCACHE_SetClearCacheHook(_ClearCacheHook);
  1992. #endif

  1993.         /* 初始化多缓冲 */
  1994. #if (NUM_BUFFERS > 1)
  1995.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  1996.         {
  1997.                 GUI_MULTIBUF_ConfigEx(i, NUM_BUFFERS);
  1998.         }
  1999. #endif

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

  2002.         /* 设置图层1 */
  2003.         if (LCD_GetSwapXYEx(0))
  2004.         {
  2005.                 LCD_SetSizeEx (0,  g_LcdHeight, g_LcdWidth);
  2006.                 LCD_SetVSizeEx(0,  g_LcdHeight * NUM_VSCREENS, g_LcdWidth);
  2007.         }
  2008.         else
  2009.         {
  2010.                 LCD_SetSizeEx (0, g_LcdWidth, g_LcdHeight);
  2011.                 LCD_SetVSizeEx(0, g_LcdWidth, g_LcdHeight * NUM_VSCREENS);
  2012.         }
  2013.        
  2014. #if (GUI_NUM_LAYERS > 1)
  2015.         /* 设置显示驱动和颜色格式转换 */
  2016.         GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER_1, COLOR_CONVERSION_1, 0, 1);

  2017.         /* 设置图层2 */
  2018.         if (LCD_GetSwapXYEx(1))
  2019.         {
  2020.                 LCD_SetSizeEx (1, g_LcdHeight, g_LcdWidth);
  2021.                 LCD_SetVSizeEx(1,  g_LcdHeight * NUM_VSCREENS, g_LcdWidth);
  2022.         }
  2023.         else
  2024.         {
  2025.                 LCD_SetSizeEx (1, g_LcdWidth, g_LcdHeight);
  2026.                 LCD_SetVSizeEx(1, g_LcdWidth, g_LcdHeight * NUM_VSCREENS);
  2027.         }
  2028. #endif
  2029.        
  2030.         /* 设置RAM地址和每个像素的字节数 */
  2031.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  2032.         {
  2033.                 /* 设置RAM地址 */
  2034.                 LCD_SetVRAMAddrEx(i, (void *)(_aAddr[i]));
  2035.                
  2036.                 /* 每个像素的字节数 */
  2037.                 _aBytesPerPixels[i] = LCD_GetBitsPerPixelEx(i) >> 3;
  2038.         }
  2039.        
  2040.         /* 设置函数重定向 */
  2041.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  2042.         {
  2043.                 PixelFormat = _GetPixelformat(i);
  2044.                
  2045.                 /* CopyBuffer重定向,多缓冲使用 */
  2046.                 LCD_SetDevFunc(i, LCD_DEVFUNC_COPYBUFFER, (void(*)(void))_LCD_CopyBuffer);

  2047.                 if (PixelFormat <= LTDC_PIXEL_FORMAT_ARGB4444)
  2048.                 {
  2049.                         /* 填充使用 */
  2050.                         LCD_SetDevFunc(i, LCD_DEVFUNC_FILLRECT, (void(*)(void))_LCD_FillRect);
  2051.                 }

  2052.                 if (_aOrientation[i] == ROTATION_0)
  2053.                 {
  2054.                         /* CopyRect重定向 */
  2055.                         LCD_SetDevFunc(i, LCD_DEVFUNC_COPYRECT, (void(*)(void))_LCD_CopyRect);

  2056.                         /* 8bpp重定向 */
  2057.                         if (PixelFormat <= LTDC_PIXEL_FORMAT_ARGB4444)
  2058.                         {
  2059.                 #if UsedDrawBitmap8bpp
  2060.                                  LCD_SetDevFunc(i, LCD_DEVFUNC_DRAWBMP_8BPP, (void(*)(void))_LCD_DrawBitmap8bpp);
  2061.                 #endif
  2062.                         }

  2063.                         /* 16bpp重定向 */
  2064.                         if (PixelFormat == LTDC_PIXEL_FORMAT_RGB565)
  2065.                         {
  2066.                                 LCD_SetDevFunc(i, LCD_DEVFUNC_DRAWBMP_16BPP, (void(*)(void))_LCD_DrawBitmap16bpp);
  2067.                         }

  2068.                         /* 32bpp重定向 */
  2069.                         if (PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888)
  2070.                         {
  2071.                                 LCD_SetDevFunc(i, LCD_DEVFUNC_DRAWBMP_32BPP, (void(*)(void))_LCD_DrawBitmap32bpp);
  2072.                         }
  2073.                 }
  2074.         }

  2075.         /* DMA2D for ARGB1555 */
  2076.         GUICC_M1555I_SetCustColorConv(_Color2IndexBulk_M1555I_DMA2D, _Index2ColorBulk_M1555I_DMA2D);

  2077.         /* DMA2D for RGB565 */  
  2078.         GUICC_M565_SetCustColorConv  (_Color2IndexBulk_M565_DMA2D,   _Index2ColorBulk_M565_DMA2D);

  2079.         /* DMA2D for ARGB4444 */
  2080.         GUICC_M4444I_SetCustColorConv(_Color2IndexBulk_M4444I_DMA2D, _Index2ColorBulk_M4444I_DMA2D);

  2081.         /* DMA2D for RGB888 */
  2082.         GUICC_M888_SetCustColorConv  (_Color2IndexBulk_M888_DMA2D,   _Index2ColorBulk_M888_DMA2D);

  2083.         /* DMA2D for ARGB8888 */
  2084.         GUICC_M8888I_SetCustColorConv(_Color2IndexBulk_M8888I_DMA2D, _Index2ColorBulk_M8888I_DMA2D);

  2085.         /* Alpha混合重定向 */
  2086.         GUI_SetFuncAlphaBlending(_DMA_AlphaBlending);

  2087.         GUI_SetFuncGetpPalConvTable(_LCD_GetpPalConvTable);

  2088.         /* 颜色混合重定向 */
  2089.         GUI_SetFuncMixColorsBulk(_LCD_MixColorsBulk);

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

  2093.         /* 16bpp存储设备重定向 */
  2094. #if GUI_USE_ARGB == 1
  2095.         GUI_MEMDEV_SetDrawMemdev16bppFunc(_LCD_DrawMemdev16bpp);
  2096. #endif

  2097. #if  DrawAlpha == 1   
  2098.         /* Alpha绘制重定向 */
  2099.         GUI_SetFuncDrawAlpha(_LCD_DrawMemdevAlpha, _LCD_DrawBitmapAlpha);
  2100. #endif
  2101. }

  2102. #if 1
  2103. /*
  2104. *********************************************************************************************************
  2105. *        函 数 名: LTDC_IRQHandler
  2106. *        功能说明: 初始化配置
  2107. *        形    参: 无
  2108. *        返 回 值: 无
  2109. *********************************************************************************************************
  2110. */
  2111. void LTDC_IRQHandler(void)
  2112. {
  2113.         U32 Addr;
  2114.         int i;

  2115.         LTDC->ICR = (U32)LTDC_IER_LIE;
  2116.        
  2117.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  2118.         {
  2119.                 if (_aPendingBuffer[i] >= 0)
  2120.                 {
  2121.                         /* 计算缓冲地址 */
  2122.                         Addr = _aAddr[i] + _axSize[i] * _aySize[i] * _aPendingBuffer[i] * _aBytesPerPixels[i];

  2123.                         /* 更新LTDC寄存器 */          
  2124.                         __HAL_LTDC_LAYER(&hltdc, i)->CFBAR = Addr;     
  2125.                         __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc);   

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

  2128.                         /* 清除标志 */
  2129.                         _aPendingBuffer[i] = -1;
  2130.                 }
  2131.         }
  2132. }

  2133. #else
  2134. /*
  2135. *********************************************************************************************************
  2136. *        函 数 名: LTDC_IRQHandler
  2137. *        功能说明: 初始化配置
  2138. *        形    参: 无
  2139. *        返 回 值: 无
  2140. *********************************************************************************************************
  2141. */
  2142. void LTDC_IRQHandler(void)
  2143. {
  2144.         HAL_LTDC_IRQHandler(&hltdc);
  2145. }

  2146. void HAL_LTDC_LineEvenCallback(LTDC_HandleTypeDef *hltdc)
  2147. {
  2148.         U32 Addr;
  2149.         int i;

  2150.         for (i = 0; i < GUI_NUM_LAYERS; i++)
  2151.         {
  2152.                 if (_aPendingBuffer[i] >= 0)
  2153.                 {
  2154.                         /* 计算缓冲地址 */
  2155.                         Addr = _aAddr[i] + _axSize[i] * _aySize[i] * _aPendingBuffer[i] * _aBytesPerPixels[i];

  2156.                         /* 更新LTDC寄存器 */          
  2157.                         __HAL_LTDC_LAYER(hltdc, i)->CFBAR = Addr;     
  2158.                         __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(hltdc);   

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

  2161.                         /* 清除标志 */
  2162.                         _aPendingBuffer[i] = -1;
  2163.                 }
  2164.         }

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

  2168. #endif

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

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2021-2-7 14:44:59 | 显示全部楼层
有工程吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107145
QQ
 楼主| 发表于 2021-2-8 08:19:30 | 显示全部楼层

第3版emWin教程和ThreadX GUIX教程开工,双管齐下,GUIX更新至第23章(2021-02-07)
http://www.armbbs.cn/forum.php?m ... 8429&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-20 12:36 , Processed in 0.205500 second(s), 34 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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