TinyUI-LCD驅動對接

       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);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章