/***************************************************************************************
* main.c   Gmess_sd = Gas u. Temperaturmessung mit Aufzeichnung auf der SD-Card
*
* Interupt Belegung                                wo              warum
*--------------------------------------------------------------------------------------------
* INT0          external Int0
* INT1          external Int1                      main.c          LowPower
* INT2          external Int2
* TIMER2_COMP   Timer/Counter2 Compare Match       main.c          10 msek timer
* TIMER2_OVF    Timer/Counter2 Overflow
* TIMER1_CAPT   Timer/Counter1 Capture Event
* TIMER1_COMPA  Timer/Counter1 Compare Match A
* TIMER1_COMPB  Timer/Counter1 Compare Match B
* TIMER1_OVF    Timer/Counter1 Overflow
* TIMER0_COMP   Timer/Counter0 Compare Match      main.c           Strom Messung
* TIMER0_OVF    Timer/Counter0 Overflow
* SPI           STC Serial Transfer Complete
* RXC           USART Rx Complete                 abc/avr_uart.c   receive Zeichen da
* UDRE          USART Data Register Empty         abc/avr_uart.c   transmit Zeichen buffer leer
* TXC           USART Tx Complete                 abc/avr_uart.c   Transmit fertig
* ADC           ADC Conversion Complete
* EE_RDY        EEPROM Ready
* ANA_COMP      Analog Comparator
* TWI           Two-wire Serial Interface
* SPM_RDY       Store Program Memory Ready
*
* Prozessor:  ATmega32
* Frequenz:   14,7456 MHz
*--------------------------------------------------------------------------
* Pin Belegung:
*
*                           +-------------------+
*  S0 StromZ. (XCK/T0) PB0 -|1       XXX      40|- PA0 (ADC0)      
*                           |                   |
*  SD Select      (T1) PB1 -|2                39|- PA1 (ADC1)
*                           |                   |
*          (INT2/AIN0) PB2 -|3                38|- PA2 (ADC2)
*                           |                   |
*  LED blau (OC0/AIN1) PB3 -|4                37|- PA3 (ADC3)
*                           |                   |
*  LED gelb       (SS) PB4 -|5                36|- PA4 (ADC4)      LED Backlight
*                           |                   |
*  MOSI         (MOSI) PB5 -|6                35|- PA5 (ADC5)      LCD Enable
*                           |                   |
*  MISO         (MISO) PB6 -|7                34|- PA6 (ADC6)      LCD Data / RS
*                           |                   |
*  SCK           (SCK) PB7 -|8                33|- PA7 (ADC7)      LCD Clock CP
*                           |                   |
*  RESET             RESET -|9                32|- AREF
*                           |                   |
*  +5V                 VCC -|10               31|- GND             GND
*                           |                   |
*  GND                 GND -|11               30|- AVCC            +5V
*                           |                   |
*  14,7456 MHz       XTAL2 -|12               29|- PC7 (TOSC2)     DS1822 1 Vorlauf
*                           |                   |
*  14,7456 MHz       XTAL1 -|13               28|- PC6 (TOSC1)     DS1822 2 Ruecklauf
*                           |                   |
*  TXD II input  (RXD) PD0 -|14               27|- PC5 (TDI)       DS1822 3 Warm Wasser
*                           |                   |
*  TXD 2 Webserv.(TXD) PD1 -|15               26|- PC4 (TDO)       
*                           |                   |
*               (INT0) PD2 -|16               25|- PC3 (TMS)       
                            |                   |
*  LowPower     (INT1) PD3 -|17               24|- PC2 (TCK)       set
*                           |                   |
*               (OC1B) PD4 -|18               23|- PC1 (SDA)       menu vor
*                           |                   |
*  BW           (OC1A) PD5 -|19               22|- PC0 (SCL)       menu rück   
*                           |                   |
*  GAS          (ICP1) PD6 -|20    ATmega32   21|- PD7 (OC2)
*                           +-------------------+
*
* JTAG enable Fuse deaktivieren !!
*--------------------------------------------------------------------------
* AVR GCC Compiler
* Gaszaehler
* 26.12.2009 li start
* 27.12.2009 li Brauchwasser Verbrauch und Gesamt Verbrauch
* 01.01.2010 li Anpassung an Verdrahtung
* 06.01.2010 li DS1822 dazu u. Display Ports korrigiert
* 10.01.2010 li LED gruen und blau dazu
* 14.01.2010 li PC5 Port defekt, PC0 benutzen
* 17.01.2010 li Bereinigungen
* 18.01.2010 li Int1 routine entfent da unsicher, eeprom save bei jedem m³
* 19.01.2010 li Korrektur bsummek = 0 wenn Ueberlauf
* 05.03.2010 li SD Chip Select an PB1
* 08.03.2010 li S2 ist an PC1 !!!!
* 09.03.2010 li Bereinigung von Konstanten und nach pgmspace
* 10.03.2010 li Schreiben geht, jetzt EEPROM nutzen wenn Stromausfall
* 11.03.2010 li Dateien Wechsel geht, stromausfall ??
* 12.03.2010 li V12 Wenn SD close, dann save alle Werte ins eeprom
* 13.03.2010 li V13 Korrektur Wert für DS1822 dazu
* 14.03.2010 li V14 Änderung in der Ansteuerung der Leuchtdiode PB3
* 17.03.2010 li V15 jede Minute einen Messwert erzeugen, das sind am Tag
*               1440 Werte a 32Byte = 46080, datei ist: 97 * 512 = 49664
* 25.03.2010 li V16 UART 8N1, Temperratur werte +1024
* 25.03.2010 li V17 alle 30 Sekunden wechsel Aus / GwH Temperatur Anzeige
* 26.03.2010 li V18 Messwerte haben neue Kennung: V2
* 27.03.2010 li V18 Low Power aktivert, da jetzt Goldcap von 0,1F eingebaut ist
* 28.03.2010 li V19 Low power Verbesserungen
* 01.04.2010 li V20 Tageswechsel verbessert
* 01.04.2010 li V21 V20 quick and dirty, noch nicht gebrannt
* 02.04.2010 li V22 doppelte Messwertgenerierung verhindern
* 09.04.2010 li V23 Sicherung der letzten Messwerte wenn sd Card close
* 26.05.2010 li V24 S0 Strom Zähler Anschluss
* 27.05.2010 li V24 Watchdog Timer dazu
* 30.05.2010 li V25 Watchdog Timer auf 2sek
* 09.06.2010 li V26 Probleme, deshalb Versuch mit 14,7456MHz
* 10.06.2010 li V27 BGas Einstellung ermöglichen, bessere Sicherung
* 13.06.2010 li V28 Korrekturen, neuer Tageswechsel 23:59:20
* 16.06.2010 li V29 EEPROM Zugriff für die Messwerte verteilt, 38*100000 updates
* 17.06.2010 li V30 Tageswechsel ohne write
* 31.11.2010 li V31 Bei einem Gasmessimpuls wird für 10sek die Leistung angezeigt
* 20.03.2011 li V32 RegenMesser Nachricht dazu, tres wird zu tregen
* 27.04.2011 li V32 Kennung wird zum Indikator 0x1234
* 11.06.2011 li V33 Regen Nachricht korrigiert sRFnnnPe
* 31.08.2011 li V34 Spiegeln der Nachrichten zum webserver
* 07.09.2011 li V35 Neue Platine V2, Anpassungen 
* 09.09.2011 li V36 menu tx 2 web dazu
* 18.09.2011 li V37 Sende management korrigiert
***************************************************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <math.h>

#include "../abc/fat.h"                   // SD Card
#include "../abc/mmc.h"                   // SD Card
#include "../abc/basis.h"                 // Basis Routinen
#include "../abc/lcd.h"                   // Display Steuerung
#include "../abc/avr_uart.h"              // UART Zeitsignale
#include "../abc/OWImain.h"               // DS1822 routinen

// #define GMESS_TEST                     // Anpassung an das Testboard atmega32

#define  wdt_reset()         asm volatile("wdr")

unsigned char volatile tim2_event_flag;   // 10 msec Trigger
unsigned char volatile tim200cnt = 0;     // 1000 msek
unsigned char volatile LowPower = 0;      // Input Power 12V down

unsigned char uart_trace = 0;
unsigned char display_power = 1;
unsigned char tx2web = 1;                 // 9.9.11 transfer to webserver 
unsigned char uart_err_abs = 0;
unsigned char uartmproz=0;                // max Prozent Wert
unsigned char uartproz=0;                 // current Prozent Wert
unsigned char uart_display_err=0;
int uarterr =0;                           // error count
int uart_ok =0;                           // erkannte Nachrichten
int uarttimer=0;
long sekunden_10 = 0;                       
float leistung = 0.0;

#define RBUF_SIZE 19

char receive_buffer[ RBUF_SIZE+1 ];
unsigned char receive_ind = 0;            // receive Index

unsigned char volatile brauchwasser = 0;  // 1 = Brauchwasser load
unsigned char volatile display_flag = 0;

unsigned char volatile eeprom_read_ok = 0;

  // ----------------------------------------------
  // INDEX test_switch_x()    0     1     2     3     4
  // ----------------------------------------------
unsigned char al_cc[5]  = {   0,    0,    0,    0,    0  };

unsigned char al_bit[5] = { BIT0, BIT1, BIT2, BIT6, BIT5 };
 //                           S2   S3    S1    GAS   BW

long volatile summe=0;
unsigned char volatile summek =0;
long volatile bsumme=0;
unsigned char volatile bsummek =0;

long volatile kWh=0;
int  volatile kWh1000=0;        // 16.6.2010 kleinste Auflösung = 2 Impulse


                        //   0   1   2   3   4   5   6   7   8   9   0   1
uint8_t daByte[14] EEMEM = {'1','d','a','t','a','0','1','.','b','l','a','p'};
                        //   I   I                                       I= pruefzahl
                        //   I   I= current Datei Name
                        //   I= 1 = Aufzeichnung aktiv


                        //   38 * 26 Bytes = 988
                        //   k                                 Wechsel nach jedem loop auf 33 bzw. 66
                        //   0   1   2   3   4   5   6   7
                        //   8   9  10  11  12  13  14  15
                        //  16  17  18  19  20  21  22  23
                        //  24
uint8_t eeByte[988] EEMEM = { 0,                               // write kennung
                            '1','2','3','4','5','6','7','8',   // Gas Summe
                            '1','2','3','4','5','6','7','8',   // Gas Brauchwasser
                            '1','2','3','4','5','6','7','8',   // Strom Verbrauch
                            'p'
                           };


                          // externe structuren
extern S_UART    volatile us;
extern S_LCD_ANZ volatile lcdanz_s;
                                      // fat.c Konstanten
extern unsigned char cluster_size;
extern unsigned int  fat_offset;
extern unsigned int  cluster_offset;
extern unsigned int  volume_boot_record_addr;

char filName[] = "data01.bla";        // file name 01 bis 99

/*******************************************************************************
** Stuktur der Werte je Messintervall, jeweils Sekunde = 10 = 60 Werte je Stunde
** die ersten 32 Byte je Sektor bleiben frei wegen der Formatierungsinfo
** danach werden 15 Werte je Sektor geschrieben.
** 24 * 60 = 1440 Werte je Tag ergiebt 96 Sektoren a 512 Byte
** erzwungener Dateiwechsel je Tag, Formatierung mit 97*512 = 49664 Byte
** 99 Dateien je SD karte = ca. 5MB
********************************************************************************/
typedef struct
{
   int kennung;                // 2  0x1234    27.4.2011 neu     
   unsigned char jahr;         // 1  00-99
   unsigned char monat;        // 1
   unsigned char tag;          // 1
   unsigned char hh;           // 1  0-23 oder 100-123  MESZ
   unsigned char mm;           // 1
   unsigned char ss;           // sollte immer 10 sein
   int tvor;                   // 2  VT 
   int truk;                   // 2  RT
   int tout;                   // 2  Aussen      Temperatur
   int twas;                   // 2  Warm Wasser Temperatur
   int tgwh;                   // 2  Gewaechshaus Temperatur
   int tregen;                 // 2  Regenmesser Ticks
   long zgsum;                 // 4  Gas Zähler Wert
   long zgwas;                 // 4  Gas, Warm Wasser Anteil 
   long zgres;                 // 4  Strom Zähler Heizung
}
S_GMESS_ENTRY;                 //32  Byte


/*******************************************************************************
** Stuktur der Zeit Werte
** Der DCF77 Empfang ist im alarm_master realisiert. Die Zeitinfo wird per
** UART messages empfangen.    
********************************************************************************/
typedef struct
{
   unsigned char tim2ovf;
   int sleep;                  // dcf_sleep
   unsigned char sleep_over;   // overflow je 900 sek.
   unsigned char display_time;
   unsigned char time_trace;
   unsigned char Sleep_Sw;     // sleep switch
   unsigned char dcf_flag;     // siehe oben
   unsigned char ss;           // Sekunden
   unsigned char dmm;          // Minute
   unsigned char dhh;          // Stunde
   unsigned char day;          // Tag
   unsigned char wday;         // Wochentag
   unsigned char mon;          // Monat
   unsigned char year;         // Jahr
   unsigned char dmz;          // MEZ oder MESZ
}
S_CLOCK;

S_CLOCK  volatile clock_s;     // real definieren

int regen = 0;                 // Regenmesser ticks von Alarm_Master

unsigned char sflag = 0;
// fine TX_POWER 0x01          // .... ...1
//                             // .... ..1.
//                             // .... .1..
//                             // .... 1...
#define TX_ALL   0x0f          // .... 1111
#define T_ALARM  0x10          // ...1 ....
//                             // ..1. ....
//                             // .1.. ....
#define T_ERROR  0x80          // 1... ....
unsigned char quitFlag = 0;

unsigned int  lcd_timer = 1;   // lcd Timer
unsigned char menu_aktiv = 0;  // menu aktiv
unsigned char mtime = 0;       // menu timer, nach 10 Sekunden weg
unsigned char ptime = 0;       // power timer, nach 10 Sekunden weg
unsigned char menu1 = 0;       // mm3 sicherung text1
unsigned char mm3 = 0;         // s3: index auf texte
unsigned char mm2 = 0;         // s2: press counter

unsigned char mm3max[2];       // s3: max index text1
unsigned char mmxlen[2];
unsigned char mmxs1;

unsigned char send_timer1 = 0;

#define SEND_M_X   0x01        // .... ...1
#define SEND_M_Y   0x02        // .... ..1.
#define SEND_M_Z   0x04        // .... .1..
#define SEND_M_V   0x08        // .... 1...
#define SEND_M_B   0x10        // ...1 ....
#define SEND_M_W   0x20        // .1.. .... 
unsigned char send_flag = 0;

static char pgm_txt1[] PROGMEM   = "SD not found\n";
static char pgm_txt2[] PROGMEM   = "data01.bla found\n";
static char pgm_txt3[] PROGMEM   = "SD: FAT Info: ";
static char pgm_txt4[] PROGMEM   = "SEC per CLUS: ";
static char pgm_txt5[] PROGMEM   = "curr sector:";
static char pgm_txt6[] PROGMEM   = "sector point:";
static char pgm_txt7[] PROGMEM   = "close SD, dann init";
static char pgm_txt8[] PROGMEM   = "Watchdog Timer:";
static char pgm_txt9[] PROGMEM   = "MCUCSR :";      // reset Grund

                   /* 123456789012345 */
char zeile11[ 27 ] = "www.ralidzba\n" ;        // temp Text

                            //1234567890
                            //0--------1
static char m_t1[] PROGMEM = "retur V37"       // 0  return               V31
                             "Displ.LED"       // 1  Display Beleuchtung
                             "UartTrace"       // 2  Uart Trace,
                             "UartErr %"       // 3  Uart Errors
                             "Password "       // 4  Password, 4 mal hintereinander ....
                             "?x0000,00"       // 5  Setzen G/Szaehlerstand, passwort ok erforderlich
                             "?0x000,00"       // 6  Setzen G/Szaehlerstand, passwort ok erforderlich
                             "?00x00,00"       // 7  Setzen G/Szaehlerstand, passwort ok erforderlich
                             "?000x0,00"       // 8  Setzen G/Szaehlerstand, passwort ok erforderlich
                             "?0000x,00"       // 9  Setzen G/Szaehlerstand, passwort ok erforderlich
                             "?00000,x0"       // 10 Setzen G/Szaehlerstand, passwort ok erforderlich
                             "?00000,0x"       // 11 Setzen G/Szaehlerstand, passwort ok erforderlich
                             "1822SerNr"       // 12 Ausgabe der Serien Nummer des DS1822 (Hex-Format)
                             "1822Data "       // 13 Ausgabe der Messdaten im Hex-Format
                             "SD Card  "       // 14 SD Card Menu  init/free
                             "SD Infos "       // 15 SD Card Infos
                             "Set Count"       // 16 MessCounter Auswahl
                             "Power kW "       // 17 Display kW, Leistung der Therme
                             "TX 2 web "       // 18 tranfer to webserver                              
#ifdef GMESS_TEST
                             "Set loop "       // 19 Watchdog Time Out Test
#endif
                             ;

#define LEN_M_T1   9           // Laenge String
#ifdef GMESS_TEST
#define ENT_M_T1  19           // Anzahl der Eintraege -1
#else
#define ENT_M_T1  18           // Anzahl der Eintraege -1
#endif
                              //0--1--2--
static char sm_t1[] PROGMEM  = "retausein";                           // standard submenu
                              //0--1--2--3--4--5--6--7--8--9--0--
static char sm_t4p[] PROGMEM = "ret  0  1  2  3  4  5  6  7  8  9";   // submenu set Zaehler
                              //0--1--2--3--4--5--6--
static char sm_t12[] PROGMEM = "retausDS1DS2DS3DS4DS5";               // submenu DS1822
                              //0----1----2----
static char sm_t14[] PROGMEM = "ret  closeinit ";                     // submenu SD Card
                              //0---1---2---
static char sm_t15[] PROGMEM = "ret FAT CURR";                        // submenu SD Infos

static char sm_t16[] PROGMEM = "ret G/S Gas kWh Bgas";                // submenu Gas m³ oder Strom

#define LEN_SM_T1  3           // Laenge String
#define ENT_SM_T1  2           // Anzahl der Eintraege -1

#define LEN_SM_T4P 3           // laenge
#define ENT_SM_T4P 10          // n-1

#define LEN_SM_T12 3           // laenge
#define ENT_SM_T12 6           // n-1        25.3.2010 DS5 dazu

#define LEN_SM_T14 5           // laenge
#define ENT_SM_T14 2           // n-1

#define LEN_SM_T15 4           // laenge
#define ENT_SM_T15 2           // n-1

#define LEN_SM_T16 4           // laenge
#define ENT_SM_T16 4           // n-1


unsigned char pass_cnt = 0;
unsigned char pass_inp[5] ;    // passwort input
unsigned char password_ok = 0;

DALLAS s_dallas0;              // stucture DALLAS Vorlauf
DALLAS s_dallas1;              // stucture DALLAS Ruecklauf
DALLAS s_dallas2;              // stucture DALLAS Warmwasser
DALLAS s_dallas3;              // stucture DALLAS dummy Aussen
DALLAS s_dallas4;              // stucture DALLAS dummy Gewaechshaus

unsigned char ds1822_sn_sw = 0;
unsigned char ds1822_da_sw = 0;

unsigned char gas0_kWh1 = 0;   // set count switch
unsigned char sd_sw = 0;
unsigned char sd_info = 1;     // fehlwert
#ifdef GMESS_TEST
unsigned char loop=0;
#endif
unsigned char sd_init = 0;
unsigned char sd_timer = 0;
unsigned char sd_intervall=0;  // 1 == write, 2 == Tageswechsel
unsigned char sd_intimer = 0;  // blockiert doppelte Impulse
int sd_offset = 0;             // offset im Buffer
int sd_file_sek = 0;           // file Sektor  0 - 2047
unsigned char Buffer[512];     // SD Card
unsigned int  Clustervar = 0;  // SD Card
unsigned char Dir_Attrib = 0;  // SD Card
unsigned long Size = 0;        // SD Card

void move_pgm( prog_char *addr );
void dump_sdtxt( void );
void dump_sd( void );
void save_eeprom( void );
void save_eeprom_SD( void );
void timer2_init(void);
void int1_init( void );
unsigned char test_switch_C( unsigned char i );
unsigned char test_switch_D( unsigned char i );
void set_todo( void );
void s3_todo( unsigned char );
void sg_todo( unsigned char );
void bw_todo( unsigned char );
void clear_zeile( char *);
void display_x( void );
void decode_message(void);
void upd_Sekunde(void);
void display_menu(unsigned char m1);
void move2( char l, char pos, char index, unsigned char quelle );
void move1( char l, char index  );
void menu_U_sw2( void );
void open_next_file(void);
void open_sd( char);
void sd_close(void);
void timer0_init( void );
void housekeeping( unsigned char);
void eeprom_read( void );                         // 15.06.2010
int search_pos( unsigned char *, unsigned char ); // 16.6.2010
void send_temperatur(char, int);                  // 31.8.2011 
void sende_2_web_server( void );

/*######################################################################
**######################################################################
*
* Init, und main loop
*/
int main(void)
{
   int ic;
   char *s;
   unsigned char aktion,rc,n,p2;
   unsigned char wdallas = 0, ds1822=2;
   unsigned char wd2=0;
   unsigned char mcucsr;
   long x;
   S_GMESS_ENTRY *pintv;       // Messintervall

   mcucsr = MCUCSR & 0x1F ;
   housekeeping( mcucsr );
   lcd_init();                 // Initialize LC-Display
   clear_zeile(zeile11);
   sd_timer = 10;
   set_cursor(0,3);
   move_pgm( (prog_char*)&pgm_txt9 );     // MCUCSR
   edit_hex( 2, mcucsr, zeile11+8 );
   zeile11[11] = 'G';
   edit99( summe, zeile11+12, 5 );     // Gas Verbrauch Brauchwasser
   zeile11[17] = ',';
   edit99( summek, zeile11+18, 2 );
   lcd_string(zeile11);

   wdallas = 0;
   ds1822=2;
   wd2=0;
   wdt_reset();
   _delay_ms(200);                   // Unterbrechungs Problem ?
   wdt_reset();
   OWI_Init( &s_dallas0, BIT7, 0 );  // Heizung Vorlauf
   _delay_ms(200);
   wdt_reset();
   OWI_Init( &s_dallas1, BIT6, 0 );  // Heizung Ruecklauf
   _delay_ms(200);
   wdt_reset();
   OWI_Init( &s_dallas2, BIT5, 0 );  // Warm Wasser
   wdt_reset();
   
   s = (char*) &s_dallas3;
   for ( unsigned char i=0; i < sizeof( DALLAS ); i++ )
   {
      *s = '\0';                  // Aussen Temp ueber Alarm_Master
      s++;                        // sim dallas
   }

   s = (char*) &s_dallas4;
   for ( unsigned char i=0; i < sizeof( DALLAS ); i++ )
   {
      *s = '\0';                  // Gewaechshaus ueber Master
      s++;                        // sim dallas
   }
                                  // jetzt interupts starten
   wdt_reset();
   int1_init();                   // low power interupt
   timer2_init();
   timer0_init();                 // 26.05.2010 Zur Strom Messung
   wdt_reset();
   uart_init();
   wdt_reset();
   sei();                         // enable int
   display_x();                   // first display

   DDRC  &=  ~(BIT2+BIT1+BIT0);    // Input (S2 und S3 )
   PORTC |= BIT4+BIT3+BIT2+BIT1+BIT0;  // mit Pull up Widerstand
   
   PORTA |= BIT0+BIT1+BIT2+BIT3;  // frei Ports schützen  
   DDRD  &=  ~(BIT5+BIT6);        // Input GAS und BW
   PORTD |=   BIT2+BIT4+BIT5+BIT6+BIT7;    // mit Pull up Widerstand

   DDRB  |=  BIT3+BIT4;           // Output LED gelb und blau
   PORTB |=  BIT2+BIT3+BIT4;      // Output = 1 = LED aus
   
   
   //clock_s.dmz = 0x03;            // TEST TEST TEST TEST CD-Card write 

   // ++++++++++++++++++++++++++++++++++++++++++++ Main LOOP +++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++++++++++++++ Main LOOP +++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++++++++++++++ Main LOOP +++++++++++++++++++++
   for(;;)
   {
      if ( LowPower & BIT0 )      // Stromausfall ?
      {
         save_eeprom();
         LowPower &= ~BIT0;       // retset Bit Stromausfall
      }
      else
      {
         //--------------------------------------------------------------
         // diesen Teil nur wenn Power On
         // damit sind SD Card Zugriffe und DS1822 Zugriffe unterbunden
         //--------------------------------------------------------------
         if (tim2_event_flag ) // 10 msek int und
         {
            tim200cnt += tim2_event_flag;
            sekunden_10 += tim2_event_flag;
            tim2_event_flag = 0;

            if ( wdallas )
            {
               wdallas--;                 // 800 msec warten
               if ( wdallas == 1 )
               {
                  wdt_reset();
                  switch ( ds1822 )
                  {
                    case 0:
                     DS1820_ReadTempStep2( &s_dallas0 );   // temp auslesen                     
                     display_flag |= 0x02 ;
                     break;

                    case 1:
                     DS1820_ReadTempStep2( &s_dallas1 );   // temp auslesen
                     display_flag |= 0x02 ;
                     break;

                    case 2:
                     DS1820_ReadTempStep2( &s_dallas2 );   // temp auslesen
                     if ( menu_aktiv == 0 )
                        display_flag |= 0x04 ;
                     break;
                  }
                  wdallas = 0;
               }
            }

            if ( tim200cnt >= 100 )          // 10 * 100 = 1 Sekunde
            {
               tim200cnt = 0;
               upd_Sekunde();
               
               send_timer1++;                            
               switch( send_timer1 )
               {                                   
                 case 7: send_flag |= SEND_M_V; break;   // Vorlauf
                 case 14: send_flag |= SEND_M_B; break;  // Rücklauf
                 case 21: send_flag |= SEND_M_W; break;  // Warmwasser
                 case 28: send_flag |= SEND_M_X; break;  // Gas Zähler
                 case 35: send_flag |= SEND_M_Y; break;  // Gas Brauchw.
                 case 42: send_flag |= SEND_M_Z; break;  // Strom
               } 

               if ( sd_timer )
               {
                 sd_timer--;
                 wdt_reset();                       // 30.5.2010
               }

               display_flag |= 0x09;                // 13.6.2010 zeit + zähler

               if ( uarterr < 99 )                  // absolute fehler Zahl
               {
                  uart_err_abs = 1;
                  uartproz = uarterr;
               }
               else
               {
                  uart_err_abs = 0;
                  x = uarterr;
                  uartproz = (x * 100) / uart_ok ;
               }

               if ( uarttimer++ > 3600 )
               {
                  uarttimer=0;
                  uarterr=0;
                  uart_ok=0;
                  if ( uartproz > uartmproz )
                     uartmproz = uartproz;         // sichere max. error prozentwert
               }
                                                   // ----------------------------------------------------
               if ( sd_intervall && sd_init )      // Write Messwerte / Tageswechsel
               {
                  if ( sd_intervall == 2 )         // Tageswechsel = 2
                  {                     
                     wdt_reset();
                     fat_write_file( Clustervar, Buffer, sd_file_sek);   // save rest write sektor
                     wdt_reset();
                     open_next_file();
                     wdt_reset();
                     if ( sd_init )                // Buffer einlesen
                     {
                        fat_read_file( Clustervar, Buffer, sd_file_sek);
                        wdt_reset();
                        sd_offset = 32;            // skip 32 Byte
                     }            
                  }
                  else                             // 17.6.2010 hier intervall == 1 
                  {
                     if ( brauchwasser )
                        PORTB |=  BIT3;            // blaue LED aus
                     else
                        PORTB &=  ~BIT3;           // blaue LED ein
                     
                     if ( clock_s.dmm % 5 == 0 )   // save alle 5 Minuten = 20 Jahre ab release V29
                        save_eeprom();             // Save Daten 
                     
                     s =(char*)Buffer;
                     s += sd_offset;
                     pintv = (S_GMESS_ENTRY*)s;    // Struktur Adresse

                     pintv->kennung = 4660;        // Kennung 27.4.11 neu, 0x1234
                     pintv->jahr  = clock_s.year;  // 1  // 00-99
                     pintv->monat = clock_s.mon;   // 1
                     pintv->tag   = clock_s.day;   // 1
                     pintv->hh    = clock_s.dhh;   // 1
                     pintv->mm    = clock_s.dmm;   // 1
                     pintv->ss    = clock_s.ss;    // 1
                     pintv->tvor  = s_dallas0.tempwert;  // 2  Vorlauf     Temperatur
                     pintv->truk  = s_dallas1.tempwert;  // 2  Ruecklauf   Temperatur
                     pintv->tout  = s_dallas3.tempwert;  // 2  Aussen      Temperatur
                     pintv->twas  = s_dallas2.tempwert;  // 2  Warm Wasser Temperatur
                     pintv->tgwh  = s_dallas4.tempwert;  // 2  gewaechshaus Temperatur
                     pintv->tregen  = regen ;            // 2  Regen messer ticks

                     x = summe * 100;
                     x += summek;
                     pintv->zgsum = x;

                     x = bsumme * 100;
                     x += bsummek;
                     pintv->zgwas = x;

                     x = kWh * 1000;
                     x += kWh1000;
                     pintv->zgres = x;

                     sd_offset += 32;
                     if ( sd_offset == 512 )       // Block ende ??
                     {
                        wdt_reset();
                        fat_write_file( Clustervar, Buffer, sd_file_sek);   // write sektor
                        sd_file_sek++;                                      // sektor nummer +1

                        if ( sd_file_sek == (Size/512) )            // File Ende ??
                        {
                           wdt_reset();
                           open_next_file();
                        }

                        if ( sd_init )             // Buffer einlesen
                        {
                           wdt_reset();
                           fat_read_file( Clustervar, Buffer, sd_file_sek);
                           sd_offset = 32;         // skip 32 Byte
                        }
                     }
                     if ( brauchwasser )
                        PORTB &=  ~BIT3;           // blaue LED ein
                     else
                        PORTB |=  BIT3;            // blaue LED aus
                  }
                  sd_intervall = 0;
               }
                                                   // ----------------------------------------------------
               if ( lcd_timer )
               {
                  if ( lcd_timer++ > 3600  )       // 1 Stunde vorbei ?
                  {
                     lcd_timer = 0;
                     password_ok = 0;
                     lcd_beleuchtung( 0 );        // Beleuchtung aus
                  }
               }

               if ( ptime )                       // power display ??
               {
                  if ( ptime++ > 10  )
                  {  
                     ptime = 0;                  
                     display_flag &= 0x7F ;       // reset display power 
                  }
               }
               
               if ( menu_aktiv )        // reset menu nach 10Sek
               {
                  if ( mtime++ > 10 )
                  {
                     menu_aktiv = 0;
                     mtime = 0;
                     mm3 = 0;
                     mm2 = 0;
                     display_flag |= 0x04 ;
                  }
               }

               if ( wdallas == 0)
               {
                  wd2++;
                  if ( wd2 >= 3 )         // 3 Sekunden warten
                  {
                     wd2 = 0;
                     ds1822++;            // Sensor auswahl +1
                     if ( ds1822 >= 3 )
                       ds1822 = 0;

                     switch ( ds1822 )   // pdallas pointer einstellen
                     {
                       wdt_reset();
                       case 0:
                        DS1820_ReadTempStep1( &s_dallas0 );  // start der Messung
                        break;

                       case 1:
                        DS1820_ReadTempStep1( &s_dallas1 );  // start der Messung
                        break;

                       case 2:
                        DS1820_ReadTempStep1( &s_dallas2 );  // start der Messung
                        break;
                     }
                     wdallas = 80 ;                    // 800 msek timer starten
                  }
               }
            }  // Ende 10 * 100 = 1 Sekunde
            
                                          // ++++++++ Schalter Abfragen 10 msec
            if ( test_switch_C(2) == 1 )  // ++ Set Switch +++
               set_todo();

            if ( test_switch_C(1) == 1 )  // ++ S3 plus +++            
               s3_todo(1);
               
            if ( test_switch_C(0) == 1 )  // ++ S3 minus +++
               s3_todo(0);   

            rc = test_switch_D(3);        // ++ Gas sensor +++
            if ( rc )
               sg_todo( rc );

            rc = test_switch_D(4);        // ++ Brauch Wasser sensor +++
            if ( rc )
               bw_todo( rc );

            if ( mcucsr )                 // any Reset ?
            {
               MCUCSR ^= mcucsr ;         // reset power on Bits
               mcucsr = MCUCSR & 0x1F ;   // reset power on Bits
               wdt_reset();

               eeprom_read();              // hole letzte Sicherung

               for( n=0; n < 12; n++)
               {
                  zeile11[n] = eeprom_read_byte( &daByte[n] );
               }
               p2  = berechne_PZ( zeile11, 11) + 0x30 ;
               if ( zeile11[11] == p2)          // pruefzahl OK ?
               {
                  eeprom_read_ok = 1;
                  if ( brauchwasser )
                     PORTB |=  BIT3;            // blaue LED aus
                  else
                     PORTB &=  ~BIT3;           // blaue LED ein

                  if ( zeile11[0] == '1' )      // war SD aktiv ??
                  {
                     n = a_to_i( (char *)zeile11+5, 2);       // datei name
                     wdt_reset();
                     open_sd( n + 1 );          // open next file 
                  }
                  if ( brauchwasser )
                     PORTB &=  ~BIT3;           // blaue LED ein
                  else
                     PORTB |=  BIT3;            // blaue LED aus
               }
            }
         }
      }

      // ++++++++++++++++ UART Abfrage auf Zeichen empfangen ++++++
      ic = uart_getc();               // Zeichen vom Master holen
      if ( ic != -1 )                 // ungleich -1: Zeichen da
      {
         aktion = (unsigned char)ic & 0xFF ;

         if ( uart_trace )
         {
            display_flag &= 0x0C ;      // nur Zeile 3 und 4 zulassen
            if ( lcdanz_s.zeile > 2 )
               set_cursor( 0,1 );
            if ( lcdanz_s.zeile == 2 && lcdanz_s.xpos > 19 )
               set_cursor( 0,1 );
            if ( us.rx_error )
               lcd_data( 'x' );
            else if ( aktion == 0x02 )
               lcd_data( 's' );
            else if ( aktion == 0x03 )
               lcd_data( ' ' );
            else
               lcd_data( aktion );
         }

         if ( us.rx_error )        // tranfer fehler ??
         {
            us.rx_error = 0;
            sflag |= T_ERROR;          // merken
            uarterr++;
         }
         else
         {
            if ( aktion == 0x02 )     // start of txt = reset error
            {
               receive_ind = 0;       // receive Index auf 0
               sflag &= ~T_ERROR;               
            }

            if ( receive_ind >= RBUF_SIZE )
            {
               receive_ind = 0;
               sflag |= T_ERROR;
               uarterr++;
            }
            else
               receive_buffer[ receive_ind++ ] = aktion;
            wdt_reset();
            if ( aktion == 0x03 && !(sflag & T_ERROR) )
            {
               receive_buffer[ receive_ind ] = '\0'; // string ende setzen
               decode_message();       // <<<<<<<<<<<<<<<<<<<<<<
            }   
         }
      }

      // ############################################### SD CARD ########################
      if ( sd_sw  )                       // SD Card Menu
      {
         switch ( sd_sw )
         {
           case 1:                        // SD_CARD close
            sd_sw = 0 ;
            if ( sd_init )                // sicherung der letzten Messwerte  09.04.2010
            {
               fat_write_file( Clustervar, Buffer, sd_file_sek);   // write sektor
            }
            sd_close();
            break;

           case 2:                        // Initialisierung der MMC/SD-Karte
            sd_sw = 0;
            sd_timer = 15 ;               // 30 Sek. Std_Anzeige ausblenden
            set_cursor(0,2);
            if ( sd_init  )               // doppelt init geht nicht
            {
               move_pgm( (prog_char*)&pgm_txt7 );
               lcd_string(zeile11);
            }
            else
            {
               open_sd( 1 );
            }
            break;

           case 3:                       // FAT Info
            sd_sw = 0;
            if ( sd_init )
            {
               sd_timer = 15 ;          // 30 Sekunden Std_Anzeige ausblenden
               set_cursor(0,1);
               clear_zeile( zeile11 );
               move_pgm( (prog_char*)&pgm_txt3 );
               lcd_string(zeile11);

               clear_zeile( zeile11 );
               move_pgm( (prog_char*)&pgm_txt4 );
               edit99( cluster_size, zeile11+13, 2 );
               lcd_string(zeile11);
            }
            break;

           case 4:                       // Current File Name, size und currBlock
            sd_sw = 0;
            sd_timer = 15 ;              // 30 Sekunden Std_Anzeige ausblenden
            set_cursor(0,1);
            clear_zeile( zeile11 );
            n = 0;
            do
            {
               zeile11[n] = filName[n] ;
               n++;

            } while( filName[n] );
            edit99( Size, zeile11+12, 7 );  // File Size
            lcd_string(zeile11);

            move_pgm( (prog_char*)&pgm_txt5 );     // curr sektor
            edit99( sd_file_sek, zeile11+13, 4 );  // currblk
            lcd_string(zeile11);

            move_pgm( (prog_char*)&pgm_txt6 );     // curr sektor
            edit99(  sd_offset, zeile11+14, 3 );   // currblk
            lcd_string(zeile11);

            clear_zeile( zeile11 );
            move_pgm( (prog_char*)&pgm_txt8 );     // Watchdog timer
            zeile11[16] = 'o';
            if ( WDTCR & (1 << WDE) )
            {
               zeile11[17] = 'n';                  // on
            }
            else
            {
               zeile11[17] = 'f';                  // off
               zeile11[18] = 'f';
            }
            lcd_string(zeile11);
            break;
          }
      }
      if ( send_flag &&  us.tx_busy == 0 )
         sende_2_web_server( );
         
      if ( sd_timer == 0 )
      {
         if ( !( WDTCR & (1 << WDE ) ))  // kein watchdog aktiv
         {
            wdt_reset();
                                        // watchdog timer auf 2 Sekunden setzen und starten
            WDTCR |= (1 << WDE) | (1 << WDP0) | (1 << WDP1) | (1 << WDP2);
         }
         
         if ( display_flag & 0x7F ) // update display
            display_x();
      }
#ifdef GMESS_TEST
      if ( loop )                   // simuliere time out
      {
         loop = 0;
         _delay_ms(600);
         _delay_ms(600);
         _delay_ms(600);
         _delay_ms(600);
      }
#endif
   }
}



/*****************************************************************************
** SD_close
*/
void sd_close(void)
{
   sd_init = 0;               // keine aktivitäten erlauben
   SPCR = 0;                  // Reset SP Control Register
   wdt_reset();
   save_eeprom_SD();          // Save Zustand
   wdt_reset();
}



/*****************************************************************************
** Wechsel zur naechsten Datei
** 11.03.2010 li OK
*/
void open_next_file(void)
{
   int x;

   if ( sd_init )
   {
      x = a_to_i( (char *)filName+4, 2);       // datei name
      x++;                                     // +1
      edit99( x, (char *)filName+4, 2 );       // naechster Dateiname
      Clustervar = 0;                          // reset 11.3.2010
      if (fat_search_file( (unsigned char*)filName, &Clustervar, &Size, &Dir_Attrib, Buffer) == 1)
      {
         sd_file_sek = 0;               // sektor wieder bei 0
         sd_offset = 32;                // offset im block
      }
      else
      {
         filName[4] = '0';
         filName[5] = '1';              // wrap around
         Clustervar = 0;                // reset 11.3.2010
         if (fat_search_file( (unsigned char*)filName, &Clustervar, &Size, &Dir_Attrib, Buffer) == 1)
         {
            sd_file_sek = 0;
            sd_offset = 32;
         }
         else
         {
            sd_close();
         }
      }
      save_eeprom_SD();                // Save Zustand
   }
}


/*****************************************************************************
** open sd Card
*/
void open_sd( char filenummer )
{
   if ( mmc_init() !=0 )      // ungleich NULL = Fehler
   {
      move_pgm( (prog_char*)&pgm_txt1 );
      lcd_string(zeile11);
   }
   else
   {
      wdt_reset();
      fat_init();             // laden Cluster OFFSET und Size
      sd_init = 1;
      edit99( filenummer, filName + 4, 2);
      Clustervar = 0;         // reset
      if ( fat_search_file( (unsigned char*)filName, &Clustervar, &Size, &Dir_Attrib, Buffer) == 1)
      {
         sd_file_sek = 0;
         sd_offset = 32;
         move_pgm( (prog_char*)&pgm_txt2 );
         lcd_string(zeile11);
      }
      else
      {
          sd_close();
      }
      wdt_reset();
      if ( sd_init )          // Buffer einlesen
      {
          fat_read_file( Clustervar, Buffer, sd_file_sek);
      }
      save_eeprom_SD();       // Save Zustand
   }
}



/*****************************************************************************
** Move Text aus dem pgm speicher
*/
void move_pgm( prog_char *addr )
{
   unsigned char n;
   char c;

   clear_zeile( zeile11 );   // file name generieren
   n = 0;
   c = pgm_read_byte( addr++ );       // data01.bla
   do
   {
      zeile11[n++] = c;
      c = pgm_read_byte( addr++ );    // data01.bla
   } while( c );
}



/*****************************************************************************
** dump 16 Byte Register Info
*/
void dump_sd( void )
{
   char *s;
   unsigned char i,tmp;
   clear_zeile( zeile11 );
   s = zeile11;
   for ( i= 0; i < 16 ; i++)
   {
      if ( i % 4 == 0 )
         s++;
      tmp = Buffer[i];
      edit_hex( 2, tmp, s );
      s += 2;
      if ( i == 7 )
      {
         lcd_string(zeile11);
         clear_zeile( zeile11 );
         lcd_string("\n");
         s = zeile11;
      }
   }
   lcd_string(zeile11);
}



/*****************************************************************************
** dump 16 Byte TextInfo
*/
void dump_sdtxt( void )
{
   unsigned char i;

   clear_zeile( zeile11 );

   for ( i= 0; i < 16 ; i++)
      zeile11[i] = Buffer[i];

   lcd_string(zeile11);
}



/**************************************************************
* Suche eeprom position
* write=1 : Position zum schreiben
* write=0 : letzte write Position   
* 38 * 26  = 988 Bytes used
*/
int search_pos( unsigned char *pken, unsigned char write )
{
   int pos=0;
   unsigned char start0, curr, kennung=0x33;
                                   
   start0 = eeprom_read_byte( &eeByte[pos]);     // position 0 Kennung lesen  
   if ( start0 == 0xFF )     // first ??
   {
      *pken = kennung;       // Übergabe 0x33 
      return pos;
   }
   else
      kennung = start0;      // return
                                                 // search  
   for ( pos=0; pos < 988; pos += 26 )
   {  
      curr = eeprom_read_byte( &eeByte[pos]);    
      if ( curr == 0xFF || curr != start0 )      // wechsel oder first 
         break;                   
   }
    
   if ( write )              // wenn write dann neue Position
   {
      if ( pos == 988 )      // loop ende ?
      {
         kennung ^= 0x55;    // change kennung  0x33 / 0x66     
         pos = 0;            // restart bei 0  
      } 
      *pken = kennung;       // Übergabe an aufrufer   
      return pos;
   }
   else                      // == read 
   {
      pos -= 26;             // letzte Position
      return pos;
   }      
}   



/*****************************************************************************
** save Gas Messwerte ins eeprom
** 25.05.2010 kWh dazu
** 16.06.2010 38 fache Messdaten Sicherungen
*/
void save_eeprom( void )
{
   int pos,x;
   unsigned char kennung,n;

   pos = search_pos( &kennung, 1 );   // write pos holen
   eeprom_write_byte( &eeByte[ pos ], kennung );
   
   edit99( summe,   zeile11,    6);
   edit99( summek,  zeile11+6,  2);
   edit99( bsumme,  zeile11+8,  6);
   edit99( bsummek, zeile11+14, 2);
   edit99( kWh,     zeile11+16, 5);
   x = kWh1000 + TCNT0;               // save incl. Timer0
   edit99( x, zeile11+21, 3);
   zeile11[24] = berechne_PZ( zeile11, 24) + 0x30 ;

   for ( n=0; n < 25; n++)
   {
      eeprom_write_byte( &eeByte[ pos+n+1 ], zeile11[ n ] );
   }
}



/*****************************************************************************
** read Gas Messwerte vom eeprom
*/
void eeprom_read( void )
{
   unsigned char n,p2;
   int pos;
   unsigned char kennung;                      // not used da read

   pos = search_pos( &kennung, 0 );

   for( n=0; n < 25; n++)
   {
      zeile11[n] = eeprom_read_byte( &eeByte[ pos+n+1 ]);
   }

   p2  = berechne_PZ( zeile11, 24) + 0x30 ;
   if ( zeile11[24] == p2)          // pruefzahl OK ?
   {
      eeprom_read_ok = 1;
      summe   = a_to_i(zeile11,6);
      summek  = a_to_i(zeile11+6,2);
      bsumme  = a_to_i(zeile11+8,6);
      bsummek = a_to_i(zeile11+14,2);
                                        // 27.05.2010
      kWh     = a_to_i(zeile11+16,5);
      kWh1000 = a_to_i(zeile11+21,3);
      n = (unsigned char)(kWh1000 % 2);
      if ( (n + TCNT0) < 2 )
      {
         TCNT0 += n;
         kWh1000 -= n;
      }
   }
}



/*****************************************************************************
** save SD Parameter ins eeprom
*  sd_init = SD Card aktiv
*  sowie den aktuellen Dateinamen
*/
void save_eeprom_SD( void )
{
   unsigned char n;

   clear_zeile( zeile11 );
   zeile11[0] = sd_init + 0x30 ;      // SD Aktiv ??
   for ( n=0; n < 10; n++)
   {
      zeile11[n+1] = filName[n] ;
   }
   zeile11[11] = berechne_PZ( zeile11, 11) + 0x30 ;

   for ( n=0; n < 12; n++)
   {
      eeprom_write_byte( &daByte[n], zeile11[n] );
   }
   sd_timer = 15 ;             // 10 sek Anzeige ausblenden
   set_cursor(0,1);
   lcd_string(zeile11);
}



/*****************************************************************************
** clear Zeile
*/
void clear_zeile( char *s )
{
   unsigned char i;

   for( i=0; i < 20 ; i++ )
   {
      *s = ' ' ;
      s++;
   }
   *s = '\0' ;
}



/*****************************************************************************
** Set Taster pressed == Set
*/
void set_todo( void )
{
   char feld[6];
   unsigned char pos=0;

   lcd_beleuchtung( 1 );     // 10.9.2009 Beleuchtung ein
   lcd_timer = 1;            // timer starten
   if ( menu_aktiv )         // s3 da gewesen  ??
   {
      mtime = 0;             // restart mtime
      mm2++;
      if ( mm2 == 1 )        // erster text da
      {
         menu1 = mm3;        // save level 1
                             // das was da ist anzeigen
         switch( menu1 )     // Anzeige submenu mit currend Einstellung
         {
           case 0: mm3 = 0; menu_U_sw2(); break;          // DCF77 Menu break;

           case 1: mm3 = lcdanz_s.lcd_backlight+1; break; // licht

           case 2: mm3 = uart_trace +1; break;            // uart trace

           case 3: mm3 = uart_display_err +1; break;      // UART ERROR

           case 4:
            if ( password_ok )
               mm3 = password_ok +1;
            else
               mm3 = pass_cnt +1;
            break;           // password

           case 5:
           case 6:
           case 7:
           case 8:
           case 9:
            if (gas0_kWh1 == 2 )      edit99( kWh,    feld, 5);
            else if (gas0_kWh1 == 3 ) edit99( bsumme, feld, 5);
            else if (gas0_kWh1 == 1 ) edit99( summe,  feld, 5);
            pos = menu1 - 5;
            mm3 = (feld[pos] & 0x0F ) + 1;
            break;

           case 10:
           case 11:
            if (gas0_kWh1 == 2 )      edit99( kWh1000, feld, 3);
            else if (gas0_kWh1 == 3 ) edit99( bsummek, feld, 2);
            else if (gas0_kWh1 == 1 ) edit99( summek,  feld, 2);
            pos = menu1 - 10;
            mm3 = (feld[pos] & 0x0F ) + 1;
            break;

           case 12: mm3 = ds1822_sn_sw +1; break;      // Display DS1822 Serien number

           case 13: mm3 = ds1822_da_sw +1; break;      // Display DS1822 messdaten

           case 14: mm3 = sd_init+1 ; break;           // SD Card

           case 15: mm3 = sd_info ; break;             // SD Info

           case 16: mm3 = gas0_kWh1 + 1 ; break;       // set Count
           
           case 17: mm3 = display_power + 1 ; break;   // display Power
           
           case 18: mm3 = tx2web + 1 ; break;          // transfer to webserver
#ifdef GMESS_TEST
           case 19: mm3 = loop+1 ; break;              // loop
#endif
         }

         if ( mm3 )
         {
            display_menu( menu1 );   // text1 und text2
         }
      }
      else
      {
         mm2 = 1;            // mm2 auf 1 halten
         menu_U_sw2();       // set
      }
   }
}



/*****************************************************************************
** S3 Taster pressed == menu++
*/
void s3_todo( unsigned char plus )
{
   lcd_beleuchtung( 1 );     // 10.9.2009 Beleuchtung ein
   lcd_timer = 1;            // timer starten
   menu_aktiv = 1;
   mtime = 0;
   
   if ( plus )
      mm3++;
   else
      mm3--;
   
   if ( mm2 == 0 )            // kein s2 switch da
   {                          // default werte einstellen
      mmxlen[0] = LEN_M_T1;
      mm3max[0] = ENT_M_T1;
      mmxlen[1] = LEN_SM_T1;
      mm3max[1] = ENT_SM_T1;
      mmxs1 = 1;
   }
   
   if ( plus )
   {
      if ( mm3 > mm3max[ mm2 ] )    // wrap around bei 0
         mm3 = 0;
   }
   else
   {
      if ( mm3 > mm3max[ mm2 ] )    // wrap around bei max
         mm3 = mm3max[ mm2 ] ;
   }
   
   if ( mm2 == 0 )
   {
      switch( mm3 )
      {
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
        case 11:
         mmxlen[1] = LEN_SM_T4P;
         mm3max[1] = ENT_SM_T4P;
         mmxs1 = 4;
         break;

        case 12:
        case 13:
         mmxlen[1] = LEN_SM_T12;
         mm3max[1] = ENT_SM_T12;
         mmxs1 = 12;
         break;

        case 14:               // sd card
         mmxlen[1] = LEN_SM_T14;
         mm3max[1] = ENT_SM_T14;
         mmxs1 = 14;
         break;

        case 15:               // sd card
         mmxlen[1] = LEN_SM_T15;
         mm3max[1] = ENT_SM_T15;
         mmxs1 = 15;
         break;

        case 16:               // sd card
         mmxlen[1] = LEN_SM_T16;
         mm3max[1] = ENT_SM_T16;
         mmxs1 = 16;
         break;
      }
      display_menu( mm3 );     // text1
   }
   else
      display_menu( menu1 );   // text 1 und text2
}



/*****************************************************************************
** die text elemente sind so angeordnet, dass bei "ein" todo=1 ist, "aus" todo=0
**
** menu1 = 0  und mm3 = 0
*/
void menu_U_sw2( void )
{
   unsigned char rc=1;
   unsigned char todo;
   char feld[6];

   mm2 = 0;               // mm2 immer auf 0
   if ( menu1 )           // menu 1
   {
      todo = mm3 - 1;
      if ( todo == 0xff ) // retur ausgewaehlt ?
      {
         display_menu( menu1 );
         rc=0;
      }
      else
      {
         switch ( menu1 )
         {
           case 1:        // backlight
            lcd_beleuchtung( todo );
            break;

           case 2:        // uart Trace
            uart_trace = todo;
            break;

           case 3:        // UART error display
            uart_display_err = todo;
            break;

           case 4:        // password
            pass_inp[ pass_cnt ] = 0x30 + todo;
            pass_cnt++;
            if ( pass_cnt == 4 )        //  password[5] = "5432" ;
            {
               if ( '5' == pass_inp[0] && '4' == pass_inp[1] &&
                    '3' == pass_inp[2] && '2' == pass_inp[3] )
               {
                  password_ok = 1;  // bleibt 1h gueltig
               }
               pass_cnt = 0;         // reset
               pass_inp[0] = ' ';   // clear input
               pass_inp[1] = ' ';
               pass_inp[2] = ' ';
               pass_inp[3] = ' ';
            }
            break;

           case 5:        // Gx0000,00
            if ( password_ok )
            {
               if ( gas0_kWh1 == 2 )
               {
                  edit99(kWh,feld,5);
                  feld[0] = 0x30 + todo ;
                  kWh = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summe,feld,5);
                  feld[0] = 0x30 + todo ;
                  summe = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsumme,feld,5);
                  feld[0] = 0x30 + todo ;
                  bsumme = a_to_i( feld, 5);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 6:        // G0x000,00
            if ( password_ok  )
            {
               if ( gas0_kWh1 == 2  )
               {
                  edit99(kWh,feld,5);
                  feld[1] = 0x30 + todo ;
                  kWh = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summe,feld,5);
                  feld[1] = 0x30 + todo ;
                  summe = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsumme,feld,5);
                  feld[1] = 0x30 + todo ;
                  bsumme = a_to_i( feld, 5);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 7:        // G00x00,00
            if ( password_ok )
            {
               if ( gas0_kWh1  == 2  )
               {
                  edit99(kWh,feld,5);
                  feld[2] = 0x30 + todo ;
                  kWh = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summe,feld,5);
                  feld[2] = 0x30 + todo ;
                  summe = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsumme,feld,5);
                  feld[2] = 0x30 + todo ;
                  bsumme = a_to_i( feld, 5);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 8:        // G000x0,00
            if ( password_ok )
            {
               if ( gas0_kWh1  == 2 )
               {
                  edit99(kWh,feld,5);
                  feld[3] = 0x30 + todo ;
                  kWh = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summe,feld,5);
                  feld[3] = 0x30 + todo ;
                  summe = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsumme,feld,5);
                  feld[3] = 0x30 + todo ;
                  bsumme = a_to_i( feld, 5);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 9:        // G0000x,00
            if ( password_ok )
            {
               if ( gas0_kWh1  == 2 )
               {
                  edit99(kWh,feld,5);
                  feld[4] = 0x30 + todo ;
                  kWh = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summe,feld,5);
                  feld[4] = 0x30 + todo ;
                  summe = a_to_i( feld, 5);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsumme,feld,5);
                  feld[4] = 0x30 + todo ;
                  bsumme = a_to_i( feld, 5);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 10:        // G00000,x0
            if ( password_ok )
            {
               if ( gas0_kWh1 == 2  )
               {
                  edit99(kWh1000,feld,3);
                  feld[0] = 0x30 + todo ;
                  kWh1000 = a_to_i( feld, 3);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summek,feld,2);
                  feld[0] = 0x30 + todo ;
                  summek = a_to_i( feld, 2);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsummek,feld,2);
                  feld[0] = 0x30 + todo ;
                  bsummek = a_to_i( feld, 2);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 11:        // G00000,0x
            if ( password_ok )
            {
               if ( gas0_kWh1 == 2 )
               {
                  edit99(kWh1000,feld,3);
                  feld[1] = 0x30 + todo ;
                  kWh1000 = a_to_i( feld, 3);
               }
               if ( gas0_kWh1 == 1 )
               {
                  edit99(summek,feld,2);
                  feld[1] = 0x30 + todo ;
                  summek = a_to_i( feld, 2);
               }
               if ( gas0_kWh1 == 3 )
               {
                  edit99(bsummek,feld,2);
                  feld[1] = 0x30 + todo ;
                  bsummek = a_to_i( feld, 2);
               }
            }
            display_flag |= 0x08 ;
            break;

           case 12:        // DS1822 Serien Nummer
            ds1822_sn_sw = todo;
            if ( ds1822_da_sw )
               ds1822_da_sw = 0;
            break;

           case 13:        // oder DS1822 Daten anzeigen
            ds1822_da_sw = todo;
            if ( ds1822_sn_sw )
               ds1822_sn_sw = 0;
            break;

           case 14:        // sd Card init
            sd_sw = todo + 1;
            break;

           case 15:        // sd Card info
            sd_info = todo + 1;
            sd_sw = sd_info + 2;
            break;

           case 16:        // set count switch
            gas0_kWh1 = todo;
            display_flag |= 0x08 ;
            break;
           
           case 17:        // Display Power
            display_power = todo;
            break; 

           case 18:        // Trabsfer to webserver
            tx2web = todo;
            break;  
            
#ifdef GMESS_TEST
           case 19:        // loop 
            loop = todo;
            break;
#endif
         }
      }
   }
   if ( rc )
   {
      mm3 = 0;            // mm3 wieder auf 0
      mtime = 0;
      menu_aktiv = 0;
      display_flag |= 0x04;
      display_x();        // normal anzeigen
   }
}



/*****************************************************************************
** reed Kontakt am Gas Zaehler
** 19.01.2010 li Korrektur bsummek = 0 wenn Ueberlauf
*/
void sg_todo( unsigned char td )
{      
   if ( td == 1)
   {
      PORTB &=  ~BIT4;         // gruene LED ein

      summek += 1;             // nachkomma +1
      if ( summek == 100 )     // Ueberlauf ?
      {
         summe += 1;
         summek = 0;
      }

      if ( brauchwasser )      // Brauchwasser Verbrauch
      {
         bsummek += 1;
         if ( bsummek == 100 )
         {
            bsumme += 1;
            bsummek =0;        // 19.1.2009
         }
      }
                               // Berechnung der aktuellen Leistung
      leistung = 385337.58;    // 0,01 * 0,9534 * 11,227 * 3600 * 10 * 100
      if ( sekunden_10 )
         leistung /= sekunden_10;      
      sekunden_10 = 0;
      if ( display_power )
      {
         ptime = 1;
         display_flag |= 0x80;  // spezial Bit bleibt 10 Sekunden an
      }   
   }
   else
   {
      PORTB |=  BIT4;         // gruene LED aus
   }
   display_flag |= 0x08;
}



/*****************************************************************************
** Brauchwasser pressed, NC = Heizkreis, open = brauchwasser
*/
void bw_todo( unsigned char td )
{
   switch (td)
   {
     case 1:
      PORTB &=  ~BIT3;        // blaue LED ein
      brauchwasser = 1;
      break;

     case 2:
      PORTB |=  BIT3;         // blaue LED aus
      brauchwasser = 0;
      break;
   }
}



/*****************************************************************************
** Schalter Abfrage PORTC
** funktionieren nur wenn Aufruf alle 10 msek
*/
unsigned char test_switch_C( unsigned char i )
{
   unsigned char bit;

   bit = al_bit[i];           // Bit holen

   if ( !(PINC & bit) )       // pressed = 0 ??
   {
      if ( !(PINC & bit) && al_cc[i] < 128 )
      {
         if ( al_cc[i]++ > 3 )
         {
            al_cc[i] = 128;    // pressed
            return 1;
         }
      }
   }
   else
   {
      if ( al_cc[i] >= 128 )
      {
         if ( PINC & bit )
         {
            if ( al_cc[i]++ > 131 )
            {
               al_cc[i] = 0;  // no pressed
               return 2;
            }
         }
      }
      else
         al_cc[i] = 0;             // no pressed
   }
   return 0;
}



/*****************************************************************************
** Schalter Abfrage PORTD
** funktionieren nur wenn Aufruf alle 10 msek
*/
unsigned char test_switch_D( unsigned char i )
{
   unsigned char bit;

   bit = al_bit[i];           // Bit holen

   if ( !(PIND & bit) )       // pressed = 0 ??
   {
      if ( !(PIND & bit) && al_cc[i] < 128 )
      {
         if ( al_cc[i]++ > 3 )
         {
            al_cc[i] = 128;    // pressed
            return 1;
         }
      }
   }
   else
   {
      if ( al_cc[i] >= 128 )
      {
         if ( PIND & bit )
         {
            if ( al_cc[i]++ > 131 )
            {
               al_cc[i] = 0;    // no pressed
               return 2;
            }
         }
      }
      else
         al_cc[i] = 0;          // no pressed
   }
   return 0;
}



/*****************************************************************************
**  4 zeilen anzeigen
**  fuer jede Zeile gibt es bit, d.h die die neuen Zeilen werden angezeigt.
*/
void display_x( void )
{
   DALLAS *pda;
   char *s = zeile11;
   unsigned char i;
   long lpower; 

   wdt_reset();                       // reset watchdog timer
   if ( uart_trace == 0 )             // wenn uart_trace dann die ersten
   {                                    // beiden Zeilen ausblenden
                        // UART ERROR Display
                        // eXXXX #XXXX p12 m12
                        //                 m12 = max. prozentwert
                        //             p12     = curent prozent wert
                        //       #xxxx         = UART OK cnt
                        // eXXXX               = UART error cnt
      if ( uart_display_err )
      {
         clear_zeile( zeile11 );
         zeile11[0] = 'e';
         edit_hex( 4, uarterr, zeile11+1 );
         zeile11[6] = '#';
         edit_hex( 4, uart_ok, zeile11+7 );
         if ( uart_err_abs )
            zeile11[12] = 'a';
         else
            zeile11[12] = 'p';
         edit99( uartproz, zeile11+13, 2 );
         zeile11[16] = 'm';
         edit99( uartmproz, zeile11+17, 2 );
         set_cursor(0,1);
         lcd_string(zeile11);
         //set_cursor(0,2);
         //eep[16] = '\0';
         //lcd_string(eep);
      }
      else if ( display_flag & 0x01 )
      {
         set_cursor(0,1);
         if ( ds1822_sn_sw )
         {
            clear_zeile( zeile11 );
            zeile11[0]= 'D';
            zeile11[1]= 0x30 + ds1822_sn_sw ;
            s += 3;
            switch ( ds1822_sn_sw )
            {
               case 2:  pda = &s_dallas1; break;
               case 3:  pda = &s_dallas2; break;
               case 4:  pda = &s_dallas3; break;
               case 5:  pda = &s_dallas4; break;
               default: pda = &s_dallas0; break;
            }
            for (i=0; i < 7;i++)
            {
               edit_hex(2,pda->sim_eeprom[i],s);
               s+=2;
            }
            lcd_string(zeile11);     // zeile 1
         }
         else if ( ds1822_da_sw )
         {
            clear_zeile( zeile11 );
            switch ( ds1822_da_sw )
            {
               case 2:  pda = &s_dallas1; break;
               case 3:  pda = &s_dallas2; break;
               case 4:  pda = &s_dallas3; break;
               case 5:  pda = &s_dallas4; break;
               default: pda = &s_dallas0; break;
            }
            for (i=0; i < 9;i++)
            {
               edit_hex( 2, pda->mdata[i], s);
               s+=2;
            }
            lcd_string(zeile11);     // zeile 1
         }
         else
         {                                // Zeitanzeige aufbereiten
            clear_zeile( zeile11 );
            if ( display_flag & 0x80 )
            {
               zeile11[0] = 'P';               // 01234567890123456789
               zeile11[1] = 'o';               // Pow. 22,3kW 18:33:13
               zeile11[2] = 'w';
               zeile11[3] = '.';                 
               lpower = leistung ;             // umwandlung nach long
               edit99(lpower,  zeile11+4, 4);
               zeile11[8] = zeile11[7];
               if ( zeile11[4] == '0' )        // mit führender Null ?   
               {
                  zeile11[4] = ' ';            // clear
                  if ( zeile11[5] == '0' )     // noch eine ?
                     zeile11[5] = ' ';         // clear
               }
               zeile11[7] = ',';
               zeile11[9] = 'k';
               zeile11[10] = 'W';
            }
            else
            {
               zeile11[0] = 'D';
               zeile11[1] = 'o';
               if ( clock_s.wday == 1 )
                  zeile11[0] = 'M';    // Mon
               else if ( clock_s.wday == 7 )
                  zeile11[0] = 'S';    // Son
               else if ( clock_s.wday == 2 )
               {
                  zeile11[1] = 'i';    // Die
               }
               else if ( clock_s.wday == 3 )
               {
                  zeile11[0] = 'M';
                  zeile11[1] = 'i';
               }
               else if ( clock_s.wday == 5 )
               {
                  zeile11[0] = 'F';
                  zeile11[1] = 'r';
               }
               else if ( clock_s.wday == 6 )
               {
                  zeile11[0] = 'S';
                  zeile11[1] = 'a';
               }
               edit99(clock_s.day,  zeile11+3, 2);
               zeile11[5] = '.';
               edit99(clock_s.mon,  zeile11+6, 2);
               zeile11[8] = '.';
               edit99(clock_s.year, zeile11+9, 2);
            }
            edit99(clock_s.dhh,  zeile11+12, 2);
            zeile11[14] = ':';
            edit99(clock_s.dmm,  zeile11+15, 2);
            zeile11[17] = ':';
            edit99(clock_s.ss,   zeile11+18, 2);
            
            lcd_string(zeile11);     // zeile 1
         }
      }
      if ( display_flag & 0x02 )    // Temperatur
      {
         clear_zeile( zeile11 );
         zeile11[0] = 'V';
         zeile11[1] = 'o';
         zeile11[2] = 'r';
         edit_temperatur( &s_dallas0, zeile11+4 );
         zeile11[10] = 'R';
         zeile11[11] = 'u';
         zeile11[12] = 'e';
         edit_temperatur( &s_dallas1, zeile11+14 );
         set_cursor(0,2);
         lcd_string(zeile11);
      }
   }
   if ( display_flag & 0x04 )      // Temperatur
   {
      clear_zeile( zeile11 );
      if ( clock_s.ss > 29 )
      {
         zeile11[0] = 'A';
         zeile11[1] = 'u';
         zeile11[2] = 's';
         edit_temperatur( &s_dallas3, zeile11+4 );   // 16.03.2010
      }
      else
      {
         zeile11[0] = 'G';
         zeile11[1] = 'w';
         zeile11[2] = 'H';
         edit_temperatur( &s_dallas4, zeile11+4 );   // 25.03.2010
      }
      zeile11[10] = 'W';
      zeile11[11] = 'a';
      zeile11[12] = 's';
      edit_temperatur( &s_dallas2, zeile11+14 );     // 16.03.2010
      set_cursor(0,3);
      lcd_string(zeile11);
   }

   if ( display_flag & 0x08 )
   {
      clear_zeile( zeile11 );
      if ( ((gas0_kWh1 == 0 || gas0_kWh1 == 3) && (clock_s.ss >= 29)) || gas0_kWh1 == 2 )
      {
         zeile11[0] = 'S';
         edit99( kWh, zeile11+1, 5 );           // Strom Verbrauch Zaehler
         zeile11[6] = ',';
         edit99( kWh1000, zeile11+7, 3 );
      }
      if ( ((gas0_kWh1 == 0 || gas0_kWh1 == 3) && (clock_s.ss < 29)) || gas0_kWh1 == 1 )
      {
         zeile11[0] = 'G';
         edit99( summe, zeile11+1, 5 );         // Gas Verbrauch Zaehler
         zeile11[6] = ',';
         edit99( summek, zeile11+7, 2 );
      }
      zeile11[11] = 'B';
      edit99( bsumme, zeile11+12, 5 );     // Gas Verbrauch Brauchwasser
      zeile11[17] = ',';
      edit99( bsummek, zeile11+18, 2 );

      set_cursor(0,4);
      lcd_string(zeile11);     // zeile 4
   }

   display_flag &= 0x80;       // reset alles bis auf 0x80
}



/*****************************************************************************
**  INT1  +12V fehlt, Gas Messdaten ins EEPROM sichern
**
**  ISC11  ISC10    Bedeutung
**      0      0    The low level of INT1 generates an interrupt request.
**      0      1    Any logical change on INT1 generates an interrupt request.
**      1      0    The falling edge of INT1 generates an interrupt request.
**      1      1    The rising edge of INT1 generates an interrupt request.
*/
ISR( INT1_vect )
{
   lcd_beleuchtung( 0 );          // lcd Beleuchtung ausschalten
   PORTB |= BIT3+BIT4;            // LEDs ausschalten
   LowPower |= BIT0;              // save eeprom anfordern, kritische Aktivitäten verhindern
}



/*****************************************************************************
**  INT1_FALLING_EDGE  0x02
*/
void int1_init( void )
{
   GICR  |= (1<<INT1);            // int1 interrupt zulassen
   MCUCR |= (1<<ISC11);           // int1 falling edge
   MCUCR &= ~(1<<ISC10);          // int1 falling edge
   DDRD  &= ~BIT3;                // (INT1) PD3 = Inputport
   PORTD &= ~BIT3;                // Input ohne internen Pullup Widerstand
}



/*****************************************************************************
**  Timer2 overflow interupt fuer 10 msec setzen
**
**  15.01.2010 li 6,144 MHz Quarz etwas zu langsam, statt 239 auf 238 gesetzt
*/
void timer2_init( void )
{
   TCCR2 = 0x8F   ;               // prescaler = 1024 setzen, CTC Modus und FOC2
   TCNT2 = 0;                     // reset
   OCR2  = 143;                   // compare match 144 * 1024 = 147456 Takte
   tim2_event_flag = 0;           // flag
   TIMSK |= (1 << OCIE2);         // enable compare match interrupt
}



/*****************************************************************************
*  8 Bit TIMER2 Compare Match
*  alle ca. 10 msek
*  1 / 12000000  * 117 * 1024 = 0,009984 msec
*/
ISR ( TIMER2_COMP_vect )
{
   tim2_event_flag++;         // timer2 flag
}



/*****************************************************************************
**  Message vom Master decodieren
**  DddmmjjwP    Datum: tag monat jahr wochentag
**  ThhmmSP      Zeit: stunde minute MESZ
**  SssP         Sekunde
**  <aaP         aa = Alarm Flag, P = Pruefziffer
**  CwwwwP       Temperaturwert + 1024 Aussen
**  GwwwwP       Temperaturwert + 1024 Gewaechshaus
**  RFnnnP       Regenmesser Ticks ( max. 999 je Stunde, dann reset)
**  
*/
void decode_message(void)
{
   int x;
   unsigned char p;
   char *s;
   
   if ( (us.tx_busy == 0 ) && tx2web)     // nachrichten spiegeln ?
   {   
      uart_putstring( (unsigned char *)receive_buffer );  // zum webserver 
   }
   
   s = receive_buffer+2;
   switch (  receive_buffer[ 1 ] )        // 2. Zeichen
   {
     case 'S':        // Sekunde += 1
      p = berechne_PZ( s, 2 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[2] )                    // check transfer
      {
         x = a_to_i( s, 2 );
         clock_s.ss = (unsigned char)x;
         uart_ok++;
      }
      else
         uarterr++;
      break;

     case 'T':        // Zeit
      p = berechne_PZ( s, 5 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[5] )                    // check transfer
      {
         x = a_to_i( s, 2 );
         clock_s.dhh = (unsigned char)x;
         x = a_to_i( s+2, 2 );
         clock_s.dmm = (unsigned char)x;
         x = a_to_i( s+4, 1 );
         clock_s.dmz = (unsigned char)x;
         uart_ok++;
      }
      else
         uarterr++;
      break;

     case 'D':        // Datum
      p = berechne_PZ( s, 7 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[7] )                    // check transfer
      {
         x = a_to_i( s, 2 );
         clock_s.day = (unsigned char)x;
         x = a_to_i( s+2, 2 );
         clock_s.mon = (unsigned char)x;
         x = a_to_i( s+4, 2 );
         clock_s.year = (unsigned char)x;
         x = a_to_i( s+6, 1 );
         clock_s.wday = (unsigned char)x;
         uart_ok++;
      }
      else
         uarterr++;
      break;

     case 'C':        // Celsius Aussen Temperatur +1024
      p = berechne_PZ( s, 4 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[4] )                    // check transfer
      {
         x = a_to_i( s, 4 );
         x -= 1024;
         s_dallas3.tempwert = x;          // Tempwert
         s_dallas3.mdata[0] = (unsigned char)x & 0xFF;
         s_dallas3.mdata[1] = (unsigned char)(x >> 8) & 0xFF;
         s_dallas3.kennung = 0x22 ;
         s_dallas3.flag |= DS_TEMP_DA ;
         uart_ok++;
      }
      else
         uarterr++;
      break;

     case 'G':        // Celsius Gewaechshaus Temperatur +1024
      p = berechne_PZ( s, 4 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[4] )                    // check transfer
      {
         x = a_to_i( s, 4 );
         x -= 1024;
         s_dallas4.tempwert = x;          // Tempwert
         s_dallas4.mdata[0] = (unsigned char)x & 0xFF;
         s_dallas4.mdata[1] = (unsigned char)(x >> 8) & 0xFF;
         s_dallas4.kennung = 0x22 ;
         s_dallas4.flag |= DS_TEMP_DA ;
         uart_ok++;
      }
      else
         uarterr++;
      break;
	
	                                       // Nachricht: sRnnnnnPe  
     case 'R':                            // Regenmenge ticks
      p = berechne_PZ( s, 5 ) + 0x30 ;    // Pruefzeichen
      if ( p == s[5] )                    // check transfer
      {
         regen = a_to_i( s, 5 );          //            
         uart_ok++;
      }
      else
         uarterr++;
      break;	

     case '<':        // Alarm
       break;
		 
	  case 'L':        // soLar Zeiten
       break;	 

     default:
      uarterr++;
      break;
   }
}



/*****************************************************************************
** 11.03.2010 li mit update jahr mon u. tag
** 02.04.2010 li Sicher nur einen Impuls fuer die Messwert Generierung erzeugen
*/
void upd_Sekunde(void)
{
   unsigned char mm;
   static unsigned char montab[] PROGMEM = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
                                            //   1   2  3  4  5  6  7  8  9 10 11 12
   prog_char *addr;
       
   clock_s.ss++;
   if (clock_s.ss == 60)
   {
      clock_s.ss = 0;
      clock_s.dmm++;
      if (clock_s.dmm == 60)
      {
         clock_s.dmm = 0;
         clock_s.dhh++;
         if (clock_s.dhh == 24)
         {
            clock_s.dhh = 0;
            addr = (prog_char*)&montab;
            addr+= clock_s.mon;
            mm = pgm_read_byte( addr );
            if ( clock_s.mon == 2 && clock_s.year % 4 == 0 )
               mm++;
            clock_s.day += 1;     // Tag + 1
            if ( clock_s.day > mm )
            {
               clock_s.mon += 1;
               if ( clock_s.mon > 12 )
               {
                  clock_s.mon = 1;
                  clock_s.year += 1;   // bis 2099 !!!
               }
            }
         }
      }
   }

#ifdef GMESS_TEST
      PORTA |= BIT0;                   // S0 Test Impuls 
      _delay_us( 50 );                 // S0 Test Impuls 
      PORTA &= ~BIT0;                  // S0 Test Impuls
#endif 
  
   if ( clock_s.dmz & 0x03 && sd_intimer == 0 )             // Zeitsignal da ??
   {
      if (clock_s.ss == 10 )           // Wenn Sekunde = 10
      {
#ifdef GMESS_TEST
         sg_todo(  1 ) ;               // Zaehler + 1
         sg_todo(  0 ) ;
#endif
         sd_intervall = 1;             // jede Minute
         sd_intimer = 1;
      }

      if (clock_s.ss == 20 )           // Wenn Sekunde = 20
      {
#ifdef GMESS_TEST
         if ( clock_s.dmm > 0 && (clock_s.dmm % 10) == 0 )  // file Wechsel
#else
         if ( clock_s.dmm == 59 && clock_s.dhh == 23 )      // neuer Tag, file Wechsel
#endif
         {
            sd_intervall = 2;       // neuer Tageswechsel um 23:59:20
            sd_intimer = 1;
         }         
      }
   } 
   if (clock_s.ss == 12 || clock_s.ss == 22 )           // Wenn Sekunde = 12 oder 22
      sd_intimer = 0;
}



/*****************************************************************************
**  Menu Zeile erzeugen und anzeigen
*/
void display_menu( unsigned char m1 )
{
   unsigned char i;

   for( i=0; i < 20 ; i++ )
   {
      zeile11[i] = ' ' ;
   }
   zeile11[20] = '\0' ;

   move1( mmxlen[0], m1  );      // move text1
   if ( password_ok )
   {
      if ( m1 >= 5 && m1 <= 11 )   // Counter Set
      {
         if ( gas0_kWh1 == 3 )
            zeile11[0] = 'B';
         if ( gas0_kWh1 == 2 )
            zeile11[0] = 'S';
         if ( gas0_kWh1 == 1 )
            zeile11[0] = 'G';
      }
   }
   if ( mm2 )
   {
      move2( mmxlen[1], mmxlen[0]+1, mm3, mmxs1 ); // move text2
   }
   set_cursor( 0, 3 );          // Hier in Zeile 3
   lcd_string( zeile11 );
}



/*****************************************************************************
**  Text nach zeile11 kopieren
*/
void move1( char l, char index  )
{
   unsigned char n,q;
   prog_char *addr;

   addr = (prog_char*)&m_t1;

   q = index * l;            // quell Position
   addr += q;
   for( n = 0; n < l ; n++)
   {
      zeile11[n] = pgm_read_byte( addr++ );
   }
}



/*****************************************************************************
**  Text2 nach zeile11 kopieren
**  9.3.2010 pgmspace
*/
void move2( char l, char pos, char index, unsigned char quelle )
{
   char n,q;
   prog_char *addr;

   addr = (prog_char*)&sm_t1;

   if ( quelle == 4 )
      addr = (prog_char*)&sm_t4p;
   else if ( quelle == 12 )
      addr = (prog_char*)&sm_t12;
   else if ( quelle == 14 )
      addr = (prog_char*)&sm_t14;
   else if ( quelle == 15 )
      addr = (prog_char*)&sm_t15;
   else if ( quelle == 16 )
      addr = (prog_char*)&sm_t16;

   q = index * l;            // quell Position
   addr += q;
   for( n = 0; n < l ; n++)
   {
      zeile11[pos+n] = pgm_read_byte( addr++ );
   }
}



/*****************************************************************************
**  Timer0 wird zum Zaehlen der SO Impulse benutzt
**  pgmspace
**  15.6.2010 Int nach 2 S0 Impulse
*/
void timer0_init( void )          // 26.05.2010
{
   TCCR0 = 0x0F  ;                // Input T0, rising Edge und CTC Mode
   TCNT0 = 0;                     // reset
   OCR0  = 1;                     // compare match 1 + 1 = 2
   TIMSK |= (1 << OCIE0);         // enable compare match interrupt
   DDRB  &=  ~BIT0;               // Input Port fuer (T0)
   PORTB |= BIT0;                 // Input mit internem Pullup Widerstand
}



/*****************************************************************************
*  8 Bit TIMER0 Compare Match
*  Int nach 2 Impulsen
*  1000 Impulse = 1 kWh
*/
ISR ( TIMER0_COMP_vect )
{
   kWh1000 += 2;
   if ( kWh1000 >= 1000 )
   {
      kWh += 1;
      kWh1000 -= 1000;
      if ( kWh > 99999 )
         kWh = 0;
   }
   display_flag |= 0x08 ;
}



/*****************************************************************************
*  clear alle variablen
*  Wenn Watchdog Timout, dann Zählerstände lassen
*/
void housekeeping( unsigned char reset)
{
   tim200cnt = 0;          // 1000 msek
   LowPower = 0;           // Input Power 12V down

   uart_trace = 0;
   display_power = 1; 
   uart_err_abs = 0;
   uartmproz=0;            // max Prozent Wert
   uartproz=0;             // current Prozent Wert
   uart_display_err=0;
   uarterr =0;             // error count
   uart_ok =0;             // erkannte Nachrichten
   uarttimer=0;

   receive_ind = 0;        // receive Index

   brauchwasser = 0;       // 1 = Brauchwasser load
   display_flag = 0;

   eeprom_read_ok = 0;

   al_cc[0]  = 0;
   al_cc[1]  = 0;
   al_cc[2]  = 0;
   al_cc[3]  = 0;

   if (  reset & 0x03 )   // power on / external
   {
      summe=0;
      summek =0;
      bsumme=0;
      bsummek =0;
      kWh=0;
      kWh1000=0;
   }

   clock_s.dmz = 0;
   
   filName[0] = 'd';
   filName[1] = 'a';
   filName[2] = 't';
   filName[3] = 'a';
   filName[4] = '0';
   filName[5] = '1';
   filName[6] = '.';
   filName[7] = 'b';
   filName[8] = 'l';
   filName[9] = 'a';
   filName[10] = '\0';

   sflag = 0;
   quitFlag = 0;

   lcd_timer = 1;          // lcd Timer
   menu_aktiv = 0;         // menu aktiv
   mtime = 0;              // menu timer, nach 10 Sekunden weg
   ptime = 0;              // power timer, nach 10 Sekunden weg
   menu1 = 0;              // mm3 sicherung text1
   mm3 = 0;                // s3: index auf texte
   mm2 = 0;                // s2: press counter

   pass_cnt = 0;
   password_ok = 0;

   ds1822_sn_sw = 0;
   ds1822_da_sw = 0;

   gas0_kWh1 = 0;          // set count switch  = G/S im Wechsel
   sd_sw = 0;
   sd_info = 1;            // fehlwert
   sd_init = 0;
   sd_timer = 0;
   sd_intervall = 0;       // wird 1 wenn Intervall erkannt
   sd_intimer = 0;         // blockiert doppelte Impulse
   sd_offset = 0;          // offset im Buffer
   sd_file_sek = 0;        // file Sektor  0 - 2047
   Clustervar = 0;         // SD Card
   Dir_Attrib = 0;         // SD Card
   Size = 0;               // SD Card
}



/*****************************************************************************
*  Temperaturen aufbereiten
*/
void send_temperatur(char kenn, int wert)                  // 31.8.2011 
{
   unsigned char n;
   char sende_buffer[10];
   
   sende_buffer[0] = 0x02;
   sende_buffer[1] = kenn;
   wert += 1024;                       // max. -55 * 16
   edit99( wert, sende_buffer+2, 4 );
   n = berechne_PZ( sende_buffer+2, 4 );
   sende_buffer[6] = n + 0x30 ;
   sende_buffer[7] = 0x03;
   sende_buffer[8] = 0x00;             // string Ende
   uart_putstring( (unsigned char *)sende_buffer );      
}



/*****************************************************************************
*  Counter 8 stellig
*/
void send_counter(char kenn, long wert)                  // 31.8.2011 
{
   unsigned char n;
   char sende_buffer[14];
   
   sende_buffer[0] = 0x02;
   sende_buffer[1] = kenn;
   edit99( wert, sende_buffer+2, 8 );
   n = berechne_PZ( sende_buffer+2, 8 );
   sende_buffer[10] = n + 0x30 ;
   sende_buffer[11] = 0x03;
   sende_buffer[12] = 0x00;             // string Ende
   uart_putstring( (unsigned char *)sende_buffer );      
}



/*****************************************************************************
*  Infos zum web server senden
*  Nicht alles auf einmal, schoen nacheinander 
*  wird je Sekunde aufgerufen  
*/
void sende_2_web_server( void )
{
   long x;
   
   if ( tx2web )        // 18.9.2011
   {
      if ( send_flag & SEND_M_V )
      {       
         send_temperatur('V', s_dallas0.tempwert);   // Vorlauf
         send_flag &= ~SEND_M_V;
      }
      else if ( send_flag & SEND_M_B )
      {       
         send_temperatur('B', s_dallas1.tempwert);   // Rücklauf
         send_flag &= ~SEND_M_B;
      }
      else if ( send_flag & SEND_M_W )
      {       
         send_temperatur('W', s_dallas2.tempwert);   // Warmwasser
         send_flag &= ~SEND_M_W;
      }
      else if ( send_flag & SEND_M_X )
      {       
         x = summe * 100;
         x += summek;
         send_counter('X',x);                        // Gas Zähler
         send_flag &= ~SEND_M_X;
      }
      else if ( send_flag & SEND_M_Y )
      {       
         x = bsumme * 100;
         x += bsummek;
         send_counter('Y',x);                        // GAS WarmWasser    
         send_flag &= ~SEND_M_Y;
      }
      else if ( send_flag & SEND_M_Z )
      {       
         x = kWh * 1000;
         x += kWh1000;
         send_counter('Z',x);                        // STROM
         send_flag &= ~SEND_M_Z;         
      }
   }   
}

