需要說明的是,上述的物件並不能涵蓋現在和將來所有的中可能出現的內容,但卻是OSD的基本的和主要的內容,通過對它們進行分類和進行統一的處理,可以幫我們完成通常意義上的OSD的80-90%的工作。
使用基於對象的方法處理OSD UI
傳統的處理手法是將特定場景下的OSD物件逐一用代碼“畫”出來,在遇到特定的UI事件時,再利用一堆if else判斷出特定場景和操作對象,並做相應的OSD處理。在OSD較簡單的情況下,其不失為一個可行的方法。但在遇到OSD場景和模式較多的情況下,這個if else的結構會變得很大,而且更為重要的是極易出錯以及維護成本提高。
隨著OSD越來越複雜以及代碼工作量的不斷提高,人們意識到我們需要花費太多時間在這些“表麵文章”上,而真正重要的應用層和設備驅動層的開發時間會受到影響,進而影響新產品的開發進度。固件工程師也不願不斷重複編寫同樣代碼來滿足不斷改變客戶的特定OSD需要。
筆者早期也曾遭遇同樣的困擾,麵對部門裏工程師毫無效率地做著同樣的事情,感覺到開發一個統一的OSD UI平 台的重要性。現在對於上述OSD UI進行的分析,可以讓我們開發出獨立於特定數字視頻處理器平台和OSD發生機製的硬件環境的獨立統一開發工具。
事實上,平板顯示芯片方案的重要提供者如Genesis、Pixelworks等為了加速其產品的開發和應用速度,已經提供了具有這樣功能的基於Windows的固件開發工具。本文試圖探討這一類工具的運作原理,或許讀者基於本文可以開發出自己所需要的工具,當然其應用具有更廣泛的代表性。
筆者在最近的液晶電視開發案例中使用了這樣一個結構:
typedef struct
{
byte mode;//UI場景適用的模式
byte lan; // UI語言
byte scene; // UI場景
byte last; // UI上個場景
byte next; // UI下個場景
byte sel; //UI 當前場景對物件的選擇
byte sel_total; //UI當前場景中選擇項的總數
byte *info; // UI的物件指針
byte pos_v; // 物件垂直方向位置
byte pos_h; // 物件水平方向的位置
byte col_f; // 物件的前景顏色
byte col_b; // 物件的背景顏色
byte att; // 物件的其它顯示屬性
ACT_Struct (*act)[]; // 該物件的響應動作表指針
byte *note; // 導航說明信息
}UI_Struct;

圖4:Pixelworks的GUI Builder OSD
UI開發工具界麵。
這樣的結構是為了描述一個OSD物件的基本屬性及規定其對於動作的相應表現。利用這樣的結構將場景中的每個物件描述清楚,則一個特定UI場景的OSD內容就可以被確定,而同時被確定的還有其上一個場景、下一個場景及動作響應特性等所有UI特性。這樣的信息構成一個數組,由一個統一的“解釋平台”對其進行翻譯和描述,從而將整個UI構造完成。
這有點類似解釋語言,而我們所需要做的就是編寫這些“腳本”,對物件進行OSD“繪製”的工作由“解釋”平台去調用外部的OSD發生器的驅動代碼來完成。當需要改變OSD發生器或基於不同平麵顯示控製器平台時,隻需要更新少量OSD部分驅動代碼,從而實現UI係統“平台無關化”。
我們需要構造相關物件的數據結構,以便“解釋”平台識別物件類型並進行正確的繪製。例如下麵的結構完成了一個語言選項(文字物件)的描述:
void UI_ChangeLan()
{
UI_Lan=VAL_Lan;
ReDraw();
}
code byte *STR_LAN_CHN[]=
{
“中文”,
“英文”,
“法文”,
“西班牙文”,
};
code word TXT_LAN_CHN[]=
{
//文字物件的標誌 對應的文字資源 對應的變量 具有的可選項目總數 當該物件被改變時的執行動作
RES_TXT,STR_LAN_CHN,VAL_LAN,sizeof(STR_LAN_CHN)/sizeof(byte *),UI_ChangeLan
};
第一個數據RES_TXT向“解釋”平台表明這個物件是文字,具有文字的數據結構。“解釋”平台依據這一點,按照事先約定的結構讀取後繼數據,第二個數據表明其文字內容的來源是STR_LAN_CHN,第三個數據表明需要根據哪個變量來決定獲取文字資源中第幾個數據,而第四個數據表明,該物件具有多少個可供選擇的文字內容,最後一個數據規定了當該物件發生改變時需要做什麼。這樣,“解釋”平台獲得了足夠的信息去“繪製”這樣一個語言選項,並可以在發生改變時去自動執行UI_ChangeLan()這個函數,幫助程序員去完成語言改變所需要進行的操作。

本文相關DataSheet:
事實上,所有這些結構完全可以進行定製,隻要與“解釋”平台保持一致就可以了。
利用這樣一個驅動結構,一旦“解釋”平台構建完成,OSD開發人員需要做的就變成利用平台支持的各種物件積木,進行擺放、堆積來構造OSD圖形表現,而不必要重複編寫實現代碼和關心與特定硬件平台相關的驅動代碼細節。
更進一步,甚至連這些積木的擺放和設計,我們可以設計一個直觀的Windows應用程序來完成諸如圖形-->字符元件生成器、OSD圖形界麵設計,以及最終的資源文件和UI資料數組的生成,並與底層的“解釋”平台進行聯接編譯,得到最後的MCU代碼。
這樣的OSD界麵開發環境會擺脫抽象、枯燥和低效率,變得直觀、有趣,甚至可以由客戶自己設計相關的OSD的界麵,而完全不需要經驗和對OSD底層驅動的了解。
需要指出的是,相較傳統的if else,結構化的OSD UI處理機製會帶來最終程序體積的增加和運行速度的變慢,但是這些缺點在MCU內部程序空間不斷增加和支持的時鍾頻率不 斷提高的情況下是微不足道的。所以,如果讀者麵對的案例是對MCU處理速度和程序存儲器受限的情況下,可能並不適用這樣的方案。以筆者開發的液晶電視項目為例,在支持所有電視功能、圖文、麗音及遊戲、日曆等附加功能的情況下,基於MCS51的多任務係統的總程序小於32KB,而基於Myson MTV230的OSD+MCU處理器的運行速度非常快,並不會感到任何延遲。而通常支持位圖OSD的開發環境使用的是X86或更快速的ARM等處理器,並具有大於2MB的程序存儲空間。
本文小結
當固件開發工程師麵對越來越複雜的應用時,麵向對象、結構化的編程方式會變得越來越重要,其直接的好處是編程效率的提高和維護成本的下降,同時對於程序的健壯性也有幫助。本文提供的方法的優越性已經在實際的開發案例中得到檢驗,這樣完成同樣的OSD界麵,筆者可以縮短到原來的1/4的時間,並提高了代碼的質量。