/*----------------------------------------------------------------------------
 Copyright:      Radig Ulrich  mailto: mail@ulrichradig.de
 Author:         Radig Ulrich
 Remarks:        
 known Problems: none
 Version:        24.10.2007
 Description:    Webserver uvm.

 Modifiziert für AVR-NET-IO:	RoBue
 Version:			1.3 Versuchsstadium
 Datum:				24.11.2008

 Dieses Programm ist freie Software. Sie können es unter den Bedingungen der 
 GNU General Public License, wie von der Free Software Foundation veröffentlicht, 
 weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder 
 (nach Ihrer Option) jeder späteren Version. 

 Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, 
 daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 
 sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT 
 FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. 

 Sie sollten eine Kopie der GNU General Public License zusammen mit diesem 
 Programm erhalten haben. 
 Falls nicht, schreiben Sie an die Free Software Foundation, 
 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
----------------------------------------------------------------------------*/

#include <avr/io.h>
#include "config.h"
#include "usart.h"
#include "networkcard/enc28j60.h"
#include "networkcard/rtl8019.h"
#include "stack.h"
#include "timer.h"
#include "wol.h"
#include "httpd.h"
#include "cmd.h"
#include "telnetd.h"
#include "ntp.h"
#include "base64.h"
#include "http_get.h"
#include "lcd.h"
#include "udp_lcd.h"
#include "analog.h"
#include "camera/cam.h"
#include "camera/servo.h"
#include "sendmail.h"

volatile unsigned int variable[MAX_VAR];

// RoBue:
// Die Uhrzeit wird zentral in main.c berechnet (s.u.)
// Die anderen Programmteile lesen nur noch hh,mm,ss aus.
// -> httpd.h/c, cmd.h/c
unsigned char hh;
unsigned char mm;
unsigned char ss;

// RoBue:	
// Das periodische Auslesen der 1-Wire-Sensoren erfolgt in main.c (s.u.)
// Die anderen Programmteile lesen nur noch "ow_array" aus.
// -> httpd.h/c, cmd.h/c 

#if USE_OW
	#include "1-wire/ds18x20.h"
	// Variable
	uint16_t 	ow_array[MAXSENSORS] = {200,200};	// Speicherplatz für 1-wire Sensorwerte
	// Position 0-4 eig. ID, Pos. 5+6 ist die Temperatur, Pos. 7 CRC-Byte
	PROGMEM	uint8_t		DS18B20IDs[MAXSENSORS+1][OW_ROMCODE_SIZE] = {
							OW_ID_T01,	// 1. DS18B20
							OW_ID_T02,
							OW_ID_Last };	// Endmarker
	uint8_t auslesen	= 0;
	uint8_t messen		= 1;
	
#endif

// RoBue
// Schaltbedingungen (evtl. in config.h auslagern!)
// Temperatur: Pin von PORTD, 'T (=Temperatur)', Sensornummer, 0 (=unbelegt), Gradzahl, 0 (=unbelegt)
// Zeit: Pin von PORTD,'Z (=Zeit)',ein-Stunden,ein-Minuten,aus-Stunden,aus-Minuten

//unsigned char Schalt_D[6][6] = {
//{2,'T',0,0,20,0},
//{3,'T',1,0,19,0},
//{4,'Z',20,0,23,0},
//{5,0,0,0,0,0},
//{6,0,0,0,0,0},
//{7,0,0,0,0,0} };

uint8_t schalten	= 1;

// Schaltbedingungen:
// -----------------

	uint8_t temperatur1  = 20; // -> 20 Grad
	uint8_t temperatur2  = 18; // -> 18 Grad
	uint8_t temperatur3  = 5;  // ->  5 Grad (Frostschutz)

	unsigned char  hh1  = 21; // -> 21:45 Uhr
	unsigned char  mm1  = 45;
	unsigned char  hh2  = 22; // -> 22:00 Uhr
	unsigned char  mm2  = 00;
//----------------------------------------------------------------------------

// Hier startet das Hauptprogramm
// ******************************

int main(void)
{  
	//Konfiguration der Ausgänge bzw. Eingänge
	//definition erfolgt in der config.h
	DDRA = OUTA;
	//DDRC = OUTC; // -> LCD
	DDRD = OUTD;
	// RoBue:
	// Pullups einschalten
	PORTA = (1 << PORTA0) | (1 << PORTA1) | (1 << PORTA2) | (1 << PORTA3) | (1 << PORTA4) | (1 << PORTA5) | (1 << PORTA6);
	
    unsigned long a;
	#if USE_SERVO
		servo_init ();
	#endif //USE_SERVO
	
    usart_init(BAUDRATE); // setup the UART
	
	#if USE_ADC
		ADC_Init();
	#endif
	
	usart_write("\n\rSystem Ready\n\r");
    usart_write("Compiliert am "__DATE__" um "__TIME__"\r\n");
    usart_write("Compiliert mit GCC Version "__VERSION__"\r\n");
	for(a=0;a<1000000;a++){asm("nop");};

	//Applikationen starten
	stack_init();
	httpd_init();
	telnetd_init();
	
	//Spielerrei mit einem LCD
	#if USE_SER_LCD
		udp_lcd_init();
		lcd_init();
		// RoBue:
		// LCD-Ausgaben:
		lcd_clear();
		lcd_print(0,0,"** AVR-NET-IO **");
		lcd_print(2,0,"Counter: ");
		lcd_print(3,0,"Zeit:");
	#endif

	//Ethernetcard Interrupt enable
	ETH_INT_ENABLE;
	
	#if USE_SER_LCD
		// RoBue:
		// IP auf LCD
		lcd_print(1,0,"%1i.%1i.%1i.%1i",myip[0],myip[1],myip[2],myip[3]);
	#endif
	
	//Globale Interrupts einschalten
	sei(); 
	
	#if USE_CAM
		#if USE_SER_LCD
			lcd_print(1,0,"CAMERA INIT");
		#endif //USE_SER_LCD
		for(a=0;a<2000000;a++){asm("nop");};
		cam_init();
		max_bytes = cam_picture_store(CAM_RESELUTION);
		#if USE_SER_LCD
			back_light = 0;
			lcd_print(1,0,"CAMERA READY");
		#endif //USE_SER_LCD
	#endif // -> USE_CAM
	
	#if USE_NTP
	        ntp_init();
	        ntp_request();
	#endif //USE_NTP
	
	#if USE_WOL
	        wol_init();
	#endif //USE_WOL
    
	#if USE_MAIL
	        mail_client_init();
	#endif //USE_MAIL  


//Hauptschlfeife
// *************
		
	while(1)
	{

	#if USE_ADC
		ANALOG_ON;
	#endif

	eth_get_data();
		
        //Terminalcommandos auswerten
	if (usart_status.usart_ready){
	usart_write("\r\n");
		if(extract_cmd(&usart_rx_buffer[0]))
		{
			usart_write("Ready\r\n\r\n");
		}
		else
		{
			usart_write("ERROR\r\n\r\n");
		}
		usart_status.usart_ready =0;
	
	}
	
	// RoBue:
	// Counter ausgeben
	#if USE_SER_LCD
		lcd_print(2,9,"%4i",var_array[MAX_VAR_ARRAY-1]);
	#endif

	// RoBue:
	// Uhrzeit bestimmen und auf LCD ausgeben
	hh = (time/3600)%24;
	mm = (time/60)%60;
	ss = time %60;
	#if USE_SER_LCD
		lcd_print(3,7,"%2i:%2i:%2i",hh,mm,ss);
	#endif

        // RoBue:
	// DS18B20 auslesen
	// Anmerkung:
	// - Sekunde (25 und) 55 -> Sensor zum Messen und Berechnen auffordern
	// - Sekunde (28 und) 58 -> Sensor(en) auslesen
	// (- delay von 750 ms ist nicht nötig !!!)
	// Ausgabe ueber UART und in ow_array
	#if USE_OW

		uint8_t i = 0;
		//uint16_t TWert;
		uint8_t subzero, cel, cel_frac_bits;
		uint8_t tempID[OW_ROMCODE_SIZE];
		
		if ( ss == 55 ) {

		// Messen?
		if ( messen == 1 ) {

		// RoBue Anmerkung:
		// Hiermit werden ALLE Sensoren zum Messen aufgefordert.
		// Aufforderung nur bestimmter Sensoren:
		// "NULL" durch "tempID" ersetzen
		
		// RoBue Testausgabe UART:
		// usart_write("Starte Messvorgang ...\r\n");		 

		DS18X20_start_meas( DS18X20_POWER_PARASITE, NULL );
		
		// Kein Messen mehr bis ss= (25 oder) 55
		messen = 0;

		// Jetzt kann ausgelesen werden
		auslesen = 1;

		}	// -> if messen
		
		}	// -> if ss

		if ( ss == 58 ) {

		// Auslesen?
		if ( auslesen == 1 ) { 

		// (erste) ID ins RAM holen
		memcpy_P(tempID,DS18B20IDs[0],OW_ROMCODE_SIZE);	
				
		while ( tempID[0] != 0 ) {
		//while ( tempID[0] == 0x10 ) {
				
			// RoBue Anmerkung:
			// Hiermit wird jeweils ein einzelner Sensor ausgelesen
			// und die Temperatur in ow_array abgelegt.
			// Achtung:
			// Pro Sekunde können max. ca. 10 Sensoren ausgelesen werden!
			if ( DS18X20_read_meas( tempID, &subzero,&cel, &cel_frac_bits) == DS18X20_OK ) {

				ow_array[i] = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
				//TWert = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
				//ow_array[i] = TWert;
				
				// RoBue:
				// Testausgabe UART:
				// usart_write("%2i:%2i:%2i: Temperatur: %3i Grad\r\n",hh,mm,ss,ow_array[i]/10);
				
			}	// -> if
			else {
				usart_write("\r\nCRC Error (lost connection?) ");
				DS18X20_show_id_uart( tempID, OW_ROMCODE_SIZE );


			}	// -> else
		
		// nächste ID ins RAM holen
		memcpy_P(tempID,DS18B20IDs[++i],OW_ROMCODE_SIZE);

		}	// -> while

		}	// -> if auslesen

		auslesen = 0;	// Auslesen vorläufig abschalten
		messen = 1;	// Messen ab ss=25 und 55 wieder ermöglichen

		// Temperatur auf LCD ausgeben
		lcd_print(1,0,"                ");
		lcd_print(1,0,"%i C",ow_array[0]/10);
		lcd_print(1,8,"%i C",ow_array[1]/10);	

		}	// -> if ss
		
	#endif
	
	// RoBue:
	// Schalten der Ports durch bestimmte Bedingungen
	// - Temperatur
	// - Zeit
	// (- PORTA (digital, analog))

	// Abfrage alle 30s
	if ( ss == 00 ) {
	if ( schalten == 1 ) {
	
	// RoBue Testausgabe UART:
	// usart_write("%2i:%2i: Schaltfunktionen testen ...\r\n",hh,mm);	
	
		// Über Temperatur: temperatur1 - Sensor0
		if ( ow_array[0]/10 < temperatur1 ) {
			PORTD |= (1 << PD2); // ein
		}
		    else {
		      PORTD &= ~(1 << PD2); // aus
		}

		// Über Temperatur: temperatur2 - Sensor1
		if ( ow_array[1]/10 < temperatur2 ){
			PORTD |= (1 << PD3); // ein
		}
		else {
			PORTD &= ~(1 << PD3); // aus
		}

		// Über Zeit: ein/aus
		if ( hh == hh1 ) {
			if ( mm == mm1 ) {
				PORTD |= (1 << PD4); // ein
			}
		}
		if ( hh == hh2 ) {
			if ( mm == mm2 ) {
				PORTD &= ~(1 << PD4); // aus
			}
		}

	schalten = 0;	// Vorerst nicht mehr schalten

	} // -> schalten == 1
	} // -> if ss == 00 u. 30

	if ( ss == 01 ) {
		schalten = 1;	// Schalten wieder ermöglichen
	}

        //Wetterdaten empfangen (Testphase)
        #if GET_WEATHER
        http_request ();
        #endif
        
        //Empfang von Zeitinformationen
	#if USE_NTP
		if(!ntp_timer){
		ntp_timer = NTP_REFRESH;
		ntp_request();
		}
	#endif //USE_NTP
		
        //Versand von E-Mails
        #if USE_MAIL
	        if (mail_enable == 1)
	        {
	            mail_enable = 0;
	            mail_send();
	        }
        #endif //USE_MAIL
        
        //Rechner im Netzwerk aufwecken
        #if USE_WOL
	        if (wol_enable == 1)
	        {
	            wol_enable = 0;
	            wol_request();
	        }
        #endif //USE_WOL
           
	//USART Daten für Telnetanwendung?
	telnetd_send_data();
    }
		
return(0);
}