TinyUI对于MCU是否集成LCD控制器都支持,但需要实现TinyUI定义的TUIFBInterface纯虚类接口,FB为frame buffer的缩写。该接口部分方法是否需要实现依赖于当前需要移植的MCU是否集成LCD控制器,如果集成了LCD控制器,则只需实现极少部分的方法,但是如果MCU未集成LCD控制器,则可能需要实现大部分的方法。
TinyUI定义的显示接口
TUIFBInterface.h
#ifndef __TUI_FB_INTERFACE__
#define __TUI_FB_INTERFACE__
#include <TUITypes.h>
class TUIFBInterface
{
public:
/*********************************************************************************************************************
@Function: readPoint
@Description: 获取LCD某个像素的颜色值
1. 未集成LCD控制器的MCU重写该方法,若不支持,则返回false。
2. 集成LCD控制器的MCU不需要重写该方法
@Param:
x: 待读取像素值的水平坐标
y: 待读取像素值的垂直坐标
color: 输出参数,返回该像素点的颜色值
@Return:
true: 支持读取像素;false: 不支持读取像素
***********************************************************************************************************************/
virtual bool readPoint(int32_t x, int32_t y, color_t* color) { return false; }
/*********************************************************************************************************************
@Function: drawPoint
@Description: 在指定位置(x, y)绘制一个点
1. 未集成LCD控制器的MCU必须立即绘制。
2. 集成LCD控制器的MCU实现空方法即可。
@Param:
x: 绘制点的水平坐标
y: 绘制点的垂直坐标
visibleX1: 水平绘制坐标左边界,当x小于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现
visibleY1: 垂直绘制坐标上边界,当y小于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现
visibleX2: 水平绘制坐标右边界,当x大于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现
visibleY2: 垂直绘制坐标下边界,当y大于该坐标部分将不绘制,未集成LCD控制器的MCU由底层实现
color: 绘制点的颜色
@Return:
none
***********************************************************************************************************************/
virtual void drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) = 0;
/*********************************************************************************************************************
@Function: drawLine
@Description: 从指定位置(x1, y1)到(x2, y2)绘制一条直线
1. 未集成LCD控制器的MCU必须立即绘制。
2. 集成LCD控制器的MCU实现空方法即可。
@Param:
x1: 绘制直线的水平起始坐标
y1: 绘制直线的垂直起始坐标
x2: 绘制直线的水平结束坐标
y2: 绘制直线的垂直结束坐标
visibleX1: 水平绘制坐标左边界,当x1或x2小于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现
visibleY1: 垂直绘制坐标上边界,当y1或y2小于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现
visibleX2: 水平绘制坐标右边界,当x1或x2大于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现
visibleY2: 垂直绘制坐标下边界,当y1或y2大于该坐标部分将不会绘制,未集成LCD控制器的MCU由底层实现
color: 绘制点的颜色
@Return:
none
***********************************************************************************************************************/
virtual void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) = 0;
/*********************************************************************************************************************
@Function: drawBuffer
@Description: 从指定左上角位置(x,y)开始绘制一段内存数据
该内存数据按照从左到右,从上到下进行绘制,该内存数据可以为图片/字体或一个矩形区域数据
1. 未集成LCD控制器的MCU必须立即绘制。
2. 集成LCD控制器的MCU实现空方法即可。
@Param:
x: 绘制点的左上角水平坐标
y: 绘制点的左上角垂直坐标
bufferWidth: 内存数据的宽度
bufferHeight: 内存数据的高度
visibleX1: 水平绘制坐标左边界,当x小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现
visibleY1: 垂直绘制坐标上边界,当y小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现
visibleX2: 水平绘制坐标右边界,当(x + bufferWidth - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现
visibleY2: 垂直绘制坐标下边界,当(y + bufferHeight - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现
buffer: 内存数据(颜色数据),数据为大端模式
@Return:
none
***********************************************************************************************************************/
virtual void drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer) = 0;
/*********************************************************************************************************************
@Function: clear
@Description: 从指定左上角位置(x,y)开始,使用指定颜色对一块矩形区域清除
1. 未集成LCD控制器的MCU必须立即绘制。
2. 集成LCD控制器的MCU实现空方法即可。
@Param:
x: 绘制点的左上角水平坐标
y: 绘制点的左上角垂直坐标
width: 矩形区域的宽度
height: 矩形区域的高度
visibleX1: 水平绘制坐标左边界,当x小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现
visibleY1: 垂直绘制坐标上边界,当y小于该坐标时将不会绘制,未集成LCD控制器的MCU由底层实现
visibleX2: 水平绘制坐标右边界,当(x + width - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现
visibleY2: 垂直绘制坐标下边界,当(y + height - 1)大于该坐标的部分将不会绘制,未集成LCD控制器的MCU由底层实现
color: 绘制点的颜色
@Return:
none
***********************************************************************************************************************/
virtual void clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color) = 0;
/*********************************************************************************************************************
@Function: getBPP
@Description: 获取LCD像素深度,如16BPP(RGB565), 18BPP(RGB888)
@Param:
none
@Return:
像素深度,如16, 18, 24等
***********************************************************************************************************************/
virtual uint8_t getBPP() = 0;
/*********************************************************************************************************************
@Function: getScreenWidth
@Description: 获取LCD宽度(像素)
@Param:
none
@Return:
宽度值,如: 320, 800, 1920
***********************************************************************************************************************/
virtual uint32_t getScreenWidth() = 0;
/*********************************************************************************************************************
@Function: getScreenHeight
@Description: 获取LCD高度(像素)
@Param:
none
@Return:
宽度值,如: 240, 480, 1080
***********************************************************************************************************************/
virtual uint32_t getScreenHeight() = 0;
/*********************************************************************************************************************
@Function: getFB
@Description: 获取显存
1. 未集成LCD控制器的MCU返回nullptr
2. 成LCD控制器的MCU返回某一块内存首地址,内存大小 = LCD宽度 * LCD高度 * (像素深度 / 8)
@Param:
none
@Return:
内存地址
***********************************************************************************************************************/
virtual uint8_t* getFB() = 0;
/*********************************************************************************************************************
@Function: submit
@Description: GDI提交数据,代表GDI需要刷新一屏数据至LCD进行显示
1. 未集成LCD控制器的MCU可以执行一些收尾工作或实现空方法
2. 集成LCD控制器的MCU,此时必须完成窗口/层(双缓存切换),并准备好另一块缓存供GDI使用
@Param:
buffer: GDI当前持有的显存
@Return:
none
***********************************************************************************************************************/
virtual void submit(uint8_t* buffer) = 0;
};
#endif // !__TUI_FB_INTERFACE__
未集成LCD控制器的MCU
1. 必须实现的接口如下:
1. drawPoint()
当TinyUI调用该方法时,LCD驱动必须立即执行绘制点的操作。
2. drawLine()
当TinyUI调用该方法时,LCD驱动必须立即执行绘制线的操作。
3. drawBuffer()
当TinyUI调用该方法时,LCD驱动必须立即执行绘制小缓存的操作。该缓存可能是一个字符的位图,或其他小缓存,该缓存具有长和宽的特性。
4. clear()
当TinyUI调用该方法时,LCD驱动必须使用指定的颜色清除参数指定的矩形区域。
5. getBPP()
当TinyUI调用该方法时,LCD驱动返回当前LCD的像素深度,如16位、24位、32位等。
6. getScreenWidth()
当TinyUI调用该方法时,LCD驱动返回当前LCD的水平宽(像素)
7. getScreenHeight()
当TinyUI调用该方法时,LCD驱动返回当前LCD的垂直高(像素)
2. 可选实现方法
1. readPoint()
读取某一个像素点当前的颜色值,主要用于实现透明效果。
集成LCD控制器的MCU
1. 必须实现的接口
1. getBPP()
当TinyUI调用该方法时,LCD驱动返回当前LCD的像素深度,如16位、24位、32位等。
2. getScreenWidth()
当TinyUI调用该方法时,LCD驱动返回当前LCD的水平宽(像素)
3. getScreenHeight()
当TinyUI调用该方法时,LCD驱动返回当前LCD的垂直高(像素)
4. getFB()
一般情况下,集成了LCD控制器的MCU,外匹配的可用内存相对比较大,因为LCD控制器一般都会提供多个窗口或显示层,窗口或显示层即是我们通常所说的缓存概念,提高LCD刷新率。
该方法主要用于获取显存,LCD驱动返回显存首地址即可。
5. submit()
该方法用于提交并显示当前显存内容,LCD驱动底层需执行响应显存的切换动作,并返回原有显存或另一个显存(多窗口或多显示层一般都设计双缓存)
移植示例
本示例主要使用STM32F103为例进行演示,STM32F103未集成LCD控制器,而是使用FSMC接口控制ILI9341控制器对LCD进行控制,LCD分辨率为320x240。
本示例中使用的LCD驱动使用了目前后台开发比较流行的依赖注入技术,移植过程中可以看到调用device_driver_autowired()获取某一个驱动,本示例的LCD驱动也是使用C语言编写的。
移植步骤
1. 创建UIDisplay.h
1) 并包含TUIFBInterface.h
2) 定义UIDisplay类,并继承自TUIFBInterface
ifndef __UI_DISPLAY_H__
#define __UI_DISPLAY_H__
#include "device_driver_ioc.h"
#include <TUIFBIntface.h>
class UIDisplay : public TUIFBInterface
{
public:
UIDisplay();
virtual ~UIDisplay();
/* 声明TUIFBInterface所有方法 */
public:
bool readPoint(int32_t x, int32_t y, color_t* color);
void drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color);
void drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color);
void drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer);
void clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color);
uint8_t getBPP();
uint32_t getScreenWidth();
uint32_t getScreenHeight();
uint8_t* getFB();
void submit(uint8_t* buffer);
private:
lcd_controller_t *ili9341 = nullptr; // ILI9341驱动对象
};
2. 创建UIDisplay.cpp,并实现UIDisplay.h中的方法
#include <UIDisplay.h>
UIDisplay::UIDisplay()
{
ili9341 = (lcd_controller_t *)device_driver_autowired(DDTYPE_LCD_CONTROLLER, DDID_LCD_CONTROLLER_ILI9341);
ili9341->ops->open();
}
UIDisplay::~UIDisplay()
{
ili9341->ops->close();
}
bool UIDisplay::readPoint(int32_t x, int32_t y, color_t* color)
{
uint16_t c = 0;
ili9341->ops->read_point(x, y, &c);
*color = c;
return true;
}
void UIDisplay::drawPoint(int32_t x, int32_t y, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color)
{
ili9341->ops->draw_point(x, y, color);
}
void UIDisplay::drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color)
{
ili9341->ops->draw_line(x1, y1, x2, y2, color);
}
void UIDisplay::drawBuffer(int32_t x, int32_t y, uint32_t bufferWidth, uint32_t bufferHeight, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, const uint8_t* buffer)
{
ili9341->ops->draw_buffer(x, y, bufferWidth, bufferHeight, buffer);
}
void UIDisplay::clear(int32_t x, int32_t y, uint32_t width, uint32_t height, int32_t visibleX1, int32_t visibleY1, int32_t visibleX2, int32_t visibleY2, color_t color)
{
ili9341->ops->clear(x, y, width, height, color);
}
uint8_t UIDisplay::getBPP()
{
return ili9341->ops->get_bpp();
}
uint32_t UIDisplay::getScreenWidth()
{
return ili9341->ops->get_width();
}
uint32_t UIDisplay::getScreenHeight()
{
return ili9341->ops->get_height();
}
uint8_t* UIDisplay::getFB()
{
return nullptr; // 无LCD控制器,返回nullptr即可
}
void UIDisplay::submit(uint8_t* buffer)
{
// 无LCD控制器,空方法
}
向TinyUI注册LCD接口
UIDisplay *display = new UIDisplay();
LUIRegisterFBInterface(display);
模拟程序演示Button&ListView测试在STM32F103显示效果
第一行置顶,滚动到第10行,再回滚到第6行的效果