// AkvarieComputer - menu.c
#include <pic18.h>
#include <stdio.h>
#include <string.h>
#include "lcd.h"
#include "delay.h"
#include "akvarie.h"
#include "menu.h"
#include "xeeprom.h"
// ---------------------------------------------------------------
// Main Menu
// ---------------------------------------------------------------
const char HardwareMenuItem[] = "Technical Setup ";
const char AutomationMenuItem[] = "Automation Setup ";
const char CaliMenuItem[] = "Calibration ";
const char ManualMenuItem[] = "Manual Operations ";
const char FyldMenuItem[] = "Secret Menu ";
const char *MainMenuTexts[] = {AutomationMenuItem,
ManualMenuItem,
CaliMenuItem,
HardwareMenuItem,
NULL};
#define MainMenuTriggerMenu 0
#define MainMenuAutomationMenu 0
#define MainMenuManualMenu 1
#define MainMenuCalMenu 2
#define MainMenuHardwareMenu 3
#define MainMenuFyldMenu 4
// ---------------------------------------------------------------
// Hardware Menu
// ---------------------------------------------------------------
const char ClockMenuItem[] = "Internal clock ";
const char Probe1MenuItem[] = "Probe 1 <%s> ";
const char Probe2MenuItem[] = "Probe 2 <%s> ";
const char Probe3MenuItem[] = "Probe 3 <%s> ";
const char Probe4MenuItem[] = "Probe 4 <%s> ";
const char PowerPanelMenuItem[] = "PowerPanel <%s> ";
const char Input1MenuItem[] = "Input 1 <%s> ";
const char Input2MenuItem[] = "Input 2 <%s> ";
const char *HardwareMenuTexts[] = {ClockMenuItem,
Probe1MenuItem,
Probe2MenuItem,
Probe3MenuItem,
Probe4MenuItem,
PowerPanelMenuItem,
Input1MenuItem,
Input2MenuItem,
NULL};
const void *HardwareMenuData[] = {NULL,
&AI.ProbeSetup[0],
&AI.ProbeSetup[1],
&AI.ProbeSetup[2],
&AI.ProbeSetup[3],
&AI.PowerPanel,
&AI.Input1,
&AI.Input2};
const char HardwareMenuTypes[] = {TYPE_TIME,
TYPE_PROBE,
TYPE_PROBE,
TYPE_PROBE,
TYPE_PROBE,
TYPE_ONOFF,
TYPE_ONOFF,
TYPE_ONOFF};
#define HardwareMenuClock 0
#define HardwareMenuProbe1 1
#define HardwareMenuProbe2 2
#define HardwareMenuProbe3 3
#define HardwareMenuProbe4 4
#define HardwareMenuPowerPanel 5
#define HardwareMenuInput1 6
#define HardwareMenuInput2 7
// ---------------------------------------------------------------
// Calibration Menu
// ---------------------------------------------------------------
const char Calibration_Probe1Item[] = "Probe 1 (%s) Cal.";
const char Calibration_Probe2Item[] = "Probe 2 (%s) Cal.";
const char Calibration_Probe3Item[] = "Probe 3 (%s) Cal.";
const char Calibration_Probe4Item[] = "Probe 4 (%s) Cal.";
const char *CalibrationMenuTexts[] = {Calibration_Probe1Item,
Calibration_Probe2Item,
Calibration_Probe3Item,
Calibration_Probe4Item,NULL};
const void *CalibrationMenuData[] = {&AI.ProbeSetup[0],
&AI.ProbeSetup[1],
&AI.ProbeSetup[2],
&AI.ProbeSetup[3]};
// ---------------------------------------------------------------
// Manual Menu
// ---------------------------------------------------------------
const char ManualPower1Item[] = "Power 1 <%s> ";
const char ManualPower2Item[] = "Power 2 <%s> ";
const char ManualPower3Item[] = "Power 3 <%s> ";
const char ManualPower4Item[] = "Power 4 <%s> ";
const char *ManualMenuTexts[]= {ManualPower1Item,ManualPower2Item,ManualPower3Item,ManualPower4Item,NULL};
const void *ManualMenuData[] = {&AI.Power[0],&AI.Power[1],&AI.Power[2],&AI.Power[3]};
const char ManualMenuTypes[] = {TYPE_ONOFF,TYPE_ONOFF,TYPE_ONOFF,TYPE_ONOFF,0};
#define ManualPower1Menu 0
#define ManualPower2Menu 1
#define ManualPower3Menu 2
#define ManualPower4Menu 3
// Global variables for menu
unsigned char CursorPosition = 1;
unsigned char MenuPosition = 0;
void ShowMenuLine(char *Menu[],void *Data[],const char *Types,int i,int pos)
{
char Text[19];
int OriginalInt;
float OriginalFloat;
switch(Types[i])
{
case TYPE_INTEGER:
memcpy(&OriginalInt,Data[i],sizeof(int));
sprintf(Text,Menu[i],OriginalInt);
break;
case TYPE_FLOAT2:
memcpy(&OriginalFloat,Data[i],sizeof(float));
sprintf(Text,Menu[i],OriginalFloat);
break;
default:
sprintf(Text,Menu[i],Data[i]);
}
lcdtext(2,pos,Text);
}
char OpenMenu(char *Menu[], void *Data[],const char *Types)
{
unsigned char i = 0;
CursorPosition = 1;
MenuPosition = 0;
// Fill Menu
lcd_clear();
while (i < 4 && Menu[i] != NULL)
{
ShowMenuLine(Menu,Data,Types,i,i+1);
i++;
}
while(1)
{
lcdtext(1,CursorPosition,"*");
if (KeyDown)
{
while (KeyDown);
if (Menu[MenuPosition + 1] != NULL)
{
MenuPosition++;
if (CursorPosition < 4)
{
lcdtext(1,CursorPosition," ");
CursorPosition++;
}
else
{
// Scroll down
for (i = 0; i < 4 ; i++)
{
ShowMenuLine(Menu,Data,Types,MenuPosition - i,4 - i);
/*
if (Types[i] != TYPE_INTEGER)
sprintf(Text,Menu[MenuPosition - i],Data[MenuPosition - i]);
else
{
int x = (int*)Data[MenuPosition - i];
sprintf(Text,Menu[MenuPosition - i],x);
}
lcdtext(2,4 - i,Text);
*/
}
}
}
}
else
if (KeyUp)
{
while (KeyUp);
if (MenuPosition > 0)
if(Menu[MenuPosition - 1] != NULL)
{
MenuPosition--;
if (CursorPosition > 1)
{
lcdtext(1,CursorPosition," ");
CursorPosition--;
}
else
{
// Scroll up
for (i = 0; i < 4 ; i++)
{
ShowMenuLine(Menu,Data,Types,MenuPosition + i,i + 1);
/*
if (Types[i] != TYPE_INTEGER)
sprintf(Text,Menu[MenuPosition + i],Data[MenuPosition + i]);
else
{
int x = (int*)Data[MenuPosition + i];
sprintf(Text,Menu[MenuPosition + i],x);
}
lcdtext(2,i + 1,Text);
*/
}
}
}
}
else
if (KeyLeft) // Exit Menu
{
while(KeyLeft);
lcd_clear();
return -1;
}
else
if (KeyRight) // Go into submenu / item
{
while(KeyRight);
return MenuPosition;
}
DelayMs(100);
}
}
char OpenAutomationMenu()
{
unsigned char i = 0;
char Text[30];
CursorPosition = 1;
MenuPosition = 0;
// Fill Menu
lcd_clear();
lcdtext(2,1,"<New Automation>");
for (i = 1; i <=3; i++)
{
ReadAutomation(i);
if (CA.MagicChar == MAGICCHAR)
{
sprintf(Text,"[%03d] %s ",CA.No,CA.Type);
}
else
sprintf(Text," ");
lcdtext(2,i + 1,Text);
}
while(1)
{
lcdtext(1,CursorPosition,"*");
if (KeyDown)
{
while (KeyDown);
if (ReadAutomation(MenuPosition + 1))
{
if (CA.MagicChar == MAGICCHAR)
{
MenuPosition++;
if (CursorPosition < 4)
{
lcdtext(1,CursorPosition," ");
CursorPosition++;
}
else
{
// Scroll down
for (i = 0; i < 4 ; i++)
{
ReadAutomation(MenuPosition - i);
sprintf(Text,"[%03d] %s ",CA.No,CA.Type);
lcdtext(2,4 - i,Text);
}
}
}
}
}
else
if (KeyUp)
{
while (KeyUp);
if (MenuPosition > 0)
if(ReadAutomation(MenuPosition - 1))
{
MenuPosition--;
if (CursorPosition > 1)
{
lcdtext(1,CursorPosition," ");
CursorPosition--;
}
else
{
// Scroll up
for (i = 0; i < 4 ; i++)
{
if (MenuPosition + i == 0)
sprintf(Text,"<New Automation>");
else
{
ReadAutomation(MenuPosition + i);
sprintf(Text,"[%03d] %s ",CA.No,CA.Type);
}
lcdtext(2,i + 1,Text);
}
}
}
}
else
if (KeyLeft) // Exit Menu
{
while(KeyLeft);
lcd_clear();
return -1;
}
else
if (KeyRight) // Go into submenu / item
{
while(KeyRight);
return MenuPosition;
}
DelayMs(100);
}
}
const char Type_power_void[] = "Void\0";
const char Type_power_on[] = "On\0";
const char Type_power_off[] = "Off\0";
const char *Type_power_values[] = {Type_power_void,Type_power_off,Type_power_on,NULL};
const char Type_onoff_on[] = "On\0";
const char Type_onoff_off[] = "Off\0";
const char *Type_onoff_values[] = {Type_onoff_off,Type_onoff_on,NULL};
const char Type_probe_off[] = "Off\0";
const char Type_probe_ph[] = "pH\0";
const char Type_probe_mV[] = "mV\0";
const char *Type_probe_values[] = {Type_probe_off,Type_probe_ph,Type_probe_mV,NULL};
const char Automation_1[] = "Off\0";
const char Automation_2[] = "Light\0";
const char Automation_3[] = "Osmolator\0";
const char Automation_4[] = "Ozonizer\0";
const char Automation_5[] = "CaReactor\0";
const char Automation_6[] = "Dos.Pump\0";
//const char Automation_5[] = "
const char *Automationtypes_values[] = {Automation_1,
Automation_2,
Automation_3,
Automation_4,
Automation_5,
Automation_6,
NULL};
char EditOption(char *Menu[], const void *Data[],const char *Types,signed char UseMenu,char Refresh)
{
char i;
char Original;
int OriginalInt;
float OriginalFloat;
char Text[30];
char *Values[20];
//far char *Values;
if (UseMenu != -1)
{
MenuPosition = 0;
}
switch(Types[MenuPosition])
{
case TYPE_ONOFF:
memcpy(Values,Type_onoff_values,3 * sizeof(char*)); // Fusk
//Values = Type_onoff_values;
break;
case TYPE_PROBE:
memcpy(Values,Type_probe_values,4 * sizeof(char*)); // Fusk
//Values = Type_probe_values;
break;
case TYPE_AUTOMATION:
memcpy(Values,Automationtypes_values,6 * sizeof(char*)); // Fusk
//Values = Automationtypes_values;
break;
case TYPE_POWER:
memcpy(Values,Type_power_values,4 * sizeof(char*)); // Fusk
//Values = Type_power_values;
break;
case TYPE_INTEGER:
break;
case TYPE_FLOAT2:
break;
default:
FatalError(1,Types[MenuPosition]);
}
if (UseMenu != -1)
{
MenuPosition = 0;
CursorPosition = UseMenu;
switch(Types[MenuPosition])
{
case TYPE_INTEGER:
memcpy(&OriginalInt,Data[MenuPosition],sizeof(int));
sprintf(Text,Menu[MenuPosition],OriginalInt);
break;
case TYPE_FLOAT2:
memcpy(&OriginalFloat,Data[MenuPosition],sizeof(float));
sprintf(Text,Menu[MenuPosition],OriginalFloat);
break;
default:
sprintf(Text,Menu[MenuPosition],Data[MenuPosition]);
}
lcdtext(2,CursorPosition,Text);
}
else
{
lcdtext(1,CursorPosition,"#");
}
switch(Types[MenuPosition])
{
case TYPE_INTEGER:
memcpy(&OriginalInt,Data[MenuPosition],sizeof(int)); // Fusk
while(1)
{
int CurrentValue;
memcpy(&CurrentValue,Data[MenuPosition],sizeof(int));
if (KeyUp)
{
if (CurrentValue < 9998)
{
CurrentValue++;
sprintf(Text,Menu[MenuPosition],CurrentValue);
lcdtext(2,CursorPosition,Text);
if (Refresh)
return 1;
}
}
if (KeyDown)
{
if (CurrentValue > -9998)
{
CurrentValue--;
sprintf(Text,Menu[MenuPosition],CurrentValue);
lcdtext(2,CursorPosition,Text);
if (Refresh)
return 1;
}
}
memcpy(Data[MenuPosition],&CurrentValue,sizeof(int));
if (KeyEnter)
{
while(KeyEnter);
return 1;
}
if (KeyLeft)
{
while(KeyLeft);
memcpy(Data[MenuPosition],&OriginalInt,sizeof(int)); // Fusk !!
sprintf(Text,Menu[MenuPosition],Data[MenuPosition]);
lcdtext(2,CursorPosition,Text);
return 0;
}
DelayMs(250);
}
break;
case TYPE_FLOAT2:
memcpy(&OriginalFloat,Data[MenuPosition],sizeof(float)); // Fusk
while(1)
{
float CurrentValue;
memcpy(&CurrentValue,Data[MenuPosition],sizeof(float)); // Fusk
if (KeyUp)
{
if (CurrentValue < 9999.98f)
{
CurrentValue = CurrentValue + 0.01f;
memcpy(Data[MenuPosition],&CurrentValue,sizeof(float)); // Fusk
sprintf(Text,Menu[MenuPosition],CurrentValue);
lcdtext(2,CursorPosition,Text);
}
}
if (KeyDown)
{
if (CurrentValue > -9999.98f)
{
CurrentValue = CurrentValue - 0.01f;
memcpy(Data[MenuPosition],&CurrentValue,sizeof(float)); // Fusk
sprintf(Text,Menu[MenuPosition],CurrentValue);
lcdtext(2,CursorPosition,Text);
}
}
if (KeyEnter)
{
DelayMs(25);
while(KeyEnter);
return 1;
}
if (KeyLeft)
{
DelayMs(25);
while(KeyLeft);
memcpy(Data[MenuPosition],&OriginalFloat,sizeof(float)); // Fusk !!
sprintf(Text,Menu[MenuPosition],Data[MenuPosition]);
lcdtext(2,CursorPosition,Text);
return 0;
}
DelayMs(25);
}
break;
case TYPE_ONOFF:
case TYPE_PROBE:
case TYPE_AUTOMATION:
case TYPE_POWER:
i = 0;
while (strcmp(Data[MenuPosition],Values[i]) != 0 && Values[i] != NULL)
i++;
if (*Values[i] == NULL)
i = 0;
Original = i;
while(1)
{
if (KeyUp)
{
while(KeyUp);
if (Values[i + 1])
{
i++;
strcpy(Data[MenuPosition],Values[i]);
sprintf(Text,Menu[MenuPosition],Data[MenuPosition]);
//sprintf(Text,"Choice %d",i);
lcdtext(2,CursorPosition,Text);
}
}
if (KeyDown)
{
while(KeyDown);
if (i > 0)
{
i--;
strcpy(Data[MenuPosition],Values[i]);
sprintf(Text,Menu[MenuPosition],Data[MenuPosition]);
//sprintf(Text,"Choice %d",i);
lcdtext(2,CursorPosition,Text);
}
}
if (KeyEnter)
{
while(KeyEnter);
return 1;
}
if (KeyLeft)
{
// Restore original value
while(KeyLeft);
strcpy(Data[MenuPosition],Values[Original]);
sprintf(Text,Menu[MenuPosition],Data[MenuPosition]);
lcdtext(2,CursorPosition,Text);
return 0;
}
}
}
}
void MenuHandler()
{
unsigned char OneUp = 0;
while(1)
{
switch(OpenMenu(MainMenuTexts,NULL,NULL))
{
case -1:
return;
break;
case MainMenuAutomationMenu:
OneUp = 0;
while (OneUp == 0)
{
char No = OpenAutomationMenu();
switch(No)
{
case 0: // New Automation
NewAutomation();
break;
case -1:
OneUp = 1;
break;
default:
EditAutomation(No);
break;
}
}
break;
case MainMenuManualMenu:
OneUp = 0;
while(OneUp == 0)
{
switch(OpenMenu(ManualMenuTexts,ManualMenuData,ManualMenuTypes))
{
case ManualPower1Menu:
case ManualPower2Menu:
case ManualPower3Menu:
case ManualPower4Menu:
EditOption(ManualMenuTexts,ManualMenuData,(char*)ManualMenuTypes,-1,0);
UpdatePowers();
break;
case -1:
OneUp = 1;
break;
}
}
break;
case MainMenuCalMenu:
OneUp = 0;
while (OneUp == 0)
{
switch(OpenMenu(CalibrationMenuTexts,CalibrationMenuData,NULL))
{
case 0:
Calibrate(0);
break;
case 1:
Calibrate(1);
break;
case 2:
Calibrate(2);
break;
case 3:
Calibrate(3);
break;
case -1:
OneUp = 1;
break;
}
}
break;
case MainMenuHardwareMenu:
OneUp = 0;
while(OneUp == 0)
switch(OpenMenu(HardwareMenuTexts,HardwareMenuData,HardwareMenuTypes))
{
case HardwareMenuClock:
SetClock();
break;
case HardwareMenuProbe1:
case HardwareMenuProbe2:
case HardwareMenuProbe3:
case HardwareMenuProbe4:
case HardwareMenuPowerPanel:
case HardwareMenuInput1:
case HardwareMenuInput2:
EditOption(HardwareMenuTexts,HardwareMenuData,(char*)HardwareMenuTypes,-1,0);
break;
case -1:
OneUp = 1;
break;
}
break;
case MainMenuFyldMenu:
break;
}
}
}