分类:
2008-10-31 09:54:40
V2 源代碼剖析
一.基礎認識
SMedia IC中內置了一顆32 bits的RISC,在源代碼一切行為判斷也都是驅駛這顆心臟來完成的,在這個RISC之上我們採了作業系統是FreeRTOS,這是個免費的作業系統,相信可以很方便的找到相關訊息。關於FreeRTOS的源代碼,我們可以在文件夾”\freertos”中看到,不過基本上不會特地去動這部份。
在開始看UI部份的代碼前,有幾件事情要先了解:我們採用的FreeRTOS是個多序(Multi-Thread)的作業系統,所以我們在設計軟件時充份利用了這個優點,在整個軟件中我們大略分為幾個thread,整個UI是一個Thread,Audio解碼部份為一個Thread,Video解碼一個及JPEG編解碼一個。也語於UI介面為單獨的一個Thread,所以有一點一定要注意不要使用”while”迴圈放在其中,避免造成無窮迴圈而造成系統死機的情況。而存取memory的方式是使用malloc/free的方式。至於一些UI上的反應行為,我們主要是事件式(Event)的方式來處理,從”dpf/main.c”的MainLoop中,可以看出目前主要接收兩種事件,按鍵(Key)及定時(Timer)。下面做個總結,我們的系統有幾點特性:
Ø Proprietary Multi-Thread OS
Ø Multi-Thread Application
Ø DO NOT contains internal “while-loop” in code
Ø Event driving programming style (windows like)
Ø Malloc/Free method for memory allocation
整個UI的源代碼起點,是從”\dpf\main.c”中的main(void)開始,做完了初始化的動作後,就進入了MainLoop中,在這個MainLoop,他會去接收兩類的Event,也就是上述所說的key及timer,而收到這兩種Event,會將訊息傳遞到當時的狀態(State),再由每個state根據情況來實現其工作。
除了state之外,我們還把除了介面樣板的其他功能切出來,我們把這些切出來的部份叫做method,
二.State
所謂的State,其實就是看到的每一種UI樣板,目前在V2中我們已經先定義好一些state,可以state.h文件中的SMTK_STATE_ID看到列表,每一個state的實體源代碼,我們可以在文件名以state_開頭的文件中找到。另外,在menu state中,還會再往下傳遞sub state,這些sub sata是以menu_開頭的文件中可以找到。
每一個state它必須處理好三件事:
(1) Initialize (2) Proc (3) Terminate
所以我們在每個相對state的文件中,都可以找得到上述三個名字的函式。
Initialize,當我們在畫面上看到華麗的效果及質感精緻的UI時,通常須要特別的照片圖示來建構,所以在Initialize中,我們會把所需要的這些元件準備好,也就是將相對應的資源取出來放在Memory中,準備之後的應用。如每一個介面上的小圖,先從jpeg文件解壓出來之類的準備動作。
Proc,上述有提過,當接收到key或timer的事件時,會傳遞到每一個狀況中處理,處理這些事件的就是在Proc中,畫面上的一些動作就是在每一個進來的timer中一格一格畫出來的。以下是兩個event的ID SMTK_MSG_ID_TIMER及SMTK_MSG_ID_KEY_DOWN。
Terminate,也就是把每一個state關閉掉時需要做的事,我們就是把memory或是surface給release掉,這裡有一個原則,在initialize中越先malloc或是create的memory或是surface,要越晚free掉。這樣可以避免掉memory fragment的問題。
l 如何建立自己的state
有關於state的一切動作,也就是event的傳遞、決定state的主體,都是靠著state.c及state.h來運作,所以當我們要新增一個state也是要對這兩個文件下手。
首先看到state.h中的
typedef enum SMTK_STATE_ID_TAG
{
SMTK_STATE_SPLASH,
SMTK_STATE_MAINTOP,
SMTK_STATE_THUMBNAIL,
SMTK_STATE_BROWSE,
SMTK_STATE_SLIDE_SHOW,
SMTK_STATE_VIDEO,
SMTK_STATE_AUDIO,
SMTK_STATE_SYSTEMSETTING,
SMTK_STATE_MENU,
SMTK_STATE_CARD,
SMTK_STATE_CLIENT,
SMTK_STATE_POWER_OFF,
SMTK_STATE_BURN_FLASH,
SMTK_STATE_ALARM,
SMTK_STATE_CALENDAR,
#ifdef SMTK_COIN_STATE_ENABLE
SMTK_STATE_COIN,
#endif
} SMTK_STATE_ID;
以上述的SMTK_STATE_ALARM為例,在這個列表中加入你要先增的state,然後建立自己的state的文件,這裡是state_alarm.c先建立
SMTK_STATE smtkAlarmState =
{
Initialize,
Terminate,
Proc
};
還有上述所說的三個state基本function
static MMP_INT Initialize(void)
static MMP_INT Proc(MMP_UINT id, MMP_ULONG arg1, MMP_ULONG arg2)
static MMP_INT Terminate(void)
接下來在state.h中,先取得smtkAlarmState,所以要加上:
extern SMTK_STATE smtkAlarmState;
另外在以下的列表中,將function pointer指定進來
static SMTK_STATE* stateEntries[] =
{
&smtkSplashState,
&smtkMainTopState,
&smtkThumbnailState,
&smtkBrowseState,
&smtkSlideShowState,
&smtkVideoState,
&smtkAudioState,
&smtkSystemSettingState,
&smtkMenuState,
&smtkCardState,
&smtkClientState,
&smtkPowerOffState,
&smtkBurnFlashState,
&smtkAlarmState,
&smtkCalendarState,
#ifdef SMTK_COIN_STATE_ENABLE
&smtkCoinState,
#endif};
三.畫面建構的概念
在整個UI做初始化的時候,我們就會先去alloc兩塊空間,這兩塊空間都是為了給屏顯示用的,一塊是當前畫面,另一塊則是在讓下一個畫面先填入所有的元素,然後在適當的時間來轉換這兩個memory,讓下一個畫面顯示在屏上面。為什麼要這樣來做呢?若只有一個空間的時候,我們每貼上一個元件在畫面上就會出現一個,在視覺上就會看到每一個不同圖片貼上去的過程,所以我們會先在背後先貼完,然後直接切換LCD屏顯示memory的位置,這樣就可以避免這樣的情況發生。在gui.c中的smtkGuiMgrInitialize,可以看到我們create兩個surface(使用mmpM2dGetScreenSurface)dispSurfA、dispSurfB,這個空間的大小會根據屏的長寬來定。用來切換這兩塊空間的function是:
MMP_INT smtkGuiMgrFlip(void)
而使用以下function先得到背面的surface,
MMP_SURFACE smtkGuiMgrGetDisplaySurface(void)
以State_splash.c中的function DrawSplash為例,一開始的時候就可以看到去做smtkGuiMgrGetDisplaySurface,然後做完要做的相對應貼圖之後,在整個function的後半段,呼叫smtkGuiMgrFlip來切換顯示buffer,畫面就可以看到剛才畫完的結果了。