#include <reg167.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <absacc.h>
#include <intrins.h>

#include "global.h"
#include "int.h"

#include "ext/MISC.H"
#include "ext/I2C_HARD.H"
#include "ext/I2C_BUS.H"
#include "ext/RTC.H"

#include "util.c"
#include "astro.c"
#include "usr.c"

#include "scope.c"


#define CONFIGINIT 12345


typedef struct configstruct {

	int __initid;

	double __LATITUDE;
	double __LONGITUDE;

	double __CFG_HSTS_HO;
	double __CFG_HSTS_VE;
	double __CFG_HSTS_FR;
	
	int __CFG_SP1_HO;
	int __CFG_SP1_VE;
	
	int __CFG_SP2_HO;
	int __CFG_SP2_VE;

	int __CFG_SP3_HO;
	int __CFG_SP3_VE;

	int __CFG_SP_FR;

	int	__CFG_ENC_HO;
	int __CFG_ENC_VE;
	
	unsigned char __ENC_FLAGS;
	unsigned char __RESERVE;

} configstruct;



configstruct cfg[4];
int curconfig;


const char main_txt0[18]  	= "      C167 ELTEL\0";
const char main_txt1[18]  	= "    VERSION 1.00\0";
const char main_txt2[18]  	= "  E. Benninghaus\0";
const char main_txt3[18]  	= "   Rottweil 2003\0";


const char menu_txt[3][18]  = {
"    ELTEL MOTORS\0",
"    ELTEL ENCODE\0",
"    ELTEL CONFIG\0"
};



const char cfg_txt[29][18]  = {
"       DATE-TIME\0",
"        LATITUDE\0",
"       LONGITUDE\0",
"      ENCODER HO\0",
"      ENCODER VE\0",
"    HSTEPSIZE HO\0",
"    HSTEPSIZE VE\0",
"    HSTEPSIZE FR\0",
"  SPEED COR.1 HO\0",
"  SPEED COR.1 VE\0",
"  SPEED COR.2 HO\0",
"  SPEED COR.2 VE\0",
"  SPEED GOTO  HO\0",
"  SPEED GOTO  VE\0",
"  SPEED GOTO  FR\0",
"  ON/OFF ENC  HO\0",
"  ON/OFF ENC  VE\0",
"  SHOW ENC  ARCS\0",
"  SHOW ENC AZALT\0",
"  SHOW ENC RADEC\0",
"  AUTOTEST ENCHO\0",
"  AUTOTEST ENCVE\0",
"     SAVE CONFIG\0",
"    SET CONFIG 1\0",
"    SET CONFIG 2\0",
"    SET CONFIG 3\0",
"    SET CONFIG 4\0",
"    EDIT OBJLIST\0",
"  SERIAL OBJLOAD\0"

};


#define CFGLASTOFFSET 25



void getConfiguration( void ) {

	if( cfg[curconfig].__initid != CONFIGINIT ) {
		return;
	}

	LATITUDE			= cfg[curconfig].__LATITUDE;
	LONGITUDE			= cfg[curconfig].__LONGITUDE;

	CFG_HSTS_HO			= cfg[curconfig].__CFG_HSTS_HO;
	CFG_HSTS_VE			= cfg[curconfig].__CFG_HSTS_VE;
	CFG_HSTS_FR			= cfg[curconfig].__CFG_HSTS_FR;
	
	CFG_SP1_HO			= cfg[curconfig].__CFG_SP1_HO;
	CFG_SP1_VE			= cfg[curconfig].__CFG_SP1_VE;
	
	CFG_SP2_HO			= cfg[curconfig].__CFG_SP2_HO;
	CFG_SP2_VE			= cfg[curconfig].__CFG_SP2_VE;

	CFG_SP3_HO			= cfg[curconfig].__CFG_SP3_HO;
	CFG_SP3_VE			= cfg[curconfig].__CFG_SP3_VE;

	CFG_SP_FR			= cfg[curconfig].__CFG_SP_FR;

	CFG_ENC_HO			= cfg[curconfig].__CFG_ENC_HO;
	CFG_ENC_VE			= cfg[curconfig].__CFG_ENC_VE;

	ENC_FLAGS			= cfg[curconfig].__ENC_FLAGS & 3;

}



void setConfiguration( void ) {

	cfg[curconfig].__LATITUDE			=	LATITUDE;
	cfg[curconfig].__LONGITUDE			=	LONGITUDE;

	cfg[curconfig].__CFG_HSTS_HO		=	CFG_HSTS_HO;
	cfg[curconfig].__CFG_HSTS_VE		=	CFG_HSTS_VE;
	cfg[curconfig].__CFG_HSTS_FR		=	CFG_HSTS_FR;
	
	cfg[curconfig].__CFG_SP1_HO			=	CFG_SP1_HO;
	cfg[curconfig].__CFG_SP1_VE			=	CFG_SP1_VE;
	
	cfg[curconfig].__CFG_SP2_HO			=	CFG_SP2_HO;
	cfg[curconfig].__CFG_SP2_VE			=	CFG_SP2_VE;

	cfg[curconfig].__CFG_SP3_HO			=	CFG_SP3_HO;
	cfg[curconfig].__CFG_SP3_VE			=	CFG_SP3_VE;

	cfg[curconfig].__CFG_SP_FR			=	CFG_SP_FR;

	cfg[curconfig].__CFG_ENC_HO			=	CFG_ENC_HO;
	cfg[curconfig].__CFG_ENC_VE			=	CFG_ENC_VE;

	cfg[curconfig].__ENC_FLAGS			=	ENC_FLAGS;

	cfg[curconfig].__initid = CONFIGINIT;
}




void config_reset( void ) {


	CFG_ENC_HO = 4000;
	CFG_ENC_VE = 4000;

	ARC10PERENCHO = ARC10_360 / 4000;
	ARC10PERENCVE = ARC10_360 / 4000;


	LATITUDE  = 48.766667;
	LONGITUDE =  9.183333;

	CUR_ARC10_HO 	= 0;
	CUR_ARC10_VE 	= 0;
	OBJ_ARC10_HO 	= 0;
	OBJ_ARC10_VE 	= 0;
	ENC_ARC10_HO 	= 0;
	ENC_ARC10_VE 	= 0;
	CUR_HSTEPS_HO 	= 0;
	CUR_HSTEPS_VE 	= 0;
	TRG_HSTEPS_HO 	= 0;
	TRG_HSTEPS_VE 	= 0;

	HSTEPSHO090		=  324000;
	HSTEPSHO180		=  648000;
	HSTEPSHO270		=  972000;
	HSTEPSHO359		= 1295999;

	CFG_HSTS_HO		= 1.0;
	CFG_HSTS_VE		= 1.0;
	CFG_HSTS_FR		= 1.0;
	
	CFG_SP1_HO		= 600;
	CFG_SP1_VE		= 600;
	
	CFG_SP2_HO		= 5;
	CFG_SP2_VE		= 5;

	CFG_SP3_HO		= 5;
	CFG_SP3_VE		= 5;

	OBJ_DEG_AZ   	= 0;
	OBJ_DEG_ALT  	= 0;
	OBJ_DEG_RA   	= 0;
	OBJ_DEG_DEC  	= 0;


	if( ( curconfig < 0 ) || ( curconfig > 3 ) ){
		curconfig = 0;
	}
	
	getConfiguration();
}





void config( void ) {

	REAL_TIME Time;
	unsigned char KEY,_y,cf;
	int y,upd,cmd,v1;

	lcd_clear();
	wait_10ms(1);

	 y  = 0;
	_y  = 0;
	upd = 1;

	KEY = NOKEY;	
	while( KEY != KEY_C ){

		if( upd ) {
		
			switch( curconfig ){
				case 0: cf = '1';break;
				case 1: cf = '2';break;
				case 2: cf = '3';break;
				case 3: cf = '4';break;				
			}
		
			lcd_clear();
			lcd_puts(0,0,cfg_txt[ y + 0 ]);
			lcd_puts(1,0,cfg_txt[ y + 1 ]);
			lcd_puts(2,0,cfg_txt[ y + 2 ]);
			lcd_puts(3,0,cfg_txt[ y + 3 ]);
		
			upd = 0;
		}

		lcd_setcursor(_y,0);
		lcd_putchar( cf );


		KEY = readkey();

		if(KEY == KEY_DOWN ){

			lcd_setcursor(_y,0);
			lcd_putchar(' ');

			_y++;
			if(_y > 3 ){
				if( y < CFGLASTOFFSET ) {
					 y++;
					 upd = 1;
				}
				_y = 3;
			}
			continue;
		}

		if(KEY == KEY_UP ){
		
			lcd_setcursor(_y,0);
			lcd_putchar(' ');

			if(_y > 0 ){
				_y--;
			}
			else {
				if( y > 0 ){
					y--;
					upd = 1;
				}
				_y = 0;
			}
			continue;
		}


		if(KEY == KEY_E ){
			
			cmd = y + _y;
			
			switch( cmd ) {
				
				case 0:
					//setting date-time

					stopTimerInt();
						
					if( usrGetDateTime() ){

   						//Time.Weekday   = THURSDAY;
   						Time.Date      = INT2BCD(DAY);
   						Time.Month     = INT2BCD(MONTH);
   						Time.Year      = INT2BCD(YEAR);
   						Time.Hour      = INT2BCD(HOUR);
   						Time.Minute    = INT2BCD(MINUTE);
   						Time.Second    = INT2BCD(SECOND);

					    if (RTCSetTime(&Time, RTCDEVICEID ) == RTC_SUCCESSFUL) {

					    	setDaysOfMonth( MONTH, YEAR );
					   		startTimerInt();

					    }					
					}
					else {
						startTimerInt();
					}
					
				break;


				case 1:
					//latitude
					LATITUDE = usrGetDouble( 0 , LATITUDE );
				break;
				
				
				case 2:
					//longitude
					LONGITUDE = usrGetDouble( 0 , LONGITUDE );
				break;

	
				case 3:
					//encoder horizontal
					CFG_ENC_HO = usrGetInt( 0 , CFG_ENC_HO );
					ARC10PERENCHO = ARC10_360 / CFG_ENC_HO;
				break;

				case 4:
					//encoder vertical
					CFG_ENC_VE = usrGetInt( 0 , CFG_ENC_VE );
					ARC10PERENCVE = ARC10_360 / CFG_ENC_VE;					
				break;
				
				case 5:
					//halfstepsize horizontal
					CFG_HSTS_HO = usrGetDouble( 0 , CFG_HSTS_HO );
				break;
				
				case 6:
					//halfstepsize vertical
					CFG_HSTS_VE = usrGetDouble( 0 , CFG_HSTS_VE );
				break;
				
				case 7:
					//halfstepsize fieldrotator
					CFG_HSTS_FR = usrGetDouble( 0 , CFG_HSTS_FR );
				break;

				case 8:
					//speed 1 horizontal correction
					CFG_SP1_HO = usrGetInt( 0 , CFG_SP1_HO );
				break;
				
				case 9:
					//speed 1 vertical correction
					CFG_SP1_VE = usrGetInt( 0 , CFG_SP1_VE );
				break;
				
				case 10:
					//speed 2 horizontal correction
					CFG_SP2_HO = usrGetInt( 0 , CFG_SP2_HO );
				break;
				
				case 11:
					//speed 2 vertical correction
					CFG_SP2_VE = usrGetInt( 0 , CFG_SP2_VE );
				break;
				
				case 12:
					//speed horizontal goto / guiding
					CFG_SP3_HO = usrGetInt( 0 , CFG_SP3_HO );
				break;
				
				case 13:
					//speed vertical goto / guiding
					CFG_SP3_VE = usrGetInt( 0 , CFG_SP3_VE );
				break;
				
				case 14:
					//speed fieldrotator
					CFG_SP_FR = usrGetInt( 0 , CFG_SP_FR );
				break;
	
				case 15:
					//on, off encoder hor
					v1 = 0;
					if( ENCHO_USE ){
						v1 = 1;
					}
					v1 = usrGetOnOff("ENCODER HO", v1);
					ENCHO_USE = OFF;
					if(v1){
						ENCHO_USE = ON;
					}					
				break;

				case 16:
					//on, off encoder ver
					v1 = 0;
					if( ENCVE_USE ){
						v1 = 1;
					}
					v1 = usrGetOnOff("ENCODER VE", v1);
					ENCVE_USE = OFF;
					if(v1){
						ENCVE_USE = ON;
					}					
				break;
				

				case 17:
					//show calculated 1/10 arcseconds values of encoders
					showEncoders( 1 );
				break;

				case 18:
					//show calculated 1/10 arcseconds encodervalues as az/alt degrees
					showEncoders( 2 );
				break;

				case 19:
					//show calculated 1/10 arcseconds encodervalues as ra/dec hours/degrees
					showEncoders( 3 );
				break;

				case 20:
					if( ENCHO_USE == ON ) {
						encAutoTestHo();
					}
				break;

				case 21:
					if( ENCVE_USE == ON ) {
						encAutoTestVe();
					}
				break;

				case 22:
					setConfiguration();
				break;

				case 23:
					curconfig = 0;
					getConfiguration();
				break;

				case 24:
					curconfig = 1;
					getConfiguration();
				break;

				case 25:
					curconfig = 2;
					getConfiguration();
				break;

				case 26:
					curconfig = 3;
					getConfiguration();
				break;

				case 27:
					setListObj();
				break;

				case 28:
					if( usrGetAck("START DOWNLOAD ?") ){
						serialObjListDownload();
					}
				break;


			}
			
			upd = 1;
		
		}


	}

}





void main( void )
{
	REAL_TIME Time;
	unsigned char KEY;
	unsigned char y,upd,cf;
			
	ADDRSEL1	=	0x0406;
	BUSCON1		=	0x04AE;

	ADDRSEL2 	= 	0x0806;
	BUSCON2 	= 	0xc40b;

	ADDRSEL3	=	0x0C06;
	BUSCON3		=	0x04AE;

	ADDRSEL4	=	0x1000;
	BUSCON4		=	0x060D;


	DP2_8  = INPUT;
	DP2_9  = INPUT;
	DP2_10 = INPUT;
	DP2_11 = INPUT;

	DP7_0  = OUTPUT;	
	DP7_1  = OUTPUT;	
	DP7_2  = OUTPUT;	
	DP7_3  = OUTPUT;	
	DP7_4  = OUTPUT;	
	DP7_5  = OUTPUT;	
	DP7_6  = OUTPUT;	
	DP7_7  = OUTPUT;	

	DP8_0  = OUTPUT;
	DP8_1  = OUTPUT;
	DP8_2  = OUTPUT;
	DP8_3  = OUTPUT;
	DP8_4  = OUTPUT;


	ENC_FLAGS = 0;
	MOT_FLAGS = 0;
	DISABLEMOTORS;
	P7 = hsteps[0];
	P8 = hsteps[0] & 0x0f;
	DISABLEMOTORS;	

	init_lcd();
	lcd_on(0);
	lcd_clear();


	YEAR      = 2003;
	MONTH     = 1;
	DAY	      = 1;
	HOUR      = 0;
	MINUTE    = 0;
	SECOND    = 0;
	MSECOND   = 0;
	TIMER10   = 0;
	THISMDAYS = 31;

	config_reset();


	HSTEP_HO     	= 0;
	HSTEP_VE     	= 0;
	HSTEP_FR     	= 0;
	
	lcd_puts(0,0,main_txt0);
	lcd_puts(1,0,main_txt1);
	lcd_puts(2,0,main_txt2);
	lcd_puts(3,0,main_txt3);


	///////////
	IEN = 1;
	//////////


	initTimerInt();
	
	/// here we should get date/time from rtc.
	/// and set YEAR ... to values
	if (RTCGetTime(&Time, RTCDEVICEID ) == RTC_SUCCESSFUL) {

   		DAY 	= BCD2INT( Time.Date );
   		MONTH 	= BCD2INT( Time.Month );
   		YEAR 	= BCD2INT( Time.Year );
   		HOUR 	= BCD2INT( Time.Hour );
   		MINUTE 	= BCD2INT( Time.Minute );
   		SECOND 	= BCD2INT( Time.Second );

		setDaysOfMonth( MONTH, YEAR );
		
		startTimerInt();
	}


	initEncoderInts();

	wait_10ms(100);
	wait_10ms(100);
	wait_10ms(100);

	lcd_clear();
	wait_10ms(1);

	 y  = 0;
	upd = 1;
	
	while(1){

		if( upd ) {

			switch( curconfig ){
				case 0: cf = '1';break;
				case 1: cf = '2';break;
				case 2: cf = '3';break;
				case 3: cf = '4';break;				
			}
		
			lcd_clear();
			lcd_puts(0,0,menu_txt[ 0 ]);
			lcd_puts(1,0,menu_txt[ 1 ]);
			lcd_puts(2,0,menu_txt[ 2 ]);
		
			upd = 0;
		}
		
		printDateTime(3);

		lcd_setcursor(y,0);
		lcd_putchar( cf );


		KEY = readkey();

		if(KEY == KEY_DOWN ){

			lcd_setcursor(y,0);
			lcd_putchar(' ');

			if(y < 2 ){
				y++;
			}
			
			continue;
		}

		if(KEY == KEY_UP ){
		
			lcd_setcursor(y,0);
			lcd_putchar(' ');

			if( y > 0 ){
				y--;
			}
			continue;
		}


		if(KEY == KEY_E ){
			
			switch( y ) {

				case 0:
					// program scope
					scope();
				break;
				
				case 1:
					// program scope
					encode();
				break;
				
				case 2:
					// program scope
					config();
				break;
	
				
			}
			
			upd = 1;
		
		}


	}

}