/* Demo: LED Menu (LED_Menu.c) Compiler: BC++ 3.1 Compile mode: large Project: led_menu.c ..\lib\8000l.lib ; you must change this lib to ; suit the hardware that you want to use. PC sends commands to I-8000, and get back responses is a very typical application. But sometimes, they don't want to use any PC to send the commands to let the I-8000 do different tasks. The I-8000 provides a simple man-machine interface (SMI),includes LEDs and push buttons.You can use it to display and key in simple information. This demo shows how to using the SMI to implempt a tree menu. Hardware: I-8000 [Sep,15,2003] by Kevin Usage: 1. Enters menu mode: press "Mode" and "Set" for a while. (the time to hold press is depend on the scan loop speed, you can change the code "if(iKeyCount_Mode>150 && iKeyCount_Set>150)" in function CheckLEDMenu) L2=on, L3=on ==> menu mode L2=off, L3=off ==> normal mode 2. "Mode": swiths node in same level For example: current level =2, level 1 is Node[1][1], Node[2][0] --> Node[2][1] --> .... --> Node[2][6] --> Node[2][0] --> Node[2][1] --> .... --> Node[2][6] --> ... 3. "Set": executes function the function is depend on iKeyInValueStatus [Back] ==> backs to up level, LED shows "Back?", "?" means back to which levle. [SubMenu] ==> enter to sub menu, LED shows current position in the menu. [Value] ==> enables to change value. press "Up and "Down" to increase and decrease value. press "Mode" to switch digits. [Reset] ==> sets values to default values. The tree of the LED menu is: 0 --+-\Node[1][0] [Back] | | +-\Node[1][1] --------+-\Node[2][0] (back) [Back] | [SubMenu] +-\Node[2][1] ('-' or '0') [Enable] | (Sets to all +-\Node[2][2] ('0' ~ '9') [Enable] | system values) +-\Node[2][3] ('0' ~ '9') [Enable] | +-\Node[2][4] ('0' ~ '9') [Enable] | +-\Node[2][5] ('0' ~ '9') [Enable] | +-\Node[2][6] (Reset) [Reset] | +-\Node[1][2] --------+-\Node[2][0~7] --+-\Node[3][0] (back) [Back] [SubMenu] | [Disable] +-\Node[3][1] ('-' or '0') [Enable] (Sets to all | (selects slot) +-\Node[3][2] ('0' ~ '9') [Enable] channels of one | +-\Node[3][3] ('0' ~ '9') [Enable] slot) | +-\Node[3][4] ('0' ~ '9') [Enable] | +-\Node[3][5] ('0' ~ '9') [Enable] | +-\Node[3][6] (Reset) [Reset] | +-\Node[2][8] [Back] */ #include "..\Lib\8000.h" #include #include // defination for key in value status #define MENU_ROOT 0 #define MENU_SUBMENU 1 #define MENU_VALUE 2 #define MENU_RESET 3 #define MENU_BACK 4 int iKeyInValueStatus; int iOldKey; int iKeyCount_Mode,iKeyCount_Up,iKeyCount_Down,iKeyCount_Set; int iMenu_Node[4]; //Recodes current node number of each level. //For example: iMenu_Node[2]=3 // ====> level 2 at node3 int iMenu_Current_Level; float fSystemValue[8][8]; int iLED_Digit[6]; //iLED_Digit[0] is not used. unsigned long sw_LED; //Records time when pushing button. (for menu mode) unsigned long sw_EnterMenu; //Recoeds time when enter menu mode. int iLED_Timeout=15000; //unit: ms. when buttons are not pressed for a while, // back to normal mode. int iLED_SwitchTime; //for normal mode int iLED_SwitchTime_Long=3000; //unit: ms. //Wait for how many ms to start to flash. int iLED_SwitchTime_Short=1500; void ShowLED_Value(float fValue) { int iDigit; if(fValue>0) iLED_Digit[1]=0; else iLED_Digit[1]=17; iLED_Digit[2]=(int)(fValue/10)%10; iLED_Digit[3]=(int)fValue%10; iLED_Digit[4]=(int)(fValue*10)%10; iLED_Digit[5]=(int)(fValue*100)%10; for(iDigit=1;iDigit<=5;iDigit++) Show5DigitLed(iDigit,iLED_Digit[iDigit]); Show5DigitLedWithDot(3,iLED_Digit[3]); } void ReShowLED_Value(void) { int iDigit; for(iDigit=1;iDigit<=5;iDigit++) Show5DigitLed(iDigit,iLED_Digit[iDigit]); Show5DigitLedWithDot(3,iLED_Digit[3]); } void ShowLED_Reset(void) { Show5DigitLedSeg(1,0x77); //R Show5DigitLed(2,0xe); //E Show5DigitLed(3,5); //S Show5DigitLed(4,0xe); //E Show5DigitLedSeg(5,0x70); //T } void ShowLED_Back(void) { Show5DigitLed(1,0xb); //B Show5DigitLed(2,0xa); //A Show5DigitLed(3,0xc); //C Show5DigitLedSeg(4,0xf); //K Show5DigitLed(5,iMenu_Current_Level-1); //back to upper level } float GetLEDValue(void) { int i; float fValue; //Set All if(iKeyInValueStatus==MENU_VALUE) { fValue=iLED_Digit[2]*10+ iLED_Digit[3]+ (float)iLED_Digit[4]/10+ (float)iLED_Digit[5]/100.0; if(iLED_Digit[1]!=0) fValue*=(-1); } else fValue=0; return fValue; } void ProcessMode(void) { iMenu_Node[iMenu_Current_Level]++; switch(iMenu_Current_Level) { case 1: if(iMenu_Node[1]>2) iMenu_Node[1]=0; if(iMenu_Node[1]==0) iKeyInValueStatus=MENU_BACK; else iKeyInValueStatus=MENU_SUBMENU; break; case 2: if(iMenu_Node[1]==1) { ReShowLED_Value(); if(iMenu_Node[2]>6) iMenu_Node[2]=0; if(iMenu_Node[2]==0) iKeyInValueStatus=MENU_BACK; else if(iMenu_Node[2]<6) iKeyInValueStatus=MENU_VALUE; else iKeyInValueStatus=MENU_RESET; } else if(iMenu_Node[1]==2) { if(iMenu_Node[2]>8) iMenu_Node[2]=0; if(iMenu_Node[2]==8) iKeyInValueStatus=MENU_BACK; else iKeyInValueStatus=MENU_SUBMENU; } break; case 3: if(iMenu_Node[1]==2) { ReShowLED_Value(); if(iMenu_Node[3]>6) iMenu_Node[3]=0; if(iMenu_Node[3]==0) iKeyInValueStatus=MENU_BACK; else if(iMenu_Node[3]<6) iKeyInValueStatus=MENU_VALUE; else iKeyInValueStatus=MENU_RESET; } break; default: iMenu_Node[iMenu_Current_Level]=1; break; } sw_LED=*TimeTicks; iLED_SwitchTime=iLED_SwitchTime_Long; sw_EnterMenu=*TimeTicks; } void ProcessUp(void) { int iDigit; iDigit=iMenu_Node[iMenu_Current_Level]; if(iDigit==1) { if(iLED_Digit[iDigit]==17) iLED_Digit[iDigit]=0; else iLED_Digit[iDigit]=17; } else if(iDigit>1 && iDigit<6) { iLED_Digit[iDigit]++; if(iLED_Digit[iDigit]>9) iLED_Digit[iDigit]=0; } sw_LED=*TimeTicks; sw_EnterMenu=*TimeTicks; } void ProcessDown(void) { int iDigit; iDigit=iMenu_Node[iMenu_Current_Level]; if(iDigit==1) { if(iLED_Digit[iDigit]==17) iLED_Digit[iDigit]=0; else iLED_Digit[iDigit]=17; } else if(iDigit>1 && iDigit<6) { iLED_Digit[iDigit]--; if(iLED_Digit[iDigit]<0) iLED_Digit[iDigit]=9; } sw_LED=*TimeTicks; sw_EnterMenu=*TimeTicks; } void ProcessSet(void) { int i; switch(iMenu_Current_Level) { case 1: if(iKeyInValueStatus==MENU_BACK) { iMenu_Current_Level--; iMenu_Node[0]=0; iMenu_Node[1]=0; } else if(iMenu_Node[1]==1) { iMenu_Current_Level++; iMenu_Node[2]=1; iKeyInValueStatus=MENU_VALUE; ShowLED_Value(fSystemValue[0][0]); } else if(iMenu_Node[1]==2) { iMenu_Current_Level++; iMenu_Node[2]=0; iKeyInValueStatus=MENU_SUBMENU; } break; case 2: if(iMenu_Node[1]==1) { if(iKeyInValueStatus==MENU_VALUE) fSystemValue[0][0]=GetLEDValue(); else if(iKeyInValueStatus==MENU_RESET) fSystemValue[0][0]=30.0; for(i=1;i<8;i++) fSystemValue[i][0]=fSystemValue[0][0]; iMenu_Current_Level--; iMenu_Node[1]=0; iMenu_Node[2]=0; iKeyInValueStatus=MENU_BACK; } if(iMenu_Node[1]==2) { if(iKeyInValueStatus==MENU_BACK) { iMenu_Current_Level--; iMenu_Node[1]=0; iMenu_Node[2]=0; iKeyInValueStatus=MENU_BACK; } else { iMenu_Current_Level++; iMenu_Node[3]=1; iKeyInValueStatus=MENU_VALUE; ShowLED_Value(fSystemValue[iMenu_Node[2]][0]); } } break; case 3: if(iKeyInValueStatus==MENU_VALUE) fSystemValue[iMenu_Node[2]][0]=GetLEDValue(); else if(iKeyInValueStatus==MENU_RESET) fSystemValue[iMenu_Node[2]][0]=30.0; iMenu_Current_Level--; iMenu_Node[2]=8; iMenu_Node[3]=0; iKeyInValueStatus=MENU_BACK; break; default: iMenu_Node[iMenu_Current_Level]=1; break; } sw_LED=*TimeTicks; iLED_SwitchTime=iLED_SwitchTime_Long; sw_EnterMenu=*TimeTicks; } void CheckLEDMenu(void) { int iKeyValue; unsigned long sw_ChangeValue; if(iMenu_Current_Level>0) if((*TimeTicks-sw_EnterMenu)>iLED_Timeout) { iMenu_Current_Level=0; iMenu_Node[1]=1; iMenu_Node[2]=0; iMenu_Node[3]=0; SetLedL2(LED_OFF); SetLedL3(LED_OFF); iKeyCount_Mode=0; iKeyCount_Set=0; } if(IsSystemKey()) { if(iOldKey!=*KeyStatus) { iOldKey=*KeyStatus; iKeyCount_Mode=0; iKeyCount_Set=0; if(iMenu_Current_Level>0) { if(iOldKey&SKEY_MODE_DOWN) ProcessMode(); if(iOldKey&SKEY_SET_DOWN) ProcessSet(); if(iKeyInValueStatus==MENU_VALUE) { if(iOldKey&SKEY_UP_DOWN) ProcessUp(); if(iOldKey&SKEY_DOWN_DOWN) ProcessDown(); } } } else { if(iMenu_Current_Level==0) { if(iOldKey&SKEY_MODE_DOWN) iKeyCount_Mode++; if(iOldKey&SKEY_SET_DOWN) iKeyCount_Set++; } } if(iMenu_Current_Level==0) { if(iKeyCount_Mode>500 && iKeyCount_Set>500) { iMenu_Current_Level=1; iMenu_Node[1]=1; iMenu_Node[2]=0; iMenu_Node[3]=0; SetLedL2(LED_ON); SetLedL3(LED_ON); iKeyCount_Mode=0; iKeyCount_Set=0; iKeyInValueStatus=MENU_SUBMENU; sw_EnterMenu=*TimeTicks; } } } //In menu mode, display menu information. if(iMenu_Current_Level>0) { if((*TimeTicks-sw_LED)<200) { switch(iKeyInValueStatus) { case MENU_BACK: ShowLED_Back(); break; case MENU_RESET: ShowLED_Reset(); break; case MENU_VALUE: Show5DigitLed(iMenu_Node[iMenu_Current_Level],16); break; default: Show5DigitLed(1,16); Show5DigitLed(2,16); Show5DigitLed(3,16); Show5DigitLed(4,16); Show5DigitLed(5,16); break; } } else if((*TimeTicks-sw_LED)>=200 && (*TimeTicks-sw_LED)<1000) { switch(iKeyInValueStatus) { case MENU_BACK: ShowLED_Back(); break; case MENU_RESET: ShowLED_Reset(); break; case MENU_VALUE: if(iMenu_Node[iMenu_Current_Level]==3) Show5DigitLedWithDot(iMenu_Node[iMenu_Current_Level], iLED_Digit[iMenu_Node[iMenu_Current_Level]]); else Show5DigitLed(iMenu_Node[iMenu_Current_Level], iLED_Digit[iMenu_Node[iMenu_Current_Level]]); break; default: Show5DigitLed(1,16); Show5DigitLed(2,iMenu_Node[1]); Show5DigitLed(3,iMenu_Node[2]); Show5DigitLed(4,iMenu_Node[3]); Show5DigitLed(1,16); Show5DigitLedWithDot(iMenu_Current_Level+1,iMenu_Node[iMenu_Current_Level]); break; } } else { sw_LED=*TimeTicks; } } //Not in menu mode, display default information. else { SetLedL2(LED_OFF); SetLedL3(LED_OFF); if((*TimeTicks-sw_LED)=iLED_SwitchTime && (*TimeTicks-sw_LED)<(iLED_SwitchTime+iLED_SwitchTime_Short)) { //Shows "88888" Show5DigitLed(1,8); Show5DigitLed(2,8); Show5DigitLed(3,8); Show5DigitLed(4,8); Show5DigitLed(5,8); } else if((*TimeTicks-sw_LED)>=(iLED_SwitchTime+iLED_SwitchTime_Short)) { sw_LED=*TimeTicks; iLED_SwitchTime=iLED_SwitchTime_Short; } } } void main(void) { fSystemValue[0][0]=12.34; fSystemValue[1][0]=11.34; fSystemValue[2][0]=22.56; fSystemValue[3][0]=33.78; fSystemValue[4][0]=44.90; fSystemValue[5][0]=55.12; fSystemValue[6][0]=66.34; fSystemValue[7][0]=77.56; InstallCom1(115200,8,0); Init5DigitLed(); iOldKey=0; sw_LED=*TimeTicks; while(1) { CheckLEDMenu(); } }