?? menufsm.c
字號:
/******************************************************************************
* MenuFSM.C - 菜單框架和FSM代碼
*
*
* DESCRIPTION: -
*
* modification history
* --------------------
* 01a, 04/sep/2007, 梁炎昌 written
* --------------------
******************************************************************************/
#include "CPU.H"
#include "KeyScan.H"
#include "KS0108.H"
#include "Menu.H"
//FIXME!
//改進想法:如何在菜單中可以接管其它有效按鍵,這里程序僅僅接管了方向按鍵,若能根據1--9這些數字按鍵跳轉也是不錯
//額外的問題是如何在應用程序中得到按鍵而卻不需要在應用程序中做鍵盤檢查循環(搶占CPU時間了,會使得原有可以在背景運行的程序無法執行)
/*
* A>改進FSM編號的機制,使得維護更簡單,能否自動編號?這樣會使得添加FSM表容易
* B>
*
*
*/
//-----------------------------------
//MenuTop.C
void DispMenuTop(void);
void DispMenuTopUp(void);
void DispMenuTopDown(void);
void DispMenuTopLeft(void);
void DispMenuTopRight(void);
void DispIcoMenuInit(void);
void DispIcoMenuUp(void);
void DispIcoMenuDown(void);
void DispIcoMenuLeft(void);
void DispIcoMenuRight(void);
//MenuFunc.C
void DispMenuFuncInit(void);
void DispMenuFuncUp(void);
void DispMenuFuncDown(void);
void DispMenuFuncLeft(void);
void DispMenuFuncRight(void);
//MenuPara.C
void DispMenuParaInit(void);
void DispMenuParaUp(void);
void DispMenuParaDown(void);
void DispMenuParaLeft(void);
void DispMenuParaRight(void);
//MenuLanguage.C
void DispMenuLanguageInit(void);
void DispMenuLanguageUp(void);
void DispMenuLanguageDown(void);
void DispMenuLanguageLeft(void);
void DispMenuLanguageRight(void);
//MenuMeasure.C
void DispMenuMeasureInit(void);
void DispMenuMeasureUp(void);
void DispMenuMeasureDown(void);
void DispMenuMeasureLeft(void);
void DispMenuMeasureRight(void);
#ifdef DynamicBar
//MenuFunc.C
void DispMenuDataInit(void);
void DispMenuDataUp(void);
void DispMenuDataDown(void);
void DispMenuDataLeft(void);
void DispMenuDataRight(void);
#endif
//-----------------------------------
void (*KeyFuncPtr)(); //按鍵功能指針
typedef struct{
U8 KeyStateIndex; //當前狀態索引號
U8 KeyUpState; //按下"向上"鍵時轉向的狀態索引號
U8 KeyDnState; //按下"向下"鍵時轉向的狀態索引號
U8 KeyLState; //按下"向左"鍵時轉向的狀態索引號
U8 KeyRState; //按下"向右"鍵時轉向的狀態索引號
void (*CurrentOperate)(); //當前狀態應該執行的功能操作
} KbdTabStruct;
//如下是菜單的關鍵代碼
//不清楚具體含義 不能改動
//因為跟編譯器相關
//如下的函數的名稱也不可以輕易修改
/*
********************************************************************************
FSM菜單實現機制說明:
A.一些約定:只有4個按鍵來做菜單周轉,這四個按鍵Up/Down/Left/Down 對應功能是:確認/回退/向上/向下
B.每一層的bar型菜單需要大概5個狀態(也就是5個函數)來實現,分別是MenuInit/MenuUp/MenuDown/MenuLeft/MenuRight
對應的功能解釋:
MenuInit : 初始化菜單/重新初始化菜單,在進入一個子Bar菜單時,該函數把Bar顯示指針根據語言指向子Bar的資源數組,
獲得需要的參數:該子菜單多少個Bar項(ItemNum)/每個Bar項的字符長度(Size)/指向Bar顯示內容的指針(DispItem).
而后,調用函數BarMenuInit,該函數初始化全部Bar顯示--這就是初始化菜單.
若是是從子菜單返回時,那么在返回前,Pop函數被調用,各種菜單參數被還原,在進入本函數后,本函數根據得到參數顯示Bar項
初始化菜單/重新初始化菜單的不同點在于:
初始化時 高亮顯示的位置是在頂部,對應選中的Item也是在頂部
重新初始化時 由于用戶通過按鍵向上/向下來選擇Bar項,而后通過按鍵確認來進入子菜單,為了在退出子菜單時能得到跟進入
前一致的顯示內容,因此需要備份一些相關數據:高亮的位置/選中的Item/當前FSM的Index號 在退出子菜單時Pop還原這些數據
本函數根據這些還原數據恢復顯示.
MenuUp : 根據Bar顯示內容執行對應動作函數/或者周轉到某層子菜單
MenuDown : 返回上層菜單 通常是簡單調用Pop函數
MenuLeft : 移至上一個Bar項 通常是調用BarMenuLeft函數--該函數維護Bar的顯示后FSM狀態返回MenunInit,但由于沒有打開Flash/Reflash項,因此沒有執行MenuInit函數
MenuRight: 移至下一個Bar項 通常是調用BarMenuright函數--該函數維護Bar的顯示后FSM狀態返回MenunInit,但由于沒有打開Flash/Reflash項,因此沒有執行MenuInit函數
********************************************************************************
*/
_CONST_ KbdTabStruct KeyTab[]={
// |-----------> Index
// | Up
// | | Down
// | | | Left
// | | | | Right --->功能函數
// | | | | | |
{ 0, 1, 2, 3, 4,(*DispMenuTop)},// 待機畫面
{ 1, 0, 0, 0, 0,(*DispMenuTopUp)},
{ 2, 0, 0, 0, 0,(*DispMenuTopDown)},
{ 3, 0, 0, 0, 0,(*DispMenuTopLeft)},
{ 4, 0, 0, 0, 0,(*DispMenuTopRight)},
{ 5, 6, 7, 8, 9,(*DispIcoMenuInit)}, //圖標層菜單
{ 6, 0, 0, 0, 0,(*DispIcoMenuUp)}, //
{ 7, 0, 0, 0, 0,(*DispIcoMenuDown)}, //
{ 8, 0, 0, 0, 0,(*DispIcoMenuLeft)}, //
{ 9, 0, 0, 0, 0,(*DispIcoMenuRight)},//
{10,11,12,13,14,(*DispMenuFuncInit)}, //"功能"
{11, 0, 0, 0, 0,(*DispMenuFuncUp)}, //
{12, 0, 0, 0, 0,(*DispMenuFuncDown)}, //
{13, 0, 0, 0, 0,(*DispMenuFuncLeft)}, //
{14, 0, 0, 0, 0,(*DispMenuFuncRight)},//
{15,16,17,18,19,(*DispMenuParaInit)}, //"參數"
{16, 0, 0, 0, 0,(*DispMenuParaUp)}, //
{17, 0, 0, 0, 0,(*DispMenuParaDown)}, //
{18, 0, 0, 0, 0,(*DispMenuParaLeft)}, //
{19, 0, 0, 0, 0,(*DispMenuParaRight)},//
{20,21,22,23,24,(*DispMenuLanguageInit)}, //"語言"
{21, 0, 0, 0, 0,(*DispMenuLanguageUp)}, //
{22, 0, 0, 0, 0,(*DispMenuLanguageDown)}, //
{23, 0, 0, 0, 0,(*DispMenuLanguageLeft)}, //
{24, 0, 0, 0, 0,(*DispMenuLanguageRight)},//
{25,26,27,28,29,(*DispMenuMeasureInit)}, //"測量"
{26, 0, 0, 0, 0,(*DispMenuMeasureUp)}, //
{27, 0, 0, 0, 0,(*DispMenuMeasureDown)}, //
{28, 0, 0, 0, 0,(*DispMenuMeasureLeft)}, //
{29, 0, 0, 0, 0,(*DispMenuMeasureRight)},//
#ifdef DynamicBar
{30,31,32,33,34,(*DispMenuDataInit)}, //"Data"
{31, 0, 0, 0, 0,(*DispMenuDataUp)}, //
{32, 0, 0, 0, 0,(*DispMenuDataDown)}, //
{33, 0, 0, 0, 0,(*DispMenuDataLeft)}, //
{34, 0, 0, 0, 0,(*DispMenuDataRight)},//
#endif
};
/*
*****************************************************************************
* CheckKey - 菜單鍵盤掃描函數
* DESCRIPTION: -
* 有有效按鍵則執行對應的功能函數
* 同時,若刷新標志有效,也執行相應的功能函數
* @Para void:
* Return :
*
*****************************************************************************
*/
U8 CheckKey(void)
{
U8 IsKey;
U8 Key;
IsKey = 1;
Key = KeyScan();
switch(Key){
case Key_Up:{ //向上鍵,找出新的菜單狀態編號
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyUpState;
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//執行當前按鍵的操作
break;
}
case Key_Down:{ //向下鍵,找出新的菜單狀態編號
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyDnState;
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//執行當前按鍵的操作
break;
}
case Key_Left:{ //向左鍵,找出新的菜單狀態編號
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyLState;
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//執行當前按鍵的操作
break;
}
case Key_Right:{ //向右鍵,找出新的菜單狀態編號
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyRState;
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//執行當前按鍵的操作
break;
}
//---------------------------------------------------------------------------
#ifdef DigiKeyLink
/*
2006/09/08
數字鍵做快捷方式輸入
1.判別數字鍵值是否小于ItemNum-1 否則是無效快捷方式
2.有效快捷方式下,把鍵值給Item,調用Key_Up的處理代碼
3.需要添加超時處理,超時了就不能使用?(需要么?不需要么?)
*/
case Key_1:
case Key_2:
case Key_3:
case Key_4:
case Key_5:
case Key_6:
case Key_7:
case Key_8:
case Key_9:
Key = chang_code(Key);
if((Key - '1') <= ItemNum-1){
Item = Key - '1';
if(ItemNum <= DispMax){//如果需要顯示的項比可以顯示的項少,那么修正Where 否則默認Where為0
Where = Item;
}else{
Where = 0;
}
//-------------------------------------------------
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyUpState;
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//執行當前按鍵的操作
//-------------------------------------------------
}else {
IsKey = 0;
}
break;
#endif
//---------------------------------------------------------------------------
default: //按鍵錯誤的處理
IsKey = 0;
break;
}
if(Flash){//兩個當中有任意一個不為零,那么執行一次,我們應該不會出現Flash和ReFlash都是1的情況
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate;
(*KeyFuncPtr)();//執行當前按鍵的操作
Flash = 0;
// ReFlash = 0;
}
return IsKey;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -