brewco/setup.c

Sun, 27 Dec 2015 17:52:26 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 27 Dec 2015 17:52:26 +0100
changeset 477
9167ad4c2e77
parent 473
fdd30e935079
permissions
-rw-r--r--

Renamed Mash-in step to Prepare on the display. Don't run the pump when the mash is added. When preparing the mash, first heat the HLT, and then the MLT so that both have the chance to reach their target temperatures.

/*****************************************************************************
 * Copyright (C) 2015
 *   
 * Michiel Broek <mbroek at mbse dot eu>
 *
 * This file is part of the mbsePi-apps
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * mbsePi-apps is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ThermFerm; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/

#include "brewco.h"
#include "slcd.h"
#include "setup.h"
#include "prompt.h"
#include "xutil.h"
#include "keyboard.h"
#include "rdconfig.h"
#include "rdrecipes.h"


extern int		my_shutdown;
extern int              debug;
extern sys_config       Config;
extern int              lcdHandle;
extern int		slcdHandle;
extern a_recipe		*recipes;



void editFloat(float *value, float low, float high, char *text)
{
    int		key;
    float	new = *value;
    char	pmpt[81];

    prompt(0, NULL);
    prompt(133, NULL);

    for (;;) {
	snprintf(pmpt, Config.lcd_cols + 1, "%s: %5.1f\001", text, new);
	prompt(200, pmpt);
	if (new == low)
	    prompt(404, NULL);
	else if (new == high)
	    prompt(402, NULL);
	else
	    prompt(403, NULL);

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if (key == KEY_UP) {
	    new = new + 0.5;
	    if (new > high)
		new = high;
	}
	if (key == KEY_DOWN) {
	    new = new - 0.5;
	    if (new < low)
		new = low;
	}
	if (key == KEY_ENTER) {
	    *value = new;
	    return;
	}
    }
}



void editDouble(double *value, double low, double high, char *text)
{
    int         key;
    double	new = *value;
    char        pmpt[81];

    prompt(0, NULL);
    prompt(138, NULL);

    for (;;) {
        snprintf(pmpt, Config.lcd_cols + 1, "%s: %5.2lf", text, new);
        prompt(200, pmpt);
        if (new == low)
            prompt(404, NULL);
        else if (new == high)
            prompt(402, NULL);
        else
            prompt(403, NULL);

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown)
            return;
        if (key == KEY_UP) {
            new = new + 0.5;
            if (new > high)
                new = high;
        }
        if (key == KEY_DOWN) {
            new = new - 0.5;
            if (new < low)
                new = low;
        }
        if (key == KEY_ENTER) {
            *value = new;
            return;
        }
    }
}



void editInteger(int *value, int low, int high, int step, char *text, char *text2)
{
    int         key, new = *value;
    char        pmpt[81];

    prompt(0, NULL);
    prompt(134, NULL);

    for (;;) {
        snprintf(pmpt, Config.lcd_cols + 1, "%s: %3d %s", text, new, text2);
        prompt(200, pmpt);
        if (new == low)
            prompt(404, NULL);
        else if (new == high)
            prompt(402, NULL);
        else
            prompt(403, NULL);

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown)
            return;
        if (key == KEY_UP) {
            new += step;
            if (new > high)
                new = high;
        }
        if (key == KEY_DOWN) {
            new -= step;
            if (new < low)
                new = low;
        }
        if (key == KEY_ENTER) {
            *value = new;
            return;
        }
    }
}



void togglePmpts(int *value, char *text, int pno, char *pmpt1, char *pmpt2)
{
    int		key, new = *value;
    char	pmpt[81];

    prompt(0, NULL);
    prompt(pno, NULL);

    for (;;) {

        snprintf(pmpt, Config.lcd_cols + 1, "%s: %s", text, new ? pmpt1:pmpt2);
	prompt(200, pmpt);
	if (new) {
	    prompt(404, NULL);
	} else {
	    prompt(402, NULL);
	}

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if ((key == KEY_UP) && new)
	    new = 0;
	else if ((key == KEY_DOWN) && (new == 0))
	    new = 1;
	if (key == KEY_ENTER) {
	    *value = new;
	    return;
	}
    }
}



void toggleYesNo(int *value, char *text)
{
    togglePmpts(value, text, 132, (char *)"Yes", (char *)"No ");
}



void toggleDirection(int *value, char *text)
{
    togglePmpts(value, text, 137, (char *)"Reverse", (char *)"Direct ");
}



void editName(char *name, char *text)
{
    char	pmpt[81];
    int		i, x = 0, key, val;

    if (debug)
	fprintf(stdout, "editName(%s)\n", name);

    prompt(0, NULL);
    prompt(131, NULL);              /* "    Change Name     " */
    prompt(417, NULL);              /* " up  dwn  next  ok  " */

    for (;;) {
	snprintf(pmpt, Config.lcd_cols + 1, "                    ");
	prompt(200, pmpt);
#ifdef HAVE_WIRINGPI_H
	lcdPosition(lcdHandle, x, 1);
	lcdPutchar(lcdHandle, '*');
#endif
        slcdPosition(slcdHandle, x, 1);
	slcdPutchar(slcdHandle, '*');
	snprintf(pmpt, Config.lcd_cols + 1, "%s", name);
	prompt(300, pmpt);

	key = keywait();

	if ((key == KEY_ENTER) || my_shutdown) {
	    if (debug)
		fprintf(stdout, "End editName(%s)\n", name);
	    for (i = strlen(name) -1; i > 1; i--) {
		if (name[i] != ' ')
		    break;
		name[i] = '\0';
	    }
	    if (debug)
		fprintf(stdout, "End editName(%s)\n", name);
	    return;
	}
	if (key == KEY_RETURN) {
	    if (x < 19)
		x++;
	    else
		x = 0;
	    if (debug)
		fprintf(stdout, "editName: strlen=%d x=%d\n", (int)strlen(name) - 1, x);
	    if (x > ((int)strlen(name) - 1)) {
		name[x + 1] = '\0';
		name[x] = ' ';
	    }
	}
	if (key == KEY_UP || key == KEY_DOWN) {
	    val = name[x];
	    if ((key == KEY_UP) && (val < 126))
	    	val++;
	    if ((key == KEY_DOWN) && (val > 32))
	    	val--;
	    name[x] = val;
	}
    }
}



void editPID(pid_var *pid)
{
    int		idx = 1, key, val;
    char	pmpt[81];
    double	Kp, Ki, Kd;

    if (debug)
	fprintf(stdout, "editPID()\n");

    for (;;) {
	prompt(0, NULL);
	prompt(192, NULL);

	if (idx == 1)
	    prompt(402, NULL);
	else if (idx == 5)
	    prompt(404, NULL);
	else
	    prompt(403, NULL);

	switch (idx) {
	    case 1:	snprintf(pmpt, Config.lcd_cols + 1, "PID Kp: %5.2f", PID_getKp(pid));
			break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, "PID Ki: %5.2f", PID_getKi(pid));
			break;
	    case 3:	snprintf(pmpt, Config.lcd_cols + 1, "PID Kd: %5.2f", PID_getKd(pid));
			break;
	    case 4:	snprintf(pmpt, Config.lcd_cols + 1, "SampleTime: %3d mSec", PID_getSampleTime(pid));
			break;
	    case 5:	snprintf(pmpt, Config.lcd_cols + 1, "Direction: %s", PID_getDirection(pid) ? (char *)"Reverse" : (char *)"Direct");
			break;
	}
	prompt(200, pmpt);

    	key = keywait();
    	if ((key == KEY_RETURN) || my_shutdown) {
	    if (debug)
	    	fprintf(stdout, "End editPID\n");
	    return;
    	}

    	if ((key == KEY_UP) && (idx > 1))
	    idx--;
    	if ((key == KEY_DOWN) && (idx < 5))
	    idx++;

    	if (key == KEY_ENTER) {

	    Kp = PID_getKp(pid);
	    Ki = PID_getKi(pid);
	    Kd = PID_getKd(pid);

	    switch(idx) {
		case 1:	editDouble(&Kp, 0.5, 50, (char *)"PID Kp");
			PID_setTunings(pid, Kp, Ki, Kd);
			break;
		case 2:	editDouble(&Ki, 0.5, 50, (char *)"PID Ki");
			PID_setTunings(pid, Kp, Ki, Kd);
			break;
		case 3:	editDouble(&Kd, 0.5, 50, (char *)"PID Kd");
			PID_setTunings(pid, Kp, Ki, Kd);
			break;
		case 4: val = PID_getSampleTime(pid);
			editInteger(&val, 50, 500, 10, (char *)"SampleTime", (char *)"mSec");
			PID_setSampleTime(pid, val);
			break;
		case 5:	val = PID_getDirection(pid);
			toggleDirection(&val, (char *)"Direction");
			PID_setDirection(pid, val);
			break;
	    }
    	}
    }
}



void editMash(mash_step *mash)
{
    int		key, idx = 1, lo, hi;
    char	pmpt[81];

    for (;;) {
	prompt(0, NULL);
	prompt(194, NULL);

	if (mash->canskip) {
	    lo = 1;
	    if (mash->skip)
		hi = 1;
	    else
	    	hi = 3;
	} else {
	    lo = 2;
	    hi = 3;
	}
	if (idx < lo)
	    idx = lo;
	if (idx > hi)
	    idx = hi;
	if (debug)
	    fprintf(stdout, "editMash canskip=%d skip=%d lo=%d hi=%d idx=%d\n", mash->canskip, mash->skip, lo, hi, idx);

	switch (idx) {
	    case 1:	snprintf(pmpt, Config.lcd_cols + 1, " Mashstep skip: %s", mash->skip ? (char *)"Yes":(char *)"No");
		    	break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, " Setpoint: %5.1f\001", mash->setpoint);
			break;
	    case 3:	snprintf(pmpt, Config.lcd_cols + 1, " Duration: %3d mins", mash->duration);
			break;
	}
	prompt(200, pmpt);

	if (lo == hi)
	    prompt(405, NULL);	/* "---  ---  quit  ok  " */
	else if (idx == lo)
	    prompt(402, NULL);	/* "---  dwn  quit  ok  " */
	else if (idx == hi)
	    prompt(404, NULL);	/* " up  ---  quit  ok  " */
	else
	    prompt(403, NULL);	/* " up  dwn  quit  ok  " */

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if ((key == KEY_UP) && (idx > lo))
	    idx--;
	if ((key == KEY_DOWN) && (idx < hi))
	    idx++;
	if (key == KEY_ENTER) {
	    switch(idx) {
		case 1:		toggleYesNo(&mash->skip, (char *)" Mashstep skip");
				break;
		case 2:		editFloat(&mash->setpoint, mash->min, mash->max, (char *)" Setpoint");
				break;
		case 3:		editInteger(&mash->duration, 1, 120, 1, (char *)" Duration", (char *)"mins");
				break;
	    }
	}
    }
}



void editHopaddition(hop_addition *hops, int boiltime)
{
    int         key, idx = 1, hi;
    char        pmpt[81];

    for (;;) {
        prompt(0, NULL);
        prompt(195, NULL);

        if (hops->skip)
            hi = 1;
        else
            hi = 2;
        if (idx > hi)
            idx = hi;
        if (debug)
            fprintf(stdout, "editHopaddition skip=%d hi=%d idx=%d\n", hops->skip, hi, idx);

        switch (idx) {
            case 1:     snprintf(pmpt, Config.lcd_cols + 1, "Addition skip: %s", hops->skip ? (char *)"Yes":(char *)"No");
                        break;
            case 2:     snprintf(pmpt, Config.lcd_cols + 1, " Boil for: %3d mins", hops->boiltime);
                        break;
        }
        prompt(200, pmpt);

        if (hi == 1)
            prompt(405, NULL);  /* "---  ---  quit  ok  " */
        else if (idx == 1)
            prompt(402, NULL);  /* "---  dwn  quit  ok  " */
        else if (idx == hi)
            prompt(404, NULL);  /* " up  ---  quit  ok  " */
        else
            prompt(403, NULL);  /* " up  dwn  quit  ok  " */

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown)
            return;
        if ((key == KEY_UP) && (idx > 1))
            idx--;
        if ((key == KEY_DOWN) && (idx < hi))
            idx++;
        if (key == KEY_ENTER) {
            switch (idx) {
                case 1:         toggleYesNo(&hops->skip, (char *)"Addition skip");
                                break;
                case 2:         editInteger(&hops->boiltime, -1, boiltime, 1, (char *)" Boil for", (char *)"mins");
                                break;
            }
        }
    }
}



void editHopstand(hop_stand *hops)
{
    int         key, idx = 1, hi;
    char        pmpt[81];

    for (;;) {
        prompt(0, NULL);
        prompt(196, NULL);

        if (hops->skip)
            hi = 1;
        else
            hi = 4;
        if (idx < 1)
            idx = 1;
        if (idx > hi)
            idx = hi;
        if (debug)
            fprintf(stdout, "editHopstand skip=%d hi=%d idx=%d\n", hops->skip, hi, idx);

        switch (idx) {
            case 1:     snprintf(pmpt, Config.lcd_cols + 1, "Hopstand skip: %s", hops->skip ? (char *)"Yes":(char *)"No");
                        break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, "Hold temperature: %s", hops->hold ? (char *)"Yes":(char *)"No");
			break;
            case 3:     snprintf(pmpt, Config.lcd_cols + 1, " Setpoint: %5.1f\001", hops->setpoint);
                        break;
            case 4:     snprintf(pmpt, Config.lcd_cols + 1, " Duration: %3d mins", hops->duration);
                        break;
        }
        prompt(200, pmpt);

        if (hi == 1)
            prompt(405, NULL);  /* "---  ---  quit  ok  " */
        else if (idx == 1)
            prompt(402, NULL);  /* "---  dwn  quit  ok  " */
        else if (idx == hi)
            prompt(404, NULL);  /* " up  ---  quit  ok  " */
        else
            prompt(403, NULL);  /* " up  dwn  quit  ok  " */

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown)
            return;
        if ((key == KEY_UP) && (idx > 1))
            idx--;
        if ((key == KEY_DOWN) && (idx < hi))
            idx++;
        if (key == KEY_ENTER) {
            switch(idx) {
                case 1:         toggleYesNo(&hops->skip, (char *)"Hopstand skip");
                                break;
		case 2:		toggleYesNo(&hops->hold, (char *)"Hold temperature");
				break;
                case 3:         editFloat(&hops->setpoint, hops->min, hops->max, (char *)" Setpoint");
                                break;
                case 4:         editInteger(&hops->duration, 10, 240, 10, (char *)" Duration", (char *)"mins");
                                break;
            }
        }
    }
}



void editSensor(char *uuid, char *text)
{
    char		pmpt[81];
    int			i, old, choices, idx = 1, key;
    devices_list	*device;

    if (debug)
	fprintf(stdout, "editSensor(%s, %s)\n", uuid, text);

    old = 1;  //             1d0e5bb8-7408-48b9-abb4-e9041d7b99fe
    if ((i = strcmp((char *)"00000000-0000-0000-0000-000000000000", uuid))) {
	for (device = Config.devices; device; device = device->next) {
	    if (device->direction == DEVDIR_IN_ANALOG) {
		old++;
		if (strcmp(device->uuid, uuid) == 0)
		    break;
	    }
	}
    }

    if (debug)
	fprintf(stdout, "editSensor(%s) old sensor index=%d\n", text, old);

    for (;;) {
	prompt(0, NULL);
	snprintf(pmpt, Config.lcd_cols + 1, "Edit %s", text);
	prompt(100, pmpt);

	/*
	 * Count valid sensors
	 */
	choices = 1;
	if (old == 1) {
	    snprintf(pmpt, Config.lcd_cols + 1, "N/A");
	} 
	for (device = Config.devices; device; device = device->next) {
	    if (device->direction == DEVDIR_IN_ANALOG) {
		choices++;
		if (choices == old) {
		    snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description);
		}
	    }
	}
	prompt(200, pmpt);	/* Display current sensor */
	i = 1;
	if (idx == 1) {
	    snprintf(pmpt, Config.lcd_cols + 1, "N/A");
	} else {
	    for (device = Config.devices; device; device = device->next) {
		if (device->direction == DEVDIR_IN_ANALOG) {
		    i++;
		    if (i == idx) {
			snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description);
		    }
		}
	    }
	}
	prompt(300, pmpt);	/* Display possible new sensor */


	if (choices == 1)
	    prompt(405, NULL);
	else if (idx == 1)
	    prompt(402, NULL);
	else if (idx == choices)
	    prompt(404, NULL);
	else
	    prompt(403, NULL);

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown) {
	    if (debug)
		fprintf(stdout, "End editSensor\n");
	    return;
	}

	if ((key == KEY_UP) && (idx > 1))
	    idx--;
	if ((key == KEY_DOWN) && (idx < choices))
	    idx++;
	
	if ((key == KEY_ENTER) && (idx != old)) {
	    /*
	     * Select new sensor.
	     */
	    if (idx == 1) {
		/*
		 * Disable the sensor
		 */
		strncpy(uuid, (char *)"00000000-0000-0000-0000-000000000000", 36);
		old = idx;
	    } else {
		i = 1;
		for (device = Config.devices; device; device = device->next) {
		    if (device->direction == DEVDIR_IN_ANALOG) {
			i++;
			if (i == idx) {
			    strncpy(uuid, device->uuid, 36);
			    break;
			}
		    }
		}
		old = idx;
	    }
	}
    }
}



void editRelay(char *uuid, char *text)
{
    char                pmpt[81];
    int                 i, old, choices, idx = 1, key;
    devices_list        *device;

    if (debug)
        fprintf(stdout, "editRelay(%s, %s)\n", uuid, text);

    old = 1;  //             1d0e5bb8-7408-48b9-abb4-e9041d7b99fe
    if ((i = strcmp((char *)"00000000-0000-0000-0000-000000000000", uuid))) {
        for (device = Config.devices; device; device = device->next) {
            if (device->direction == DEVDIR_OUT_ANALOG) {
                old++;
                if (strcmp(device->uuid, uuid) == 0)
                    break;
            }
        }
    }

    if (debug)
        fprintf(stdout, "editRelay(%s) old sensor index=%d\n", text, old);

    for (;;) {
        prompt(0, NULL);
        snprintf(pmpt, Config.lcd_cols + 1, "Edit %s", text);
        prompt(100, pmpt);

        /*
         * Count valid sensors
         */
        choices = 1;
        if (old == 1) {
            snprintf(pmpt, Config.lcd_cols + 1, "N/A");
        }
        for (device = Config.devices; device; device = device->next) {
            if (device->direction == DEVDIR_OUT_ANALOG) {
                choices++;
                if (choices == old) {
                    snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description);
                }
            }
        }
        prompt(200, pmpt);      /* Display current relay */
        i = 1;
        if (idx == 1) {
            snprintf(pmpt, Config.lcd_cols + 1, "N/A");
        } else {
            for (device = Config.devices; device; device = device->next) {
                if (device->direction == DEVDIR_OUT_ANALOG) {
                    i++;
                    if (i == idx) {
                        snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description);
                    }
                }
            }
        }
        prompt(300, pmpt);      /* Display possible new relay */

        if (choices == 1)
            prompt(405, NULL);
        else if (idx == 1)
            prompt(402, NULL);
        else if (idx == choices)
            prompt(404, NULL);
        else
            prompt(403, NULL);

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown) {
            if (debug)
                fprintf(stdout, "End editRelay\n");
            return;
        }

        if ((key == KEY_UP) && (idx > 1))
            idx--;
        if ((key == KEY_DOWN) && (idx < choices))
            idx++;

        if ((key == KEY_ENTER) && (idx != old)) {
            /*
             * Select new output.
             */
            if (idx == 1) {
                /*
                 * Disable the output
                 */
                strncpy(uuid, (char *)"00000000-0000-0000-0000-000000000000", 36);
                old = idx;
            } else {
                i = 1;
                for (device = Config.devices; device; device = device->next) {
                    if (device->direction == DEVDIR_OUT_ANALOG) {
                        i++;
                        if (i == idx) {
                            strncpy(uuid, device->uuid, 36);
                            break;
                        }
                    }
                }
                old = idx;
            }
        }
    }
}



/*
 * Edit a single unit
 */
void editUnit(units_list *unit)
{
    int		idx = 1, key;
    char	pmpt[81], *uuid, *name;
    uLong	ocrc, ncrc;

    if (debug)
    	fprintf(stdout, "Start edit brewsystem %d %s\n", unit->number, unit->uuid);

    prompt(0, NULL);
    ncrc = ocrc = crc32(0L, Z_NULL, 0);
    ocrc = crc32(ocrc, (const Bytef *) unit, sizeof(units_list));

    for (;;) {

	prompt(0, NULL);
	prompt(193, NULL);

	if (idx == 1)
	    prompt(402, NULL);
	else if (idx == 21)
	    prompt(404, NULL);
	else
	    prompt(403, NULL);

	switch (idx) {				//   12345678901234567890
	    case 1:	snprintf(pmpt, Config.lcd_cols + 1, "Unit name:");
			prompt(200, pmpt);
			snprintf(pmpt, Config.lcd_cols + 1, "%s", unit->name);
			prompt(300, pmpt);
			break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, "  HLT sensor setup");
			prompt(200, pmpt);
			break;
	    case 3:	snprintf(pmpt, Config.lcd_cols + 1, "  HLT heater setup");
			prompt(200, pmpt);
			break;
	    case 4:	snprintf(pmpt, Config.lcd_cols + 1, "  MLT sensor setup");
			prompt(200, pmpt);
			break;
	    case 5:	snprintf(pmpt, Config.lcd_cols + 1, "  MLT heater setup");
			prompt(200, pmpt);
			break;
	    case 6:	snprintf(pmpt, Config.lcd_cols + 1, "   MLT pump setup");
			prompt(200, pmpt);
			break;
	    case 7:	snprintf(pmpt, Config.lcd_cols + 1, "MLT heat b4 HLT: %s", unit->hlt_heater_mltfirst ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 8:	snprintf(pmpt, Config.lcd_cols + 1, "Pump cycle: %3d mins", unit->pump_cycle);
			prompt(200, pmpt);
			break;
	    case 9:	snprintf(pmpt, Config.lcd_cols + 1, "Pump rest : %3d mins", unit->pump_rest);
			prompt(200, pmpt);
			break;
	    case 10:	snprintf(pmpt, Config.lcd_cols + 1, " Pump pre-mash: %s", unit->pump_premash ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 11:	snprintf(pmpt, Config.lcd_cols + 1, " Pump on-mash: %s", unit->pump_onmash ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 12:	snprintf(pmpt, Config.lcd_cols + 1, " Pump mashout: %s", unit->pump_mashout ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 13:	snprintf(pmpt, Config.lcd_cols + 1, " Pump on-boil: %s", unit->pump_onboil ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 14:	snprintf(pmpt, Config.lcd_cols + 1, " Pump stop: %5.1f\001", unit->pump_stop);
			prompt(200, pmpt);
			break;
	    case 15:	snprintf(pmpt, Config.lcd_cols + 1, "    Skip Add: %s", unit->skip_add ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 16:	snprintf(pmpt, Config.lcd_cols + 1, "  Skip Remove: %s", unit->skip_remove ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 17:	snprintf(pmpt, Config.lcd_cols + 1, "  Skip Iodine: %s", unit->skip_iodine ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 18:	snprintf(pmpt, Config.lcd_cols + 1, "Iodine time: %3d min", unit->iodine_time);
			prompt(200, pmpt);
			break;
	    case 19:	snprintf(pmpt, Config.lcd_cols + 1, "   Whirlpool: %s", unit->whirlpool ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 20:	snprintf(pmpt, Config.lcd_cols + 1, "   HLT PID setup");
			prompt(200, pmpt);
			break;
	    case 21:	snprintf(pmpt, Config.lcd_cols + 1, "   MLT PID setup");
			prompt(200, pmpt);
			break;
	}

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown) {
	    ncrc = crc32(ncrc, (const Bytef *)unit, sizeof(units_list));
	    if (ocrc != ncrc)
		wrconfig();
	    if (debug)
		fprintf(stdout, "End edit brewsystem %d %s\n", unit->number, unit->uuid);
	    return;
	}

	if ((key == KEY_UP) && (idx > 1))
	    idx--;
	if ((key == KEY_DOWN) && (idx < 21))
	    idx++;

	if (key == KEY_ENTER) {
	    switch(idx) {
		case 1:		name = calloc(sizeof(char), 21);
				snprintf(name, 21, unit->name);
				editName(name, (char *)"Unit name");
				if (unit->name)
				    free(unit->name);
				unit->name = xstrcpy(name);
				free(name);
				break;
		case 2:		uuid = xstrcpy(unit->hlt_sensor.uuid);
				editSensor(uuid, (char *)"HLT sensor");
				strncpy(unit->hlt_sensor.uuid, uuid, 36);
				free(uuid);
				break;
		case 3:		uuid = xstrcpy(unit->hlt_heater.uuid);
				editRelay(uuid, (char *)"HLT heater");
				strncpy(unit->hlt_heater.uuid, uuid, 36);
				free(uuid);
				break;
		case 4:		uuid = xstrcpy(unit->mlt_sensor.uuid);
				editSensor(uuid, (char *)"MLT sensor");
				strncpy(unit->mlt_sensor.uuid, uuid, 36);
				free(uuid);
				break;
		case 5:		uuid = xstrcpy(unit->mlt_heater.uuid);
				editRelay(uuid, (char *)"MLT heater");
				strncpy(unit->mlt_heater.uuid, uuid, 36);
				free(uuid);
				break;
		case 6:		uuid = xstrcpy(unit->mlt_pump.uuid);
				editRelay(uuid, (char *)"MLT pump");
				strncpy(unit->mlt_pump.uuid, uuid, 36);
				free(uuid);
				break;
		case 7:		toggleYesNo(&unit->hlt_heater_mltfirst, (char *)"MLT heat b4 HLT");
				break;
		case 8:		editInteger(&unit->pump_cycle, 5, 15, 1, (char *)"Pump cycle", (char *)"mins");
				break;
		case 9:		editInteger(&unit->pump_rest, 1, 5, 1, (char *)"Pump rest ", (char *)"mins");
				break;
		case 10:	toggleYesNo(&unit->pump_premash, (char *)" Pump pre-mash");
				break;
		case 11:	toggleYesNo(&unit->pump_onmash, (char *)" Pump on-mash");
				break;
		case 12:	toggleYesNo(&unit->pump_mashout, (char *)" Pump mashout");
				break;
		case 13:	toggleYesNo(&unit->pump_onboil, (char *)" Pump on-boil");
				break;
		case 14:	editFloat(&unit->pump_stop, 80.0, 110.0, (char *)" Pump stop");
				break;
		case 15:	toggleYesNo(&unit->skip_add, (char *)"Skip add water");
				break;
		case 16:	toggleYesNo(&unit->skip_remove, (char *)"Skip remove Mash");
				break;
		case 17:	toggleYesNo(&unit->skip_iodine, (char *)"Skip iodine test");
				break;
		case 18:	editInteger(&unit->iodine_time, 10, 240, 10, (char *)"Iodine time", (char *)"min");
				break;
		case 19:	toggleYesNo(&unit->whirlpool, (char *)"Do a whirlpool");
				break;
		case 20:	editPID(unit->PID_hlt);
				break;
		case 21:	editPID(unit->PID_mlt);
				break;
	    }
	}
    }
}



void addUnit(int number)
{
    units_list	*tmpu, *unit = (units_list *)malloc(sizeof(units_list));
    char	name[81];
    uuid_t	uu;
    double	Input, Output, Setpoint;

    if (debug)
	fprintf(stdout, "Adding new brewsystem %d\n", number);
    unit->next = NULL;
    unit->version = 1;
    unit->uuid = malloc(37);
    uuid_generate(uu);
    uuid_unparse(uu, unit->uuid);
    snprintf(name, 20, "System %d", number);
    unit->name = xstrcpy(name);
    unit->number = number;
    if (number == 1)
	unit->active = 1;
    else
	unit->active = 0;
    unit->hlt_sensor.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000");
    unit->hlt_sensor.state = DEVPRESENT_UNDEF;
    unit->hlt_sensor.value = 0;
    unit->mlt_sensor.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000");
    unit->mlt_sensor.state = DEVPRESENT_UNDEF;
    unit->mlt_sensor.value = 0;
    unit->hlt_heater.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000");
    unit->hlt_heater.value = 0;
    unit->hlt_heater.delay = 0;
    unit->mlt_heater.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000");
    unit->mlt_heater.value = 0;
    unit->mlt_heater.delay = 0;
    unit->mlt_pump.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000");
    unit->mlt_pump.value = 0;
    unit->mlt_pump.delay = 0;
    unit->hlt_heater_mltfirst = 1;
    unit->pump_cycle = 7;
    unit->pump_rest = 2;
    unit->pump_premash = 1;
    unit->pump_onmash = 1;
    unit->pump_mashout = 0;
    unit->pump_onboil = 0;
    unit->pump_stop = 90;
    unit->skip_add = 0;
    unit->skip_remove = 0;
    unit->skip_iodine = 0;
    unit->iodine_time = 90;
    unit->whirlpool = 1;
    unit->PID_hlt = (pid_var *)malloc(sizeof(pid_var));
    unit->PID_mlt = (pid_var *)malloc(sizeof(pid_var));
    Input = Setpoint = 20.0;
    Output = 0;
    PID_init(unit->PID_hlt, &Input, &Output, &Setpoint, 2, 5, 1, P_DIRECT);
    PID_init(unit->PID_mlt, &Input, &Output, &Setpoint, 2, 5, 1, P_DIRECT);

    editUnit(unit);

    if (Config.units == NULL) {
	Config.units = unit;
    } else {
	for (tmpu = Config.units; tmpu; tmpu = tmpu->next) {
	    if (tmpu->next == NULL) {
		tmpu->next = unit;
		break;
	    }
	}
    }
    syslog(LOG_NOTICE, "Brewsystem %d added to the configuration", number);
    if (debug)
	fprintf(stdout, "Brewsystem %d added to the configuration\n", number);
}



/*
 * Edit a single recipe
 */
void editRecipe(a_recipe *recipe)
{
    int         idx = 1, i, key;
    char        pmpt[81], *name;
    uLong       ocrc, ncrc;

    if (debug)
        fprintf(stdout, "Start edit recipe `%s' %s\n", recipe->name, recipe->uuid);

    prompt(0, NULL);
    ncrc = ocrc = crc32(0L, Z_NULL, 0);
    ocrc = crc32(ocrc, (const Bytef *) recipe, sizeof(a_recipe));

    for (;;) {

        prompt(0, NULL);
        prompt(191, NULL);	/* "    Edit recipe     " */

        if (idx == 1)
            prompt(402, NULL);	/* "---  dwn  quit  ok  " */
        else if (idx == 24)
            prompt(404, NULL);	/* " up  ---  quit  ok  " */
        else
            prompt(403, NULL);	/* " up  dwn  quit  ok  " */

        switch (idx) {                          //   12345678901234567890
            case 1:     snprintf(pmpt, Config.lcd_cols + 1, "Recipe name:");
                        prompt(200, pmpt);
                        snprintf(pmpt, Config.lcd_cols + 1, "%s", recipe->name);
                        prompt(300, pmpt);
                        break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, "Recipe code:");
			prompt(200, pmpt);
			snprintf(pmpt, Config.lcd_cols + 1, "%s", recipe->code);
			prompt(300, pmpt);
			break;
	    case 3:     snprintf(pmpt, Config.lcd_cols + 1, "Boil time: %3d mins", recipe->boiltime);
			prompt(200, pmpt);
			break;
	    case 4:	snprintf(pmpt, Config.lcd_cols + 1, "  Cool to: %5.1f\001", recipe->coolto);
			prompt(200, pmpt);
			break;
	    case 5:
	    case 6:
	    case 7:
	    case 8:
	    case 9:
	    case 10:
	    case 11:
	    case 12:	snprintf(pmpt, Config.lcd_cols + 1, "Mash: %s", recipe->mash[idx - 5].name);
			prompt(200, pmpt);
			if (recipe->mash[idx - 5].skip)
			    snprintf(pmpt, Config.lcd_cols + 1, "      Skipped");
			else
			    snprintf(pmpt, Config.lcd_cols + 1, " Sv %4.1f\001 %3d mins", recipe->mash[idx - 5].setpoint, recipe->mash[idx - 5].duration);
			prompt(300, pmpt);
			break;
	    case 13:
	    case 14:
	    case 15:
	    case 16:
	    case 17:
	    case 18:
	    case 19:
	    case 20:
	    case 21:
	    case 22:	snprintf(pmpt, Config.lcd_cols + 1, "Add: %s", recipe->hops[idx - 13].name);
			prompt(200, pmpt);
			if (recipe->hops[idx - 13].skip)
			    snprintf(pmpt, Config.lcd_cols + 1, "      Skipped");
			else {
			    if (recipe->hops[idx - 13].boiltime == -1)
				snprintf(pmpt, Config.lcd_cols + 1, "   First Wort Hop");
			    else
			        snprintf(pmpt, Config.lcd_cols + 1, " Boil for %3d mins", recipe->hops[idx - 13].boiltime);
			}
			prompt(300, pmpt);
			break;
	    case 23:    
	    case 24:
	    case 25:	snprintf(pmpt, Config.lcd_cols + 1, "Hopstand: %s", recipe->hopstand[idx - 23].name);
			prompt(200, pmpt);
			if (recipe->hopstand[idx - 23].skip)
			    snprintf(pmpt, Config.lcd_cols + 1, "      Skipped");
			else if (recipe->hopstand[idx - 23].hold)
			    snprintf(pmpt, Config.lcd_cols + 1, "Hold at %4.1f %3d mins", recipe->hopstand[idx - 23].setpoint, recipe->hopstand[idx - 23].duration);
			else
			    snprintf(pmpt, Config.lcd_cols + 1, "Hold for %3d mins", recipe->hopstand[idx - 23].duration);
			prompt(300, pmpt);
			break;
	}

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown) {
            ncrc = crc32(ncrc, (const Bytef *)recipe, sizeof(a_recipe));
            if (ocrc != ncrc) {
		/*
		 * Fix some user errors
		 */
		for (i = 0; i < 8; i++)
		    if (recipe->hops[i].boiltime > recipe->boiltime)
			recipe->hops[i].boiltime = recipe->boiltime;
                wrrecipes();
	    }
            if (debug)
                fprintf(stdout, "End edit recipe `%s' %s\n", recipe->name, recipe->uuid);
            return;
        }

        if ((key == KEY_UP) && (idx > 1))
            idx--;
        if ((key == KEY_DOWN) && (idx < 24))
            idx++;

        if (key == KEY_ENTER) {
            switch(idx) {
                case 1:         name = calloc(sizeof(char), 21);
				snprintf(name, 21, recipe->name);
				editName(name, (char *)"Recipe name");
				if (recipe->name)
				    free(recipe->name);
				recipe->name = xstrcpy(name);
				free(name);
                                break;
		case 2:		name = calloc(sizeof(char), 21);
				snprintf(name, 21, recipe->code);
				editName(name, (char *)"Recipe code");
				if (recipe->code)
				    free(recipe->code);
				recipe->code = xstrcpy(name);
				free(name);
				break;
		case 3:		editInteger(&recipe->boiltime, 60, 240, 5, (char *)"Boil time:", (char *)"mins");
				break;
		case 4:		editFloat(&recipe->coolto, 10.0, 30.0, (char *)"  Cool to");

		case 5:
		case 6:
		case 7:
		case 8:
		case 9:
		case 10:
		case 11:
		case 12:	editMash(&recipe->mash[idx-5]);
				break;
		case 13:
		case 14:
		case 15:
		case 16:
		case 17:
		case 18:
		case 19:
		case 20:
		case 21:
		case 22:	editHopaddition(&recipe->hops[idx-13], recipe->boiltime);
				break;
		case 23:
		case 24:
		case 25:	editHopstand(&recipe->hopstand[idx-23]);
				break;
	    }
    	}
    }
}



void addRecipe(int number)
{
    a_recipe	*tmpu, *recipe = (a_recipe *)malloc(sizeof(a_recipe));
    char        name[81];
    uuid_t      uu;

    if (debug)
        fprintf(stdout, "Adding new recipe %d\n", number);
    recipe->next = NULL;
    recipe->uuid = malloc(37);
    uuid_generate(uu);
    uuid_unparse(uu, recipe->uuid);
    snprintf(name, 21, "New recipe %d", number);
    recipe->name = xstrcpy(name);
    snprintf(name, 21, "%04d", number);
    recipe->code = xstrcpy(name);
    recipe->boiltime = 90;
    recipe->coolto = 20.0;
    recipe->starttime = recipe->endtime = (time_t)0;
    /*
     * Initial mash schedule, set a single-step 67 degr. mash
     */
    recipe->mash[0].name = xstrcpy((char *)"Mash-in");
    recipe->mash[0].min = 20;
    recipe->mash[0].max = 80;
    recipe->mash[0].canskip = 0;
    recipe->mash[0].setpoint = 68.0;
    recipe->mash[0].skip = 0;
    recipe->mash[0].duration = 1;
    recipe->mash[1].name = xstrcpy((char *)"Phytase");
    recipe->mash[1].min = 25;
    recipe->mash[1].max = 55;
    recipe->mash[1].canskip = 1;
    recipe->mash[1].setpoint = 40.0;
    recipe->mash[1].skip = 1;
    recipe->mash[1].duration = 10;
    recipe->mash[2].name = xstrcpy((char *)"Glucanase");
    recipe->mash[2].min = 35; 
    recipe->mash[2].max = 50;
    recipe->mash[2].canskip = 1;
    recipe->mash[2].setpoint = 45.0;
    recipe->mash[2].skip = 1;
    recipe->mash[2].duration = 10;
    recipe->mash[3].name = xstrcpy((char *)"Protease");
    recipe->mash[3].min = 45; 
    recipe->mash[3].max = 60;
    recipe->mash[3].canskip = 1;
    recipe->mash[3].setpoint = 55.0;
    recipe->mash[3].skip = 1;
    recipe->mash[3].duration = 10;
    recipe->mash[4].name = xstrcpy((char *)"B-Amylase");
    recipe->mash[4].min = 50; 
    recipe->mash[4].max = 70;
    recipe->mash[4].canskip = 1;
    recipe->mash[4].setpoint = 62.0;
    recipe->mash[4].skip = 1;
    recipe->mash[4].duration = 30;
    recipe->mash[5].name = xstrcpy((char *)"A-Amylase 1");
    recipe->mash[5].min = 60; 
    recipe->mash[5].max = 76;
    recipe->mash[5].canskip = 1;
    recipe->mash[5].setpoint = 67.0;
    recipe->mash[5].skip = 1;
    recipe->mash[5].duration = 30;
    recipe->mash[6].name = xstrcpy((char *)"A-Amylase 2");
    recipe->mash[6].min = 60; 
    recipe->mash[6].max = 76;
    recipe->mash[6].canskip = 0;
    recipe->mash[6].setpoint = 67.0;
    recipe->mash[6].skip = 0;
    recipe->mash[6].duration = 60;
    recipe->mash[7].name = xstrcpy((char *)"Mash-out");
    recipe->mash[7].min = 75;
    recipe->mash[7].max = 80;
    recipe->mash[7].canskip = 0;
    recipe->mash[7].setpoint = 78.0;
    recipe->mash[7].skip = 0;
    recipe->mash[7].duration = 10;

    /*
     * Add 2 hop additions, maximum 10
     */
    recipe->hops[0].name = xstrcpy((char *)"Hops 1");
    recipe->hops[0].skip = 0;
    recipe->hops[0].boiltime = 90;
    recipe->hops[1].name = xstrcpy((char *)"Hops 2");
    recipe->hops[1].skip = 0;
    recipe->hops[1].boiltime = 5;
    recipe->hops[2].name = xstrcpy((char *)"Hops 3");
    recipe->hops[2].skip = 1;
    recipe->hops[2].boiltime = 0;
    recipe->hops[3].name = xstrcpy((char *)"Hops 4");
    recipe->hops[3].skip = 1;
    recipe->hops[3].boiltime = 0;
    recipe->hops[4].name = xstrcpy((char *)"Hops 5");
    recipe->hops[4].skip = 1;
    recipe->hops[4].boiltime = 0;
    recipe->hops[5].name = xstrcpy((char *)"Hops 6");
    recipe->hops[5].skip = 1;
    recipe->hops[5].boiltime = 0;
    recipe->hops[6].name = xstrcpy((char *)"Hops 7");
    recipe->hops[6].skip = 1;
    recipe->hops[6].boiltime = 0;
    recipe->hops[7].name = xstrcpy((char *)"Hops 8");
    recipe->hops[7].skip = 1;
    recipe->hops[7].boiltime = 0;
    recipe->hops[8].name = xstrcpy((char *)"Hops 9");
    recipe->hops[8].skip = 1;
    recipe->hops[8].boiltime = 0;
    recipe->hops[9].name = xstrcpy((char *)"Hops 10");
    recipe->hops[9].skip = 1;
    recipe->hops[9].boiltime = 0;

    /*
     * Add 3 hopstands, disabled by default.
     */
    recipe->hopstand[0].name = xstrcpy((char *)"Hopstand hot");
    recipe->hopstand[0].min = 88;
    recipe->hopstand[0].max = 100;
    recipe->hopstand[0].hold = 0;
    recipe->hopstand[0].setpoint = 93.0;
    recipe->hopstand[0].skip = 1;
    recipe->hopstand[0].duration = 30;
    recipe->hopstand[1].name = xstrcpy((char *)"Hopstand default");
    recipe->hopstand[1].min = 72;
    recipe->hopstand[1].max = 77;
    recipe->hopstand[1].hold = 0;
    recipe->hopstand[1].setpoint = 75.0;
    recipe->hopstand[1].skip = 1;
    recipe->hopstand[1].duration = 60;
    recipe->hopstand[2].name = xstrcpy((char *)"Hopstand cool");
    recipe->hopstand[2].min = 60;
    recipe->hopstand[2].max = 66;
    recipe->hopstand[2].hold = 0;
    recipe->hopstand[2].setpoint = 63.0;
    recipe->hopstand[2].skip = 1;
    recipe->hopstand[2].duration = 60;

    editRecipe(recipe);

    if (recipes == NULL) {
        recipes = recipe;
    } else {
        for (tmpu = recipes; tmpu; tmpu = tmpu->next) {
            if (tmpu->next == NULL) {
                tmpu->next = recipe;
                break;
            }
        }
    }
    syslog(LOG_NOTICE, "Recipe %d added", number);
    if (debug)
        fprintf(stdout, "Recipe %d added\n", number);
}



void editRecipes(void)
{
    int         total, i, key, choice = 1;;
    a_recipe	*recipe;
    char        pmpt[81];

    prompt(0, NULL);
    for (;;) {
	total = 0;
	for (recipe = recipes; recipe; recipe = recipe->next) {
	    total++;
	}

	if (debug)
	    fprintf(stdout, "editRecipes total=%d choice=%d\n", total, choice);

	i = 0;
	if (total) {
	    for (recipe = recipes; recipe; recipe = recipe->next) {
	    	i++;
	    	if (i == choice)
		    break;
	    }
	}

	prompt(102, NULL);          /* "     SETUP MENU     " */
	prompt(221, NULL);          /* "   Select Recipe    " */
	if (total) {
	    snprintf(pmpt, Config.lcd_cols + 1, "%s %s                   ", recipe->code, recipe->name);
	    prompt(300, pmpt);
	}
	if (total == 0)
	    prompt(416, NULL);      /* "add  ---  quit  --- " */
	else if (total == 1)
	    prompt(415, NULL);      /* "add  ---  quit  ok  " */
	else if (total && (choice == 1))
	    prompt(414, NULL);      /* "add  dwn  quit  ok  " */
	else if (total && (choice == total))
	    prompt(404, NULL);      /* " up  ---  quit  ok  " */
	else
	    prompt(403, NULL);      /* " up  dwn  quit  ok  " */

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if (total && (key == KEY_ENTER)) {
	    editRecipe(recipe);
	    prompt(0, NULL);
	}
	if (key == KEY_UP) {
	    if ((total == 1) || (choice == 1))
		addRecipe(total + 1);
	    else if (choice > 1)
	    	choice--;
	}
	if ((key == KEY_DOWN) && (total > 1) && (choice < total))
	    choice++;
    }
}



void editUnits(void)
{
    int		total, i, key, choice = 1;;
    units_list	*unit;
    char	pmpt[81];

    prompt(0, NULL);
    for (;;) {
    	total = 0;
        for (unit = Config.units; unit; unit = unit->next) {
	    total++;
    	}

	if (debug)
	    fprintf(stdout, "editUnits total=%d choice=%d\n", total, choice);

	if (total == 0) {
	    /*
	     * Impossible unless first setup was skipped
	     */
	    addUnit(1);
	    total = 1;
	} else {
	    i = 0;
	    for (unit = Config.units; unit; unit = unit->next) {
		i++;
		if (i == choice)
		    break;
	    }
	    prompt(102, NULL);		/* "     SETUP MENU     " */
	    prompt(222, NULL);		/* " Select Brewsystem  " */
	    snprintf(pmpt, Config.lcd_cols + 1, "%s                    ", unit->name);
	    prompt(300, pmpt);
	    if (total == 1)
		prompt(415, NULL);	/* "add  ---  quit  ok  " */
	    else if (choice == 1)
		prompt(414, NULL);	/* "add  dwn  quit  ok  " */
	    else if (choice == total)
		prompt(404, NULL);	/* " up  ---  quit  ok  " */
	    else
		prompt(403, NULL);	/* " up  dwn  quit  ok  " */

	    key = keywait();
	    if ((key == KEY_RETURN) || my_shutdown)
		return;
	    if (key == KEY_ENTER) {
		editUnit(unit);
		prompt(0, NULL);
	    }
	    if (key == KEY_UP) {
		if ((total == 1) || (choice == 1))
		    addUnit(total + 1);
		else if (choice > 1)
		    choice--;
	    }
	    if ((key == KEY_DOWN) && (total > 1) && (choice < total))
		choice++;
	}
    }
}



void setup(void)
{
    int		key, option = 202;

    for (;;) {
	if (debug)
	    fprintf(stdout, "setup() option=%d\n", option);
	prompt(0, NULL);
	prompt(102, NULL);		/* "     SETUP MENU     " */
	prompt(option, NULL);
	if (option == 202)
	    prompt(402, NULL);		/* "---  dwn  quit  ok  " */
#ifdef USE_SIMULATOR
	else if (option == 205)
#else
	else if (option == 204)
#endif
	    prompt(404, NULL);		/* " up  ---  quit  ok  " */
	else
	    prompt(403, NULL);		/* " up  dwn  quit  ok  " */

	key = keywait();

	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if ((key == KEY_UP) && (option > 202)) {
	    option--;
	}
#ifdef USE_SIMULATOR
	if ((key == KEY_DOWN) && (option < 205)) {
#else
	if ((key == KEY_DOWN) && (option < 204)) {
#endif
	    option++;
	}

	if (key == KEY_ENTER) {
	    switch(option) {
		case 202:	editRecipes();
				break;
		case 203:	editUnits();
				break;
		case 204:	// devices
				break;
#ifdef USE_SIMULATOR
		case 205:	// simulator
				break;
#endif
	    }
	    if (my_shutdown)
		return;
	}
    }
}

mercurial