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控制器,而是使用SPI接口控制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);