/*----------------------------------------------------------------------------
 Copyright:      Radig Ulrich  mailto: mail@ulrichradig.de
 Author:         Radig Ulrich
 Remarks:        angepasst von Shortie
 known Problems: none
 Version:        15.10.2010
 Description:    Webserver uvm.
	com74hc595_init();
 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 "config.h"
#include "usart.h"
#include "networkcard/enc28j60.h"
#include "stack.h"
#include "timer.h"
#include "cmd.h"

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>

#include "com74hc595.h"

#include "R_TRIG.c"

#if USE_ADC
	#include "analog.h"
#endif

#if USE_HTTPD
	#include "httpd.h"
	#include "base64.h"
#endif

#if USE_WOL
	#include "wol.h"
#endif

#if USE_TELNETD
	#include "telnetd.h"
#endif

#if USE_NTP
	#include "ntp.h"
#endif

#if USE_GET_WEATHER
	#include "http_get.h"
#endif

#if USE_LCD_EXT
	#include "lcd.h"
#endif

#if USE_MAIL
	#include "base64.h"
	#include "sendmail.h"
#endif

#if USE_DHCP
	#include "dhcpc.h"
#endif

#if USE_DNS
	#include "dnsc.h"
#endif

#if USE_SYSLOG
	#include "syslog/syslog.h"
#endif

#if USE_UDPSEND
	#include "udp_send/udp_send.h"
#endif

#if USE_OW
	#include "1-wire/ds18x20.h"
	#include "1-wire/messung.h"
	
	uint8_t ow_auslesen	= 0;	// 0 -> Sensoren nicht auslesen

	#if OW_MINMAX
	uint8_t minmax		= 1;	// 1 -> Zurücksetzen der Min/Max-Werte 1x/Tag
	#endif //OW_MINMAX
#endif

#if LCD_BL_AUTO
	uint8_t bl_automatik = 0;	// 0 -> Backlight Automatik aus
#endif

#if USE_TWI
	#include "i2c/i2cmaster.h"
#endif

#if ADDON_IR_RC5
	#include "infrared/rc5.h"
#endif

#if ADDON_LCD
	#include "i2clcd/i2clcd.h"
#endif

#if ADDON_LEDS
	#include "led/led.h"
#endif

#if ADDON_SDCARD
	#include "sdcard/fat16.h"
	#include "sdcard/sdcard.h"
#endif

#if SDCARD_LOGFILE
	#include <stdbool.h>
	#include "sdcard/sd_logging.h"
#endif

#if (USE_LCD_EXT || ADDON_LCD)
	char zeile[20];
	unsigned char lcd_update = 0;
#endif

#if USE_SCHALTAUTOMATIK
	int ende;
#endif

#if USE_CNY
// Hilfsvariablen für CNY70
uint8_t signal = 0;
uint8_t signalg = 0;
#endif

//----------------------------------------------------------------------------
// Variablen-Array / Variablen-Array2 bei USE_UDPSEND
//----------------------------------------------------------------------------
// zum Abspeichern verschiedener Werte und zum Einfügen in die Webseite 
// als %VA@00 bis %VA@xx
//
// VA0-7	-> PORT A0-7
// VA8		-> PORT C
// VA9		-> Port D
// VA10		-> Sonderfunktionen (siehe README.txt)
// VA11		-> Tasterdefinition PORT C
// VA12		-> Tastdauer von VA11 in Millisekunden
// VA13		-> Intervall in Sekunden für Logfile schreiben - Default: 300 Sekunden
// VA14		-> gas_m3 
// VA15		-> gas_liter
// VA16		-> gas_schwelle  
// VA17		-> gas_toleranz 	
// VA18		-> strom_puls	
// VA19		-> strom_kwh 
// VA20		-> strom_schwelle 	
// VA21		-> strom_toleranz 	
// VA22		-> strom_nachkomma
// VA23		-> strom_min
// VA24		-> strom_max
// VA25		-> gas_min
// VA26		-> gas_max
// VA27		-> Counter Webseite

unsigned int var_array[MAX_VAR_ARRAY] = {0,0,0,0,0,0,0,0,0,0, 31, 0,500, 60,50,99,155,15,99,99,119,7,0,50,350,50,350, 0,0,0,0,0};

#if USE_UDPSEND
unsigned int va2_array[MAX_VAR_ARRAY] = {0,0,0,0,0,0,0,0,0,0,  0, 0,  0,   0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0};
#endif	//USE_UDPSEND


unsigned long counter =0;
unsigned long a;
int m = 0;
int y =0;
int Eingangskarten =0;

bool RelaisSchaltenStart[100]	= {false};
bool RelaisGeschaltet[100]		= {false};
bool Eingang[64] 				= {false};


volatile unsigned int variable[MAX_VAR];
volatile bool Nulldurchgang = false;
volatile long SekMemmCount = 0;
volatile int ReceiveSerial[5];
		
uint8_t ausgaenge_status[40];
uint8_t ausgaenge_schalten[40];
uint8_t au8Value[4];

extern uint8_t u8_Uebergabe;

//uint8_t u8_Uebergabe = 0;
//extern  volatile uint8_t  u8_Uebergabe =0;
//uint8_t  u8_Uebergabe;

unsigned char StatusEingangByte1 = 0;
unsigned char StatusEingangByte2 = 0;
unsigned char StatusEingangByte3 = 0;
unsigned char StatusEingangByte4 = 0;

unsigned char StatusPort1 = 0;
unsigned char StatusPort2 = 0;
unsigned char StatusPort3 = 0;
unsigned char StatusPort4 = 0;

/////////////////////////////////////////////////////
//Festlegung der Zahlenkombination
/////////////////////////////////////////////////////
// Handshake
char HSs[] = {11,22,33,44};

//Statusmeldung der Beleuchtung zur Visu
//xx,       xx,      xx,         xx
//Kennung | Raumnr | Elementnr. |0=Aus - 1=Ein  

char Ls89110100[]  = {89,11,01,00};
char Ls89110101[]  = {89,11,01,01};



// Handhsake
char HSr[]  = "11|22|33|44";

//xx,       xx,      xx,         xx
//Kennung | Raumnr | Elementnr. |0=Aus - 1=Ein  

char Lr99110100[]  = "99|11|01|00";
char Lr99110101[]  = "99|11|01|01";
	
char Lr99110200[]  = "99|11|02|00";
char Lr99110201[]  = "99|11|02|01";
char Bufferchar[20];


struct Relais {
   uint8_t   bitToSet; 
   uint8_t   bitToClear;
   uint16_t  setCycles;     // Zaehlt die 0-Durchgänge bis zum Abschalten
};


struct Relais   K1_Ein   = { 0, 1, 0 };
struct Relais   K1_Aus   = { 1, 0, 1 };

struct Relais   K2_Ein   = { 2, 3, 2 };
struct Relais   K2_Aus   = { 3, 2, 3 };

struct Relais   K3_Ein   = { 4, 5, 4 };
struct Relais   K3_Aus   = { 5, 4, 5 };

struct Relais   K4_Ein   = { 6, 7, 6 };
struct Relais   K4_Aus   = { 7, 6, 7 };

struct Relais   K5_Ein   = { 8, 9, 8 };
struct Relais   K5_Aus   = { 9, 8, 9 };

struct Relais   K6_Ein   = { 10, 11, 10 };
struct Relais   K6_Aus   = { 11, 10, 11 };

struct Relais   K7_Ein   = { 12, 13, 12 };	
struct Relais   K7_Aus   = { 13, 12, 13 };

struct Relais   K8_Ein   = { 14, 15, 14 };
struct Relais   K8_Aus   = { 15, 14, 15 };





struct Relais   K9_Ein   = { 16, 17, 16 };
struct Relais   K9_Aus   = { 17, 16, 17 };

struct Relais   K10_Ein   = { 18, 19, 18 };
struct Relais   K10_Aus   = { 19, 18, 19 };

struct Relais   K11_Ein   = { 20, 21, 20 };
struct Relais   K11_Aus   = { 21, 20, 21 };

struct Relais   K12_Ein   = { 22, 23, 22 };
struct Relais   K12_Aus   = { 23, 22, 23 };

struct Relais   K13_Ein   = { 24, 25, 24 };
struct Relais   K13_Aus   = { 25, 24, 25 };

struct Relais   K14_Ein   = { 26, 27, 26 };
struct Relais   K14_Aus   = { 27, 26, 27 };

struct Relais   K15_Ein   = { 28, 29, 28 };
struct Relais   K15_Aus   = { 29, 28, 29 };

struct Relais   K16_Ein   = { 30, 31, 30 };
struct Relais   K16_Aus   = { 31, 30, 31 };





struct Relais   K17_Ein   = { 32, 33, 32 };
struct Relais   K17_Aus   = { 33, 32, 33 };

struct Relais   K18_Ein   = { 34, 35, 34 };
struct Relais   K18_Aus   = { 35, 34, 35 };

struct Relais   K19_Ein   = { 36, 37, 36 };
struct Relais   K19_Aus   = { 37, 36, 37 };

struct Relais   K20_Ein   = { 38, 39, 38 };
struct Relais   K20_Aus   = { 39, 38, 39 };

struct Relais   K21_Ein   = { 40, 41, 40 };
struct Relais   K21_Aus   = { 41, 40, 41 };

struct Relais   K22_Ein   = { 42, 43, 42 };
struct Relais   K22_Aus   = { 43, 42, 43 };

struct Relais   K23_Ein   = { 44, 45, 44 };
struct Relais   K23_Aus   = { 45, 44, 45 };

struct Relais   K24_Ein   = { 46, 47, 46 };
struct Relais   K24_Aus   = { 47, 46, 47 };



// Triac Zünden	
void TriacZuenden (uint8_t DimmWert, uint8_t Bit)
{

//if (TCNT0 >= DimmWert) 
if (TCNT0 >= DimmWert) 
	
	{		
	//Triac zünden
	AusgangSetBit(Bit);
	AusgangOut();	
	}	
}
	
	
uint8_t RelaisSchalten( struct Relais* theRelais)  
{

  AusgangSetBit( theRelais->bitToSet );
  AusgangUnsetBit( theRelais->bitToClear ); 
  AusgangOut();


  // Merken welches Relais geschaltet ist
  //ArrayGeschaltet[theRelais->bitToSet] = true;
  //ArrayGeschaltet[theRelais->bitToClear] = false;
  

//  if (Nulldurchgang)
 //   {
    theRelais->setCycles++;
   // }      
 
  if (theRelais->setCycles >= 25)
    {
    AusgangUnsetBit( theRelais->bitToSet ); 
    AusgangUnsetBit( theRelais->bitToClear ); 
    AusgangOut();

    theRelais->setCycles = 0;
    return true;
    }  

  return false;
}

void Eingaenge_abfragen (void)
{
	  PORTC |= (1<<PC4);

	  // Mit PL alle Eingänge in das Register schieben.

	  // PL auf High
	  PORTC |= (1<<PC5);
	  // PL auf Low
	  PORTC &= ~(1<<PC5);
	  // PL auf High
	  PORTC |= (1<<PC5);

	    
      //Abfragen welches Registerbit gesetzt -> mit clock weiter schieben
	  for(m=(Eingangskarten * 16)-1;m>=0;m--)
		{
			  	
		  if (PINA & (1<<PINA0)) 
			{ // Logisch 1 wenn Schalter nicht gedrückt da Pullup an
			Eingang[m] = false; 		
			
            if      (m<= 8) StatusEingangByte1 &= ~(1 << m);
			else if (m<=16) StatusEingangByte2 &= ~(1 << m);
			else if (m<=24) StatusEingangByte3 &= ~(1 << m);
			else if (m<=32) StatusEingangByte4 &= ~(1 << m);

			} 
		  else 
			{
			Eingang[m] = true;	
			
			if      (m<= 8)  StatusEingangByte1 |= ( 1 << m );
			else if (m<= 16) StatusEingangByte2 |= ( 1 << m );
			else if (m<= 24) StatusEingangByte3 |= ( 1 << m );
			else if (m<= 32) StatusEingangByte4 |= ( 1 << m );			
			}				
          
		  // Mit Clock weiterschieben

		  // Clock auf High
		  PORTC |= (1<<PC4);
		  // Clock auf Low
		  PORTC &= ~(1<<PC4);
		  // Clock auf High
		  PORTC |= (1<<PC4);	  
		}			
}





void parse ( uint8_t* sChar, uint8_t* sValue, uint8_t u8Len )
{
  uint8_t  u8Cnt       = 0;
  //-----------------------------------------------------------
  *sValue = 0;

  while ( *sChar != 0x00 )
  {
    //-- Trennzeichen ? -----------------------
    if ( *sChar == '|' )
    {
      *++sValue = 0;
      if ( ++u8Cnt == u8Len ) return;
    }
    //-- Ziffer -------------------------------
    else if (    ( *sChar >= '0' )
              && ( *sChar <= '9' )  )
    {
      *sValue = (10 * *sValue) + ( *sChar - '0' );
    }
    //-- weiter -------------------------------
    sChar++;
  }

}
//----------------------------------------------------------------------------
// Hier startet das Hauptprogramm
//----------------------------------------------------------------------------

int main(void)
{  	
    unsigned long a;
	unsigned char oldss = 0;
	
	//Konfiguration der Ausgänge bzw. Eingänge
	//definition erfolgt in der config.h
	DDRA = OUTA; //Eingang
	DDRC = OUTC;
	DDRD = OUTD;
	
	PORTD   = 0b11110100;
//	PORTA   = 0b11111111; // 1 Pull up aktiv = Eingang 
	
	// Pullups einschalten PortA  1 Pull up aktiv = Eingang 
	PORTA |= (1 << PORTA0) | (1 << PORTA1) | (1 << PORTA2) | (1 << PORTA3);

//	PORTC = 0;
	
	
	#if USE_ADC
		ADC_Init();
	#else
		PORTA |= (1 << PORTA4) | (1 << PORTA5) | (1 << PORTA6);
		#if !OW_PORTA
		PORTA |= (1 << PORTA7);  // Mit externen Pullup da internen nicht aktiv
		#endif
	#endif
	
	//DDRB  &= ~(1 << DDB1); 	// Pin B1 (Pollin Prog.-Jumper) als Eingang definieren
	//PORTB |= (1 << PORTB1);	// Pullup einschalten PortB1
	
	
	eepvar_init();				// Grundeinstellungen einlesen

    usart_init(BAUDRATE); 		// setup the UART
    com74hc595_init();

	usart_write("\r\nSystem Ready\r\n");
    usart_write("Compiliert am "__DATE__" um "__TIME__"\r\n");
    usart_write("Compiliert mit GCC Version "__VERSION__"\r\n\r\n");

	for(a=0;a<1000000;a++) { asm("nop"); };

	//Applikationen starten
	stack_init();
	
	#if USE_HTTPD
	httpd_init();
	#endif
	
	#if USE_TELNETD
	telnetd_init();
	#endif
	
	//LCD_BACKLIGHT aktivieren
	#if LCD_BACKLIGHT
		lcd_backlight = 1;
	#endif

	//LCD initialisieren
	#if USE_LCD_EXT
		lcd_init();
		lcd_clear();
		
		//Spielerrei mit einem LCD
		lcd_print(0,1,"Booting");
		#if LCD_USER_CHARS
		//lcd_print(1,3,"I %c my AVR",3);
		#endif
	#endif

	#if	USE_TWI
        i2c_init();
	#endif
	
	#if ADDON_LCD
        i2clcd_init();
		i2clcd_command(LCD_DISPLAYON | LCD_CURSOROFF);
		
		i2clcd_printlr(1,1,"Booting");
		#if LCD_USER_CHARS
		sprintf(zeile, "   I %c my AVR   ",0x03);
		i2clcd_printlr(2,1,zeile);
		#endif
	#endif

	//Ethernetcard Interrupt enable
	ETH_INT_ENABLE;
		
	
/////////////////////////////////////////////////
/////////////////////////////////////////////////
//Interrupt 0 steigende Flanke Nulldurchgang 
///////////////////////////////////////////////// 
 
	EIMSK  |= (1<<INT0);                 // External Interrupt 0 Enable PIN PD2	
	EICRA  |= (1<<ISC00) | (1<<ISC01);   // Int auslösen bei steigender Flanke
 
////////////////////////////////////////////////
// Timer 0 Dimmwert für Triac Ansteuerung erhöhen (8-bit) 
/////////////////////////////////////////////////


    TCCR0A  = (1<<WGM01);                 // CTC Modus
    TCCR0B |= (1<<CS00) | (1<<CS02);      // Prescaler 1024
	TCNT0   = 0;
    OCR0A   = 255;                      // Load register                                    
  //  TIMSK0 |= (1<<OCIE0A);              // Interrupt nach Overflow
		
 ////////////////////////////////////////////////////
 // Timer 1 Timer für den Dimmwertvergleich (16-bit)
 ////////////////////////////////////////////////////
 
    TCCR1B |= (1<<CS10) | (1<<WGM12);     // CTC uns Prescaler 1 (16.000.000/256)= 0,016ms Interrupt auslösen) 
	TCNT1   = 0;                          // Timer Startwert
    OCR1A   = 255;                        // Load register      
    TIMSK1 |= (1<<OCIE1A);                // Interrupt nach Overflow	

	//Globale Interrupts einschalten
	sei(); 
	
    #if USE_DHCP
    dhcp_init();
    if ( dhcp() == 0) {
		save_ip_addresses();
		dhcp_ok = 1;
    } else {
		usart_write("DHCP fail\r\n\r\n");
		read_ip_addresses(); //get from EEPROM
		dhcp_ok = 0;
    }
    #endif //USE_DHCP
	
    usart_write("IP   %1i.%1i.%1i.%1i"    , myip[0]     , myip[1]     , myip[2]     , myip[3]);
	#if USE_DHCP
	if(dhcp_ok == 1) {
		usart_write(" (DHCP)");
	}
	#endif //USE_DHCP
	usart_write("\r\n");
    usart_write("MASK %1i.%1i.%1i.%1i\r\n", netmask[0]  , netmask[1]  , netmask[2]  , netmask[3]);
    usart_write("GWi   %1i.%1i.%1i.%1i\r\n", router_ip[0], router_ip[1], router_ip[2], router_ip[3]);

    #if USE_DNS
    usart_write("DNS  %1i.%1i.%1i.%1i\r\n", dns_server_ip[0], dns_server_ip[1], dns_server_ip[2], dns_server_ip[3]);
    #endif //USE_DNS
    
	#if USE_NTP
		#if !USE_DHCP
        #if USE_DNS
        dns_init();
		if ( dns_resolve("1.de.pool.ntp.org") == 0) {			// resolve NTP server
			for (unsigned char count = 0; count<4; count++) {
				eeprom_busy_wait ();
				eeprom_write_byte((unsigned char *)(NTP_IP_EEPROM_STORE + count),dns_resolved_ip[count]);
			}
		} else {
			usart_write("DNS Err.\r\n");
		}
        #endif // USE_DNS
		#endif // !USE_DHCP
    
	ntp_init(); 
   
	usart_write("NTP  %1i.%1i.%1i.%1i\r\n", ntp_server_ip[0], ntp_server_ip[1], ntp_server_ip[2], ntp_server_ip[3]);
   
	for(a=0;a<1000000;a++) { asm("nop"); };
   
	ntp_request();
   
    if (ntp() != 0) {
		usart_write("NTP Err.\r\n");
	} else {
		command_time();
	}
	#endif // USE_NTP

	#if USE_WOL
        wol_init();
	#endif // USE_WOL
    
    #if USE_MAIL
        mail_client_init();
	#endif // USE_MAIL  

	#if USE_OW
		uint8_t i;
		for (i=0;i<OW_MAXSENSORS;i++) {
			ow_array[i]=OW_START;
		}
		#if OW_MINMAX
		for (i=OW_MAXSENSORS;i<OW_MAXSENSORS*3;i++) {
			ow_array[i]=OW_MINMAX_START;
		}
		#endif // OW_MINMAX
		messung_init();
    #endif

	#if ADDON_SDCARD
		f16_init();
	#endif

	#if ADDON_IR_RC5
		rc5_init();
	#endif

	#if USE_UDPSEND
		udp_send_init();
	#endif

	#if USE_SYSLOG
		usart_write("SYSLOG  %1i.%1i.%1i.%1i\r\n", syslog_server_ip[0], syslog_server_ip[1], syslog_server_ip[2], syslog_server_ip[3]);
		syslog_send(5,0,"system: AVR-NET-IO is running");
	#endif	// USE_SYSLOG
	
	#if USE_LCD_EXT
		lcd_clear();
		lcd_print(0,0,"System ready   ");
	#endif	// USE_LCD_EXT

	#if ADDON_LCD
		i2clcd_command(LCD_CLEAR);
		i2clcd_printlr(1,1,"System ready   ");		// Print a string
	#endif	// ADDON_LCD

	#if LCD_BL_AUTO
		lcd_bl_timer = LCD_BL_TIME;
	#endif	// LCD_BL_AUTO

	#if ADDON_LEDS
		LED_on(1);
		#if LED3_PWM
		InitPWM_LED3();
		#endif	// LED3_PWM
	#endif		// ADDON_LEDS
	
	#if SDCARD_LOGFILE
		machineStatus.LogEnabled = (var_array[10] & 0x04); // Bit 3 von var_array[10] auslesen
	
		if (machineStatus.LogEnabled) {
			machineStatus.LogInit = true;
		}
	#endif	// SDCARD_LOGFILE

#if USE_SCHALTAUTOMATIK
	automatikschalten = 1;	// automatische Schaltvorgänge ausführen bei Start
#endif	// USE_SCHALTAUTOMATIK

/////////////////////////////////////////////////
/////////////////////////////////////////////////		
	// Allgemeine Einstellungen	
	Eingangskarten = 1;		
/////////////////////////////////////////////////
/////////////////////////////////////////////////	


//---------------------------------------------------------------------------
// Hauptschleife
//---------------------------------------------------------------------------

	while(1)
	{
	
 
   Eingaenge_abfragen();

	/*Undefenierter Counter*/
	if (counter >=5000)
	{
	//eth.timer = 1;
//	Nulldurchgang = true;
	counter = 0UL;
	}	
		
	counter++;	 		
  

	
	
	

 

	
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//Nulldurchgang aktiv
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////

if (Nulldurchgang)
{
	if (R_TRIG(Eingang[4]))
	{
		ausgaenge_schalten[4] = true;		
	}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Ausgänge schalten / status Port für Webpage einsetzen
/////////////////////////////////////////////////////////////////////////////////////////////////////////

	for (int i = 0; i < 40; i++)
	{
	  ausgaenge_status[i] = (ausgaenge_status[i] ^ ausgaenge_schalten[i]);
	  ausgaenge_schalten[i] = 0;	  
	    
	  if (ausgaenge_status[i]) 
		{
	        if      (i<= 8)  StatusPort1 |= ( 1 << i );
			if      (i<= 16) StatusPort2 |= ( 1 << i );
			if      (i<= 24) StatusPort3 |= ( 1 << i );
			if      (i<= 32) StatusPort4 |= ( 1 << i );			
		}				
		else
		{
	        if      (i<= 8) StatusPort1 &= ~(1 << i);
			else if (i<=16) StatusPort2 &= ~(1 << i);
			else if (i<=24) StatusPort3 &= ~(1 << i);
			else if (i<=32) StatusPort4 &= ~(1 << i);
		}
	} // For Schleife Ende
		
		
	if (R_TRIG(ausgaenge_status[4]))
	{
	RelaisSchaltenStart[2] = true;
	RelaisSchaltenStart[3] = false;
	}


	if (R_TRIG(!ausgaenge_status[4]))
	{
	RelaisSchaltenStart[2] = false;
	RelaisSchaltenStart[3] = true;
	}
	
	
	
		if (RelaisSchaltenStart[2] && !RelaisSchaltenStart[3])
		{
			
		 if (RelaisSchalten( &K2_Ein))
			{
			usart_write_str("--2--");
			RelaisSchaltenStart[2] = false;    
			}	
		}

	if (RelaisSchaltenStart[3] && !RelaisSchaltenStart[2])
		{
	
		 if (RelaisSchalten( &K2_Aus))
			{
			usart_write_str("--3--");
			RelaisSchaltenStart[3] = false;	        	
			}		
		}
		
 } // Nulldurchgang zu Ende
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
	
		//-------------------------------------------------------------------
		// Zeit aktualisieren
		//-------------------------------------------------------------------
		
		unsigned char hh = (time/3600)%24;
		hh = hh;
		unsigned char mm = (time/60)%60;
		mm = mm;
		unsigned char ss = time %60;
		
		//-------------------------------------------------------------------
		// Zeitabhängige Dinge erledigen
		//-------------------------------------------------------------------

		if(ss != oldss) {			// bei Sekundenwechsel

		if((stack_watchdog++) > WTT)
		{
			RESET();
		}
		eth.timer = 1;
		
		#if USE_DNS
		if ( dns_timer > 0 ) dns_timer--;		// dnsc interner Timer
		#endif //USE_DNS

		#if USE_NTP
		if ( ntp_resync > 0 ) ntp_resync--;
		if ( ntp_timer > 0 ) ntp_timer--;		// ntp interner Timer
		#endif //USE_NTP
		
		#if USE_DHCP
		if ( dhcp_lease > 0 ) dhcp_lease--;
		if ( dhcp_timer > 0 ) dhcp_timer--;	// dhcpc interner Timer
		#endif //USE_DHCP
		
		#if (LCD_BACKLIGHT && LCD_BL_AUTO)
		if ( lcd_bl_timer > 0 ) lcd_bl_timer--;
		#endif

		#if (UDPSEND_SPORT!=0)
		udp_send_timer--;
		#endif

		#if SDCARD_LOGFILE
		if( sdcard_log_timer > 0 ) sdcard_log_timer--;
		#endif


		#if USE_CNY
		strom_nachkomma = strom_puls * 133 / 100;
		#endif
		
			#if ADDON_LEDS
			LED_toggle(2);			// LED_2 wechselt im Sekundentakt
			#endif
			
			#if LED3_PWM
			SetPWMOutput(ss*4);		// PWM-Demo an LED3
			#endif

			if(ss == 0) {			// nur bei Minutenwechsel
				#if SDCARD_LOGFILE
				if((hh == 0) && (mm == 0) && (ss == 0) && machineStatus.LogEnabled) {
					// Um 0.00 Uhr wird ein neues Logfile angelegt
					machineStatus.LogInit = true;
				}
				#endif

				#if USE_SCHALTAUTOMATIK
				automatikschalten = 1;	// automatische Schaltvorgänge ausführen
				#endif
			}
			oldss = ss;
		#if(USE_LCD_EXT || ADDON_LCD)	
			lcd_update = 1;
		#endif
		
		}

		//-------------------------------------------------------------------
		// Schaltautomatik
		//-------------------------------------------------------------------
		
		#if USE_SCHALTAUTOMATIK

		// Bit 4 von var_array[10] und automatikschalten auswerten
		if((var_array[10] & 0x08) && (automatikschalten == 1))	 {
		/*
			//---------------------------------------------------------------
			// Automatik 1 -> Relais 7
			//---------------------------------------------------------------
			
			ende  = ((var_array[16]*60) + var_array[17]);
			if(ende < ((var_array[14]*60) + var_array[15]))
			{
				ende = ende+1440;
			}
			if (((var_array[14]*60 + var_array[15]) <= (hh*60 + mm)) && ((hh*60 + mm) < ende))
			{
				PORTC |= (1<<PC6);		// Relais 7 ein
			} else {
				PORTC &= ~(1<<PC6);		// Relais 7 aus
			}
		*/
		
			//---------------------------------------------------------------
			// Automatik 2 -> Relais 8
			//---------------------------------------------------------------

			ende  = ((var_array[20]*60) + var_array[21]);
			if(ende < ((var_array[18]*60) + var_array[19])) {
				ende = ende+1440;

			}
			if (((var_array[18]*60 + var_array[19]) <= (hh*60 + mm)) && ((hh*60 + mm) < ende)) {
				#if LCD_BACKLIGHT
				lcd_backlight = 1;		// LCD Hintergrundbeleuchtung ein
				#endif
				PORTC |= (1<<PC7);		// Relais 8 ein
			} else {
				#if LCD_BACKLIGHT
				lcd_backlight = 0;		// LCD Hintergrundbeleuchtung aus
				#endif
				PORTC &= ~(1<<PC7);	// Relais 8 aus
			}

			//---------------------------------------------------------------
			automatikschalten = 0;		// automatikschalten wurde ausgeführt
		}
		#endif

		//-------------------------------------------------------------------
		// Variable mit Portwerten füllen
		//-------------------------------------------------------------------

		var_array[0] = (PINA&0b00000001);
		var_array[1] = (PINA&0b00000010)>>1;
		var_array[2] = (PINA&0b00000100)>>2;
		var_array[3] = (PINA&0b00001000)>>3;
		
		// ADC-Werte werden in analog.c in die Variablen geschrieben
		// hier werden bei USE_ADC 0 die Werte geschrieben.
		#if !USE_ADC
		var_array[4] = (PINA&0b00010000)>>4;
		var_array[5] = (PINA&0b00100000)>>5;
		var_array[6] = (PINA&0b01000000)>>6;
		#if !OW_PORTA
		var_array[7] = (PINA&0b10000000)>>7;
		#endif	// !OW_PORTA
		#endif	// !USE_ADC
		
		var_array[8] = PORTC;

		//-------------------------------------------------------------------

		#if USE_ADC
		ANALOG_ON;
		#endif
		
	    eth_get_data();
		
       
        //Wetterdaten empfangen (Testphase)
        #if USE_GET_WEATHER
        http_request ();
        #endif
        
        //Empfang von Zeitinformationen
		#if USE_NTP
		if(!ntp_resync) {
			ntp_request();
			ntp_resync = NTP_REFRESH;
		}
		#endif //USE_NTP
	
        //Versand von E-Mails
        #if USE_MAIL
        if (mail_enable == 1) {
            mail_send();
            mail_enable = 0;
        }
        #endif //USE_MAIL
        
        //Rechner im Netzwerk aufwecken
        #if USE_WOL
		if (wol_enable == 1) {
			wol_request();
			wol_enable = 0;
		}
        #endif //USE_WOL
        
        #if USE_DHCP
		if(dhcp_ok == 1) {			// nur ausfuehren wenn DHCP beim Start verfügbar war
			if ( dhcp() != 0) {	//check for lease timeout
				usart_write("dhcp lease renewal failed\r\n");
				RESET();
			}
		}
		#endif //USE_DHCP
  
		#if USE_TELNETD
		telnetd_send_data();	//USART Daten für Telnetanwendung?
		#endif
        
		#if USE_NETCMDS
        if(ping.result) {
            usart_write("Get PONG: %i.%i.%i.%i\r\n",ping.ip1[0],ping.ip1[1],ping.ip1[2],ping.ip1[3]); 
            ping.result = 0;
        }
		#endif

		#if (UDPSEND_SPORT!=0)
		if(!udp_send_timer) {
			udp_send(UDPSEND_IP);
			udp_send_timer = UDPSEND_REFRESH;
		}
		#endif //UDPSEND_SPORT

		#if LCD_BL_AUTO
		bl_automatik = (var_array[10] & 0x02);	// Bit 2 von var_array[10] auslesen
		
		if (bl_automatik == 1) {
			if((!lcd_bl_timer) && (lcd_backlight))	{ // Wenn lcd_bl_timer = 0 und lcd_backlight = 1
				#if LCD_4Bit
				LCD_Port2_Write &= ~(1<<LCD_LIGHT_PIN);	// LCD-Backlight ausschalten
				#endif
				lcd_backlight = 0;
			}
		}
		#endif	//LCD_BL_AUTO
		
		//-------------------------------------------------------------------
		// Infrarotempfänger auslesen und RC5 Code interpretieren
		//-------------------------------------------------------------------
		
		#if ADDON_IR_RC5
		cli();
		int fbc = rc5_data;	// read two bytes from interrupt !
		rc5_data = 0;
		sei();
		
		if(fbc) {
			if (fbc != lastRC5data) {
				// neuer Tastendruck
				lastRC5data = fbc;	// letzten Tastendruck speichern

				rc5_device = (fbc >> 6 & 0x1F);
				rc5_keycode = (fbc & 0x3F) | (~fbc >> 7 & 0x40);

				RC5_DEBUG("\r\nRC5 %i",( fbc >> 11 & 1));	// Toggle Bit
				RC5_DEBUG(" %i", rc5_device);				// Device address
				RC5_DEBUG(" %i -",rc5_keycode);				// Key Code
				
				// RC5_DEBUG kann in infrared/rc5.h aktiviert werden um
				// die Device address und (weitere) Tastencodes einer 
				// RC5-Fernbedienung herauszufinden.
				
				//-----------------------------------------------------------
				// Schaltvorgänge über Fernbedienung
				//-----------------------------------------------------------

				if (rc5_device == RC5DEV_ID)		// Nur Codes für angebene Device Adresse verarbeiten
				{									// Wenn mehrere Geräte RC5 Codes benutzen
					if (rc5_keycode == RC5KEY_0) {	// Wenn FB-Taste 0 gedrückt
						PORTC = 0x00;				// schalte alle Ausgänge an PORTC aus
					}

					if (( rc5_keycode >= RC5KEY_1 ) && (rc5_keycode <= RC5KEY_8)) { // Wenn FB-Taste 1 - 8
						PORTC = PINC ^ (1 << (rc5_keycode - 1));					 // schalte Ausgang PC0 - PC7
					}

					if (rc5_keycode == RC5KEY_9) {	// Wenn FB-Taste 9 gedrückt
						#if USE_TWI
						PORTC = 0xFC;				// schalte alle Ausgänge ein außer TWI/i2c
						#else
						PORTC = 0xFF;				// schalte alle Ausgänge ein
						#endif
					}

					#if LCD_BACKLIGHT
					if (rc5_keycode == RC5KEY_VUP)	{	// FB-Taste VOL+
						lcd_backlight = 1;
						lcd_update = 1;
						#if LCD_BL_AUTO
						lcd_bl_timer = LCD_BL_TIME;
						#endif	//LCD_BL_AUTO
					}
					if (rc5_keycode == RC5KEY_VDN)	{	// FB-Taste VOL-
						lcd_backlight = 0;
						lcd_update = 1;
					}
					#endif
				}
			} else {
				RC5_DEBUG("\r\nTaste %i wird gehalten",rc5_keycode);
			}
		}
		#endif

		//-------------------------------------------------------------
		// Taster an PB1 abfragen und LCD-Backlight schalten
		//-------------------------------------------------------------
/*
		#if LCD_BACKLIGHT
		if (debounce(PINB, PB1)) {	// Falls Taster an PIN PB1 gedrueckt..
			#if LCD_4Bit
			LCD_Port2_Write = LCD_Port2_Read ^ ( 1 << LCD_LIGHT_PIN );	// LCD-Backlight an- bzw. ausschalten
			#endif
			
			if(lcd_backlight == 1) {
				lcd_backlight = 0;
			} else {
				lcd_backlight = 1;
			}
			
			lcd_update = 1;
			
			#if LCD_BL_AUTO
			lcd_bl_timer = LCD_BL_TIME;
			#endif	//LCD_BL_AUTO
		}
		#endif	//LCD_BACKLIGHT
*/
		//-----------------------------------------------------
		// 1-Wire Bus abfragen und Temperaturen auslesen
		//-----------------------------------------------------
		
		#if USE_OW
		
		ow_auslesen = (var_array[10] & 0x01);	// Bit 1 von var_array[10] auslesen
		
		
		if ((ss%10 == 8) && (ow_auslesen != 0)) {
		
			#if OW_EXT_POWER
			start_OW();
			#endif
			 

			lese_Temperatur();	// Temperatursensoren lesen
			
			#if OW_MINMAX
			for (i=0;i<OW_MAXSENSORS;i++) {
				if ((( hh == 00 )&&( mm == 00 )) || (minmax == 1)) {
					// Zurücksetzen der Min/Max_Werte 1x/Tag
					// auf die gerade aktuellen Temperaturen
					ow_array[i+OW_MAXSENSORS] = ow_array[i];
					ow_array[i+OW_MAXSENSORS*2] = ow_array[i];
				} else {
					// Abgleich der Temp. mit den gespeicherten Min/Max-Werten
					if (ow_array[i]  < ow_array[i+OW_MAXSENSORS])
						ow_array[i+OW_MAXSENSORS] = ow_array[i];
					if (ow_array[i]  > ow_array[i+OW_MAXSENSORS*2])
						ow_array[i+OW_MAXSENSORS*2] = ow_array[i];
				}
			}
			minmax = 0;
			#endif //OW_MINMAX
		}
		#endif	//USE_OW

		//-------------------------------------------------------------
		// SD-Card auf ADD-ON Board und Logging auf SD-Card
		//-------------------------------------------------------------
		
		#if ADDON_SDCARD
		f16_check();    // Ein-/Ausstecken der SD-Karte erkennen
		#endif

		#if SDCARD_LOGFILE
		machineStatus.LogEnabled = (var_array[10] & 0x04); // Bit 3 von var_array[10] auslesen
					
		if(machineStatus.LogEnabled) {		// Wenn Logging auf SD-Karte eingeschalten 
		
			if(!sdcard_log_timer) {						// Bei Ablauf des SD-Card Timers  ...
				machineStatus.LogSchreiben = true;		// ... LogSchreiben zulassen
				
				// Wenn Einstellung geringer als 10 Sekunden auf Defaultwert (60 Sek.) setzen.
				if(var_array[13] < 10) {
					var_array[13] = 60;
				}
				sdcard_log_timer = var_array[13];
			}
		
			if (machineStatus.LogInit) {
				log_init();						// neue Logdatei anlegen
				machineStatus.LogInit = false;
			}
		
			if (machineStatus.LogSchreiben) {
				log_status();					// Logfile schreiben
				machineStatus.LogSchreiben = false;
			}
		}
		#endif

//---------------------------------------------------------------------
// ab hier eigenen Code wie Ausgaben oder weitere Verarbeitung der 
// Werte einfügen
//---------------------------------------------------------------------



#if USE_CNY
	
		if (( hh == 00 )&&( mm == 00 )&&( ss == 00 )){ // Reset Min/Max
			gas_min = var_array[5];
			gas_max = gas_min;
			strom_min = var_array[4];
			strom_max = strom_min;
		}
		else { 
			if((var_array[5] < gas_min)&&(var_array[5] > 10)){gas_min = var_array[5];}
			if((var_array[5] > gas_max)&&(var_array[5] < 1010)){gas_max = var_array[5];}
			if((var_array[4] < strom_min)&&(var_array[4] > 10)){strom_min = var_array[4];}
			if((var_array[4] > strom_max)&&(var_array[4] < 1010)){strom_max = var_array[4];}
		}
	
// Strom 
    #if USE_LCD_EXT
	if((PINB&0b00000010) == 0)
	{lcd_print(0,11," %3i",strom_signal);}
	#endif
	
	if(var_array[10] & 0x10){
	if (strom_max - strom_min > 11){
	strom_schwelle = strom_min + ((strom_max - strom_min) / 3);
	strom_toleranz = ((strom_max - strom_min) / 4);
		}}
	//else {
	//strom_schwelle = 120;
	//strom_toleranz = 7;
	//	}
	
		
	if (strom_signal <= strom_schwelle)     // var4 enthält ADC-Wert CNY-70 Stromzähler, var 24 Schaltschwelle 
    { 
		if (signal ==0)                    // nur Flanke zählen 
		{ 
		strom_puls++;
		signal = 1; 
		} 
    } 
    else 
    { 
		if (strom_signal >= strom_schwelle + strom_toleranz) 
		{signal = 0        ;} 
    }
 
    if (strom_puls == 75) {                 // 75 Umdr. sind 1kWh 
		if (strom_kwh == 10000){
		strom_kwh_zt++;
		strom_kwh = 0;
		strom_puls = 0;
		strom_nachkomma = 0;
		}
		else{
		strom_kwh++;                        // var 19 Strom in kWh 
		strom_puls = 0;
		strom_nachkomma = 0;
		}
		} 
   
// Gas 
	#if USE_LCD_EXT
	if((PINB&0b00000010) == 0) 
	{lcd_print(1,11," %3i",gas_signal);}
	#endif
	
	if(var_array[10] & 0x10){
	if(gas_max - gas_min > 20){
	gas_schwelle = gas_max - ((gas_max - gas_min) / 3);
	gas_toleranz = ((gas_max - gas_min) / 4);
		}}
	//else {
	//gas_schwelle = 150;
	//gas_toleranz = 18;
	//	}
	
	if (gas_signal >= gas_schwelle)          // var5 enthält ADC-Wert CNY-70 Gaszähler, var 25 Schaltschwelle 
	{ 
		if (signalg ==0)                    // nur Flanke zählen 
		{ 
		gas_liter = gas_liter + 10; // Gaszähler Liter 
		signalg = 1; 
		} 
	} 
	else 
    { 
		if (gas_signal <= gas_schwelle - gas_toleranz) 
		{signalg = 0        ;} 
	} 
   
	if (gas_liter > 996) { 
		if (gas_m3 == 10000){
		gas_m3_zt++;
		gas_m3 = 0;
		gas_liter = 6;
		}
		else{
		gas_m3++;                        // Gaszähler m3 
		gas_liter = 6;  } 
		}
// 1mal pro Stunde var_array ins eprom sichern
/*
if (mm == 58) {
	uint8_t i = 0;
	for(i=14;i<32;i++)  // von Arrayposition 14 bis 27 
	{
	eeprom_busy_wait ();
	eeprom_write_word((unsigned int*)(SV_EEPROM_STORE + (2*(i-10))),var_array[i]);
	}}
*/

#endif


		#if(USE_LCD_EXT || ADDON_LCD)
		if(lcd_update) {
		#if USE_LCD_EXT
		if((PINB&0b00000010) == 0) {
		lcd_print(0,0,"S:%5i:%2i ",strom_kwh,strom_nachkomma);
		lcd_print(0,2,"%1i",strom_kwh_zt);
		lcd_print(1,0,"G:%5i%3i ",gas_m3,gas_liter);
		lcd_print(1,2,"%1i",gas_m3_zt);}
		#endif	//USE_LCD_EXT
		
		#if ADDON_LCD
			#if USE_OW
			i2clcd_printlr(1,1,"Aussen ");
			dtostrf(ow_array[0] / 10.0,5,1,zeile);
			i2clcd_print(zeile);
			i2clcd_print("C");
			i2clcd_printlr(2,1,"Innen  ");
			dtostrf(ow_array[1] / 10.0,5,1,zeile);
			i2clcd_print(zeile);
			i2clcd_print("C");
			
			sprintf(zeile, "%02d:%02d:%02d", hh, mm, ss);
			i2clcd_printlr(3,1,zeile);
			#else
			sprintf(zeile, "%02d:%02d:%02d", hh, mm, ss);
			i2clcd_printlr(1,1,zeile);
			#endif	// USE_OW
/*
			// Demo der 8 benutzerdefinierten Zeichen
			#if LCD_USER_CHARS
			uint8_t udc;
			for (udc=0;udc<8;udc++) {
				i2clcd_putcharlr(4,udc+1,udc);	// Die 8 benutzerdefinierten Zeichen
			}									// in Zeile 4 des Displays anzeigen
			#endif	// LCD_USER_CHARS
*/
		#endif	// ADDON_LCD

			lcd_update = 0;
		}
		#endif	// if(USE_LCD_EXT || ADDON_LCD)
		
	
//////////////////////////////////////////////////////////////////////////	
	Nulldurchgang = false;
//////////////////////////////////////////////////////////////////////////	

		
//////////////////////////////////////////////////////////////////////////	
///////////////////////////////////////////////////////////////////////////	
//Terminalcommandos auswerten
///////////////////////////////////////////////////////////////////////////	
///////////////////////////////////////////////////////////////////////////	
//-----------------------------------------------

		
	if (usart_status.usart_ready) 
	{
			 
			if (!strcmp(usart_rx_buffer,"99|11|01|00")) 
			{	
			usart_write("----Jipppieee----");
			}			 


memset ( au8Value, 0, sizeof(au8Value) );
parse( usart_rx_buffer, au8Value, 4 );


// in au8Value sollten jetzt die Ziffern stehen.

	usart_write_int(au8Value[0]);
	usart_write_int(au8Value[1]);
	usart_write_int(au8Value[2]);
	usart_write_int(au8Value[3]);	 	 
		 
	u8_Uebergabe = au8Value[3];	
	
usart_status.usart_ready = 0;
				 	
	}
				
		
				
				
				
				
		
    } //while (1)
//---------------------------------------------------------------------
	return(0);
}





//==================================================================================
//Timerinterrupt bei Überlauf
//==================================================================================

// Timer 0 Alle 9.92ms nach dem Nulldurchgang
/*
ISR (TIMER0_COMPA_vect)
{
 
}*/



//==================================================================================
// Timer 1 Dimmwertvergleich
//==================================================================================
ISR (TIMER1_COMPA_vect)
{
 	usart_write_int(u8_Uebergabe);	


// Max 130 für Triac zünden
TriacZuenden(12 ,16);


// Timer zurücksetzen  
if (TCNT0 >= 140) 
	{
	
	AusgangUnsetBit(16);
	AusgangOut();

	TCNT0   = 0;
	TCCR0B  = 0b00000000;   // Timer stoppen
	}	


	// Sekunde erzeugen
	SekMemmCount++;
	
	if (SekMemmCount >= 62500) 
	{
		time++;
		SekMemmCount=0;
	}
}
//==================================================================================
//Interrupt 0 Nulldurchgangerkennung steigende Flanke
//==================================================================================

ISR(INT0_vect)
{    
		
    Nulldurchgang = true;
	
    // gestoppten Timer mit  Prescaler 1024 wieder starten
    TCCR0B |= (1<<CS00) | (1<<CS02);   // Prescaler 1024
	TCNT0   = 0;	

	
}

//==================================================================================
//Empfang eines Zeichens auf der UART
//==================================================================================
ISR (USART_RX)
{


	if (!usart_status.usart_disable)
	{
		unsigned char receive_char;
		receive_char = (UDR);

#if USART_ECHO
		usart_write_char(receive_char);
#endif

		if (usart_status.usart_ready)
		{
			usart_status.usart_rx_ovl = 1;
			return;
		}

		if (receive_char == 0x08)
		{
			if (buffercounter) buffercounter--;
			return;
		}

		if (receive_char == '\r' && (!(usart_rx_buffer[buffercounter-1] == '\\')))
		{
			usart_rx_buffer[buffercounter] = 0;
			buffercounter = 0;
			usart_status.usart_ready = 1;
			return;
		}

		if (buffercounter < BUFFER_SIZE - 1)
		{
			usart_rx_buffer[buffercounter++] = receive_char;
			
		}
		
	
	}
	else
	{
		if (rx_buffer_pointer_in == (rx_buffer_pointer_out - 1))
		{
			//Datenverlust
			return;
		}

		*rx_buffer_pointer_in++ = UDR;

		if (rx_buffer_pointer_in == &usart_rx_buffer[BUFFER_SIZE-1])
		{
			rx_buffer_pointer_in = &usart_rx_buffer[0];
		}
	}
	return;
}


