日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 裸機思維
[導讀]在前面的文章《【例說Arm-2D界面設計】“手擼GUI”的利器——場景播放器》中,我們詳細介紹了智能設備時代一種“基于面板(Panel)的嵌入式界面設計范式”,并以Arm-2D的場景播放器(Scene Player)為例,介紹了小資源環(huán)境下具體“手搓GUI”的方式。

【說在前面的話】


在前面的文章《【例說Arm-2D界面設計】“手擼GUI”的利器——場景播放器》中,我們詳細介紹了智能設備時代一種“基于面板(Panel)的嵌入式界面設計范式”,并以Arm-2D的場景播放器(Scene Player)為例,介紹了小資源環(huán)境下具體“手搓GUI”的方式。
很多小伙伴看了以后大為震撼,并紛紛發(fā)出了叩問靈魂的拷問:

我芯片內部Flash已經(jīng)很緊張了,隨便一個背景圖你讓我存哪里?


這是個好問題。一般來說,我們所說的小資源環(huán)境是指:內部FLASH空間小于64K,當然也包括那些雖然芯片F(xiàn)lash較大(比如有128K)但原本的應用代碼已經(jīng)非常龐大——“留給GUI的空間已經(jīng)不多”的情況。總之,留給Arm-2D的代碼空間已經(jīng)捉襟見肘,圖片資源又該保存到哪里呢?

一般來說,很多芯片會提供一個叫做 XIP 的外設(也許你的芯片中對應的外設并不叫這個名字,但你可以根據(jù)下面的功能描述來對號入座),以便:
  • 通過QSPI接口連接外部的SPI Flash芯片;
  • 將外部Flash芯片中的內容映射到4G地址空間中

換句話說,我們可以像訪問內部Flash那樣使用芯片外部的SPI Flash,這其中不僅包括存儲數(shù)據(jù)(比如圖片),甚至還可以執(zhí)行代碼。


如果你芯片擁有XIP,那么你的芯片已經(jīng)不屬于我們所討論的“資源受限”的環(huán)境了——因為大容量的片外Flash不僅長見而且廉價。相信很多人對此都非常熟悉,我就不再贅述了。


如果你的芯片沒有XIP,而你也只能通過外設 SPI 和自己編寫的驅動來訪問外部 Flash,此時,我們如何使用 Arm-2D 來簡化“手搓GUI” 的開發(fā)過程呢?不要急,本文就將為你揭曉謎底。


【什么是虛擬資源(Virtual Resource)】


Arm-2D幾乎所有API的基本操作單位都是“貼圖(Tile)”,它的數(shù)據(jù)結構定義如下:
/*! * \brief a type for tile *  */typedef struct arm_2d_tile_t arm_2d_tile_t;struct arm_2d_tile_t { implement_ex(struct { uint8_t bIsRoot              : 1; //!< is this tile a root tile uint8_t bHasEnforcedColour   : 1; //!< does this tile contains enforced colour info uint8_t bDerivedResource     : 1; //!< indicate whether this is a derived resources (when bIsRoot == 0) uint8_t bVirtualResource     : 1; //!< indicate whether the resource should be loaded on-demand uint8_t : 4; uint8_t : 8; uint8_t : 8; arm_2d_color_info_t tColourInfo; //!< enforced colour }, tInfo);  implement_ex(arm_2d_region_t, tRegion); //!< the region of the tile  union { /* when bIsRoot is true, phwBuffer is available, * otherwise ptParent is available */ arm_2d_tile_t *ptParent; //!< a pointer points to the parent tile uint8_t *pchBuffer; //!< a pointer points to a buffer in a 8bit colour type uint16_t *phwBuffer; //!< a pointer points to a buffer in a 16bit colour type uint32_t *pwBuffer; //!< a pointer points to a buffer in a 32bit colour type  intptr_t nAddress; //!< a pointer in integer };};
如果看著比較暈,不要緊,其實它就只有三大部分而已:
  • 貼圖的各類屬性描述信息:tInfo

  • 貼圖的尺寸和位置信息: tRegion

  • 貼圖的指針或引用


貼圖從種類上來說分類兩種:根貼圖(Root Tile)子貼圖(Child Tile)。其中,根貼圖是指那些直接“擁有”具體圖片資源(或者是顯示緩沖區(qū))的貼圖(Tile),這表現(xiàn)在:
  • 根貼圖的屬性 tInfo.bIsRoot 一定為 true
  • 根貼圖的指針直接指向具體的資源數(shù)組或者現(xiàn)實緩沖區(qū)

從前面的數(shù)據(jù)結構中,我們可以看到union中有很多指針,比如 pchBuffer、phwBuffer和pwBuffer。由于他們都是共用體,因此這些指針保存的地址值都是相同的,而具體使用哪個類型的指針則取決于目標資源的顏色格式,這一信息可以是省略的,但一般通過 img2c.py 腳本轉換出來的tile都會在tInfo.tColourInfo中包含具體的顏色信息。

值得強調的是 ptParent 僅在子貼圖中有意義,用于指向自己的父貼圖(Parent Tile),而 nAddress 僅僅是方便對地址值進行四則運算的一個整形變量(uintptr_t)。


推論1:我們所有的圖片資源都是用根貼圖來描述的。
也許你已經(jīng)從根貼圖的指針看出了端倪:普通的根貼圖要求其指向的圖片資源必須存在于4G地址空間中——換句話說就是普通指針可以訪問的地方——保存在外部Flash中的圖片資源(在未經(jīng)XIP幫助的情況下)則無法滿足上述要求,因此無法直接用 arm_2d_tile_t 進行描述

為了解決這一問題,arm-2d 在基類 arm_2d_tile_t 的基礎上派生出了一個新的類:虛擬資源(Virtual Resource),arm_2d_vres_t——專門用于描述這類無法直接訪問的圖片資源。其數(shù)據(jù)結構如下:

/*! * \brief a type for virtual resource * * \note the flag tTile.tInfo.bVirtualResource must be true (1) */typedef struct arm_2d_vres_t arm_2d_vres_t;struct arm_2d_vres_t {  /*! base class: tTile */ implement_ex( arm_2d_tile_t, tTile);  /*!  a reference of an user object  */ uintptr_t pTarget;  /*! *  \brief a method to load a specific part of an image *  \param[in] pTarget a reference of an user object  *  \param[in] ptVRES a reference of this virtual resource *  \param[in] ptRegion the target region of the image *  \return intptr_t the address of a resource buffer which holds the content */ intptr_t (*Load)   ( uintptr_t pTarget,  arm_2d_vres_t *ptVRES,  arm_2d_region_t *ptRegion);  /*! *  \brief a method to despose the buffer *  \param[in] pTarget a reference of an user object  *  \param[in] ptVRES a reference of this virtual resource *  \param[in] pBuffer the target buffer */ void (*Depose) ( uintptr_t pTarget,  arm_2d_vres_t *ptVRES,  intptr_t pBuffer );};



對上述結構提描述感到一頭霧水的小伙伴不要慌張——實際使用中,我們并不需要與 arm_2d_vres_t 的內部結構打交道——arm-2d為我們提供了傻瓜式的封裝服務,使用起來依然非常簡單。


【如何使用虛擬資源?】


這里,我們假設你已經(jīng)按照文章《【喂到嘴邊了的模塊】準備徒手擼GUI?用Arm-2D三分鐘就夠了》的步驟完成了Arm-2D的部署。
準備階段:
在工程管理器中展開 Acceleration,并找到你的LCD驅動模板 arm_2d_disp_adapter_0.h(這里假設你只有一個屏幕):


通過Configuraion Wizard打開圖形配置界面:


假設你已經(jīng)配置好了其它部分,勾選這里的“Enable the virtual resoure helper service” 選項后保存——至此,我們就為 Display Adapter 0 開啟了其專屬的虛擬資源輔助服務(Helper Service)。需要強調的是,每個Display Adapter 都有自己獨立的虛擬資源輔助服務,需要獨立的打開。


此時,如果直接編譯,會看到如下的錯誤:
Error: L6218E: Undefined symbol __disp_adapter0_vres_get_asset_address (referred from arm_2d_disp_adapter_0.o).Error: L6218E: Undefined symbol __disp_adapter0_vres_read_memory (referred from arm_2d_disp_adapter_0.o).

不要慌,這是我們有意為之——它提醒我們作為用戶需要提供(實現(xiàn))兩個最基本額接口函數(shù):

  • __disp_adapter0_vres_read_memory()

一個專門用于從外部存儲器的指定地址讀取指定長度字節(jié)的函數(shù),其原型如下:
void __disp_adapter0_vres_read_memory( intptr_t pObj,  void *pBuffer, uintptr_t pAddress, size_t nSizeInByte);

這里:

    • pObj 我們可以暫時忽略

    • pBuffer 指向一塊緩沖區(qū),用于保存我們從外部存儲器中讀取到的內容;

    • pAddress 保存的是目標內容在外部存儲器中的地址;

    • nSizeInByte 保存的是要讀取的字節(jié)數(shù)


一般來說,如果我們已經(jīng)事先調試好了一個SPI Flash讀取函數(shù),就可以輕松的實現(xiàn)這一函數(shù),比如:

extern void spi_flash_read(void *pBuffer,  uint32_t nAddressInFlash, size_t nSize); void __disp_adapter0_vres_read_memory(intptr_t pObj,  void *pBuffer, uintptr_t pAddress, size_t nSizeInByte){ ARM_2D_UNUSED(pObj); /* it is just a demo, in real application, you can place a function to  * read SPI Flash  */ spi_flash_read(pBuffer, (void * const)pAddress, nSizeInByte);}



  • __disp_adapter0_vres_get_asset_address()

一個專門用于返回當前虛擬資源起始地址的函數(shù)。需要注意的是,它的返回類型是 uintptr_t,在Cortex-M環(huán)境下是一個32位的無符號整形(uint32_t),我們用它來返回目標圖片在SPI Flash中的起始地址綽綽有余。其函數(shù)原型是:
uintptr_t __disp_adapter0_vres_get_asset_address( uintptr_t pObj, arm_2d_vres_t *ptVRES);

這里:

    • pObj 我們可以暫時忽略

    • ptVRES 指向的是我們的目標虛擬資源


在最簡單的情況下,假設你的系統(tǒng)只有一背景圖保存在外部SPI Flash中,且地址為 0x00000000,那么這個函數(shù)就極其簡單了:

uintptr_t __disp_adapter0_vres_get_asset_address(uintptr_t pObj, arm_2d_vres_t *ptVRES){ ARM_2D_UNUSED(ptVRES); ARM_2D_UNUSED(pObj);  return 0x00000000;}

也許你要問,如果我要處理多個圖片該怎么辦呢?別著急,后面會有專門的章節(jié)詳細介紹?,F(xiàn)階段我們先專注于完成一個最簡單的例子。


完成了上述準備工作,再次編譯就應該毫無問題了。




創(chuàng)建自己的虛擬資源:


在要創(chuàng)建虛擬資源的源代碼中加入對 Display Adapter 0 的頭文件引用:

#include "arm_2d_disp_adapter_0.h"


定義一個 arm_2d_vres_t 類型的靜態(tài)變量(或者全局變量),并使用專門的宏 disp_adapter0_impl_vres 來描述資源的顏色和尺寸信息,比如:

static arm_2d_vres_t s_tMyVirtualRes =  disp_adapter0_impl_vres(  ARM_2D_COLOUR_RGB565, // 圖片的顏色格式 320, // 圖片的寬度 256, // 圖片的高度 );

其中,宏disp_adapter0_impl_vres() Display Adapter 0 專用的,以此類推,如果你的虛擬資源要在 Display Adapter 1上使用,則對應的描述宏為 disp_adapter1_impl_vres()。不管如何,它們的原型是一樣的:

disp_adapter0_impl_vres(__COLOUR_FORMAT, __WIDTH, __HEIGHT,...)

這里:

    • __COLOUR_FORMAT 是目標素材的顏色格式,具體可用的顏色在 arm_2d_type.h 中定義,都以 ARM_2D_COLOUR_ 作為前綴。

    • __WIDTH 是目標素材的像素寬度

    • __HEIGHT是目標素材的像素高度

    • ... 是一系列可選的參數(shù),主要用于初始化 arm_2d_vres_t 中的一些特殊成員(比如 pTarget),這個在隨后的章節(jié)中會用到。


在上述例子中,我們創(chuàng)建了一個虛擬資源 s_tMyVirtualRes,由于它是 arm_2d_tile_t 的派生類,因此可以像普通的貼圖那樣在arm-2d的API中作為素材(source tile)蒙版(mask)來直接使用,比如:

/* 把 虛擬素材 顯示在屏幕上 */arm_2d_tile_copy(   &s_tMyVirtualRes.tTile, /* 素材 */ ptTile, /* 目標緩沖區(qū) */ NULL,  ARM_2D_CP_MODE_COPY); 


效果如下:




正如我們前面說過的,虛擬素材(virtual resource)也是貼圖(Tile)的一種,因此,也可以在它的基礎上創(chuàng)建子貼圖(Child Tile),比如:

staticconst arm_2d_tile_t c_tChildImage = { .tRegion = { .tLocation = { .iX = 160, .iY = 128, }, .tSize = { .iWidth = 160, .iHeight = 128, }, }, .tInfo = { .bIsRoot = false, .bDerivedResource = true, }, .ptParent = (arm_2d_tile_t *)&s_tMyVirtualRes.tTile,};

這里:

  • bIsRootfalse,清晰的標明了 c_tChildImage 的子貼圖身份;

  • 創(chuàng)建子貼圖作為素材時,bDerivedResource一定要設置為 true,切記切記!

  • 這個例子中,觀察 tLocationtSize容易發(fā)現(xiàn):我們實際上是取了原圖右下角的1/4作為新的素材


修改代碼,將新的素材也拷貝到屏幕上:

/* 把 虛擬素材 顯示在屏幕上 */arm_2d_tile_copy(   &s_tMyVirtualRes.tTile, /* 素材 */ ptTile, /* 目標緩沖區(qū) */ NULL,  ARM_2D_CP_MODE_COPY);/* 把 子貼圖 顯示在屏幕上 */arm_2d_tile_copy(   &c_tChildImage, /* 素材 */ ptTile, /* 目標緩沖區(qū) */ NULL,  ARM_2D_CP_MODE_COPY);

由于我們在拷貝子貼圖時沒有指定要復制的位置(給了NULL),因此被默認放置到了屏幕的左上角,形成了如下的效果:





【我們有多個圖片該怎么辦?】


前面的例子中,為了讓小伙伴們快速的體驗虛擬資源的爽快,因此我們對內容作了簡化——只演示了一個圖片的情況——實際應用中,顯然這是無法滿足要求的。

聰明的小伙伴也許已經(jīng)注意到了,當存在多個圖片資源的時候,決定我們實際讀取那一張圖片的關鍵就是函數(shù) __disp_adapter0_vres_get_asset_address() 的返回值——它返回誰的地址,讀取的就是誰的圖片。
觀察它的函數(shù)原型,容易發(fā)現(xiàn)兩個形參都很有潛質。
uintptr_t __disp_adapter0_vres_get_asset_address( uintptr_t pObj, arm_2d_vres_t *ptVRES)

換句話說,支持多圖片的關鍵就在于如何使用傳遞進來的參數(shù)返回對應圖片在外部存儲器中的地址


進一步觀察 arm_2d_vres_t 的結構,我們可以注意到一個有趣的成員 pTarget
 typedef struct arm_2d_vres_t arm_2d_vres_t;struct arm_2d_vres_t { ... /*!  a reference of an user object  */ uintptr_t pTarget; ...};


無論我們給它賦任何內容,它的值都會作為第一個實參傳遞給接口函數(shù)

__disp_adapter0_vres_read_memory(intptr_t pObj, …… )

__disp_adapter0_vres_get_asset_address(uintptr_t pObj, ……)

也就是這里的 pObj。


至此,對多圖片的支持實際上就形成了兩種方式:

  • 面向對象的方式(OOPC)

  • 所見即所得的方式


對于熟悉使用C語言進行面向對象開發(fā)(OOPC)的小伙伴來說,恐怕看了上面的描述就已經(jīng)心領神會了吧。這里就不再贅述。


剩下的篇幅,我們將著重介紹“所見即所得”的方法:


步驟一:在建立(描述)虛擬資源時,將目標圖片在外部存儲器中的地址直接賦值給 pTarget。比如:
static arm_2d_vres_t s_tVRes0 =  disp_adapter0_impl_vres(  ARM_2D_COLOUR_RGB565, 32, 32, .pTarget = <這個資源在外部存儲器中的地址> ); static arm_2d_vres_t s_tVRes1 =  disp_adapter0_impl_vres(  ARM_2D_COLOUR_RGB565, 32, 32, .pTarget = <這個資源在外部存儲器中的地址> );...


步驟二:在函數(shù) __disp_adapter0_vres_get_asset_address 直接將 pObj 的值(也就是 ptVRES->pTarget)的值返回:

uintptr_t __disp_adapter0_vres_get_asset_address(uintptr_t pObj, arm_2d_vres_t *ptVRES){ ARM_2D_UNUSED(ptVRES); return pObj;}


本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉