久久精品国产精品国产一区,少妇扒开毛毛自慰喷水,国产精品无码电影在线观看 ,久久天天躁夜夜躁狠狠85麻豆

思澈科技軟件開發(fā)工具包  2.20
LCD

簡介

LCD device是一個rt_device,內(nèi)部是一個簡單的LCD框架用于注冊不同屏幕驅(qū)動。本章節(jié)主要介紹LCD device的使用及框架,以及如何注冊一個新屏幕到該框架。

內(nèi)部結(jié)構(gòu)

LCD驅(qū)動有3層:

  • rt_device_graphic層 - 對上層提供統(tǒng)一調(diào)用接口
    • 內(nèi)部支持多個驅(qū)動查找功能,方便兼容多個屏(根據(jù)比較注冊的ID和ReadID函數(shù)返回的值決定)
    • 內(nèi)部包含3個framebuffer機制,讓渲染和送屏可以同步進行,支持壓縮。
  • 具體驅(qū)動的邏輯層
    • 具體各個屏驅(qū)動的接口、頻率、TE等配置,以及初始化代碼、送屏命令,睡眠,開關(guān)指令
  • 屏物理接口的抽象層
    • 對大部分接口提供統(tǒng)一的操作函數(shù) 詳見LCDC
Figure 1: lcd device SW arch
Note
SDK內(nèi)實現(xiàn)了2個rt_device_graphic實例,rt_device name:
  • lcd(drv_lcd.c)
    • 正常物理LCD屏
  • ram_lcd(drv_ram_lcd.c)
    • 將輸出寫到SRAM(打開后將從系統(tǒng)堆內(nèi)存分配一個LCD buffer)
    • ram_lcd的使用跟正常屏幕一樣(屏幕尺寸固定)

上層使用LCD device的示例

在屏幕中央繪制一個100*100的RGB565格式的紅色區(qū)域,每刷新一次紅色加深一點,32次后從頭循環(huán)。

#define RGB565_FB_WIDTH 100
#define RGB565_FB_HEIGHT 100
static uint16_t rgb565_frambuffer[RGB565_FB_WIDTH * RGB565_FB_HEIGHT];
static struct rt_semaphore lcd_sema;
static rt_err_t lcd_flush_done(rt_device_t dev, void *buffer)
{
rt_sem_release(&lcd_sema);
return RT_EOK;
}
void lcd_flush_task(void *parameter)
{
rt_err_t ret;
uint8_t color = 0;
struct rt_device_graphic_info info;
uint16_t framebuffer_color_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
/* LCD Device Init */
rt_device_t lcd_device = rt_device_find("lcd");
RT_ASSERT(lcd_device != RT_NULL);
rt_device_set_tx_complete(lcd_device, lcd_flush_done);
if (rt_device_open(lcd_device, RT_DEVICE_OFLAG_RDWR) == RT_EOK)
{
if (rt_device_control(lcd_device, RTGRAPHIC_CTRL_GET_INFO, &info) == RT_EOK)
{
rt_kprintf("Lcd info w:%d, h%d, bits_per_pixel %d\r\n", info.width, info.height, info.bits_per_pixel);
}
}
rt_device_control(lcd_device, RTGRAPHIC_CTRL_SET_BUF_FORMAT, &framebuffer_color_format);
rt_sem_init(&lcd_sema, "lv_lcd", 1, RT_IPC_FLAG_FIFO);
while (1)
{
rt_err_t err;
int32_t dx, dy;
/*Draw framebuffer at center of screen*/
dx = (info.width - RGB565_FB_WIDTH) / 2;
dy = (info.height - RGB565_FB_HEIGHT) / 2;
/* Fill RGB565 framebuffer with red color*/
color = (color + 1) % 0x1F;
for(uint32_t i = 0; i < RGB565_FB_HEIGHT; i++)
for(uint32_t j = 0; j < RGB565_FB_WIDTH; j++)
{
rgb565_frambuffer[(i * RGB565_FB_WIDTH) + j] = ((uint16_t )color) << 11;
}
//Wait lcd_flush_done to release lcd_sema
err = rt_sem_take(&lcd_sema, rt_tick_from_millisecond(1000));
RT_ASSERT(RT_EOK == err);
/*
設(shè)置繪圖操作的有效區(qū)域,以下所有坐標的坐標系原點是屏幕左上角
*/
rt_graphix_ops(lcd_device)->set_window(dx, dy, dx + RGB565_FB_WIDTH - 1, dy + RGB565_FB_HEIGHT - 1);
/*
將一個buffer畫到LCD設(shè)備上,異步函數(shù),完成后調(diào)用lcd_flush_done
關(guān)于{x0,y0,x1,y1}區(qū)域:
1. 該區(qū)域表示整個buffer在屏幕上占據(jù)的區(qū)域,并不是用于剪切該buffer的
2. 如果只更新buffer中的某一部分,需配合set_window函數(shù)使用
*/
rt_graphix_ops(lcd_device)->draw_rect_async((const char *)&rgb565_frambuffer, dx, dy, dx + RGB565_FB_WIDTH - 1, dy + RGB565_FB_HEIGHT - 1);
}
}

增加一個新屏幕的流程

1. 選擇example\rt_driver下對應(yīng)板子的工程

  • 這個工程里面有一個簡單的繪制矩形區(qū)域的示例(見前面 “rt_device_graphic層接口的使用示例”)
  • 如果選擇用watch_demo工程,需要 把tp線程關(guān)閉再調(diào)屏幕 ,防止TP不通阻塞UI送屏線程(關(guān)閉辦法:drv_touch.c touch_open函數(shù),去掉rt_thread_startup(touch_thread); )

2. 將新驅(qū)動添加到編譯工程里面

  • 添加新屏幕代碼到目錄customer\peripherals內(nèi)

    • 可以從其他已有的驅(qū)動復(fù)制一份代碼,然后將名字、ID、對應(yīng)的命令(絕大部分都一樣不需要改)改成自己的
    • 注意修改內(nèi)部的Kconfig文件的depend宏
    • 屏驅(qū)注冊的宏說明:
      LCD_DRIVER_EXPORT(
      rm69090, //屏驅(qū)的名稱,字符串
      RM69090_ID, //屏驅(qū)的ID,用于和RM69090_ReadID的返回值做比較
      &lcdc_int_cfg, //屏驅(qū)的初始化配置(包括接口、頻率、輸出顏色格式等)
      &RM69090_drv, //屏驅(qū)的對外API接口實現(xiàn)
      RM69090_LCD_PIXEL_WIDTH, // IC的橫向最大分辨率(注意不是玻璃的分辨率)
      RM69090_LCD_PIXEL_HEIGHT, // IC的垂直最大分辨率(注意不是玻璃的分辨率)
      2 //刷新時的像素對齊(不需要則寫1)
      );
    Note
    玻璃的分辨率固定在宏LCD_DRIVER_EXPORT的定義內(nèi),見宏LCD_HOR_RES_MAX和LCD_VER_RES_MAX
  • 在customer\peripherals\Kconfig內(nèi),為新加的驅(qū)動添加一個隱藏開選項,比如:
    config LCD_USING_RM69090
    bool
    default n
  • 在板級的配置中添加屏幕模組的開關(guān),模組開關(guān)內(nèi)選上前面添加的隱藏開關(guān)以及使用的接口開關(guān)(接口開關(guān)用于修改pinmux),比如customer\boards\ec-lb551XXX\Kconfig內(nèi),添加模組開關(guān):
    config LCD_USING_ED_LB55SPI17801_QADSPI_LB551
    bool "1.78 rect QAD-SPI LCD(ED-LB55SPI17801)"
    select TSC_USING_FT3168 if BSP_USING_TOUCHD
    select LCD_USING_RM69090
    select BSP_LCDC_USING_QADSPI
    if LCD_USING_ED_LB55SPI17801_QADSPI_LB551
    config LCD_RM69090_VSYNC_ENABLE
    bool "Enable LCD VSYNC (TE signal)"
    def_bool n
    endif
    Note
    觸控的添加流程類似屏,并在此處模組開關(guān)內(nèi)一并選擇
  • 還是在上面文件中,為新添加的屏幕定義分辨率、DPI值(***注意此處是模組玻璃的分辨率,不是屏幕IC能支持的最大分辨率***)
    config LCD_HOR_RES_MAX
    int
    default 454 if LCD_USING_ED_LB55SPI17201_QADSPI_LB551
    default 400 if LCD_USING_ED_LB55_77903_QADSPI_LB551
    default 240 if LCD_USING_ED_LB55_387A_JDI_LB551
    default 368 if LCD_USING_ED_LB55SPI17801_QADSPI_LB551 <-------- 新添加的行
    config LCD_VER_RES_MAX
    int
    default 454 if LCD_USING_ED_LB55SPI17201_QADSPI_LB551
    default 400 if LCD_USING_ED_LB55_77903_QADSPI_LB551
    default 240 if LCD_USING_ED_LB55_387A_JDI_LB551
    default 448 if LCD_USING_ED_LB55SPI17801_QADSPI_LB551 <-------- 新添加的行
    config LCD_DPI
    int
    default 315 if LCD_USING_ED_LB55SPI17201_QADSPI_LB551
    default 315 if LCD_USING_ED_LB55_77903_QADSPI_LB551
    default 315 if LCD_USING_ED_LB55_387A_JDI_LB551
    default 315 if LCD_USING_ED_LB55SPI17801_QADSPI_LB551 <-------- 新添加的行
  • 若用scons 編譯,則需要進入工程的menuconfig選擇菜單,然后選擇前面新增的屏幕模組,最終生成.config和rtconfig.h
  • 若用Keil編譯,也可以直接添加源代碼進入(但還是建議和scons編譯添加方法一樣,這樣下次重新生成Keil工程后會自動加入)

3. 檢查新增LCD用到的pin,以及reset pin 的pinmux是否正確

  • 如前所述,在模組的配置時會選擇一個接口的宏,SDK內(nèi)部有對不同的LCDC接口宏做pin mux處理
  • reset pin由于是獨立的GPIO控制,需要確認BPS_LCD_Reset函數(shù)控制的pin是否正確

4. 修改新屏幕的接口、頻率、輸出顏色格式

  • 見下面示例,修改LCD_DRIVER_EXPORT宏內(nèi)init_cfg結(jié)構(gòu)體(輸出頻率跟配置的可能會有偏差,請以實際輸出的為準,因為HAL層實現(xiàn)輸出頻率=HCLK/divider, HCLK在console輸入"sysinfo"可以查看,divider為2~255的整數(shù))
  • TE在調(diào)試初期建議關(guān)閉,防止LCDCD因為等不到TE信號而不送數(shù)(我們的TE信號是LCDC自動處理,不需要軟件參與)
    Note
    我們的TE信號是LCDC自動處理,不需要軟件參與,所以沒有TE軟件中斷上來。只要TE pin mux和極性正確配置,啟動LCDC送數(shù)后(HAL_LCDC_SendLayerData2Reg_IT),收到了TE脈沖LCDC就會啟動送數(shù)

5 使用任意GPIO作為TE信號(可選)

大部分情況下,只要定義相應(yīng)的管腳為TE功能,LCDC就可以自動處理TE信號,但在某些特殊情況下,TE信號無法從期望的通路來時,需要改成普通GPIO來實現(xiàn),此時可以通過軟件GPIO中斷辦法實現(xiàn):

  • 按照正常的配置將TE打開、設(shè)置好TE的延遲
  • 定義宏“LCD_USE_GPIO_TE”為一個普通GPIO, 它將會在中斷上升沿主動去人為制造一個TE信號(翻轉(zhuǎn)TE極性),從而觸發(fā)LCDC送數(shù)據(jù)
    Note
    因為正常TE通路不正常,所以第一步的設(shè)置無法工作,只能靠第二步的人為制造信號去觸發(fā)送數(shù),從而實現(xiàn)正常TE處理

6. 修改新屏幕驅(qū)動的初始化代碼

  • 一般是先初始化LCDC,配置接口、頻率等. 調(diào)用API - HAL_LCDC_Init.
  • 然后是reset LCD , 通過drv_io.c內(nèi)實現(xiàn)的BPS_LCD_Reset函數(shù)去控制GPIO 復(fù)位屏幕。
  • 然后就是屏廠給的初始化代碼

7. 修改read id函數(shù)

  • drv_lcd.c 將利用該函數(shù)返回值和LCD_DRIVER_EXPORT注冊的ID比較, 相同則認為該驅(qū)動可用,才會去調(diào)用。

8. QAD-SPI LCD擴展命令修改

  • QAD-SPI LCD 一般會把標準8bit命令擴展成32bit,需要修改擴展方法。 可以參考rm69330.c, 一般有這幾個函數(shù)需要修改: RM69330_WriteMultiplePixels, RM69330_WriteReg,RM69330_ReadData。




客戶新增屏幕驅(qū)動代碼示例(部分)

以下示例代碼展示了RM69330如何注冊到drv_lcd.c(rt_device_graphic層)以及接口配置、函數(shù)回調(diào)等. 具體每個函數(shù)的實現(xiàn)請參考SDK代碼,此處不贅述。

//RM69330 chip IDs
#define RM69330_ID 0x8000
//RM69330 resulution
#define RM69330_LCD_PIXEL_WIDTH (454)
#define RM69330_LCD_PIXEL_HEIGHT (454)
//Interface, Frequency, Output color format, TE
static LCDC_InitTypeDef lcdc_int_cfg_qspi =
{
.lcd_itf = LCDC_INTF_SPI_DCX_4DATA, //QAD-SPI mode
.freq = 48000000,
.color_mode = LCDC_PIXEL_FORMAT_RGB565,
.cfg = {
.spi = {
.dummy_clock = 0, //0: QAD-SPI/SPI3 1:SPI4
.syn_mode = HAL_LCDC_SYNC_VER,
.vsyn_polarity = 0,
.vsyn_delay_us = 1000,
.hsyn_num = 0,
},
},
};
//Function callbacks
static const LCD_DrvOpsDef RM69330_drv =
{
RM69330_Init,
RM69330_ReadID,
RM69330_DisplayOn,
RM69330_DisplayOff,
RM69330_SetRegion,
RM69330_WritePixel,
RM69330_WriteMultiplePixels,
RM69330_ReadPixel,
RM69330_SetColorMode,
RM69330_SetBrightness
};
//Regist to drv_lcd.c
LCD_DRIVER_EXPORT(rm69330, RM69330_ID, &lcdc_int_cfg_qspi,
&RM69330_drv,
RM69330_LCD_PIXEL_WIDTH,
RM69330_LCD_PIXEL_HEIGHT,2);
Note
如前面所述,drv_lcd.c 初始化時將比較 LCD_DRIVER_EXPORT注冊的RM69330_IDRM69330_ReadID返回的ID,如果相同才會調(diào)用。




同時兼容多個屏幕模組

假設(shè)要兼容2各模組:

  • 模組一為LB55SPI17801(屏幕IC是RM69090,觸控IC是FT3168),
  • 模組二為LB55BILI8688E(屏幕IC是ILI8688E,觸控IC是CST918),

跟前面添加屏幕一樣,往工程對應(yīng)的Kconfig文件添加一項同時選擇2款模組的屏驅(qū)和觸控驅(qū)動即可(注意:屏驅(qū)的ReadID函數(shù)要能分別2款I(lǐng)C,同理觸控的probe函數(shù)也要能區(qū)分不同的IC)。

Kconfig文件示例如下:

config LCD_USING_ED_LB55SPI17801_LB55BILI8688E_QADSPI_LB551
bool "1.78 rect QAD-SPI LCD(ED-LB55SPI17801 and ED-LB55BILI8688E)"
select TSC_USING_FT3168 if BSP_USING_TOUCHD
select TSC_USING_CST918 if BSP_USING_TOUCHD
select LCD_USING_RM69090
select LCD_USING_ILI8688E
select BSP_LCDC_USING_QADSPI
if LCD_USING_ED_LB55SPI17801_LB55BILI8688E_QADSPI_LB551
config LCD_RM69090_VSYNC_ENABLE
bool
def_bool n
config LCD_ILI8688E_VSYNC_ENABLE
bool
def_bool y
endif
Note
其他的屏幕分辨率配置,DPI配置就共用LCD_USING_ED_LB55SPI17801_LB55BILI8688E_QADSPI_LB551宏去設(shè)置即可,既然兼容這些參數(shù)應(yīng)該都是一樣的




DSI屏幕調(diào)試

建議先調(diào)低速模式 因為低速可以繞過因為硬件導(dǎo)致的問題,并且好用示波器分析。    低速模式調(diào)通后讀ID,讀ID 能檢查屏幕上電是否正常。
低速模式讀ID,刷屏都正常后,再改用高速模式刷屏

DSI低速模式操作流程

  • 降低LCDC送數(shù)的速度
    • 需要將系統(tǒng)時鐘降到48M,在drv_io.c內(nèi),將HAL_RCC_HCPU_ClockSelect(RCC_CLK_MOD_SYS, XXX); XXX就是系統(tǒng)時鐘頻率,改成RCC_SYSCLK_HXT48(晶體時鐘48MHz)
    • 將所有命令都改成LP模式(低速模式)發(fā)送,并且打開LCD acknowledge,方便用邏分儀或示波器抓取波形分析(在前面的LCDC_InitTypeDef那個結(jié)構(gòu)體內(nèi)配置,如下:)
      .LPCmd = {
      .LPGenShortWriteNoP = DSI_LP_GSW0P_ENABLE,
      .LPGenShortWriteOneP = DSI_LP_GSW1P_ENABLE,
      .LPGenShortWriteTwoP = DSI_LP_GSW2P_ENABLE,
      .LPGenShortReadNoP = DSI_LP_GSR0P_ENABLE,
      .LPGenShortReadOneP = DSI_LP_GSR1P_ENABLE,
      .LPGenShortReadTwoP = DSI_LP_GSR2P_ENABLE,
      .LPGenLongWrite = DSI_LP_GLW_ENABLE,
      .LPDcsShortWriteNoP = DSI_LP_DSW0P_ENABLE,
      .LPDcsShortWriteOneP = DSI_LP_DSW1P_ENABLE,
      .LPDcsShortReadNoP = DSI_LP_DSR0P_ENABLE,
      .LPDcsLongWrite = DSI_LP_DLW_ENABLE, //DSI_LP_DLW_DISABLE, ENABLE - LP mode, DISABLE - high speed mode
      .LPMaxReadPacket = DSI_LP_MRDP_ENABLE,
      .AcknowledgeRequest = DSI_ACKNOWLEDGE_ENABLE, //Enable LCD error reports
      },
      Note
      init->cfg.dsi.LPCmd.LPDcsLongWrite調(diào)成DSI_LP_DLW_ENABLE后, HAL_LCDC_Init內(nèi)部會主動將DBI的送數(shù)頻率降到最低(48 * 16 / 126 = 6Mbps 左右,48為系統(tǒng)時鐘,16為DBI帶寬,126為最大分頻系數(shù))
  • 調(diào)整DSI LP 模式的頻率到屏幕能支持的范圍(一般在6~20Mbps), 如下配置時LP頻率 = 480 / 8 / 4 = 15Mbps(其中480為freq, 8 為固定值, 4為TXEscapeCkdiv)
    static LCDC_InitTypeDef lcdc_int_cfg_dsi =
    {
    .freq = DSI_FREQ_480MHZ,
    .color_mode = LCDC_PIXEL_FORMAT_RGB888,
    .cfg = {
    .dsi = {
    .Init = {
    .AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_ENABLE,
    .NumberOfLanes = RM69090_DSI_DATALANES,
    .TXEscapeCkdiv = 0x4,
    },
    ...
    }
    ...
    }
    ...
    }
  • 將drv_lcd 層的刷屏超時時間加長,否則默認的500ms在低速下容易超時,調(diào)整宏MAX_LCD_DRAW_TIME的值即可
  • 使能bf0_hal_dsi.c里面的log(需要覆蓋HAL_DBG_printf), 可以通過log檢查通信過程發(fā)生的錯誤
    #define DSI_LOG_D(...) HAL_DBG_printf(__VA_ARGS__)
    #define DSI_LOG_E(...) HAL_DBG_printf(__VA_ARGS__)
  • 如果有條件可以用邏分儀或示波器抓取DATALANE0上P,N兩個引腳的波形,解析各個命令、顏色格式等是否是期望的數(shù)據(jù)
    Note
    讀ID時,屏幕在bus turnaround之后有沒有ack,若沒有可能上電或者reset異常

DSI 高速模式配置

  • 低速模式可以讀ID和刷期望的顏色后,可以調(diào)成高速模式,一般來說就通了。
    • 高速模式要把AcknowledgeRequest改成disable,否則容易引起發(fā)數(shù)fifo溢出,
    • 另外注意有的屏幕不同的顏色格式對應(yīng)不一樣的最高頻率。
在前面的LCDC_InitTypeDef那個結(jié)構(gòu)體內(nèi)配置,如下:
.LPCmd = {
...
.LPDcsLongWrite = DSI_LP_DLW_DISABLE, //高速模式主要就是這里把長包改成高速模式
...
.AcknowledgeRequest = DSI_ACKNOWLEDGE_DISABLE, //高速模式下需要把Ack包關(guān)掉
},

DSI 顏色,TE功能配置

  • DSI顏色格式 參考DSI
  • DSI TE功能 DSI TE有2條通路可選:通過DSI鏈路或者通過LCDC_TE的功能管腳 如果走LCDC_TE管腳,需要同時指定一個物理管腳的pinmux 為 LCDC_TE功能(可以是LCDCx_SPI_TE/LCDCx_8080_TE)
    static LCDC_InitTypeDef lcdc_int_cfg_dsi =
    {
    .freq = DSI_FREQ_480MHZ,
    .color_mode = LCDC_PIXEL_FORMAT_RGB888,
    .cfg = {
    .dsi = {
    ...
    .CmdCfg = {
    ...
    .TearingEffectSource = DSI_TE_EXTERNAL, <<<---- DSI_TE_EXTERNAL 代表走LCDC_TE管腳, DSI_TE_DSILINK代表走DSI鏈路
    Note
    在55x系列芯片上,不支持DSI使用LCDC_TE的功能管腳,請參考上面“使用任意GPIO作為TE信號”章節(jié)的辦法。
HAL_LCDC_SYNC_VER
@ HAL_LCDC_SYNC_VER
Definition: bf0_hal_lcdc.h:176
LCDC_INTF_DSI
@ LCDC_INTF_DSI
DSI interface(Command mode)
Definition: bf0_hal_lcdc.h:136
LCDC_INTF_SPI_DCX_4DATA
@ LCDC_INTF_SPI_DCX_4DATA
SPI which has DCX pin, output with 4 data line.
Definition: bf0_hal_lcdc.h:127
LCDC_InitTypeDef
Definition: bf0_hal_lcdc.h:310
LCDC_InitTypeDef::lcd_itf
HAL_LCDC_IF_TypeDef lcd_itf
Definition: bf0_hal_lcdc.h:311