/********************************************************************\ Name: menu.c Created by: Stefan Ritt Contents: Menu handling with switches and LED display \********************************************************************/ #include #include #include #include #include "mscbemb.h" #include "mpdc.h" #include "git-revision.h" /*------------------------------------------------------------------*/ // states for state machine #define ST_DEFAULT 0 #define ST_POWER 1 #define ST_CHANNEL 2 #define ST_CURR 3 #define ST_TEMP 4 #define ST_MSCB 5 #define ST_VERSION 6 #define ST_LAST ST_VERSION #define SW_PREV (1 << 3) #define SW_NEXT (1 << 2) #define SW_INC (1 << 1) #define SW_DEC (1 << 0) sbit NSW_PREV = P2^3; sbit NSW_NEXT = P2^4; sbit NSW_INC = P2^5; sbit NSW_DEC = P2^6; static unsigned char state; extern USER_DATA xdata user_data; extern char host_name[20]; extern MSCB_INFO_VAR *variables; extern SYS_INFO idata sys_info; extern unsigned char xdata update_on[32]; /*------------------------------------------------------------------*/ unsigned char read_switches() { return (!NSW_PREV*SW_PREV) | (!NSW_NEXT*SW_NEXT) | (!NSW_INC*SW_INC) | (!NSW_DEC*SW_DEC); } /*------------------------------------------------------------------*/ void menu_yield(void) { static unsigned char menu_init_flag = 0; static unsigned long last; static unsigned char sw_old; static unsigned char t_index; static unsigned char chn_index; static unsigned long sw_time; static unsigned long def_time; static unsigned char menu_block; char str[10], *p; unsigned char sw, next, prev, inc, dec; unsigned char *ppwr, progr; // wait for LED to have initialized if (time() < 50 && !menu_init_flag) return; if (!menu_init_flag) { led_init(); menu_init_flag = 1; // too many static initializes crash program, // so we do it here... last = 0; sw_old = 0; t_index = 0; chn_index = 0; sw_time = 0; def_time = 0; menu_block = 0; state = ST_DEFAULT; } // only do ten times per second if (time() - last < 10) return; last = time(); // evaluate switches next = prev = inc = dec = 0; sw = read_switches(); // next item on release OFF/NEXT if (!menu_block) { if ((sw & SW_PREV) && !(sw_old & SW_PREV)) prev = 1; if ((sw & SW_NEXT) && !(sw_old & SW_NEXT)) next = 1; if (!(sw & SW_INC) && (sw_old & SW_INC)) inc = 1; if (!(sw & SW_DEC) && (sw_old & SW_DEC)) dec = 1; } if (sw == 0) menu_block = 0; // fall back to default display if (sw != 0) def_time = time(); if (time() > def_time+60*100) state = ST_DEFAULT; // on/off logic if (state == ST_CHANNEL) ppwr = &user_data.chn[chn_index]; else ppwr = &user_data.power; if ((sw & SW_INC) && (*ppwr & 0x01) == 0) { if (!(sw_old & SW_INC)) sw_time = time(); progr = (time() - sw_time) / 10; // go in "hold" mode after 0.5 sec if (progr >= 5) { menu_block = 1; // do not use for next/prev sprintf(str, "Hold %c", (progr-5) / 2); led_puts(str); // switch after 1.6 secs if (progr >= 5+15) { *ppwr = 1; if (state == ST_CHANNEL) { // enable individual channel update_on[68] = 1; } else { // enable all channels update_on[68] = 1; user_data.error = 0; } } sw_old = sw; return; } } if ((sw & SW_DEC) && (*ppwr & 0x01) == 0x01) { if (!(sw_old & SW_DEC)) sw_time = time(); progr = (time() - sw_time) / 10; if (progr >= 5) { menu_block = 1; sprintf(str, "Hold %c", 7-(progr-5) / 2); led_puts(str); if (progr >= 5+15) { *ppwr = 0; if (state == ST_CHANNEL) { // disable individual channel update_on[68] = 1; } else { // disable all channels update_on[68] = 1; user_data.error = 0; } } sw_old = sw; return; } } sw_old = sw; // next/previous state if (next) state = (state + 1) % (ST_LAST+1); if (prev) state = (state - 1 + (ST_LAST+1)) % (ST_LAST+1); switch (state) { case ST_DEFAULT: if (user_data.error == 0) { if (user_data.power > 0) { led_puts(">>>ON<<<"); } else led_puts("--OFF--"); } else if (user_data.error & (ERROR_TEMP)) { led_puts("OVERTEMP"); } else if (user_data.error & (ERROR_OVERCURRENT)) { led_puts("OVERCURR"); } break; case ST_POWER: if (user_data.power > 0) led_puts("PWR ON"); else led_puts("PWR OFF"); break; case ST_CHANNEL: if (user_data.chn[chn_index] & (1 <<2)) sprintf(str, "CH%02bd:FLT", chn_index); else sprintf(str, "CH%02bd:%s", chn_index, (user_data.chn[chn_index] & 1) ? "EN": "DIS"); led_puts(str); if (inc) chn_index = (chn_index + 1) % 32; if (dec) chn_index = (chn_index - 1 + 32) % 32; break; case ST_CURR: sprintf(str, "I%02bd:%3.1fA", chn_index, user_data.current[chn_index]); led_puts(str); if (inc) chn_index = (chn_index + 1) % 32; if (dec) chn_index = (chn_index - 1 + 32) % 32; break; case ST_TEMP: sprintf(str, "T%bd:%4.1f\x08", t_index, user_data.temp[t_index]); led_puts(str); if (inc) t_index = (t_index + 1) % 4; if (dec) t_index = (t_index - 1 + 4) % 4; break; case ST_MSCB: sprintf(str, "MSCB:%d", sys_info.node_addr); led_puts(str); break; case ST_VERSION: if (strrchr(GIT_REVISION, '-')) { p = strrchr(GIT_REVISION, '-')+2; str[0] = '#'; strncpy(str+1, p, 7); led_puts(str); } else led_puts("--------"); break; } } /*------------------------------------------------------------------*/