/****************************************************************************
* main.c
* Strahlungsmesser in c
*
* Mit dem Testboard (6,144MHz ) funktioniert es mit einer 4*20 Anzeige gut.
* Die beiden zusätzlichen Zeilen werden für eine Grafische Anzeige der
* Verteilung der Messwerte benutzt.
*
* Die Auswertung des Vorverstärker Eingangs erfolgt in einer Int routine
* die freilaufend gestartet wird.
* Daher hat die Auswertung im normalen Modus keine Nachteile für die Messung.
* Lediglich werden für die Übernahme der Messergebnisse die Unterbrechungen
* so kurz wie möglich ausgeschaltet.
*
*****************************************************************************
* Prozessor:  ATmega168 Testboard
* Frequenz:   6,144 MHz
*
* Interupt Belegung                       wo              warum
*--------------------------------------------------------------------------
* INT0          external Int0
* INT1          external Int1
* PCINT0        Pin Change 0
* PCINT1        Pin Change 1
* PCINT2        Pin Change 2              main.c          Abfrage drehimpulsgeber
* WDT           Watchdog Time-out
* TIMER2 COMPA  compare match A           main.c          10 msek
* TIMER2 COMPB  compare match B
* TIMER2 OVF    overflow
* TIMER1 CAPT   capture event
* TIMER1 COMPA  compare match A
* TIMER1 COMPB  compare match B                           
* TIMER1 OVF    overflow
* TIMER0 COMPA  compare match A
* TIMER0 COMPB  compare match B
* TIMER0 OVF    overflow
* SPI           Serial Transfer
* USART RX      RX complete               abc/avr_uart.c  receive Zeichen da
* USART UDRE    Data Empty                abc/avr_uart.c  transmit Zeichen buffer leer
* USART TX      TX complete               abc/avr_uart.c  Transmit fertig
* ADC           ADC conversion complete   main.c          Messung der Impulse
* EE_RDY        EE_PROM ready
* ANA_COMP      analogue comparator
* TWI           two wire Interface
* SPM_RDY       store pgm mem ready
**--------------------------------------------------------------------------
* Pin Belegung:
*                                      +-------------------+
* Reset/ISP       (PCINT14/RESET) PC6 -|1       XXX      28|- PC5 ((ADC5/SCL/PCINT13) Relais
*                                      |                   |
* USART Buchse      (PCINT16/RXD) PD0 -|2                27|- PC4 (ADC4/SDA/PCINT12)  vom Vorverstärker
*                                      |                   |
* USART Buchse      (PCINT17/TXD) PD1 -|3                26|- PC3 (ADC3/PCINT11)      LiPo Akku
*                                      |                   |
*                  (PCINT18/INT0) PD2 -|4                25|- PC2 (ADC2/PCINT10)
*                                      |                   |
* LED         (PCINT19/OC2B/INT1) PD3 -|5                24|- PC1 (ADC1/PCINT9)
*                                      |                   |
* Speaker        (PCINT20/XCK/T0) PD4 -|6                23|- PC0 (ADC0/PCINT8)
*                                      |                   |
*                                 VCC -|7                22|- GND
*                                      |                   |
*                                 GND -|8   ATmega168    21|- AREF
*                                      |                   |
* 6,144 MHz  (PCINT6/XTAL1/TOSC1) PB6 -|9                20|- AVCC
*                                      |                   |
* 6,144 MHz  (PCINT7/XTAL2/TOSC2) PB7 -|10               19|- PB5 (SCK/PCINT5)        ISP / LCD_CP
*                                      |                   |
* S2 rechts     (PCINT21/OC0B/T1) PD5 -|11               18|- PB4 (MISO/PCINT4)       ISP / LCD_DA
*                                      |                   |
* S2 links    (PCINT22/OC0A/AIN0) PD6 -|12               17|- PB3 (MOSI/OC2A/PCINT3)  ISP / LCD_EN
*                                      |                   |
* S1 Taster        (PCINT23/AIN1) PD7 -|13               16|- PB2 (SS/OC1B/PCINT2)    LCD_LED Backlight
*                                      |                   |
*              (PCINT0/CLKO/ICP1) PB0 -|14               15|- PB1 (OC1A/PCINT1)
*                                      +-------------------+
*--------------------------------------------------------------------------
*
* AVR GCC Compiler
*
* 10.09.2013 li Wenn am Drehimpulsgeber schnell gedreht wird, menu in größeren steps
* 11.09.2013 li V3 Verbesserung der Drehimpulsgeber Abfrage
* 20.09.2013 li V5 Ohne Mittenmessung des Akkus
* 28.09.2013 li V7 Beleuchtung ohne PWM
* 29.09.2013 li V8 Trace im menu dazu
* 30.09.2013 li V10 Neue Klasseneinteilung, (11 * 13) + (8 * 14) + 1 = 256
* 01.10.2013 li V11 read_eeprom, default korr.
* 02.10.2013 li V12 korrektur
* 03.10.2013 li V13 Main loop erweitert um clear_cnt
* 03.10.2013 li V14 Korr tim2_event_flag wenn clear_counter, flag7 ins eeprom
* 13.10.2013 li V15 alle 60 Minuten check Akku 
* 14.10.2013 li V16 Zeile 2 verbessert
* 01.11.2013 li V17 Power aus wenn batterie zu niedrig, bistabile Relais Control  
* -------------------------------------------------------------------------------------------
*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <math.h>
#include "config.h"
#include "../abc/basis.h"
#include "../abc/lcd.h"
#include "../abc/avr_uart.h"


uint8_t eeByte[512] EEMEM = { 0,                               // write kennung
                             '1','2','3',                      // Schwellwert
                             '1',                              // Ton Signal
                             '1',                              // USART / RS-232
                             '1',                              // Flag7 (backlight, trace_pin, reserve)
                             'p'                               // Prüfzeichen
                           };

char zeile[ LCD_CHARS + 1 ];


                            //012345678     menu Strahlungsmesser
static char m_t1[] PROGMEM = "retur V17"   // 0
                             "Backlight"   // 1
                             "Tonsignal"   // 2   
                             "RS-232 .."   // 3   serielles Interface
                             "restart  "   // 4
                             "Schwellw."   // 5   Schwellwert
                             "Basiswert"   // 6
                             "Trace PIN"   // 7
                             "Batterie "   // 8
                             ;


                             //012      sub menu diverses
static char sm_t1[] PROGMEM = "ret"     // 0
                              "aus"     // 1
                              "ein";    // 2


                             //012     submenu threshold
static char sm_t5[] PROGMEM = "ret"    // 0
                              "  1"    // 1
                              "  2"    // 2
                              "  3"    // 3
                              "  4"    // 4
                              "  5"    // 5
                              "  6"    // 6
                              "  7"    // 7
                              "  8"    // 8
                              "  9"    // 9
                              " 10"    // 10
                              " 11"    // 11
                              " 12"    // 12
                              " 13"    // 13
                              " 14"    // 14
                              " 15"    // 15
                              " 16"    // 16
                              " 17"    // 17
                              " 18"    // 18
                              " 19"    // 19
                              " 20"    // 20
                              " 21"    // 21
                              " 22"    // 22
                              " 23"    // 23
                              " 24"    // 24
                              " 25"    // 25
                              " 26"    // 26
                              " 27"    // 27
                              " 28"    // 28
                              " 29"    // 29
                              " 30"    // 30
                              " 31"    // 31
                              " 32"    // 32
                              " 33"    // 33
                              " 34"    // 34
                              " 35"    // 35
                              " 36"    // 36
                              " 37"    // 37
                              " 38"    // 38
                              " 39"    // 39
                              " 40"    // 40
                              " 41"    // 41
                              " 42"    // 42
                              " 43"    // 43
                              " 44"    // 44
                              " 45"    // 45
                              " 46"    // 46
                              " 47"    // 47
                              " 48"    // 48
                              " 49"    // 49
                              " 50"    // 50
                              " 51"    // 51
                              " 52"    // 52
                              " 53"    // 53
                              " 54"    // 54
                              " 55"    // 55
                              " 56"    // 56
                              " 57"    // 57
                              " 58"    // 58
                              " 59"    // 59
                              " 60"    // 60
                              " 61"    // 61
                              " 62"    // 62
                              " 63"    // 63
                              " 64"    // 64
                              " 65"    // 65
                              " 66"    // 66
                              " 67"    // 67
                              " 68"    // 68
                              " 69"    // 69
                              " 70"    // 70
                              " 71"    // 71
                              " 72"    // 72
                              " 73"    // 73
                              " 74"    // 74
                              " 75"    // 75
                              " 76"    // 76
                              " 77"    // 77
                              " 78"    // 78
                              " 79"    // 79
                              " 80"    // 80
                              " 81"    // 81
                              " 82"    // 82
                              " 83"    // 83
                              " 84"    // 84
                              " 85"    // 85
                              " 86"    // 86
                              " 87"    // 87
                              " 88"    // 88
                              " 89"    // 89
                              " 90"    // 90
                              " 91"    // 91
                              " 92"    // 92
                              " 93"    // 93
                              " 94"    // 94
                              " 95"    // 95
                              " 96"    // 96
                              " 97"    // 97
                              " 98"    // 98
                              " 99"    // 99
                              "100"    // 100
                              ;

                                  // Laengen Definitionen
#define LEN_M_T1   9
#define LEN_SM_T1  3
#define LEN_SM_T6  3
#define LEN_SM_T5  3
                                  // Anzahl der Eintraege -1
#define ENT_M_T1   8              // basis menu
#define ENT_SM_T1  2
#define ENT_SM_T6  2
#define ENT_SM_T5  100            // Schwellwerte
                                  // Index auf den Subtext
#define INDEX_SM_T1  1
#define INDEX_SM_T5  2
#define INDEX_SM_T6  3

unsigned char menu_aktiv = 0;     // menu aktiv und menu_timer
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 = 1;          // index auf submenu texte

                                  // flag fuer PIN change int
#define SW2_DA  BIT0              // .... ...1
#define SW3_DA  BIT1              // .... ..1.
volatile unsigned char pc2_flag = 0;

volatile unsigned char usart_on  = 0;

volatile unsigned long matrix[20];    // für die Int-Routine 

float matrix_2[20];                   // Berechnungen in der Main-loop

// Tabelle: Einteilung der Messwerte in 20 Spalten
// Spalte 20 = maximaler Level 255 und größer 
// verbleiben 255 Werte, 255 / 19 = 13,42
// deshalb 11*13 und 8*14 Werte
//                                                                    //  10  11  12  13  14
static unsigned char ttab[256] = { 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,         // 13   00-12
                                   1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,         // 13   13-25
                                   2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,         // 13   26-38
                                   3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,         // 13   39-51
                                   4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,         // 13   52-64
                                   5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,         // 13   65-77
                                   6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,         // 13   78-90
                                   7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,         // 13   91-103
                                   8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,         // 13  104-116
                                   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,         // 13  117-129
                                  10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,         // 13  130-142
                                  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,     // 14  143-156
                                  12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,     // 14  157-170
                                  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,     // 14  171-184
                                  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,     // 14  185-198
                                  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,     // 14  199-212
                                  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,     // 14  213-226
                                  17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,     // 14  227-240
                                  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,     // 14  241-254
                                  19                                                          // 1   255
                              };


// Definition eigene Grafik Zeichen (8 Zeichen)
unsigned char ctab[64] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F,
                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F,
                                   0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F,
                                   0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
                                   0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
                                   0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };

                  // Zeichentabelle je Zeile
unsigned char char_tab1[25] PROGMEM = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,              // obere Zeile
                                        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                        0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x1F };

unsigned char char_tab2[25] PROGMEM = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,              // Mittlere Zeile
                                        0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                        0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1F, 0x1F };

unsigned char char_tab3[25] PROGMEM = { 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,              // untere Zeile
                                        0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1F,
                                        0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1F, 0x1F };




unsigned char tim0cnt = 0;                  // alle  10 msek trigger
unsigned char volatile tim2_event_flag;     // 10 msec Trigger


   // ----------------------------------------------
   // INDEX test_switch_x()    0
   // ----------------------------------------------
unsigned char al_cc[1]  = {    0 };
unsigned char al_bit[1] = { BIT7 };
   //                         set Sw

                                            // externe structuren
extern S_UART    volatile us;               // siehe ../../abc/avr_uart.h
extern S_LCD_ANZ volatile lcdanz_s;         // siehe ../../abc/lcd.h

#define BATTERIE   BIT2                     // .... .1.. Akku Power 
#define TRACE_PIN  BIT1                     // .... ..1.
#define BACKLIGHT  BIT0                     // .... ...1 
unsigned char flag7 = 0;                    // flag7  

int Um;                                     // mittlerer Signalwert 
volatile int U0;                            // realer Schwellwert
volatile unsigned char threshold;
volatile unsigned char impuls = 0;
volatile unsigned long counter = 0;         // PIN Impuls Counter
volatile int max;
volatile unsigned char trace_value=0;

#define ZERO_COUNTER   BIT0
#define ZERO_CHECKAKKU BIT1
unsigned char zero_flag = 1;                // 

unsigned long lw;                           // Counter Mittelwert je Minute * 1000

unsigned char sekunde = 0;
unsigned int  minute = 0;
unsigned char mean_flag = 0;
volatile unsigned char ton_signal = 1;      // Ton ein oder ausschalten
                                            // prototypen
void timer2_init( void );
void start_adc( unsigned char padr );
void init_adc(unsigned char padr);          // start Messung
void init_adc_Mean( void );                 // Mean Messung und Batterie Check
void display_x( void );
void clear( char *);
unsigned char test_switch_D( unsigned char i );
void edit99b( unsigned long wert, char *ziel, unsigned char stellen );

void display_menu(unsigned char m1);
void move2( unsigned char l, unsigned char pos, unsigned char index, unsigned char quelle );
void move1( unsigned char l, unsigned char index  );
void s1_todo(void);
void s23_todo( unsigned char, unsigned char );
void menu_U_sw2( void );

void eeprom_read( void );
void save_eeprom( void );
int search_pos( unsigned char *pken, unsigned char write );

void shut_down( long v1 );

/*****************************************************************************
*  Main
*/
int main(void)
{
   int ic;
   long U;
   int n;
   long v1;
   unsigned char aktion;
   unsigned char speed;
   unsigned char rotation_time = 0;
                                               // static schutz
   PORTD |=  (BIT2+BIT3+BIT4+BIT5+BIT6+BIT7);  // mit pull up Widerstand
   PORTB |=  (BIT0+BIT1+BIT2+BIT3+BIT4+BIT5);  // mit pull up Widerstand
   PORTC |=  (BIT0+BIT1+BIT2);                 // mit pull up Widerstand
   
   PORTC &= ~BIT5;                             // auf 0 
   DDRC  |= BIT5;                              // 1.11.2013 Relais output  

   SPEAKER_DDR  |= SPEAKER_BIT;                // set output
   SPEAKER_OFF;

   LED_DDR |= LED_BIT;                         // Output
   LED_OFF;                                    // LED
   
   flag7 |= BATTERIE;                          // Power Indikator 

   lcd_init(0);                                // Initialize LC-Display
   lcd_dataWrite((prog_char *)&ctab, 64 );     // spezial Zeichen setzen

   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   // ++++++++++++++++++++++++++++++++ Main LOOP ++++++++++++++++++++++++++++
   for(;;)
   {
      if ( zero_flag )            // clear_cnt? ( via menu oder first )
      {
         cli();                   // disable int

         init_adc_Mean();         // ADC free running aus
                                  // Akku komplett messen
         v1 = 0;
         for ( n=0; n < 16; n++)
         {
            start_adc( ADC_BATTERIE_PORT );
            do
            {
            } while ( ADCSRA & (1 << ADSC));   // loop bis Wandlung fertig
            v1 += ADC;            // Werte addieren
         }
         v1 /= 16;
         v1 *= 990;               // 5V * 100 * 2 da über Spannungsteiler - 1%
         v1 /= 1024;
         
         if ( v1 < 735 )          // Spannung kleiner 7,35 Volt, power off
         {
            shut_down( v1 );
         }
         
         if ( (zero_flag & ZERO_CHECKAKKU) == 0 )            
         { 
            eeprom_read();           // threshold usw. laden
            lcd_beleuchtung( flag7 & BACKLIGHT );

            U = 0;                   // Basis level ermitteln
            for ( n=0; n < 1024; n++)
            {
               start_adc( ADC_STRAHLUNG_PORT );
               do
               {
               } while ( ADCSRA & (1 << ADSC));   // loop bis Wandlung fertig
               U += ADC;             // Werte addieren
            }
                                     // 5V als Bezug ergibt eine Auflösung von 4,88mV
            U /= 1024;               // Mittelwert ruhe
            Um = (int)U;             // merken
            U0 = Um + threshold;         // minimaler Pulse erkennungs threshold
            max = U0;

            clear( zeile );
            
            zeile[0] = 'A';
            zeile[1] = 'k';
            zeile[2] = 'k';
            zeile[3] = 'u';
            zeile[4] = ':';

            edit99( v1, zeile+7,3);  // Akku Spannung anzeigen: n,nn V
            zeile[6] = zeile[7];
            zeile[7] = ',';
            zeile[11] = 'V';

            set_cursor( 0, 1 );
            lcd_string( zeile );

            clear( zeile );
            set_cursor( 0, 2 );
            lcd_string( zeile );
            set_cursor( 0, 3 );
            lcd_string( zeile );
            set_cursor( 0, 4 );
            zeile[1] = 0x08;         // wie x00
            zeile[2] = 0x01;
            zeile[3] = 0x02;
            zeile[4] = 0x03;
            zeile[5] = 0x04;
            zeile[6] = 0x05;
            zeile[7] = 0x06;
            zeile[8] = 0x07;
            lcd_string( zeile );

            _delay_ms( 20000 );      // Batterie Spannung für 20 Sekunden anzeigen
                                     // PIN CHANGE INT fuer S2 und S3
            PCICR |= (1<<PCIE2 );    // PCINT2 erlauben
            PCMSK2 |= BIT5 + BIT6;   // PORT PD5 und PD6

            timer2_init();           // 10 msec Int
            uart_init();             //
           
            mean_flag = 0;

            trace_value = 0;
            counter = 0;

            for ( n=0; n < 20; n++)  // clear matrix
               matrix[n] = 0;
            
            sekunde = 0;
            minute  = 0;
            tim0cnt = 0;            
         }
         
         init_adc( ADC_STRAHLUNG_PORT );   // Messung Starten als free running adc
         _delay_us( 200 );
                                  // Ordentlicher Start
         zero_flag = 0;
         tim2_event_flag = 0;     // clear 10 msek flag    
         sei();                   // enable int   
         
      }                           // Ende zero_flag

      if ( tim2_event_flag )      // 10 msek int ******************
      {
         tim0cnt += tim2_event_flag;  // merke ticks
         tim2_event_flag = 0;

         if ( tim0cnt >= 100  )       // ticks >= 100  = 1000 msek ??
         {
            tim0cnt = 0;
            sekunde++;

            if ( menu_aktiv )
            {
               menu_aktiv--;
               if ( menu_aktiv == 0 )
               {
                  mm3 = 0;
                  mm2 = 0;
                  lcd_beleuchtung( flag7 & BACKLIGHT );
               }
            }
            display_x();
         }

         if ( test_switch_D(0) == 1 )  // ++ Set Switch +++
            s1_todo();
                                   // Drehimpulsgeber Ticks
                                   // Wenn schnell gedreht wird
         if ( pc2_flag & SW2_DA)
         {
            pc2_flag &= ~SW2_DA;
            if ( rotation_time )
            {
               if ( rotation_time >= 5 )
                  speed = 5;
               else
                  speed = rotation_time;
            }
            else
               speed = 1;
            rotation_time = 15;
            s23_todo( 1, speed );
         }

         if ( pc2_flag & SW3_DA)
         {
            pc2_flag &= ~SW3_DA;
            if ( rotation_time )
            {
               if ( rotation_time >= 5 )
                  speed = 5;
               else
                  speed = rotation_time;
            }
            else
               speed = 1;
            rotation_time = 15;
            s23_todo( 0, speed );
         }

         if ( rotation_time )     // Drehimpulsgeber Umdrehungszeit
            rotation_time--;
      }                           // ende timer 10msek int *******************


                                  // ++++++++++++++++ UART Abfrage auf Zeichen empfangen ++++++
      if ( usart_on )             // USART Empfang abfragen ?
      {
         ic = uart_getc();        // Schwellwert
         if ( ic != -1 )          // ungleich -1: Zeichen da
         {
            aktion = (unsigned char)ic & 0xFF ;
            if ( aktion < 101 )
            {
               threshold = aktion;
               U0 = Um + threshold;   // minimaler Pulse erkennungs level
               max = U0;
            }
            else
            {
               aktion -= 100;
               eeprom_write_byte( &eeByte[ 0 ], aktion );
            }
         }
      }
   }   // MAIN LOOP
}



/*****************************************************************************
* Akku Spannung zu niedrig oder Power off via menu 
*/
void shut_down( long v1 )
{
   long dtime=1;
   
   clear( zeile );
   
   if ( v1 == 0 )               // power off über menu ?  
   {
      zeile[0] = 'P';
      zeile[1] = 'o';
      zeile[2] = 'w';
      zeile[3] = 'e';
      zeile[4] = 'r';
      zeile[5] = ' ';
      zeile[6] = 'o';
      zeile[7] = 'f';
      zeile[8] = 'f';
      dtime = 2000;             // 2 sekunden delay  
   }
   else
   {
      zeile[0] = 'A';
      zeile[1] = 'k';
      zeile[2] = 'k';
      zeile[3] = 'u';
      zeile[4] = ':';

      edit99( v1, zeile+7, 3);  // Akku Spannung anzeigen: n,nn V
      zeile[6] = zeile[7];
      zeile[7] = ',';
      zeile[11] = 'V';
      dtime = 60000;
   }
      
   set_cursor( 0, 1 );
   lcd_string( zeile );
   lcd_string( zeile );
   lcd_string( zeile );
   lcd_string( zeile );
   _delay_ms( dtime );      // delay
   
   flag7 &= ~BATTERIE;      // nur so
   PORTC |= BIT5;           // Power off;
   
   _delay_ms( 60000 );      // 1 Minute delay   
}



/*****************************************************************************
* Suche eeprom position
* write=1 : Position zum schreiben
* write=0 : letzte write Position
* 27.09.2013 li EEPROM_SIZE und EEPROM_ENTRY benutzt
*/
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 < EEPROM_SIZE; pos += EEPROM_ENTRY )
   {
      curr = eeprom_read_byte( &eeByte[pos]);
      if ( curr == 0xFF || curr != start0 )      // wechsel oder first
         break;
   }

   if ( write )              // wenn write dann neue Position
   {
      if ( pos == EEPROM_SIZE )      // loop ende ?
      {
         kennung ^= 0x55;    // change kennung  0x33 / 0x66
         pos = 0;            // restart bei 0
      }
      *pken = kennung;       // Übergabe an aufrufer
      return pos;
   }
   else                      // == read
   {
      pos -= EEPROM_ENTRY;   // letzte Position
      return pos;
   }
}



/*****************************************************************************
** save Einstellungen ins eeprom
*/
void save_eeprom( void )
{
   int pos;
   unsigned char kennung,n;
   char zeile11[EEPROM_ENTRY-1];

   pos = search_pos( &kennung, 1 );   // write pos holen
   eeprom_write_byte( &eeByte[ pos ], kennung );

   edit99( threshold, zeile11, 3);
   zeile11[3] = ton_signal + 0x30 ;
   zeile11[4] = usart_on  + 0x30 ;
   zeile11[5] = flag7 + 0x30 ;

   zeile11[EEPROM_ENTRY-2] = berechne_PZ( zeile11, EEPROM_ENTRY-2) + 0x30 ;

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



/*****************************************************************************
** read eeprom, Einstellungen
*/
void eeprom_read( void )
{
   unsigned char n,p2;
   int pos;
   unsigned char kennung;                      // not used da read
   char zeile11[EEPROM_ENTRY-1];

   pos = search_pos( &kennung, 0 );

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

   p2  = berechne_PZ( zeile11, EEPROM_ENTRY-2) + 0x30 ;
   if ( zeile11[EEPROM_ENTRY-2] == p2)          // pruefzahl OK ?
   {
      threshold = a_to_i( zeile11, 3);
      if ( threshold < 8 )
         threshold = 10;
      ton_signal = zeile11[3] & 0x01 ;
      usart_on   = zeile11[4] & 0x01 ;
      flag7 = zeile11[5] & 0x07 ;               // derzeit für 3 Bits vorbereitet    
   }
   else
   {
      threshold = 11;
      ton_signal = 1;
      usart_on = 0;
      flag7 = BACKLIGHT + TRACE_PIN;
   }
}



/*****************************************************************************
** S23 Menu
*/
void s23_todo( unsigned char plus, unsigned char adv )
{
   lcd_beleuchtung( 1 );            // Beleuchtung ein
   menu_aktiv = 15;                 // 15 Sekunden reichen

   if ( mm3max[1] != ENT_SM_T5 )    // Beschleunigung nur im submenu 5
      adv = 1;

   if ( plus )
      mm3 += adv;
   else
      mm3 -= adv;

   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 = INDEX_SM_T1;
   }

   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 5:
         mmxlen[1] = LEN_SM_T5;
         mm3max[1] = ENT_SM_T5;
         mmxs1 = INDEX_SM_T5;
         break;

        case 6:
         mmxlen[1] = LEN_SM_T6;
         mm3max[1] = ENT_SM_T6;
         mmxs1 = INDEX_SM_T6;
         break;

        default:
         mmxlen[1] = LEN_SM_T1;
         mm3max[1] = ENT_SM_T1;
         mmxs1 = INDEX_SM_T1;         //  sm_t1;
         break;
      }
      display_menu( mm3 );          // text1
   }
   else
      display_menu( menu1 );        // text 1 und text2
}



/*****************************************************************************
** S1 = Set Switch
*/
void s1_todo( void )
{      
   lcd_beleuchtung( 1 );         // 10.9.2009 Beleuchtung ein

   if ( menu_aktiv )             // s3 da gewesen  ??
   {
      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;       // break;
           case 1: mm3 = (flag7 & BACKLIGHT) + 1; break;  // licht
           case 2: mm3 = ton_signal+1; break;          // Speaker
           case 3: mm3 = usart_on+1; break;            // USART
           case 4: mm3 = zero_flag+1; break;           // clear counter
           case 5: mm3 = threshold; break;             // Schwellwert
           case 6: mm3 = 1; break;                     // basis level
           
           case 7:                                     // Trace   
            if ( flag7 & TRACE_PIN)
               mm3 = 2;
            else
               mm3 = 1;             
            break;          
           
           case 8:                                     // Batterie power 
            if ( flag7 & BATTERIE) 
               mm3 = 2;
            else
               mm3 = 1;             
            break;                      
         }

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



/*****************************************************************************
** 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;

   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:                    // display backlight  
            if ( todo )
               flag7 |= BACKLIGHT;
            else
                flag7 &= ~BACKLIGHT;             
            lcd_beleuchtung( flag7 & BACKLIGHT );
            save_eeprom();
            break;  

           case 2:                    // Speaker
            ton_signal = todo;
            save_eeprom();
            break;        

           case 3:                    // USART ON/OFF
            usart_on = todo;
            if ( usart_on )
               uart_init();
            else
               UCSR0B = 0;            // disable usart
            save_eeprom();
            break;

           case 4:                    // clear counter und Akku Spannungsanzeige 
            zero_flag = todo;
            break;

           case 5:                    // threshold
            threshold = todo+1;
            U0 = Um + threshold;      // realer Schwellwert
            max = U0;
            save_eeprom();
            break;          

           case 7:                    // 4.10.13 flag7 ins eeprom
            if ( todo )
               flag7 |= TRACE_PIN;
            else
               flag7 &= ~TRACE_PIN;
             save_eeprom();                                       
            break;
            
           case 8:                    // Power off gefordert
            if ( todo == 0 )
               shut_down(0);                                                    
            break; 

           default:
            break;
         }
         menu_aktiv = 0;
         mm3 = 0;
         mm2 = 0;
      }
   }
   if ( rc )
   {
      menu_aktiv=0;
      mm3 = 0;
      mm2 = 0;
      lcd_beleuchtung( flag7 & BACKLIGHT );
   }
}



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

   move1( mmxlen[0], m1  );      // move text1

   if ( mm2 )
   {
      move2( mmxlen[1], mmxlen[0]+1, mm3, mmxs1 ); // move text2
   }
   set_cursor( 0, 1 );          // Hier in Zeile 3
   lcd_string( zeile );
}



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

   addr = (prog_char*)&m_t1;   // DCF77 Menu
   q = index * l;              // quell Position
   addr += q;

   for( n = 0; n < l ; n++)
   {
      zeile[n] = pgm_read_byte( addr++ );
   }
}



/*****************************************************************************
**  Text2 nach zeile kopieren
**  Sonderfall Basiswert anzeige
*/
void move2( unsigned char l, unsigned char pos, unsigned char index, unsigned char quelle )
{
   unsigned char n;
   unsigned int  q;
   prog_char *addr;

   addr = (prog_char*)&sm_t1;

   switch ( quelle )
   {
     case INDEX_SM_T5:
      addr = (prog_char*)&sm_t5;
      break;

     case INDEX_SM_T6:
      edit99b( Um, zeile+pos+4, 3 );       // Basiswert anzeigen
      break;
   }

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



/*****************************************************************************
**  PIN CHANGE INT
**  negative Impulse auswerten
**  22.09.2013 li Bit6 und 5 vertauscht
*/
ISR ( PCINT2_vect )
{
   if ( (PIND & BIT6) == 0 )    // S2 auf 0 ?
       pc2_flag |= SW2_DA;       // main aktion starten

   if ( (PIND & BIT5) == 0 )    // S3 auf 0 ?
      pc2_flag |= SW3_DA;       // main aktion starten
}



/*****************************************************************************
** Aufbereitung als Dezimalzahl mit fuehrenden blanks
** stellen von 2 bis 11, nur positive Zahlen
*/
void edit99b( unsigned long wert, char *ziel, unsigned char stellen )
{
   unsigned char n;
   unsigned char fb = 0;

   if ( wert < 0 )
   {
      ziel[0] = 'N';
   }
   else
   {
      if ( stellen > 1 && stellen < 11 )
      {
         for( n = stellen-1; n > 0; n-- )

         {
            if ( fb )
               ziel[n] = ' ';
            else
            {
               ziel[n] = (wert % 10) + 0x30 ;
               wert /= 10 ;
               if ( wert == 0)
                 fb = 1;
            }
         }
         if ( wert < 10 )
         {
            if ( wert == 0)
               ziel[0] = ' ';
            else
               ziel[0] = wert + 0x30 ;
         }
         else
            ziel[0] = 'F';
      }
      else
         ziel[0] = 'E';
   }
}



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

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



/*****************************************************************************
** Display
** Zeilen 2 bis 4 : Grafische Anzeige des Spektrums in vereinfachter
** Form mit 20 Balken von maximal 24 Pixeln. Dazu wurden Sonderzeichen definiert.
** 
**         01234567890123456789
** zeile1  mmmm:ss C:nnnnnnnnn     minute:sekunde   C: Counter, M: Mean Count je Minute  / wechsel alle 10 Sekunden
** zeile2  x               ttt     ttt = wenn trace PIN, letztes Signal Level
** zeile3  xx                      xx   
** zeile4  xxx___                  xx  grafische Anzeige des Signalspectrums
**         ||||||||||||||||||||-level 255  siehe Definitionen in der ttab[256]
**         3333333333344444444-4=14 level-werte, von 143-156 usw. bis 241-254 
**         |-3=13 levelwerte, von 0-12, 13-25, usw. bis 130-142     
*/
void display_x( void)
{
   unsigned char n;
   unsigned char pos;
   float mean;
   long current_cnt;
   float maxWert, rest ;
   prog_char *addr;
   
   cli();                         // disable Ints
   current_cnt = counter;
   sei();                         // enable int

   if ( sekunde > 59 )
   {
      sekunde = 0;
      minute++;      
      mean = current_cnt;
      mean /= minute;
      mean *= 1000;               // 3 stellen nach dem komma
      lw = (long)mean;            // merke mittelwert je Minute
      mean_flag = 1;
      
      if ( (minute % 60) == 0 ) 
         zero_flag |= ZERO_CHECKAKKU ;  // check alle Stunde Akku Spannung
   }

   if ( menu_aktiv == 0  )        // wenn menu dann zeile 1 ausblenden
   {
      clear( zeile );

      if ( minute < 100 )         // Minuten 2 Stellig ?
      {
         edit99b( minute, zeile, 2 );        // minuten
         edit99( sekunde, zeile+3, 2 );      // sekunde
         zeile[2] = ':';
      }
      else                        // 4 Stellig anzeigen
      {
         edit99b( minute, zeile, 4 );        // minuten
         edit99( sekunde, zeile+5, 2 );      // sekunde
         zeile[4] = ':';
      }

      n = sekunde / 10;
      if ( mean_flag && ( n == 0 || n == 2 || n == 4 ))
      {
         zeile[8] = 'M';
         zeile[9] = ':';
         edit99b( lw, zeile+10, 9 );
                                  // letze 3 stellen im 1 nach rechts
         zeile[19] = zeile[18];
         n = zeile[17];
         if ( n == ' ' )
            n = '0';
         zeile[18] = n;

         n = zeile[16];
         if ( n == ' ' )
            n = '0';
         zeile[17] = n;

         zeile[16] = ',';
         if ( zeile[15] == ' ' )
            zeile[15] = '0';
      }
      else
      {
         zeile[8] = 'C';
         zeile[9] = ':';
         edit99b( current_cnt, zeile+10, 9 );  // Counter
      }
      set_cursor( 0, 1 );
      lcd_string( zeile );
   }
                                  // Grafik Ausgabe
   maxWert = 0.0;
                                  // matrix lesen und maximalwert sichern
   for( n=0; n < 20; n++)
   {
      cli();                      // disable Ints
      mean = matrix[n];
      sei();                      // enable int
      matrix_2[n] = mean;
      if ( maxWert < mean )
         maxWert = mean;
   }
                                  // werte normieren und aufrunden.
                                  // dadurch bleiben auch kleine Werte sichtbar.
   for( n=0; n < 20; n++)
   {
      matrix_2[n] *= 24.0;
      matrix_2[n] /= maxWert;     // alles an den Maxwert anpassen

      rest = fmod( matrix_2[n] , 1.0 );
      if ( rest > 0.5 )
         matrix_2[n] += 0.5 ;

      if ( matrix_2[n] > 24.0 )
         matrix_2[n] = 24.0 ; // Limit
   }
                                  // Aufbereitung der 3 Grafik Zeilen
                                  // selbst definierte Zeichen
   set_cursor( 0, 2 );
   addr = (prog_char*)&char_tab1; // Darstellung obere Grafik Zeile
   for( n=0; n < 20; n++)
   {
      pos = (unsigned char)matrix_2[n];
      zeile[n] = pgm_read_byte( addr + pos);
   }
   if ( flag7 & TRACE_PIN )       // trace last PIN Impuls level
   {
      edit99b( trace_value, zeile+16, 3 );
   }
   lcd_string( zeile );
   

   set_cursor( 0, 3 );
   addr = (prog_char*)&char_tab2; // Darstellung obere Grafik Zeile
   for( n=0; n < 20; n++)
   {
      pos = (unsigned char)matrix_2[n];
      zeile[n] = pgm_read_byte( addr + pos);
   }
   lcd_string( zeile );

   set_cursor( 0, 4 );
   addr = (prog_char*)&char_tab3; // Darstellung untere Grafik Zeile
   for( n=0; n < 20; n++)
   {
      pos = (unsigned char)matrix_2[n];
      if ( pos == 0 )             // kleiner als 0,5
      {
         if ( matrix_2[n] > 0.0 ) // was da ??
            zeile[n] = 0x08;      // zeichen 0x00 bzw. 0x08 = 3 Punkte
         else
            zeile[n] = ' ';       // echte null
      }
      else
         zeile[n] = pgm_read_byte( addr + pos);
   }
   lcd_string( zeile );
}



/*****************************************************************************
**  Timer2 overflow interupt fuer 10 msec setzen
**
*/
void timer2_init( void )
{
   TCCR2A = (1 << WGM21 );         // CTC Modus
   TCNT2 = 0;                      // Clear

#if F_CPU == 6144000
   TCCR2B = (1 << CS21) + (1 << CS22) ;               // prescaler = 256
   OCR2A = 239;                    // compare match 240 * 256 = 61440 Takte
#endif

#if F_CPU == 8000000
   TCCR2B = (1 << CS20) + (1 << CS21) + (1 << CS22) ; // prescaler = 1024
   OCR2A = 77;                     // compare match 78 * 1024 = 79872 Takte
#endif

#if F_CPU == 14745600
   TCCR2B = (1 << CS20) + (1 << CS21) + (1 << CS22) ; // prescaler = 1024
   OCR2A = 143;                    // compare match 144 * 1024 = 147456 Takte
#endif

   tim2_event_flag = 0;            // flag
   TIMSK2 |= (1 << OCIE2A);        // enable compare match interrupt
}



/*****************************************************************************
*  8 Bit TIMER2 Compare Match
*  alle ca. 10 msek
*/
ISR ( TIMER2_COMPA_vect )
{
   tim2_event_flag++;             // timer2 flag
}



/*****************************************************************************
** Analog digital wandler initialisieren
** free running mode, ziel 200kHz Abtastrate
** Mit 6,144 Mhz wird der kürzeste Zyklus erreicht, es bleiben 32 * 13 = 416 Takte
** für die Auswertung in der Int Routine.
** Die ist aber nicht so lang.
*/
void init_adc( unsigned char padr )
{
   DIDR0  = (~padr & 0x3F);                // Nur padr zulassen
   ADMUX = padr ;                          // AREF +5V benutzen, ADC0 Input Port
#if F_CPU == 6144000
   ADCSRA = (1 << ADPS0) + (1 << ADPS2)    // ADC Takt einstellen 6144000/32=192kHz, 5,2*13=67µsek
#endif

#if F_CPU == 8000000
   ADCSRA = (1 << ADPS1) + (1 << ADPS2)    // ADC Takt einstellen 8000000/64=125kHz, 8*13=104µsek
#endif

#if F_CPU == 12000000
   ADCSRA = (1 << ADPS1) + (1 << ADPS2)    // ADC Takt einstellen 12000000/64=187,5kHz, 5,3*13=69,3µsek
#endif

#if F_CPU == 14745600
   ADCSRA = (1 << ADPS0)  + (1 << ADPS1) + (1 << ADPS2)    //ADC 14745600/128=115kHz, 8,79*13=113µsek
#endif

   + (1 << ADEN)                    // ENABLE
   + (1 << ADSC)                    // Start Conversion
   + (1 << ADIE)                    // Interrupt wenn fertig
   + (1 << ADATE);                  // free running mode
}



/*****************************************************************************
** Analog digital wandler initialisieren, Messung des Basiswertes und Spannungen 
*/
void init_adc_Mean( void )
{
   ADMUX = 0 ;                                 // AREF +5V benutzen, ADC0 Input Port
   DIDR0 = BIT0 + BIT1 + BIT2 ;                // BIT3 BIT4 und BIT5 als Input, spart Strom
   ADCSRA = 0;
}



/*****************************************************************************
** single start, für die Ermittlung des Basiswertes oder Akkuspannung 
*/
void start_adc( unsigned char padr )
{
   ADMUX = padr;                           // AREF +5V benutzen, ADC0 Input Port

   #if F_CPU == 6144000
   ADCSRA = (1 << ADPS0) + (1 << ADPS2)    // ADC Takt einstellen 6144000/32=192kHz, 5,2*13=67µsek
#endif

#if F_CPU == 8000000
   ADCSRA = (1 << ADPS1) + (1 << ADPS2)    // ADC Takt einstellen 8000000/64=125kHz, 8*13=104µsek
#endif

#if F_CPU == 12000000
   ADCSRA = (1 << ADPS1) + (1 << ADPS2)    // ADC Takt einstellen 12000000/64=187,5kHz, 5,3*13=69,3µsek
#endif

#if F_CPU == 14745600
   ADCSRA = (1 << ADPS0)  + (1 << ADPS1) + (1 << ADPS2)    //ADC 14745600/128=115kHz, 8,79*13=113µsek
#endif
          + (1 << ADEN)                    // ENABLE
          + (1 << ADSC);                   // Start Conversion
}



/*****************************************************************************
** 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;
            }
         }
      }
   }
   return 0;
}



/*****************************************************************************
**  ADC complete wenn die Messung aktiv.
**  Auswertung der Impulse vom Vorverstärker
**  ISR ADC wird je ca. 67,7µsek ausgeführt (ca. 415 Takte ) 
**  gemessene maximale Pfadlänge: 10µsek + ca. 72 Takte = 12µsek = 22µsek
*/
ISR ( ADC_vect )
{
   int wert;
   unsigned char pos;
   
   wert = ADC;                    // Wandlerwert sichern
   
   if ( impuls )                  // Impuls erkannt ??
   {      
      if ( wert > max )
         max = wert;              // maximalwert sichern

      if ( wert < U0 )            // Signalimpuls am Ende ?
      {
         counter++;               // Counter +1
         max = max - Um;          // Maximalwert normalisieren
         if ( max > 255 )         // auf maximal 255
            max = 255;
         trace_value = max;       // Trace_PIN Anzeige  
         
         if ( usart_on )
         {
            uart_putc((unsigned char)max ); // Zeichen senden
            start_tx();           // start transfer
         }
         
         pos = ttab[max];         // Analyse matrix adresse ermitteln 
         matrix[pos] += 1;        // Spaltencounter +1  

         impuls = 0;              // Impuls fertig
         max = U0;                // restart max
         SPEAKER_OFF;             
         LED_OFF;
      }
   }
   else                           // Test auf neuen Impuls
   {
      if ( wert > U0 )            // wert > realer Schwellwert = Impuls da ?
      {
         if ( ton_signal )        
            SPEAKER_ON;
         LED_ON;
         if ( wert > max )
            max = wert;           // maximalwert sichern
         impuls = 1;              // Impuls erkannt setzen
      }
   }   
}
