/*
	SC1LCD.C

	CM71xx/Z1 and CM72xx/Z2

	Display time and date to the LCD. Use the field(3), up(4) and down(5)
	keys to change the time and date of the Real Time Clock. Use the function
	keys F1 to F4 to toggle the led's.
	The lcd-keypad module for the SmartCore Evaluation Board is needed to run
	this demo program.
*/

#use lcd2l.lib
#use vdriver.lib

#define DebounceCount 20      // key debounce rate, 20*0.025 = 0.5 sec
#define BeepScale     0.04    // scale the time in up_beep(millisecond) to
										// turn on beeper for the correct millisecond
										// on time. Since lc_beepscan is called every
										// 25ms, therefore 1/25 = 0.04. 

void process_time(int key, int cursor);
void showtime(struct tm thistime);
main()
{
	char *text[] = {
							"Z-World Engineering ",
							"Field(3) key to chng",
							"time adjust field.  ",
							"Up(4) key to incrmnt",
							"time data field.    ",
							"Dwn(5) key to dcrmnt",
							"time data field.    ",
							"F1 to toggle led D1.",
							"F2 to toggle led D2.",
							"F3 to toggle led D3.",
							"F4 to toggle led D4.",
							"Key is not used.    "
						};
	char lctext[21];
	struct tm thistime;
	int key;
	int textoffset;
	int cursor;
	int oldsec;
	char lcdcursor[10];
	char nextcursor[20] = {2,2,4,4,5,7,7,8,10,10,12,12,13,15,15,16,18,18,19,2};
	int led1onoff, led2onoff, led3onoff, led4onoff;

	led1onoff = led2onoff = led3onoff = led4onoff = 0;             
	cursor = 2;
	lctext[20] = '\0';   // null the last character of lctext
	textoffset = 0;      // text offset for display start at 0. 

	lc_kxinit();      // initialize the keypad first
	lc_init();        // initialize the LCD

	sprintf(lcdcursor,"\x1bp1%02d",cursor);

	tm_rd(&thistime);       // read the real time clock

	// adjust real time clock if not already running or out of range
	if( (thistime.tm_year < 95) || (thistime.tm_year >99) )
	{
		thistime.tm_hour = 8;
		thistime.tm_min = 0;
		thistime.tm_sec = 0;
		thistime.tm_mon = 6;
		thistime.tm_mday = 1;
		thistime.tm_year = 95;
		thistime.tm_wday = 4;
		tm_wr(&thistime);
	}  

	VdInit();      // initialize the virtual driver

	while(1)
	{
		runwatch();
		costate     // scan keypad and service beeper every 25ms
		{
				lc_beepscan();
				lc_keyscan();
				waitfor(DelayMs(25L));
		}

		costate 
		{
				lc_printf("\x1bp000%s", text[textoffset++]);
				lc_printf("%s",lcdcursor);    // update the cursor position
				if(textoffset > 10) textoffset = 0;
				waitfor(DelaySec(1L));        // update every 1 second
		}

		costate
		{
				tm_rd(&thistime);          // read the real time clock
				showtime(thistime);
				lc_printf("%s",lcdcursor);
				waitfor(DelaySec(1L));     // update time every 1 second
		}           

		if((key = lc_kxget(0))!= -1)     // check for key pressed
		{
			up_beep(100);        // beep for 100 ms
			if( key == 4 || key == 5)        // change the time/date field
			{                                
				if(key==4) textoffset = 3;
				else textoffset = 5;
				process_time(key, cursor);
				tm_rd(&thistime);
				showtime(thistime);
			}
			else
			{
				switch(key)
				{
					case 3:              // process the field key
							textoffset = 1;
							cursor = nextcursor[cursor];
							sprintf(lcdcursor,"\x1bp1%02d",cursor);
							break;
					case 7:              // turn led D2 on/off
							textoffset = 7;
							if(led1onoff) led1onoff = 0;
							else led1onoff = 1;
							outport(CS1, led1onoff);
							break;
					case 8:              // turn led D3 on/off
							textoffset = 8;
							if(led2onoff) led2onoff = 0;
							else led2onoff = 1;
							outport(CS1+1, led2onoff);
							break;
					case 9:              // turn led D4 on/off
							textoffset = 9;
							if(led3onoff) led3onoff = 0;
							else led3onoff = 1;
							outport(CS1+2, led3onoff);
							break;
					case 10:             // turn led D5 on/off   
							textoffset = 10;
							if(led4onoff) led4onoff = 0;
							else led4onoff = 1;
							outport(CS1+3, led4onoff);
							break;
					default:
							textoffset = 11;
							up_beep(250);     // beep for 250 ms
													// for invalid key
							break;
				}  // end of switch
			}  // end of else

			lc_printf("\x1bp000%s", text[textoffset]);      
												// print current text to match key
			lc_printf("%s",lcdcursor); // position the cursor accordingly
		}  // end of if
	}  // end of while
}  // end of main


// Increment or decrement specified field of the time/date. 
// Field is specified by the cursor.
void process_time(int key, int cursor)
{
		int monlimit, temp;
		struct tm thistime;

		tm_rd(&thistime);
		switch(thistime.tm_mon)    // get the number of days per active month
		{
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12: monlimit = 31;
						break;
			case 4:
			case 6:
			case 9:
			case 11:
						monlimit = 30;
						break;
			case 2:
						if(((thistime.tm_year+1900) % 4)==0)
							monlimit = 29;
						else
							monlimit = 28;
						break;
			default:
						break;
		}  

		if(key==4)
		{
			switch(cursor)
			{
				case 2:
						thistime.tm_mon = thistime.tm_mon + 1;
						if(thistime.tm_mon > 12) thistime.tm_mon = 1;
						break;
				case 4:
						thistime.tm_mday = thistime.tm_mday + 10;
						if(thistime.tm_mday > monlimit) thistime.tm_mday = 1;
						//printf("%d\n", thistime.tm_mday);
						break;
				case 5:
						thistime.tm_mday = thistime.tm_mday + 1;
						if(thistime.tm_mday > monlimit) thistime.tm_mday = 1;
						
						break;
				case 7:
						thistime.tm_year = thistime.tm_year + 10;
						if(thistime.tm_year > 99)
								thistime.tm_year = thistime.tm_year - 100; 
						break;
				case 8:
						thistime.tm_year = thistime.tm_year + 1;
						if(thistime.tm_year > 99) thistime.tm_year - 100;
						break;
				case 10:
						thistime.tm_wday = thistime.tm_wday + 1;
						if(thistime.tm_wday > 6) thistime.tm_wday = 0;
						break;
				case 12:
						thistime.tm_hour = thistime.tm_hour + 10;
						if(thistime.tm_hour > 23) thistime.tm_hour = 0;
						break;
				case 13:
						thistime.tm_hour = thistime.tm_hour + 1;
						if(thistime.tm_hour > 23) thistime.tm_hour = 0;
						break;
				case 15:
						thistime.tm_min = thistime.tm_min + 10;
						if(thistime.tm_min > 59) thistime.tm_min = 0;
						break;
				case 16:
						thistime.tm_min = thistime.tm_min + 1;
						if(thistime.tm_min > 59) thistime.tm_min = 0;
						break;
				case 18:
						thistime.tm_sec = thistime.tm_sec + 10;
						if(thistime.tm_sec > 59) thistime.tm_sec = 0;
						break;
				case 19:
						thistime.tm_sec = thistime.tm_sec + 1;
						if(thistime.tm_sec > 59) thistime.tm_sec = 0;
						break;
			}  
		}
		else
		{
			switch(cursor)
			{
				case 2:
						thistime.tm_mon = thistime.tm_mon - 1;
						if(thistime.tm_mon < 1 ) thistime.tm_mon = 12;
						break;
				case 4:
						temp = thistime.tm_mday;
						temp = temp - 10;
						if(temp < 1) temp = monlimit;
						thistime.tm_mday = temp;
						break;
				case 5:
						temp = thistime.tm_mday;
						temp = temp - 1;
						if(temp < 1) temp = monlimit;
						thistime.tm_mday = temp;
						break;
				case 7:
						temp = thistime.tm_year;
						if(temp==0) temp = 100;
						temp = temp - 10;
						if(temp < 0) temp = temp + 100;
						thistime.tm_year = temp;
						break;
				case 8:
						temp = thistime.tm_year;
						if(temp==0) temp = 100;
						temp = temp - 1;
						if(temp < 0) temp = temp + 100;
						thistime.tm_year = temp;
						break;
				case 10:
						temp = thistime.tm_wday;
						temp = temp - 1;
						if(temp < 0) temp = 0;
						thistime.tm_wday = temp;
						break;
				case 12:
						temp = thistime.tm_hour;
						temp = temp - 10;
						if(temp < 0) temp = 0;
						thistime.tm_hour = temp;
						break;
				case 13:
						temp = thistime.tm_hour;
						temp = temp - 1;
						if(temp < 0) temp = 0;
						thistime.tm_hour = temp;
						break;
				case 15:
						temp = thistime.tm_min;
						temp = temp - 10;
						if(temp < 0) temp = 0;
						thistime.tm_min = temp;
						break;
				case 16:
						temp = thistime.tm_min;
						temp = temp - 1;
						if(temp < 0) temp = 0;
						thistime.tm_min = temp;
						break;
				case 18:
						temp = thistime.tm_sec;
						temp = temp - 10;
						if(temp < 0) temp = 0;
						thistime.tm_sec = temp;
						break;
				case 19:
						temp = thistime.tm_sec;
						temp = temp - 1;
						if(temp < 0) temp = 0;
						thistime.tm_sec = temp;
						break;
			}
		}                 

		tm_wr(&thistime);
}                    


// show the time and date to the LCD.
void showtime(struct tm thistime)
{
	lc_printf("\x1bp100 %02d-%02d-%02d-%d %02d:%02d:%02d",
					thistime.tm_mon, thistime.tm_mday, thistime.tm_year,
					thistime.tm_wday,
					thistime.tm_hour, thistime.tm_min, thistime.tm_sec);
}
					




