2021-04-15 21:07:13 +03:00

655 lines
20 KiB
C

#include <includes.h>
#include "menu.h"
#include "menudesc.h"
#include "data.h"
#include "keyboard.h"
#include "lcd.h"
#include "mode.h"
#include "app_serv.h"
#include "time.h"
OS_STK MenuTaskStk[MENU_TASK_STK_SIZE];
#define STACKPANELSIZE 8
TMenuStack MenuStack[STACKPANELSIZE];
CPU_INT08U MenuStackPtr;
CPU_INT08U MenuActiveLine, MenuFirstLine, MenuEditStatus;
TMenuPanel* MenuCurrentPanel;
CPU_INT08U EditPos, EditStart, EditLen, EditLine;
TVariant32 EditVal, EditMax, EditMin;
TDataDescStruct* EditDesc;
TRTC_Data EditTime;
// ïîçèöèè äëÿ ðåäàêòèðîâàíèÿ âðåìåíè
const CPU_INT08U EditTimePos[12] =
{
0, 1,
3, 4,
6, 7,
9,10,
12,13,
15,16
};
CPU_INT08U EditBuf[32];
#define EDIT_TYPE_NUMBER 0
#define EDIT_TYPE_ITEMS 1
CPU_INT08U refresh_menu = 0;
void ShowMenuLine(TMenuLine* line_ptr, CPU_INT08U pos)
{
CPU_INT08U strbuf[32];
if (line_ptr->LineType == MENU_LINE_STRING)
{
sprintf((char*)strbuf, " %s", (CPU_INT08U*)line_ptr->Ptr);
LCD_puts(strbuf, pos);
}
else if (line_ptr->LineType == MENU_LINE_SHOW_DESC)
{
strbuf[0] = ' ';
if ((MenuEditStatus) && (pos == EditLine))
{
// âûâîäèì ðåäàêòèðóåìóþ ñòðîêó
if (EditDesc->IsIndex)
{
GetDataNameStr((const TDataDescStruct*)EditDesc, &strbuf[1]);
strcat((char*)strbuf, "<");
strcat((char*)strbuf, (char const*)EditBuf);
strcat((char*)strbuf, ">");
LCD_puts(strbuf, pos);
}
else
{
GetDataNameStr((const TDataDescStruct*)EditDesc, &strbuf[1]);
if (EditDesc->Name) strcat((char*)strbuf, "=");
strcat((char*)strbuf, (char const*)EditBuf);
LCD_puts(strbuf, pos);
}
}
else
{
GetDataFullStr((const TDataDescStruct*)line_ptr->Ptr, &strbuf[1], 0, DATA_FLAG_SYSTEM_INDEX);
LCD_puts(strbuf, pos);
}
}
else if (line_ptr->LineType == MENU_LINE_GOTO_MENU)
{
sprintf((char*)strbuf, " %s", (CPU_INT08U*)line_ptr->Ptr);
LCD_puts(strbuf, pos);
}
}
void ClearMenuLine(CPU_INT08U pos)
{
CPU_INT08U c = 0;
LCD_puts(&c, pos);
}
void ClearDisplay(void)
{
LCD_clear();
}
TMenuPanel* GetCurrentMenu(void)
{
return MenuCurrentPanel;
}
// âûâîä òåêóùåãî ìåíþ
void ShowCurrentMenu(void)
{
// ïîäñ÷èòàåì ÷èñëî ñòðîê â òåêóùåé ïàíåëè
CPU_INT08U i, j;
TMenuLine* pLine;
//MenuCurrentPanel->LineNum
// åñëè ïàíåëü ñòàòè÷åñêàÿ, ïðîñòî âûâîäèì ïåðâûå 4 ñòðîêè
if (MenuCurrentPanel->PanelType == MENU_PANEL_STATIC)
{
j=0;
LCD_cursor_off();
for (i=0; i<MENU_LINES_NUMBER; i++)
{
pLine = (TMenuLine*)MenuCurrentPanel->LineArray[i].pMenuLine;
if (pLine == NULL) break;
ShowMenuLine(pLine, j++);
}
while (j<MENU_LINES_NUMBER)
{
ClearMenuLine(j++);
}
if ((((TMenuLine*)MenuCurrentPanel->LineArray[0].pMenuLine)->Flags) & MENU_INDEX_LINE)
{
LCD_putc_embed(SYMB_IND_MARK, MENU_SYMB_NUMBER-2, 0); LCD_putc_embed(SYMB_DESC_MARK, MENU_SYMB_NUMBER-1, 0);
}
return;
}
// â îáû÷íîì ìåíþ ïåðâàÿ ëèíèÿ âñåãäà ôèêñèðîâàííàÿ
pLine = (TMenuLine*)MenuCurrentPanel->LineArray[0].pMenuLine;
if (pLine == NULL) {ClearDisplay(); return;}
ShowMenuLine(pLine, 0);
// âûâîäèì 3 ñòðîêè ñ ïåðåìåùåíèåì ïî ìåíþ
// MenuFirstLine - âåðõíÿÿ ñòðîêà äëÿ îòîáðàæåíèÿ
if (MenuActiveLine == 0) MenuFirstLine = 0;
else
{
if (MenuCurrentPanel->LineNum < MENU_LINES_NUMBER) MenuFirstLine = MenuActiveLine-1;
else
{
if (MenuActiveLine < MenuCurrentPanel->LineNum-2) MenuFirstLine = MenuActiveLine-1;
else MenuFirstLine = MenuActiveLine-2;
}
}
i=MenuFirstLine+1;
j=1;
while((j<MENU_LINES_NUMBER) && (i<MenuCurrentPanel->LineNum))
{
TMenuLine* pline = (TMenuLine*)MenuCurrentPanel->LineArray[i].pMenuLine;
if (pline == NULL) ClearMenuLine(j);
else ShowMenuLine(pline, j);
i++;
j++;
}
while(j<MENU_LINES_NUMBER) ClearMenuLine(j++);
// ñòðåëî÷êà òåêóùåãî âûáðàííîãî ïóíêòà
CPU_INT08U linetype = (((TMenuLine*)MenuCurrentPanel->LineArray[MenuActiveLine+1].pMenuLine)->LineType);
if (linetype == MENU_LINE_STRING)
{
LCD_putc_embed(SYMB_POINT_MARK, 0, MenuActiveLine-MenuFirstLine+1);
}
else if (linetype == MENU_LINE_GOTO_MENU)
{
LCD_putc_embed(SYMB_RIGHT_ARROW, 0, MenuActiveLine-MenuFirstLine+1);
}
else if (linetype == MENU_LINE_SHOW_DESC)
{
TMenuLine* mline = ((TMenuLine*)MenuCurrentPanel->LineArray[MenuActiveLine+1].pMenuLine);
if (((const TDataDescStruct*)mline->Ptr)->Desc == DATA_DESC_EDIT)
LCD_putc_embed(SYMB_DESC_MARK, 0, MenuActiveLine-MenuFirstLine+1);
else
LCD_putc_embed(SYMB_POINT_MARK, 0, MenuActiveLine-MenuFirstLine+1);
}
// çíàê èíäåêñà
CPU_INT08U lineflags = (((TMenuLine*)MenuCurrentPanel->LineArray[0].pMenuLine)->Flags);
if (lineflags & MENU_INDEX_LINE)
{
LCD_putc_embed(SYMB_IND_MARK, MENU_SYMB_NUMBER-2, 0); LCD_putc_embed(SYMB_DESC_MARK, MENU_SYMB_NUMBER-1, 0);
}
// êóðñîð (àïïàðàòíûé)
if ((MenuEditStatus) && (!EditDesc->IsIndex))
{
if (EditDesc->Type == DATA_TYPE_ULONG)
{
LCD_goto(EditStart+EditPos, MenuActiveLine-MenuFirstLine+1);
}
else if ((EditDesc->Type == DATA_TYPE_TIME) || (EditDesc->Type == DATA_TYPE_HOUR_MIN))
{
LCD_goto(EditStart+EditTimePos[EditPos], MenuActiveLine-MenuFirstLine+1);
}
LCD_cursor_on();
}
else
{
LCD_cursor_off();
}
}
void RefreshMenu(void)
{
refresh_menu = 1;
}
// ïîèñê ïåðâîé àêòèâíîé ñòðîêè â ïàíåëè ìåíþ
CPU_INT08U GetFirstActiveLine(TMenuPanel *menu)
{
CPU_INT08U line = 0;
CPU_INT08U i = 0;
while (i++ < menu->LineNum)
{
TMenuLine* mline = (TMenuLine*)menu->LineArray[i].pMenuLine;
if ((mline->LineType == MENU_LINE_GOTO_MENU) || (mline->LineType == MENU_LINE_SHOW_DESC))
{
line = i;
break;
}
}
return line-1;
}
// ïîèñê ñëåäóþùåé àêòèâíîé ñòðîêè â ïàíåëè ìåíþ
CPU_INT08U GetNextActiveLine(TMenuPanel *menu, CPU_INT08U recent)
{
CPU_INT08U line = recent+1;
CPU_INT08U i = recent+1;
while (i++ < menu->LineNum)
{
TMenuLine* mline = (TMenuLine*)menu->LineArray[i].pMenuLine;
if ((mline->LineType == MENU_LINE_GOTO_MENU) || (mline->LineType == MENU_LINE_SHOW_DESC))
{
line = i;
break;
}
}
return line-1;
}
// ïîèñê ïðåäûäóùåé àêòèâíîé ñòðîêè â ïàíåëè ìåíþ
CPU_INT08U GetPrevActiveLine(TMenuPanel *menu, CPU_INT08U recent)
{
CPU_INT08U line = recent+1;
CPU_INT08U i = recent+1;
if (recent == 0) return 0;
while (i--)
{
TMenuLine* mline = (TMenuLine*)menu->LineArray[i].pMenuLine;
if ((mline->LineType == MENU_LINE_GOTO_MENU) || (mline->LineType == MENU_LINE_SHOW_DESC))
{
line = i;
break;
}
}
return line-1;
}
void GoToMenu(const TMenuPanel* Menu)
{
if (MenuStackPtr >= STACKPANELSIZE) return;
MenuStack[MenuStackPtr].PrevMenu = MenuCurrentPanel;
MenuStack[MenuStackPtr].PrevActiveLine = MenuActiveLine;
MenuStackPtr++;
MenuCurrentPanel = (TMenuPanel*)Menu;
MenuActiveLine = GetFirstActiveLine(MenuCurrentPanel);
if (Menu->InitFunc) Menu->InitFunc();
refresh_menu = 1;
}
void SetMenu(const TMenuPanel* Menu)
{
MenuCurrentPanel = (TMenuPanel*)Menu;
MenuActiveLine = GetFirstActiveLine(MenuCurrentPanel);
if (Menu->InitFunc) Menu->InitFunc();
refresh_menu = 1;
}
void GoToPreviousMenu(void)
{
if (!MenuStackPtr) return;
--MenuStackPtr;
MenuCurrentPanel = (TMenuPanel*)MenuStack[MenuStackPtr].PrevMenu;
MenuActiveLine = MenuStack[MenuStackPtr].PrevActiveLine;
if (MenuCurrentPanel->InitFunc) MenuCurrentPanel->InitFunc();
refresh_menu = 1;
}
void GoToNextMenu(void)
{
if ((MenuCurrentPanel->LineArray[MenuActiveLine+1].pMenuLine)->GoToPtr)
GoToMenu((MenuCurrentPanel->LineArray[MenuActiveLine+1].pMenuLine)->GoToPtr);
}
void MenuSprintf(CPU_INT08U* str, CPU_INT08U len, CPU_INT32U Val)
{
if (EditDesc->Type == DATA_TYPE_ULONG)
{
CPU_INT08U format[6];
format[0]='%';
format[1]='0';
format[2]='0'+len/10;
format[3]='0'+len%10;
format[4]='u';
format[5]=0;
sprintf((char*)str, (char const*)format, Val);
}
else if ((EditDesc->Type == DATA_TYPE_TIME) || (EditDesc->Type == DATA_TYPE_HOUR_MIN))
{
GetDataStr(EditDesc, str, 0, DATA_FLAG_SYSTEM_INDEX);
}
}
// íà÷àëî ðåäàêòèðîâàíèÿ
void EnterEdit(void)
{
// ïîçèöèÿ ðåäàêòèðîâàíèÿ, 0 - ñàìîå ñòàðøåå äåñÿòè÷íîå ÷èñëî
EditPos = 0;
// óêàçàòåëü íà ðåäàêòèðóåìûé äåñêðèïòîð
EditDesc = (TDataDescStruct*)(MenuCurrentPanel->LineArray[MenuActiveLine+1].pMenuLine)->Ptr;
// íîìåð ñòðîêè ñ ðåäàêòèðóåìûì äåñêðèïòîðîì
EditLine = MenuActiveLine+1-MenuFirstLine;
// ðåäàêòèðóåìîå ÷èñëî
GetData(EditDesc, &EditVal, 0, DATA_FLAG_SYSTEM_INDEX);
// ãðàíèöû
TRangeValueULONG* RVal = EditDesc->RangeValue;
memcpy(&EditMin, &RVal->Min, sizeof(CPU_INT32U));
memcpy(&EditMax, &RVal->Max, sizeof(CPU_INT32U));
if (EditDesc->IsIndex)
{
GetDataStr((const TDataDescStruct*)EditDesc, EditBuf, 0, DATA_FLAG_SYSTEM_INDEX);
}
else
{
GetDataNameStr((const TDataDescStruct*)EditDesc, EditBuf);
if (EditDesc->Name) strcat((char*)EditBuf, "=");
EditStart = strlen((char const*)EditBuf)+1;
if (EditDesc->Type == DATA_TYPE_ULONG)
{
sprintf((char*)EditBuf, "%u", RVal->Max);
EditLen = strlen((char const*)EditBuf);
}
else if (EditDesc->Type == DATA_TYPE_TIME)
{
EditLen = 12;
}
else if (EditDesc->Type == DATA_TYPE_HOUR_MIN)
{
EditLen = 4;
}
else
{
EditLen = 0;
}
MenuSprintf(EditBuf, EditLen, EditVal.Val32U);
}
MenuEditStatus = 1;
}
// âûõîä èç ðåäàêòèðîâàíèÿ áåç ñîõðàíåíèÿ
void EscEdit(void)
{
MenuEditStatus = 0;
}
// ñîõðàíåíèå ïàðàìåòðà
void SaveEdit(void)
{
if (EditDesc->Type == DATA_TYPE_ULONG)
{
if (!EditDesc->IsIndex)
{
sscanf((char const*)EditBuf, "%d", &EditVal.Val32U);
}
SetData(EditDesc, &EditVal, 0, DATA_FLAG_SYSTEM_INDEX);
}
else if (EditDesc->Type == DATA_TYPE_TIME)
{
TRTC_Data rtc;
ScanRTCDateTimeStringRus((char*)EditBuf, &rtc);
if (RTCCheckTime(&rtc) == 0)
{ // îê
CPU_INT32U time;
time = GetSec(&rtc);
SetData(EditDesc, &time, 0, DATA_FLAG_SYSTEM_INDEX);
}
}
else if (EditDesc->Type == DATA_TYPE_HOUR_MIN)
{
int hour, min, hour_min;
sscanf((char*)EditBuf, "%02d:%02d", &hour, &min);
hour_min = hour * 60 + min;
SetData(EditDesc, &hour_min, 0, DATA_FLAG_SYSTEM_INDEX);
}
MenuEditStatus = 0;
}
void MenuTask(void *p_arg)
{
int pause = 0;
SetMenu(START_MENU);
while (1)
{
int key=0;
if (GetKbrdEvent(&key) || (++pause >= 1000) || ((pause >= 500) && (MenuEditStatus)) || (refresh_menu != 0))
{
if (refresh_menu) {refresh_menu = 0; ShowCurrentMenu();}
// îòðàáîòêà êëàâèàòóðû
if (!MenuEditStatus)
{ // îòîáðàæåíèå ìåíþ
pause = 0;
if (key)
{
switch (key){
case KEY_UP:
//if (MenuActiveLine) MenuActiveLine--;
MenuActiveLine = GetPrevActiveLine(MenuCurrentPanel, MenuActiveLine);
ShowCurrentMenu();
break;
case KEY_DOWN:
//MenuActiveLine++;
//if (MenuActiveLine+1 >= MenuCurrentPanel->LineNum) MenuActiveLine--;
MenuActiveLine = GetNextActiveLine(MenuCurrentPanel, MenuActiveLine);
ShowCurrentMenu();
break;
case KEY_LEFT:
{
TMenuLine* pLine = (TMenuLine*)MenuCurrentPanel->LineArray[0].pMenuLine;
if (pLine->Flags & MENU_INDEX_LINE)
{// ñâåðõó èíäåêñíûé ïàðàìåòð - ïîïðîáóåì åãî ïåðåêëþ÷èòü
TDataDescStruct* desc = (TDataDescStruct*)pLine->Ptr;
if (desc->Type == DATA_TYPE_ULONG)
{
CPU_INT32U i, min, max;
GetData(desc, &i, 0, DATA_FLAG_SYSTEM_INDEX);
GetDataMin(desc, &min);
GetDataMax(desc, &max);
i--;
if ((i < min) || (i > max)) i = max;
SetData(desc, &i, 0, DATA_FLAG_SYSTEM_INDEX);
}
ShowCurrentMenu();
}
}
break;
case KEY_RIGHT:
{
TMenuLine* pLine = (TMenuLine*)MenuCurrentPanel->LineArray[0].pMenuLine;
if (pLine->Flags & MENU_INDEX_LINE)
{// ñâåðõó èíäåêñíûé ïàðàìåòð - ïîïðîáóåì åãî ïåðåêëþ÷èòü
TDataDescStruct* desc = (TDataDescStruct*)pLine->Ptr;
if (desc->Type == DATA_TYPE_ULONG)
{
CPU_INT32U i, min, max;
GetData(desc, &i, 0, DATA_FLAG_SYSTEM_INDEX);
GetDataMin(desc, &min);
GetDataMax(desc, &max);
i++;
if ((i < min) || (i > max)) i = min;
SetData(desc, &i, 0, DATA_FLAG_SYSTEM_INDEX);
}
ShowCurrentMenu();
}
}
break;
case KEY_STOP:
// ïðîáóåì âûéòè â ïðåäûäóùåå ìåíþ
GoToPreviousMenu();
break;
case KEY_START:
{
if (MenuCurrentPanel->PanelType == MENU_PANEL_STATIC) {ShowCurrentMenu();break;}
TMenuLine* pLine = (TMenuLine*)MenuCurrentPanel->LineArray[MenuActiveLine+1].pMenuLine;
if (pLine->LineType == MENU_LINE_SHOW_DESC)
{// âõîäèì â ðåäàêòèðîâàíèå, åñëè ìîæíî
TDataDescStruct* desc = (TDataDescStruct*)pLine->Ptr;
if (desc->Desc == DATA_DESC_EDIT) {EnterEdit(); pause=1000;}
}
else if (pLine->LineType == MENU_LINE_GOTO_MENU)
{// ïðîáóåì ïåðåéòè â ñëåäóþùåå ìåíþ
GoToNextMenu();
}
}
break;
}//switch (key)
}//if (key)
else
{
ShowCurrentMenu();
}
}
else//if (!MenuEditStatus)
{ // ðåäàêòèðîâàíèå ïàðàìåòðà
if (key)
{
switch (key){
case KEY_UP:
if (EditDesc->IsIndex)
{
CPU_INT32U min, max;
GetDataMin(EditDesc, &min);
GetDataMax(EditDesc, &max);
EditVal.Val32U++;
if ((EditVal.Val32U < min) || (EditVal.Val32U > max)) EditVal.Val32U = min;
GetDataItem(EditDesc, EditBuf, EditVal.Val32U);
}
else
{
if (EditDesc->Type == DATA_TYPE_ULONG)
{
EditBuf[EditPos]++;
if (EditBuf[EditPos] > '9') EditBuf[EditPos] = '0';
}
else if (EditDesc->Type == DATA_TYPE_TIME)
{
EditBuf[EditTimePos[EditPos]]++;
if (EditBuf[EditTimePos[EditPos]] > '9') EditBuf[EditTimePos[EditPos]] = '0';
}
else if (EditDesc->Type == DATA_TYPE_HOUR_MIN)
{
EditBuf[EditTimePos[EditPos]]++;
if (EditBuf[EditTimePos[EditPos]] > '9') EditBuf[EditTimePos[EditPos]] = '0';
}
}
break;
case KEY_DOWN:
if (EditDesc->IsIndex)
{
CPU_INT32U min, max;
GetDataMin(EditDesc, &min);
GetDataMax(EditDesc, &max);
EditVal.Val32U--;
if ((EditVal.Val32U < min) || (EditVal.Val32U > max)) EditVal.Val32U = max;
GetDataItem(EditDesc, EditBuf, EditVal.Val32U);
}
else
{
if (EditDesc->Type == DATA_TYPE_ULONG)
{
EditBuf[EditPos]--;
if (EditBuf[EditPos] < '0') EditBuf[EditPos] = '9';
}
else if (EditDesc->Type == DATA_TYPE_TIME)
{
EditBuf[EditTimePos[EditPos]]--;
if (EditBuf[EditTimePos[EditPos]] < '0') EditBuf[EditTimePos[EditPos]] = '9';
}
else if (EditDesc->Type == DATA_TYPE_HOUR_MIN)
{
EditBuf[EditTimePos[EditPos]]--;
if (EditBuf[EditTimePos[EditPos]] < '0') EditBuf[EditTimePos[EditPos]] = '9';
}
}
break;
case KEY_LEFT:
if (EditDesc->IsIndex)
{
CPU_INT32U min, max;
GetDataMin(EditDesc, &min);
GetDataMax(EditDesc, &max);
EditVal.Val32U--;
if ((EditVal.Val32U < min) || (EditVal.Val32U > max)) EditVal.Val32U = max;
GetDataItem(EditDesc, EditBuf, EditVal.Val32U);
}
else
{
if (EditPos) EditPos--;
}
break;
case KEY_RIGHT:
if (EditDesc->IsIndex)
{
CPU_INT32U min, max;
GetDataMin(EditDesc, &min);
GetDataMax(EditDesc, &max);
EditVal.Val32U++;
if ((EditVal.Val32U < min) || (EditVal.Val32U > max)) EditVal.Val32U = min;
GetDataItem(EditDesc, EditBuf, EditVal.Val32U);
}
else
{
if (EditPos < EditLen-1) EditPos++;
}
break;
case KEY_STOP:
EscEdit();
break;
case KEY_START:
SaveEdit();
break;
}//switch (key)
ShowCurrentMenu();
}//if (key)
else
{
pause = 0;
ShowCurrentMenu();
}
}//if (!MenuEditStatus)
}
}
}
void InitMenu(void)
{
MenuStackPtr = 0;
MenuActiveLine = 0;
MenuFirstLine = 0;
MenuEditStatus = 0;
MenuCurrentPanel = NULL;
memset(&MenuStack, 0, sizeof(TMenuStack)*STACKPANELSIZE);
OSTaskCreate(MenuTask, (void *)0, (OS_STK *)&MenuTaskStk[MENU_TASK_STK_SIZE-1], MENU_TASK_PRIO);
}
void ReInitMenu(void)
{
OSTaskDel(MENU_TASK_PRIO);
ClearDisplay();
OSTimeDly(100);
InitMenu();
OSTimeDly(100);
if (GetMode() == MODE_WORK) SetMenu(WORK_MENU);
else SetMenu(SERVICE_MENU);
}