main/buttons.c

Sat, 06 Jun 2020 13:28:46 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 06 Jun 2020 13:28:46 +0200
changeset 77
66c77497d86d
parent 56
756d1a63d129
child 87
47253f294a9f
permissions
-rw-r--r--

Changed the recipe database so that it is expandable, version 2. More mash fields and allow 16 steps. Allow 20 Additions. Removed separate mash steps from the state machine, the steps are moved to the runtime data. There is no fixed step number for mashout anymore. There is no fixed step for mash-in anymore, just use the first step and heat to the infusion temperature. After malt add, switch to the normal step temperature. Implemented decoction steps.

/**
 * @file buttons.c
 * @brief The touch buttons.
 */

#include "config.h"


sButton				Buttons[MAXBUTTONS];	///< 40 buttons on a screen.
int				level = 1;		///< Keyboard level.

const char 			*mashTypes[] = { "Infusion", "Temperature", "Decoction" };
const char			*SSR2Types[] = { "Uit", "HLT of MLT", "HLT en MLT", "Idle" };

uint8_t				WS_pressed = 0;		///< Websocket button received
uint16_t			WS_pointer_x = 0;	///< Websocket coordinate x
uint16_t			WS_pointer_y = 0;	///< Websocket coordinate y

#define	EDIT_TYPE_TEXT		0			///< Editor type is text
#define	EDIT_TYPE_INT		1			///< Editor type is integer
#define	EDIT_TYPE_FLOAT		2			///< Editor type is float


/***************************************************************************/


void WaitTouchReleased(void)
{
    int		tx, ty;

    // Do raw reads.
    while (TFT_read_touch(&tx, &ty, 1) == 1) {
	vTaskDelay(50 / portTICK_PERIOD_MS);
    }
}



void Buttons_Clear(void)
{
    int		i;

    for (i = 0; i < MAXBUTTONS; i++) {
	if ((Buttons[i].x != -1) && strlen(Buttons[i].text)) {
	    TFT_fillRect(Buttons[i].x, Buttons[i].y, Buttons[i].w, Buttons[i].h, TFT_BLACK);
	}
	Buttons[i].x = -1;
    }
}



void Buttons_Add(int x, int y, int w, int h, char *txt, int order)
{
    Buttons[order].x = x;
    Buttons[order].y = y;
    Buttons[order].w = w;
    Buttons[order].h = h;
    strncpy(Buttons[order].text, txt, 11);
    Buttons[order].dark = Buttons[order].small = Buttons[order].lock = false;
}



void Buttons_Show(void)
{
    int		i;
    const color_t KEY_NORM        = { 191, 191, 191};
    const color_t KEY_DARK        = {  95,  95,  95};
    const color_t KEY_LOCK        = { 127, 127, 255};

    _fg = TFT_BLACK;

    for (i = 0; i < MAXBUTTONS; i++) {
	if (Buttons[i].x != -1) {

	    if (Buttons[i].lock) {
		_fg = TFT_BLACK;
		TFT_fillRoundRect(Buttons[i].x, Buttons[i].y, Buttons[i].w, Buttons[i].h, 5, KEY_LOCK);
	    } else if (Buttons[i].dark) {
		_fg = TFT_WHITE;
		TFT_fillRoundRect(Buttons[i].x, Buttons[i].y, Buttons[i].w, Buttons[i].h, 5, KEY_DARK);
	    } else {
		_fg = TFT_BLACK;
	    	TFT_fillRoundRect(Buttons[i].x, Buttons[i].y, Buttons[i].w, Buttons[i].h, 5, KEY_NORM);
	    }
	    TFT_drawRoundRect(Buttons[i].x, Buttons[i].y, Buttons[i].w, Buttons[i].h, 5, TFT_LIGHTGREY);
	    if (Buttons[i].small)
		TFT_setFont(DEFAULT_FONT, NULL);	// DEF_SMALL_FONT
	    else
		TFT_setFont(DEJAVU18_FONT, NULL);
	    font_transparent = 1;
	    TFT_print(Buttons[i].text, 
		      Buttons[i].x + ((Buttons[i].w - TFT_getStringWidth(Buttons[i].text)) / 2), 
		      Buttons[i].y + 1 + ((Buttons[i].h - TFT_getfontheight()) / 2));
	}
    }

    font_transparent = 0;
}



int Buttons_Search(int x, int y)
{
    int		i;

    for (i = 0; i < MAXBUTTONS; i++) {
	if (Buttons[i].x != -1) {
	    if ((x >= Buttons[i].x) && (x <= (Buttons[i].x + Buttons[i].w)) &&
		(y >= Buttons[i].y) && (y <= (Buttons[i].y + Buttons[i].h))) {
		return i;
	    }
	}
    }

    return -1;
}



int Buttons_Scan(void)
{
    int		tx, ty, rc;
    static int	ox = -1, oy = -1, vx = -1, vy = -1;
    static bool t_pressed = false, v_pressed = false;

    if (TFT_read_touch(&tx, &ty, 0)) {
	t_pressed = true;
	ox = tx;
	oy = ty;
	return -1;
    } else if (t_pressed) {
	rc = Buttons_Search(ox, oy);
	t_pressed = false;
	ox = oy = -1;
	return rc;
    }

    if (WS_pressed) {
	v_pressed = true;
        vx = WS_pointer_x;
        vy = WS_pointer_y;
	WS_pressed = 0;
        return -1;
    } else if (v_pressed) {
	rc = Buttons_Search(vx, vy);
	v_pressed = false;
	vx = vy = -1;
	return rc;
    }

    return -1;
}



void WS_touched(int x, int y)
{
    WS_pointer_x = x;
    WS_pointer_y = y;
    WS_pressed = 1;
}



static const uint8_t alphalow_tab[] = { 'q','w','e','r','t','y','u','i','o','p',
					'a','s','d','f','g','h','j','k','l',
					'z','x','c','v','b','n','m' };

/**
 * @brief Level 1 keys, lowercase alpha.
 */
void B_AlphaLow(void)
{
    Buttons_Clear();

    Buttons_Add(  2, 80,28,36,(char *)"q", 0);
    Buttons_Add( 34, 80,28,36,(char *)"w", 1);
    Buttons_Add( 66, 80,28,36,(char *)"e", 2);
    Buttons_Add( 98, 80,28,36,(char *)"r", 3);
    Buttons_Add(130, 80,28,36,(char *)"t", 4);
    Buttons_Add(162, 80,28,36,(char *)"y", 5);
    Buttons_Add(194, 80,28,36,(char *)"u", 6);
    Buttons_Add(226, 80,28,36,(char *)"i", 7);
    Buttons_Add(258, 80,28,36,(char *)"o", 8);
    Buttons_Add(290, 80,28,36,(char *)"p", 9);

    Buttons_Add( 18,120,28,36,(char *)"a",10);
    Buttons_Add( 50,120,28,36,(char *)"s",11);
    Buttons_Add( 82,120,28,36,(char *)"d",12);
    Buttons_Add(114,120,28,36,(char *)"f",13);
    Buttons_Add(146,120,28,36,(char *)"g",14);
    Buttons_Add(178,120,28,36,(char *)"h",15);
    Buttons_Add(210,120,28,36,(char *)"j",16);
    Buttons_Add(242,120,28,36,(char *)"k",17);
    Buttons_Add(274,120,28,36,(char *)"l",18);

    Buttons_Add( 50,160,28,36,(char *)"z",19);
    Buttons_Add( 82,160,28,36,(char *)"x",20);
    Buttons_Add(114,160,28,36,(char *)"c",21);
    Buttons_Add(146,160,28,36,(char *)"v",22);
    Buttons_Add(178,160,28,36,(char *)"b",23);
    Buttons_Add(210,160,28,36,(char *)"n",24);
    Buttons_Add(242,160,28,36,(char *)"m",25);

    Buttons_Add(  2,160,42,36,(char *)"caps",26);
    Buttons[26].dark = true;
    Buttons[26].small = true;
    Buttons[26].lock = false;
    Buttons_Add(276,160,42,36,(char *)"del",27);
    Buttons[27].dark = true;
    Buttons[27].small = true;

    Buttons_Add(  2,200,60,36,(char *)"123",28);
    Buttons[28].dark = true;
    Buttons_Add( 72,200,28,36,(char *)"/",29);
    Buttons_Add(108,200,104,36,(char *)" ",30);
    Buttons_Add(220,200,28,36,(char *)".",31);
    Buttons_Add(258,200,60,36,(char *)"Ok",32);
    Buttons[32].dark = true;

    Buttons_Show();
}



static const uint8_t alphacaps_tab[] = { 'Q','W','E','R','T','Y','U','I','O','P',
					 'A','S','D','F','G','H','J','K','L',
					 'Z','X','C','V','B','N','M' };

/**
 * @brief Level 2 and 3 keys, uppercase alpha.
 */
void B_AlphaCaps(int level)
{
    Buttons_Clear();

    Buttons_Add(  2, 80,28,36,(char *)"Q", 0);
    Buttons_Add( 34, 80,28,36,(char *)"W", 1);
    Buttons_Add( 66, 80,28,36,(char *)"E", 2);
    Buttons_Add( 98, 80,28,36,(char *)"R", 3);
    Buttons_Add(130, 80,28,36,(char *)"T", 4);
    Buttons_Add(162, 80,28,36,(char *)"Y", 5);
    Buttons_Add(194, 80,28,36,(char *)"U", 6);
    Buttons_Add(226, 80,28,36,(char *)"I", 7);
    Buttons_Add(258, 80,28,36,(char *)"O", 8);
    Buttons_Add(290, 80,28,36,(char *)"P", 9);

    Buttons_Add( 18,120,28,36,(char *)"A",10);
    Buttons_Add( 50,120,28,36,(char *)"S",11);
    Buttons_Add( 82,120,28,36,(char *)"D",12);
    Buttons_Add(114,120,28,36,(char *)"F",13);
    Buttons_Add(146,120,28,36,(char *)"G",14);
    Buttons_Add(178,120,28,36,(char *)"H",15);
    Buttons_Add(210,120,28,36,(char *)"J",16);
    Buttons_Add(242,120,28,36,(char *)"K",17);
    Buttons_Add(274,120,28,36,(char *)"L",18);

    Buttons_Add( 50,160,28,36,(char *)"Z",19);
    Buttons_Add( 82,160,28,36,(char *)"X",20);
    Buttons_Add(114,160,28,36,(char *)"C",21);
    Buttons_Add(146,160,28,36,(char *)"V",22);
    Buttons_Add(178,160,28,36,(char *)"B",23);
    Buttons_Add(210,160,28,36,(char *)"N",24);
    Buttons_Add(242,160,28,36,(char *)"M",25);

    Buttons_Add(  2,160,42,36,(char *)"caps",26);
    Buttons[26].dark = true;
    Buttons[26].small = true;
    if (level == 3)
	Buttons[26].lock = true;
    else
	Buttons[26].lock = false;
    Buttons_Add(276,160,42,36,(char *)"del",27);
    Buttons[27].dark = true;
    Buttons[27].small = true;

    Buttons_Add(  2,200,60,36,(char *)"123",28);
    Buttons[28].dark = true;
    Buttons_Add( 72,200,28,36,(char *)"/",29);
    Buttons_Add(108,204,100,36,(char *)" ",30);
    Buttons_Add(220,200,28,36,(char *)".",31);
    Buttons_Add(258,200,60,36,(char *)"Ok",32);
    Buttons[32].dark = true;

    Buttons_Show();
}



static const uint8_t nums1_tab[] = { '1','2','3','4','5','6','7','8','9','0', 
				     '!','@','#','$','/','^','&','*','(',')', 
				     '-','\'','\"',':',';',',','?' };

/**
 * @brief Level 4, numeric keys and symbol
 */
void B_Nums1(void)
{
    Buttons_Clear();

    Buttons_Add(  2, 80,28,36,(char *)"1", 0);
    Buttons_Add( 34, 80,28,36,(char *)"2", 1);
    Buttons_Add( 66, 80,28,36,(char *)"3", 2);
    Buttons_Add( 98, 80,28,36,(char *)"4", 3);
    Buttons_Add(130, 80,28,36,(char *)"5", 4);
    Buttons_Add(162, 80,28,36,(char *)"6", 5);
    Buttons_Add(194, 80,28,36,(char *)"7", 6);
    Buttons_Add(226, 80,28,36,(char *)"8", 7);
    Buttons_Add(258, 80,28,36,(char *)"9", 8);
    Buttons_Add(290, 80,28,36,(char *)"0", 9);

    Buttons_Add(  2,120,28,36,(char *)"!",10);
    Buttons_Add( 34,120,28,36,(char *)"@",11);
    Buttons_Add( 66,120,28,36,(char *)"#",12);
    Buttons_Add( 98,120,28,36,(char *)"$",13);
    Buttons_Add(130,120,28,36,(char *)"/",14);
    Buttons_Add(162,120,28,36,(char *)"^",15);
    Buttons_Add(194,120,28,36,(char *)"&",16);
    Buttons_Add(226,120,28,36,(char *)"*",17);
    Buttons_Add(258,120,28,36,(char *)"(",18);
    Buttons_Add(290,120,28,36,(char *)")",19);

    Buttons_Add( 50,160,28,36,(char *)"-",20);
    Buttons_Add( 82,160,28,36,(char *)"'",21);
    Buttons_Add(114,160,28,36,(char *)"\"",22);
    Buttons_Add(146,160,28,36,(char *)":",23);
    Buttons_Add(178,160,28,36,(char *)";",24);
    Buttons_Add(210,160,28,36,(char *)",",25);
    Buttons_Add(242,160,28,36,(char *)"?",26);

    Buttons_Add(  2,160,42,36,(char *)"1/2",27);
    Buttons[27].dark = true;
    Buttons_Add(276,160,42,36,(char *)"del",28);
    Buttons[28].dark = true;
    Buttons[28].small = true;

    Buttons_Add(  2,200,60,36,(char *)"ABC",29);
    Buttons[29].dark = true;
    Buttons_Add( 72,200,28,36,(char *)"/",30);
    Buttons_Add(108,204,100,36,(char *)" ",31);
    Buttons_Add(220,200,28,36,(char *)".",32);
    Buttons_Add(258,200,60,36,(char *)"Ok",33);
    Buttons[33].dark = true;

    Buttons_Show();
}


static const uint8_t nums2_tab[] = { '+','*','/','=','<','>','{','}','[',']',
	                             ' ',' ',' ',' ','%','~','`',' ',' ',' ',
				     '_','\\','|',' ',' ',' ',' ' };

/**
 * @brief Level 5, symbol keys
 */
void B_Nums2(void)
{
    Buttons_Clear();

    Buttons_Add(  2, 80,28,36,(char *)"+", 0);
    Buttons_Add( 34, 80,28,36,(char *)"*", 1);
    Buttons_Add( 66, 80,28,36,(char *)"/", 2);
    Buttons_Add( 98, 80,28,36,(char *)"=", 3);
    Buttons_Add(130, 80,28,36,(char *)"<", 4);
    Buttons_Add(162, 80,28,36,(char *)">", 5);
    Buttons_Add(194, 80,28,36,(char *)"{", 6);
    Buttons_Add(226, 80,28,36,(char *)"}", 7);
    Buttons_Add(258, 80,28,36,(char *)"[", 8);
    Buttons_Add(290, 80,28,36,(char *)"]", 9);

    Buttons_Add(  2,120,28,36,(char *)" ",10);
    Buttons_Add( 34,120,28,36,(char *)" ",11);
    Buttons_Add( 66,120,28,36,(char *)" ",12);
    Buttons_Add( 98,120,28,36,(char *)" ",13);
    Buttons_Add(130,120,28,36,(char *)"%",14);
    Buttons_Add(162,120,28,36,(char *)"~",15);
    Buttons_Add(194,120,28,36,(char *)"`",16);
    Buttons_Add(226,120,28,36,(char *)" ",17);
    Buttons_Add(258,120,28,36,(char *)" ",18);
    Buttons_Add(290,120,28,36,(char *)" ",19);

    Buttons_Add( 50,160,28,36,(char *)"_",20);
    Buttons_Add( 82,160,28,36,(char *)"\\",21);
    Buttons_Add(114,160,28,36,(char *)"|",22);
    Buttons_Add(146,160,28,36,(char *)" ",23);
    Buttons_Add(178,160,28,36,(char *)" ",24);
    Buttons_Add(210,160,28,36,(char *)" ",25);
    Buttons_Add(242,160,28,36,(char *)" ",26);

    Buttons_Add(  2,160,42,36,(char *)"2/2",27);
    Buttons[27].dark = true;
    Buttons_Add(276,160,42,36,(char *)"del",28);
    Buttons[28].dark = true;
    Buttons[28].small = true;

    Buttons_Add(  2,200,60,36,(char *)"ABC",29);
    Buttons[29].dark = true;
    Buttons_Add( 72,200,28,36,(char *)"/",30);
    Buttons_Add(108,204,100,36,(char *)" ",31);
    Buttons_Add(220,200,28,36,(char *)".",32);
    Buttons_Add(258,200,60,36,(char *)"Ok",33);
    Buttons[33].dark = true;

    Buttons_Show();
}


static const uint8_t digits_tab[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '.' };

/**
 * @brief A small nummeric keyboard
 */
void B_Digits(void)
{
    Buttons_Clear();

    Buttons_Add( 61,200,147,36,(char *)"0", 9);

    Buttons_Add( 61,160,47,36,(char *)"1", 0);
    Buttons_Add(111,160,47,36,(char *)"2", 1);
    Buttons_Add(161,160,47,36,(char *)"3", 2);
    Buttons_Add(211,160,47,36,(char *)"+",10);
    Buttons[10].dark = true;

    Buttons_Add( 61,120,47,36,(char *)"4", 3);
    Buttons_Add(111,120,47,36,(char *)"5", 4);
    Buttons_Add(161,120,47,36,(char *)"6", 5);
    Buttons_Add(211,120,47,36,(char *)"-",11);
    Buttons[11].dark = true;

    Buttons_Add( 61, 80,47,36,(char *)"7", 6);
    Buttons_Add(111, 80,47,36,(char *)"8", 7);
    Buttons_Add(161, 80,47,36,(char *)"9", 8);
    Buttons_Add(211, 80,47,36,(char *)".",12);
    Buttons[12].dark = true;

    Buttons_Add(211,200,47,36,(char *)"del",13);
    Buttons[13].dark = true;
    Buttons[13].small = true;

    Buttons_Add(271,200,47,36,(char *)"Ok",14);
    Buttons[14].dark = true;

    Buttons_Show();
}



int KeyBoardAll(void)
{
    int		key;

    key = Buttons_Scan();
    if (key == -1)
	return -1;

    switch (level) {
	    case 1:	if (key >= 0 && key <= 25) {
			    key = alphalow_tab[key];
	    		} else if (key == 26) {
			    level = 2;
			    B_AlphaCaps(level);
			} else if (key == 27) {
			    key = 127;
			} else if (key == 28) {
			    level = 4;
			    B_Nums1();
			} else if (key == 29) {
			    key = '/';
			} else if (key == 30) {
			    key = ' ';
			} else if (key == 31) {
			    key = '.';
			} else if (key == 32) {
			    key = 0;
			}
			break;
	    case 2:
	    case 3:	if (key >= 0 && key <= 25) {
			    key = alphacaps_tab[key];
			    if (level == 2) {
				level = 1;
				B_AlphaLow();
			    }
			} else if (key == 26 && level == 3) {
			    level = 1;
			    B_AlphaLow();
			} else if (key == 26 && level == 2) {
			    level = 3;
			    B_AlphaCaps(level);
			} else if (key == 27) {
			    key = 127;
			} else if (key == 28) {
			    level = 4;
			    B_Nums1();
			} else if (key == 29) {
			    key = '/';
			} else if (key == 30) {
			    key = ' ';
			} else if (key == 31) {
			    key = '.';
			} else if (key == 32) {
			    key = 0;
			}
			break;
	    case 4:	if (key >= 0 && key <= 26) {
			    key = nums1_tab[key];
			} else if (key == 27) {
			    level = 5;
			    B_Nums2();
			} else if (key == 28) {
			    key = 127;
			} else if (key == 29) {
			    level = 1;
			    B_AlphaLow();
			} else if (key == 30) {
			    key = '/';
			} else if (key == 31) {
			    key = ' ';
			} else if (key == 32) {
			    key = '.';
			} else if (key == 33) {
			    key = 0;
			}
			break;
	    case 5:	if (key >= 0 && key <= 26) {
			    key = nums2_tab[key];
			} else if (key == 27) {
			    level = 4;
			    B_Nums1();
			} else if (key == 28) {
			    key = 127;
			} else if (key == 29) {
			    level = 1;
			    B_AlphaLow();
			} else if (key == 30) {
			    key = '/';
			} else if (key == 31) {
			    key = ' ';
			} else if (key == 32) {
			    key = '.';
			} else if (key == 33) {
			    key = 0;
			}
			break;
    }

    return key;
}


int KeyBoardDigits(void)
{
    int         key;

    key = Buttons_Scan();
    if (key == -1)
	return -1;

    if (key >= 0 && key <= 12) {
	key = digits_tab[key];
    } else if (key == 13) {
	key = 127;
    } else if  (key == 14) {
	key = 0;
    }

    return key;
}



/**************************************************************************/
/*
 *  Data show and edit functions.
 */

void ShowText(uint16_t x, uint16_t y, char *label, char *txt)
{
    _fg = TFT_LIGHTGREY;
    TFT_print(label, x, y);
    _fg = TFT_YELLOW;
    TFT_print((char *)" ", LASTX, LASTY);
    TFT_print(txt, LASTX, LASTY);
}



void ShowInteger(uint16_t x, uint16_t y, char *label, char *suffix, int val)
{
    char        tmp[32];

    _fg = TFT_LIGHTGREY;
    TFT_print(label, x, y);
    _fg = TFT_YELLOW;
   sprintf(tmp, " %d", val);
   TFT_print(tmp, LASTX, LASTY);
   if (suffix) {
        _fg = TFT_LIGHTGREY;
        TFT_print(suffix, LASTX, LASTY);
   }
}



void ShowBool(uint16_t x, uint16_t y, char *label, bool val)
{
    _fg = TFT_LIGHTGREY;
    TFT_print(label, x, y);
    _fg = TFT_YELLOW;
    if (val)
        TFT_print((char *)" J", LASTX, LASTY);
    else
        TFT_print((char *)" N", LASTX, LASTY);
}



void ShowSSR2(uint16_t x, uint16_t y, int val)
{
    _fg = TFT_LIGHTGREY;
    TFT_print((char *)"SSR2 ", x, y);
    _fg = TFT_YELLOW;
    TFT_clearStringRect(TFT_X, TFT_Y, (char *)"HLT en MLT");
    TFT_print((char *)SSR2Types[val], LASTX, LASTY);
}



void ShowFloat(uint16_t x, uint16_t y, char *label, char *suffix, float val, int decimals)
{
    char        tmp[32];

    _fg = TFT_LIGHTGREY;
    TFT_print(label, x, y);
    _fg = TFT_YELLOW;
    sprintf(tmp, " %.*f", decimals, val);
    TFT_print(tmp, LASTX, LASTY);
    if (suffix) {
        _fg = TFT_LIGHTGREY;
        TFT_print(suffix, LASTX, LASTY);
    }
}



void ShowDouble(uint16_t x, uint16_t y, char *label, char *suffix, double val, int decimals)
{
    char        tmp[32];

    _fg = TFT_LIGHTGREY;
    TFT_print(label, x, y);
    _fg = TFT_YELLOW;
    sprintf(tmp, " %.*f", decimals, val);
    TFT_print(tmp, LASTX, LASTY);
    if (suffix) {
	_fg = TFT_LIGHTGREY;
	TFT_print(suffix, LASTX, LASTY);
    }
}



void Editer(char *label, char *txt, char *errmsg, int len, int type)
{
    int		key;

    _bg = TFT_BLACK;
    TFT_fillScreen(_bg);
    TFT_resetclipwin();
    TopMessage((char *)"Wijzigen");
    _fg = TFT_LIGHTGREY;
    TFT_setFont(DEFAULT_FONT, NULL);
    TFT_print(label, 2, 28);
    if (strlen(errmsg)) {
	_fg = TFT_RED;
	TFT_print(errmsg, 2, 60);
    }
    TFT_fillRect(2, 40, 10 * len, 14, TFT_BLUE);
    _fg = TFT_YELLOW;
    _bg = TFT_BLUE;
    TFT_print(txt, 2, 41);
    TFT_fillRect(TFT_X, 50, 10, 4, TFT_GREEN);

    switch(type) {
	case EDIT_TYPE_INT:	
			B_Digits();
			break;

	default:	level = 1;
			B_AlphaLow();
			break;
    }

    while (1) {
	switch (type) {
	   case  EDIT_TYPE_INT:
		   	key = KeyBoardDigits();
			break;

	    default:	key = KeyBoardAll();
			break;
	}

	if (key != -1) {

	    if (key >= 32 && key <= 126 && strlen(txt) < len) {
	    	// Append key
		txt[strlen(txt) + 1] = '\0';
	    	txt[strlen(txt)] = key;
	    } else if (key == 127 && strlen(txt)) {
	    	// Delete key
	    	txt[strlen(txt) - 1] = '\0';
	    }

	    _fg = TFT_YELLOW;
	    _bg = TFT_BLACK;
	    TFT_setFont(DEFAULT_FONT, NULL);
	    TFT_fillRect(2, 40, 10 * len, 14, TFT_BLUE);
	    TFT_print(txt, 2, 41);
	    TFT_fillRect(TFT_X, 50, 10, 4, TFT_GREEN);
	}

	if (key == 0)
	    break;

	vTaskDelay(20 / portTICK_PERIOD_MS);
    }
}



void EditText(char *label, char *txt, int len)
{
    char		errmsg[40];

    errmsg[0] = '\0';
    while (1) {
    	Editer(label, txt, errmsg, len, EDIT_TYPE_TEXT);
	if (strlen(txt))
	    break;
	sprintf(errmsg, "Tekst veld mag niet leeg zijn");
    }
}



void EditTextMin(char *label, char *txt, int len, int min)
{
    char                errmsg[40];

    errmsg[0] = '\0';
    while (1) {
	Editer(label, txt, errmsg, len, EDIT_TYPE_TEXT);
	if (strlen(txt) >= min)
	    break;
	sprintf(errmsg, "Tekst veld moet tussen %d en %d lang zijn", min, len);
    }
}



void EditInt(char *label, int *val, int min, int max)
{
    char	*valstr, errmsg[40];
    int		newval;

    errmsg[0] = '\0';
    valstr = malloc(20);
    sprintf(valstr, "%d", *val);

    while (1) {
	Editer(label, valstr, errmsg, 8, EDIT_TYPE_INT);
	newval = atoi(valstr);
	if (newval < min || newval > max) {
	    sprintf(errmsg, "De waarde moet tussen %d en %d zijn.", min, max);
	} else {
	    break;
	}
    }

    *val = newval;
    free(valstr);
}



void EditUint8(char *label, uint8_t *val, uint8_t min, uint8_t max)
{
    char        *valstr, errmsg[40];
    uint8_t	newval;

    errmsg[0] = '\0';
    valstr = malloc(20);
    sprintf(valstr, "%d", *val);

    while (1) {
	Editer(label, valstr, errmsg, 5, EDIT_TYPE_INT);
	newval = atoi(valstr);
	if (newval < min || newval > max) {
	    sprintf(errmsg, "De waarde moet tussen %d en %d zijn.", min, max);
	} else {
	    break;
	}
    }

    *val = newval;
    free(valstr);
}



void EditUint16(char *label, uint16_t *val, uint16_t min, uint16_t max)
{   
    char        *valstr, errmsg[64];
    uint16_t     newval;

    errmsg[0] = '\0';
    valstr = malloc(20);
    sprintf(valstr, "%d", *val);

    while (1) {
	Editer(label, valstr, errmsg, 5, EDIT_TYPE_INT);
	newval = atoi(valstr);
	if (newval < min || newval > max) {
	    sprintf(errmsg, "De waarde moet tussen %d en %d zijn.", min, max);
	} else {
	    break;
	}
    }

    *val = newval;
    free(valstr);
}



void EditFloat(char *label, float *val, float min, float max, int decimals)
{
    char        *valstr, errmsg[672];
    float	newval;

    errmsg[0] = '\0';
    valstr = malloc(30);
    sprintf(valstr, " %.*f", decimals, *val);

    while (1) {
	Editer(label, valstr, errmsg, 25, EDIT_TYPE_INT);
	newval = atof(valstr);
	if (newval < min || newval > max) {
	    sprintf(errmsg, "De waarde moet tussen %.*f en %.*f zijn.", decimals, min, decimals, max);
	} else {
	    break;
	}
    }

    *val = newval;
    free(valstr);
}



void EditDouble(char *label, double *val, double min, double max, int decimals)
{
    char        *valstr, errmsg[672];
    double	newval;

    errmsg[0] = '\0';
    valstr = malloc(30);
    sprintf(valstr, " %.*f", decimals, *val);

    while (1) {
	Editer(label, valstr, errmsg, 25, EDIT_TYPE_INT);
	newval = atof(valstr);
	if (newval < min || newval > max) {
	    sprintf(errmsg, "De waarde moet tussen %.*f en %.*f zijn.", decimals, min, decimals, max);
	} else {
	    break;
	}
    }

    *val = newval;
    free(valstr);
}



void EditBool(char *label, bool *val)
{
    bool	loop = true, value = *val;
    int		curpos;

    _bg = TFT_BLACK;
    TFT_fillScreen(_bg);
    TFT_resetclipwin();
    TopMessage((char *)"Wijzigen");
    _fg = TFT_LIGHTGREY;
    TFT_setFont(DEFAULT_FONT, NULL);
    TFT_print(label, 2, 28);
    curpos = TFT_X;
    _fg = TFT_YELLOW;
    (value) ? TFT_print((char *)" J ", curpos, 28) : TFT_print((char *)" N ", curpos, 28);

    Buttons_Clear();
    Buttons_Add( 40, 100, 80, 40, (char *)"J/N", 0);
    Buttons_Add(200, 100, 80, 40, (char *)"Ok",  1);
    Buttons_Show();

    while (loop) {
	switch (Buttons_Scan()) {
	    case 0:	TFT_setFont(DEFAULT_FONT, NULL);
			_fg = TFT_YELLOW;
		    	if (value) {
			    value = false;
			    TFT_print((char *)" N ", curpos, 28);
			} else {
			    value = true;
			    TFT_print((char *)" J ", curpos, 28);
			}
			break;

	    case 1:	loop = false;
			break;

	    default:	break;
	}
	vTaskDelay(20 / portTICK_PERIOD_MS);
    }
    *val = value;
}



void EditSSR2(int *val)
{
    bool        loop = true;
    int		value = *val;
    int		key;

    _bg = TFT_BLACK;
    TFT_fillScreen(_bg);
    TFT_resetclipwin();
    TopMessage((char *)"Wijzigen");

    Buttons_Clear();
    Buttons_Add( 20,  60,120, 40, (char *)SSR2Types[0], 0);
    Buttons_Add(180,  60,120, 40, (char *)SSR2Types[1], 1);
    Buttons_Add( 20, 130,120, 40, (char *)SSR2Types[2], 2);
    Buttons_Add(180, 130,120, 40, (char *)SSR2Types[3], 3);
    Buttons_Add(120, 200, 80, 40, (char *)"Ok",  4);
    Buttons[4].dark = true;
    Buttons[value].lock = true;
    Buttons_Show();

    while (loop) {
	key = Buttons_Scan();

	if (key >= 0 && key <= 3) {
	    Buttons[value].lock = false;
	    value = key;
	    Buttons[value].lock = true;
	    Buttons_Show();
	} else if (key == 4) {
	    loop = false;
	}
        vTaskDelay(20 / portTICK_PERIOD_MS);
    }
    *val = value;
}



void EditMashType(uint8_t *val)
{
    bool        loop = true;
    int		value = (int)*val;
    int         key;

    _bg = TFT_BLACK;
    TFT_fillScreen(_bg);
    TFT_resetclipwin();
    TopMessage((char *)"Wijzigen");

    Buttons_Clear();
    Buttons_Add( 80,  40,160, 40, (char *)mashTypes[0], 0);
    Buttons_Add( 80,  90,160, 40, (char *)mashTypes[1], 1);
    Buttons_Add( 80, 140,160, 40, (char *)mashTypes[2], 2);
    Buttons_Add(120, 200, 80, 40, (char *)"Ok",  3);
    Buttons[3].dark = true;
    Buttons[value].lock = true;
    Buttons_Show();

    while (loop) {
	key = Buttons_Scan();

	if (key >= 0 && key <= 2) {
	    Buttons[value].lock = false;
	    value = key;
	    Buttons[value].lock = true;
	    Buttons_Show();
	} else if (key == 3) {
	    loop = false;
	}
	vTaskDelay(20 / portTICK_PERIOD_MS);
    }
    Buttons[value].lock = false;
    *val = (uint8_t)value;
}



int Confirm(char *top, char *ack, char *nak)
{
    int		rc = false;
    bool	loop = true;

    TFT_fillScreen(TFT_BLACK);
    TopMessage(top);
    Buttons_Clear();
    Buttons_Add( 40, 100, 80, 40, ack, 0);
    Buttons_Add(200, 100, 80, 40, nak, 1);
    Buttons_Show();
    SoundPlay(SOUND_Prompt);

    while (loop) {
	switch (Buttons_Scan()) {
	    case 0:	loop = false;
			rc = true;
			break;

	    case 1:	loop = false;
			rc = false;
			break;

	    default:
			break;
	}
	vTaskDelay(50 / portTICK_PERIOD_MS);
    }

    Buttons_Clear();
    return rc;
}

mercurial