/*
  LK_KEY_2.C

  Any board that has a native LCD port or PLC-bus.
  
  Demonstration of the use of the LCD menuing system.
  
  The keypad has three states, depending on whether the item is display,
  limited entry, or direct user entry and is setup as follows:
  
            |-----|-----|-----|-----|
            |7/esc|  8  |  9  |  -  |
            |-----|-----|-----|-----|
   keypad   |  4  |  5  |  6  | + ^ |
   lower    |-----|-----|-----|-----|
   left     |  1  |  2  |  3  | # v |
   corner   |-----|-----|-----|-----|
    |       |  0  | * <-| . ->|Selct|
     -----> |-----|-----|-----|-----|
            
   Use the right and left arrows to scroll through the menu items and press
   select to choose an item.  After selecting an adjustable item use the 
   right and left arrow keys to move from item to item.  The up and down 
   arrow keys to increment and decrement the item that the cursor is 
   positioned on. Press select when you complete the changes.

   User entry items allow the user to enter an actual value.
*/

// local function prototypes
void date_set(struct tm *ptr);
void DelayAWhile(void);
void extrabeep(float *ptr);
void fencealarm(char *logical);
void fivebeep(void);
int func40t(void);

// global variables
float temp, exbeep;
struct tm today;
char fence;
unsigned time16;

#if 1	// set to 1 if using a 4x20 KDM, otherwise set to 0
#define KEYPAD_SIZE 24	// set to the appropriate number of keys
#ifdef LK_COLS
#undef LK_COLS
#endif
#define LK_COLS 20

#ifdef LK_LINES
#undef LK_LINES
#endif
#define LK_LINES 4
#endif

#if 0	// set to 1 if using a 4x40 KDM, otherwise set to 0
#define KEYPAD_SIZE 40	// set to the appropriate number of keys
#ifdef LK_COLS
#undef LK_COLS
#endif
#define LK_COLS 40
#endif

#if 0	// set to 1 if using a 2x16 (old version) LCD, otherwise set to 0
#define KEYPAD_SIZE 16	// set to the appropriate number of keys
#ifdef LK_COLS
#undef LK_COLS
#endif
#define LK_COLS 16

#ifdef LK_LINES
#undef LK_LINES
#endif
#define LK_LINES 2
#endif

#use "kdm.lib"

// define keys to match minimal keypad from above
int tab_keys[KEYPAD_SIZE] = { '0', '1', '4', '7',
                              '*', '2', '5', '8',
                              '.', '3', '6', '9',
                              '\n', '#', '+', '-' };

// Please see lk_run_menu() function help for information about the
// menu system and structures.

struct lk_limits limeelow = { 0.0, 64.0, 1.0 };
struct lk_limits limeehi = { 256.0, 320.0, 1.0 };
struct lk_limits limtemp = { 10.0, 120.0, 1.0 };
struct lk_limits beeplimits = { 0.0, 94.0, 1.0 };

struct lk_menu story[20] =
{
	{ 1, "\x1bp100\x1bcOnce upon a time", 0, 0, 0 },
	{ 1, "\x1bp100\x1bcin a distant ", 0, 0, 0 },
	{ 1, "\x1bp100\x1bcland, far, far", 0, 0, 0 },
	{ 1, "\x1bp100\x1bcaway, the sun ", 0, 0, 0 },
	{ 1, "\x1bp100\x1bcalways shone.", 0, 0, 0 },
	{ 1, "\x1bp100\x1bcThis land was", 0, 0, 0 },
	{ 1, "\x1bp100\x1bccalled the world", 0, 0, 0 },
	{ 1, "\x1bp100\x1bcof Z.", 0, 0, 0 },
	0	// end of menu marker
};

struct lk_menu setup[20] =
{
	{ 1, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcTemp is %4.0f.", &temp,
	  &limtemp, 0 },
	{ 2, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcAdjust temp %4.0f.", &temp,
	  &limtemp, 0 },
	{ 3, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcEnter temp  %4.0f.", &temp,0,0},
	{ 4, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcExtra beep %4.1f.", &exbeep,
	  &beeplimits, extrabeep },
	{ 8, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcFence is off./\x1bp100\x1bcFence is on.",
	  &fence, 0, 0 },
	{ 9, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcSet fence off./\x1bp100\x1bcSet fence on.",
	  &fence, 0, 0 },
	{ 10, "\x1bp000\x1bcWelcome menu\x1bp100\x1bcElec. fence is off./\x1bp100\x1bcElec. fence is on.",
	  &fence, 0, fencealarm },
	{ 16, "\x1bp000\x1bcTime/date:", &today, 0, 0 },
	{ 17, "\x1bp000\x1bcSet time/date:", &today, 0, 0 },
	{ 18, "\x1bp000\x1bcSet time/date/f:", &today, 0, date_set },
	{ 20, "\x1bp000\x1bc16-bit time:", &time16, 0, 0 },
	{ 21, "\x1bp000\x1bcSet 16-bit time:", &time16, 0, 0 },
	{ 22, "\x1bp000\x1bcSet 16-time/f:", &time16, 0, fivebeep },
	{ 32, "\x1bp000\x1bcStory Menu\x1bp100\x1bcGo to Story Menu.", &story, 0,0},
	{ 40, "\x1bp100\x1bcCall func40t().", 0, 0, func40t },
	0	// end of menu marker
};

nodebug root
void date_set(struct tm *ptr)
{
	tm_wr(ptr);	// write to real time clock
	today=*ptr;	// move entire structure
}

nodebug root
void extrabeep(float *ptr)
{
	lk_setbeep((int) *ptr*10);
}

nodebug root
void fencealarm(char *logical)
{
	if(*logical)
	{
		lk_setbeep(800);	// alarm notification that fence is on
	}
}

nodebug root
void fivebeep(void)
{
	int k,j;

	for(k=0; k<5; k++)
	{
		for(j=0; j<8000; j++)
		{
			hitwd();
		}
		lk_setbeep(60);
	}
}

nodebug root
int func40t(void)
{
	lk_printf("\x1bp100\x1bcfunc40t() active");
	lk_setbeep(50);
	DelayAWhile();
	lk_setbeep(100);
	return 0;
}

nodebug
void DelayAWhile(void)
{
	unsigned k;

	for(k = (unsigned) -1; k; k--)
	{
		hitwd();
	}
}

//nodebug
main()
{
	char key;
	int index;

	lk_init_keypad();
	lk_loadtab (tab_keys, sizeof (tab_keys));
	lk_settab (1);

	temp = 18.0;
	exbeep = 80.5;
	tm_rd (&today);

	key = ' ';
	index = 0;
	while(1)
	{
		hitwd();
		// Beep for 1 second.
		lk_setbeep(400);
		// Position cursor to start of line 1, erase line 1, then print welcome.
		lk_printf("\x1bp000\x1bcWelcome");
		// Position cursor to start of line 2, erase line 2, then print info.
		lk_printf("\x1bp100\x1bckey: %c index: %d", key, index);
		// Delay a while to display index value on LCD.
		DelayAWhile();
		// Start or restart the menu.
		// When not setting a value, escape keys are 3 through 9 inclusive.
		index = lk_run_menu("\x1bp100\x1bc\x1bp000\x1bcWelcome menu", setup, 0);
		// Get the escape key press character.
		key = (char) lk_kxget(0);
	}
}
