Homepage von Peter Rachow Startseite - Home

Der Selbstbau-Tauchcomputer

Allgemeines 

Forschung und Entwicklung: LCD-Anzeige | Mikrocontroller | Software | Sensoren | Gehäuse | Erfahrungsberichte

Geräte: SBTC3 | SBTC4 | Datenmodem zum PC | Simulator für Drucksensor

Quellcode der Altversion 2 (nicht mehr dokumentiert)
/*****************************************************************/
/*  Dekompressionsprogramm fuer Selbstbau-Tauchcomputer (SBTC2)  */
/*  ************************************************************ */
/*  Mikrocontroller:  ATMEL AVR ATmega32, 8 MHz                  */
/*                                                               */
/*  Compiler:         GCC (GNU AVR C-Compiler)                   */
/*  Autor:            Peter Rachow                               */
/*  Letzte Aenderung: 22. Aug. 2006                              */
/*****************************************************************/

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/sleep.h>

/*******************/
/*  Benutzermenue  */
/*******************/
#define MENU_ITEMS 8
char menu_str[MENU_ITEMS][18]={"Luftdruck NN",
                                "Hoehe ueber NN",
                                "Kabinendruck Fl.",
                                "Max. ppO2",
                                "Const. ppO2",
                                "Toleranzen",
                                "ADG-Modus",
                        "ppN2 anzeigen"};

char menu_unitstr[MENU_ITEMS][6]={"mbar",
                                   "m",
                                   "mbar",
                                   "bar",
                                   "bar",
                                   "",
                                   "",
                           ""};

int menu_digits[MENU_ITEMS] = {-1, -1, -1, 2, 2, 2, -1, -1}; /* Zahl der Ziffern */
int menu_dec[MENU_ITEMS] = {-1, -1, -1, 1, 1, 1, -1, -1};    /* Position des Dezimalpunktes */

/*******************/
/* EEPROM-Speicher */
/*******************/
#include <avr/eeprom.h>
#define MAX_EEPROM_ADR 1023
#define EEPROM_PROF_START 50

void eeprom_store_byte(char);
void clear_flash(int);
void display_profile(void);
void display_rcd(void);
void display_log(void);
int eeprom_byte_count;                 /* Positionszeiger fuer EEPROM */

/*********************/
/* Timer & Interrupt */
/*********************/
#define SCLOCK 8             /* Taktfrequenz im MHz                               */
#define INITWAIT 750         /* Wartezeit fuer Anzeigewechsel bei Programmstart   */
unsigned long runseconds = 0, diveseconds = 0, surf_seconds = 0;

/***********/
/* M I S C */
/***********/
int main(void);
void led(char, char);
int round_depth(int);
int get_keys(void);
void settings(void);

void showtemp(void);
void show_gas(int);
void set_curgas(void);

#define SWITCHDEPTH 10 /* Tiefe, bei der von TG- in Oberflaechenmodus */
/* gewechselt wird [dm].                        */
#define SURF_SECONDS_MAX 120 /* Oberflaechenzeit, nach der von TG- in OFP-Modus */
/* gewechselt wird [s].                           */

void check_vasc(void);

/* Softwareversion */
unsigned char softwareversion[3] = {2, 76, 'm'};

/***************/
/* LCD-Display */
/***************/
#define LCD_INST 0x00
#define LCD_DATA 0x01

void lcd_write(char, unsigned char, int);
void set_rs(char);
void set_e(char);
void lcd_init(void);
void lcd_cls(void);
void lcd_linecls(int, int);
void lcd_putchar(int, int, unsigned char);
void lcd_putstring(int, int, unsigned char*);
int lcd_putnumber(int, int, int, int, int, char);
void wait_ms(int);
void lcd_printdiveinfo(int, int, int);
void lcd_display_test(void);

/*********/
/* USART */
/*********/
#define RX_BUF_SIZE 32

void usart_init(void);
void usart_putc(char);
void clear_rx_buf(void);
char make_crc(int, int);
void sbtc2pc(void);

char rx_buf[RX_BUF_SIZE];
unsigned char rx_buf_cnt = 0;

/*************************/
/* Dekompressionrechnung */
/*************************/
#define NCOMP 16   /* Anzahl der Kompartimente des Modells */
#define FN2 0.78   /* N2-Anteil im Atemgas                 */
#define MAX_DECO_STEPS 10

/* Gewebekonstanten fuer 16 Kompartimente  */
/* STICKSTOFF                              */
float t05N2[] = {4, 8, 12.5, 18.5, 27, 38.3, 54.3, 77, 109, 146, 187, 239, 305, 390, 498, 635};
float aN2[] = {1.2599, 1, 0.8618, 0.7562, 0.662, 0.5043, 0.441, 0.4,
    0.375, 0.35, 0.3295, 0.3065, 0.2835, 0.261, 0.248, 0.2327};
float bN2[] = {0.505, 0.6514, 0.7222, 0.7825, 0.8126, 0.8434, 0.8693, 0.891,
    0.9092, 0.9222, 0.9319, 0.9403, 0.9477, 0.9544, 0.9602, 0.9653};

/* HELIUM */
float t05He[] = {1.51, 3.02, 4.72, 6.99, 10.21, 14.48, 20.53, 29.11,
    41.2, 55.2, 70.7, 90.2, 115.2, 147.2, 188, 240};
float aHe[] = {1.7424, 1.383, 1.1919, 1.0458, 0.922, 0.8205, 0.7305, 0.6502,
    0.595, 0.5545, 0.5333, 0.5189, 0.5181, 0.5176, 0.5172, 0.5119};
float bHe[] = {0.4245, 0.5747, 0.6527, 0.7223, 0.7582, 0.7957, 0.8279, 0.8553,
    0.8757, 0.8903, 0.8997, 0.9073, 0.9122, 0.9171, 0.9217, 0.9267};

/* Kompartimentsaettigung */
float piN2[] = {0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72,
    0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72};
float piHe[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float pig[] = {0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72,
    0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72, 0.72};

/* 4 durch Anwender waehlbare Gase (Gas1 = Luft) */
unsigned char curgas = 0;
double figN2[5] = {FN2, 0, 0, 0, 0};              /* N2-Anteil in 5 Auswahlgasen    */
double figHe[5] = {0, 0, 0, 0, 0};                /* He-Anteil in in 5 Auswahlgasen */

float airp = 0.995;                  /* Umgebungsluftdruck in bar am Tauchort        */
float airp0 = 0.995;                 /* Umgebungsluftdruck in bar auf NN             */
float cabinp = 0.600;                /* Kabinendruck im Flugzeug in bar              */
int altitude = 0;                    /*Hoehe ueber NN                                */
int depth = 0, maxdepth = 0;         /* Akt. und max. Tiefe [dm]                     */
int fixmaxdepth = 410;               /* Tiefe die nach dem TG fuer                   */
                                      /* Diveguide angezeigt wird [m]                 */
char adg_mode = 0;                   /* ADG-Mode */
int ldepth = 0;                      /* Letzte aktuelle Tiefe fuer v.asc             */
int deepest_decostep = 0;            /* Tiefster Dekostopp in dm                     */
int deco_minutes_total = 0;          /* Gesamtdekozeit in min.                       */
char dphase = 0;                     /* TG-Phase: 1=tauchen 0=OFP                    */
int temp;                            /* Aktuelle Temperatur                          */
int temp_min;                        /* niedrigste Temperatur                        */
int temp_maxdepth;                   /* Temperatur auf max Tiefe                     */
unsigned char f_cons;               /* Faktor fuer ab-Modifikation (10facher Wert)  */
char show_ppN2 = 0;                  /* ppN2 nach TG anzeigen für 16 Kompartimente   */

unsigned char rcd_decotime[MAX_DECO_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* Speicherdaten fuer die Decostufen, die */
/* im EEPROM fuer den TG abgelegt werden  */

unsigned char rcd_deco_minutes_total = 0;
unsigned char tmp_decotime_total = 0;

unsigned char surfaced = 0, vasc_exceeded = 0, ppo2_exceeded = 0;
unsigned char decostep_skipped = 0, ndt_runout = 0; /* Flags fuer Ereignisaufzeichnung im Profilespeicher */
unsigned char temp_low = 0;

float get_water_pressure(int);
void calc_p_inert_gas(int);
float get_water_depth(float);
int calc_ndt(void);
void calc_deco(void);
unsigned int calc_no_fly_time(void);
void get_dsensor(void);
void get_tsensor(void);
void set_ab_values(int, unsigned char);
void calc_airp_divesite(char);
/***********************/
/* ppO2-bezogene Werte */
/***********************/
float cns_day = 0, cns_dive;
float otu = 0;
int maxppO2 = 16;  /* 1.6 bar */
int constppO2 = 16;

int calc_ppO2(char);
void calc_cns_otu(void);
void calc_figN2_for_constppO2(void);

/**************/
/* AD-Wandler */
/**************/
#define ADWAITSTATE 3
int adc_val;
char adc_mode = 0;

/********************************************/
/* Funktionen und Prozeduren fuer DEKO-Teil */
/********************************************/

/* Wasserdruck p.amb aus Tiefe depth  */
/* berechnen                          */
float get_water_pressure(int depth)
{
    return depth * 0.1 + airp;
}

/* Inertgaspartialdruck im Gewebe berechnen */
/* d: Tiefe in m  Intervall immer 10 sec.   */
void calc_p_inert_gas(int d)
{
    unsigned char t1;
    float pamb = get_water_pressure(d) - 0.0627;

    for(t1 = 0; t1 < NCOMP; t1++)
    {
        piN2[t1] += (pamb * figN2[curgas]  - piN2[t1]) * (1 - exp((-0.1667 / t05N2[t1]) * log(2)));
        piHe[t1] += (pamb * figHe[curgas]  - piHe[t1]) * (1 - exp((-0.1667 / t05He[t1]) * log(2)));
        pig[t1] = piN2[t1] + piHe[t1];
    }
}

/* Wassertiefe depth aus p.amb berechnen */
float get_water_depth(float pamb)
{
    return (pamb - airp) * 10;
}

/* erechnen der Restnullzeit */
int calc_ndt()
{
    char calcok = 0;      /* Flag, ob Rechnung OK ist */
    unsigned char t1;

    int dp = depth * 0.1; /* Wassertiefe in m */
    int t0min = 999;

    float te, xN2, xHe;
    float piigN2, piigHe, pamb = get_water_pressure(dp) - 0.0627;

    piigN2 = pamb * figN2[curgas];
    piigHe = pamb * figHe[curgas];

    for(t1 = 0; t1 < NCOMP; t1++)
    {
        /* Stickstoff */
        if(piigN2  - piN2[t1] && figN2[curgas])
        {
            xN2 = -1 * (airp / bN2[t1] + aN2[t1] - piN2[t1]) / (piigN2  - piN2[t1]) + 1;

            if(xN2 > 0) /* N2 Logarithmieren moeglich? */
            {
                te = -1 * log(xN2) / log(2) * t05N2[t1];
                if(te < t0min)
                    t0min = te;
                calcok = 1;
            }
        }

        /* Helium */
        if(piigHe - piHe[t1] && figHe[curgas])
        {
            xHe = -1 * (airp / bHe[t1] + aHe[t1] - piHe[t1]) / (piigHe - piHe[t1]) + 1;

            if(xHe > 0)
            {
                te = -1 * log(xHe) / log(2) * t05He[t1];
                if(te < t0min && te > 0)
                    t0min = te;
                calcok = 1;
            }
        }
    }

    if(calcok && dp > 10)
    {
        if(t0min > 0)
            return (int) t0min;
        else
            return 0;
   }
    else
    {
        return -1;
    }
}


/* Dekompressionsstufen berechnen */
void calc_deco()
{
    float piN2x[NCOMP], piHex[NCOMP], pigx[NCOMP];
   float a[NCOMP], b[NCOMP];
    float pambtol, pambtolmax = 1.0;
    unsigned int decostep, deco_minutes1 = 0;
    unsigned char xpos = 0, t1, t2;
    unsigned char tmp_decotime[MAX_DECO_STEPS];
    unsigned int cnt = 0;
    int ndt;

    for(t1 = 0; t1 < MAX_DECO_STEPS; t1++)
        tmp_decotime[t1] = 0;

    deco_minutes_total = 0;

    /* Signal LED ein */
    led(2, 1);

    /* Aktuelle Gasspannungen in temporaeres eindimensionales Datenfeld uebertragen */
    for(t1 = 0; t1 < NCOMP; t1++)
    {
        piN2x[t1] = piN2[t1];
        piHex[t1] = piHe[t1];
        pigx[t1] = piN2x[t1] + piHex[t1];
    }

    /* Erste Dekostufe */
    for(t1 = 0; t1 < NCOMP; t1++)
        if((pigx[t1] - aN2[t1]) * bN2[t1] > pambtolmax)
            pambtolmax = (pigx[t1] - aN2[t1]) * bN2[t1];

    decostep = get_water_depth(pambtolmax);
    decostep = ((decostep / 3) + 1) * 3;

    deepest_decostep = 0;

    if(dphase)
        lcd_linecls(1, 15);

    get_dsensor();

   /* a- und b-Konstanten errechnen, Gewichtung entsprechend dem Inertgaspartial-  */
   /* druck im Gewebe                                                              */
   for(t1 = 0; t1 < NCOMP; t1++)
   {
       if(piHex[t1] > 0.1)
      {
           a[t1] = (aN2[t1] * piN2x[t1] + aHe[t1] * piHex[t1]) / (piN2x[t1] + piHex[t1]);
         b[t1] = (bN2[t1] * piN2x[t1] + bHe[t1] * piHex[t1]) / (piN2x[t1] + piHex[t1]);
      }
       else
      {
            a[t1] = aN2[t1];
         b[t1] =  bN2[t1];
       }
    }

    /* Nachfolgende Dekostufen bis 0 m Wassertiefe errechnen */
    while(decostep > 0)
    {
        pambtolmax = 0.0;

        for(t1 = 0; t1 < NCOMP; t1++)
        {
            piN2x[t1] += ((get_water_pressure(decostep) - 0.0627) * figN2[curgas]  - piN2x[t1]) * (1 - exp((-1 / t05N2[t1]) * log(2)));
            piHex[t1] += ((get_water_pressure(decostep) - 0.0627) * figHe[curgas]  - piHex[t1]) * (1 - exp((-1 / t05He[t1]) * log(2)));
            pigx[t1] = piN2x[t1] + piHex[t1];

            pambtol = (pigx[t1] - a[t1]) * b[t1];
            if(pambtol > pambtolmax)
                pambtolmax = pambtol;
        }

        if(get_water_depth(pambtolmax) < decostep - 3)
        {
            if(deco_minutes1)
                xpos += lcd_putnumber(1, xpos, deco_minutes1, -1, -1, 'l') + 1;

            deco_minutes_total += deco_minutes1;

            /* Werte im Datenfeld speichern fuer EEPROM-Aufzeichnung       */
            cnt = (decostep / 3) - 1; /* Nr. des Decostopp ermitteln */
            if(cnt >= 0 && cnt < MAX_DECO_STEPS)
                tmp_decotime[cnt] = deco_minutes1;

            decostep -= 3;
            deco_minutes1 = 0;
        }
        deco_minutes1 += 1;

        /* Laengste gesamte Dekozeit speichern */
        if(deco_minutes_total > tmp_decotime_total)
        {
            for(t2 = 0; t2 < MAX_DECO_STEPS; t2++)
                rcd_decotime[t2] = tmp_decotime[t2];
            tmp_decotime_total = deco_minutes_total;
        }

        /* Tiefsten errechneten Dekostopp speichern */
        if(decostep > deepest_decostep)
            deepest_decostep = decostep;
    }

    if(dphase || deco_minutes_total) /* Restliche Anzeige (Gesamtdekozeit bzw. Nullzeit nur, wenn getaucht wird) */
    {
        if(!deco_minutes_total)      /* Gesamte Dekozeit <= 0 also NZ-TG */
        {
            lcd_putstring(1, 0, "NZ: ");

            ndt = calc_ndt();

            if(ndt < 0)       /* Unplausible NZ-Werte abfangen */
                lcd_putstring(1, 4, "-");
            else
            {
                xpos = lcd_putnumber(1, 4, ndt, -1, -1, 'l') + 4;
                lcd_putchar(1, xpos, 39);
            }
        }
        else  /* Dekompressionsstopps sind erforderlich */
        {
            /* Summe der Dekozeiten anzeigen */
            lcd_putchar(1, xpos++, 246);    /* Sigma-Zeichen */
            lcd_putchar(1, xpos++, '=');
            xpos += lcd_putnumber(1, xpos, deco_minutes_total, -1, -1, 'l');
            lcd_putchar(1, xpos, 39);

            if(!ndt_runout) /* Flag setzen fuer Profilaufzeichnung: Nullzeit zu Ende,  */
            {               /* PADIes muessen jetzt auftauchen! ;-P                     */
                eeprom_store_byte(225);
                ndt_runout = 1;
            }

        }
    }

    if(xpos < 12)
        showtemp();

    led(2, 0);
}

/* Flugverbotszeit für N2-Kompartimente berechnen */
/* Aufloesung: 1 h            */
unsigned int calc_no_fly_time()
{
    float a[NCOMP], b[NCOMP];
   float piN2_b[NCOMP];
   float piHe_b[NCOMP];
    float p_amb_tol;
    unsigned int nft = 0, flag_no_fly, t1;

    /* Aktuelle Gasspannungen in temporaeres Datenfeld uebertragen */
    for(t1 = 0; t1 < NCOMP; t1++)
   {
        piN2_b[t1] = piN2[t1];
      piHe_b[t1] = piHe[t1];
    }

   /* a- und b-Konstanten errechnen, Gewichtung entsprechend dem Inertgaspartial-  */
   /* druck im Gewebe                                                              */
   for(t1 = 0; t1 < NCOMP; t1++)
   {
        if(piHe_b[t1] > 0.1) /* Mischgastauchen */
      {
           a[t1] = (aN2[t1] * piN2_b[t1] + aHe[t1] * piHe_b[t1]) / (piN2_b[t1] + piHe_b[t1]);
         b[t1] = (bN2[t1] * piHe_b[t1] + bHe[t1] * piHe_b[t1]) / (piN2_b[t1] + piHe_b[t1]);
      }
       else  /* Luft bzw. Nitrox */
      {
            a[t1] = aN2[t1];
         b[t1] =  bN2[t1];
       }
    }

    while(nft < 48)
    {
        flag_no_fly = 0;

        for(t1 = 0; t1 < NCOMP; t1++)
        {
            piN2_b[t1] += ((airp - 0.0627) * 0.78 - piN2_b[t1]) * (1 - exp((-60 / t05N2[t1]) * log(2)));
         piHe_b[t1] += ((airp - 0.0627) * 0.78 - piHe_b[t1]) * (1 - exp((-60 / t05He[t1]) * log(2)));

            p_amb_tol = (piN2_b[t1] - a[t1]) * b[t1];
            if(p_amb_tol > cabinp) /* Kabinendruck in bar */
                flag_no_fly = 1;
        }

        if(!flag_no_fly)
            return nft;
        nft++;
    }
    return nft;
}

/* Uebersaettigungstoleranzen veraendern */
void set_ab_values(int k, unsigned char showmode)
{
    unsigned char t1;
    double f = k * 0.1;

    for(t1 = 0; t1 < NCOMP; t1++)
    {
        aN2[t1] = 2 * exp(-0.33333333 * log(t05N2[t1]));
        aHe[t1] = 2 * exp(-0.33333333 * log(t05He[t1]));
        bN2[t1] = 1.005 - exp(-0.5 * log(t05N2[t1]));
        bHe[t1] = 1.005 - exp(-0.5 * log(t05He[t1]));
    }

    for(t1 = 0; t1 < NCOMP; t1++)
    {
        aN2[t1] /= f;
        bN2[t1] *= f;
        aHe[t1] /= f;
        bHe[t1] *= f;
    }

    if(!showmode)
        return;

    /* A- und B-Werte anzeigen */
    lcd_putstring(0, 0, "a- und b-Werte:");
    wait_ms(1000);
    lcd_cls();

    for(t1 = 0; t1 < NCOMP; t1++)
    {
        lcd_putchar(0, 0, 'a');
        lcd_putnumber(0, 1, t1, -1, -1, 'l');
        lcd_putnumber(0, 4, aN2[t1 + 1] * 10000, 5, 4, 'l');
        lcd_putchar(1, 0, 'b');
        lcd_putnumber(1, 1, t1, -1, -1, 'l');
        lcd_putnumber(1, 4, bN2[t1 + 1] * 10000, 5, 4, 'l');
        wait_ms(1000);
        lcd_cls();
    }
}

/* Aufstiegsgeschwindigkeit ueberpruefen */
void check_vasc()
{
    float v;
   int vmax = 10;

    if(depth > 200) /* Unterhalb von 20m WT darf schneller aufgetaucht werden */
        vmax = 18;

    v = (ldepth - depth) * 0.6; // /10 * 6 Messungen/min.

   if(v <= 0)
   {
       led(3, 0);
       return;
   }

    if(v > vmax)
        vasc_exceeded++;

    if(vasc_exceeded > 8)
    {
        led(3, 1);
        eeprom_store_byte(222); /* Aufstiegsgeschwindigkeit zu hoch                                     */
        vasc_exceeded = 0;      /* Flag setzen, um Wiederholung DER aUFZEICHNUNG im gleichen Zeitintervall zu verhindern */
    }
    else
        led(3, 0);
}

/* Drucksensor auslesen */
void get_dsensor()
{
    unsigned char xpos;

    adc_mode = 0;

    /* AD-Wandler */
    outp(64, ADMUX);     /* Interne Referenz und Kanal 0 aktivieren PA0 PIN 40 */
    wait_ms(ADWAITSTATE);
    outp(206, ADCSRA);   /* AD-Wandler abfragen */
    wait_ms(ADWAITSTATE);

    if(depth > maxdepth)
    {
        maxdepth = depth;
        temp_maxdepth = temp;
    }

    lcd_printdiveinfo(depth, maxdepth, diveseconds * 0.0166666667);

    if(depth < (deepest_decostep - 1) * 10)
    {
        led(4, 1);
        lcd_putstring(0, 6, "!  ");
        xpos = lcd_putnumber(0, 7, deepest_decostep, -1, -1, 'l') + 7;
        lcd_putstring(0, xpos, "m! ");
        wait_ms(50);
        led(4, 0);

        if(!decostep_skipped) /* Flag fuer Profilaufzeichnung setzen */
        {
            eeprom_store_byte(223);
            decostep_skipped = 1;
        }
    }
}

/* Temperatursensor auslesen */
void get_tsensor()
{
    adc_mode = 1;

    /* AD-Wandler */
    outp(64 + 1, ADMUX); /* Interne Referenz und Kanal 1 aktivieren PA1 PIN 39 */
    wait_ms(ADWAITSTATE);
    outp(206, ADCSRA);   /* AD-Wandler abfragen */
    wait_ms(ADWAITSTATE);
}

/* ppO2 (Rueckgabe = 10facher Wert!) */
int calc_ppO2(char display_warning)
{
    int lppO2 = 10 * ((depth * 0.01) + airp) * (1 - figN2[curgas] - figHe[curgas]);

    if(lppO2 > maxppO2 && display_warning)
    {
        lcd_putstring(1, 10, " ppO2!");
        if(!ppo2_exceeded)
        {
            eeprom_store_byte(224);
            ppo2_exceeded = 1;
        }
    }
    return lppO2;
}

void calc_figN2_for_constppO2()
{
    float figO2 = (constppO2 * 0.1) / (depth / 91.8 + airp);

    figN2[4] = 1 - figO2;

    if(figN2[4] < 0)
        figN2[4] = 0;

    if(figN2[4] > 0.78)
        figN2[4] = 0.78;
}

/* ZNS- und OTU-Werte berechnen (Aufruf 1 x pro Minute) */
void calc_cns_otu()
{
    /* ZNS-Tabelle */
    unsigned int f_day[11] =  {720, 570, 450, 360, 300, 270, 240, 210, 180, 165, 150};
    unsigned int f_dive[11] = {720, 570, 450, 360, 300, 240, 210, 180, 150, 120, 45};

    /* Index des Tabellenwertes zu geg. ppO2 */
    int ndx = calc_ppO2(0) - 6;

    /* ppO2-Rechnungen */
    float otu_ppO2 = calc_ppO2(0) * .1 - .5;
    float cns_ppO2 = calc_ppO2(0) * .1;

    /* ZNS in Oberflaechenmodus t1/2 = 90 min. */
    if(!dphase)
    {
        cns_day *= 0.992327946262943;
        return;
    }

    if(ndx >= 0 && ndx <= 10) /* Normaler ppO2 => Berechnung der Dosis auf Basis der Tabelle*/
    {
        cns_day += 100 * exp(-1 * log(f_day[ndx]));
        cns_dive += 100 * exp(-1 * log(f_dive[ndx]));
    }

    if(ndx > 10) /* Sehr hoher ppO2 => Berechnung der Dosis auf funktionaler Basis */
    {
        cns_day +=   100 * exp(-1 * log((cns_ppO2 * 432) - (cns_ppO2 - .6) * 120));
        cns_dive += 100 * exp(-1 * log((cns_ppO2 * 432) - (cns_ppO2 - .6) * 120));
    }

    /* OTU */
    if(otu_ppO2 > 0)
        otu += exp(0.83 * log(otu_ppO2 * 2));
}

/*****************/
/* Ende Dekoteil */
/*****************/

/**************************************/
/* Funktionen und Prozeduren fuer LCD */
/**************************************/
/* Ein Byte (Befehl bzw. Zeichen) zum Display senden */
void lcd_write(char lcdmode, unsigned char value, int waitcycles)
{
    set_e(0);

    if(!lcdmode)
        set_rs(0);    /* RS=0 => Befehl */
    else
        set_rs(1);    /* RS=1 => Zeichen */

    wait_ms(waitcycles * 2);

    set_e(1);
    outp(value & 0xF0, PORTD);           /* Hi byte */
    set_e(0);
    set_e(1);
    outp((value & 0x0F) * 0x10, PORTD);  /* Lo byte */
    set_e(0);

}

/* Ein Zeichen (Char) zum Display senden, dieses in */
/* Zeile row und Spalte col positionieren           */
void lcd_putchar(int row, int col, unsigned char ch)
{
    lcd_write(LCD_INST, col + 128 + row * 0x40, 1);
    lcd_write(LCD_DATA, ch, 1);
}


/* Eine Zeichenkette direkt in das LCD schreiben */
/* Parameter: Startposition, Zeile und Pointer   */
void lcd_putstring(int row, int col, unsigned char *s)
{
    unsigned char t1;

    for(t1 = col; *(s); t1++)
        lcd_putchar(row, t1, *(s++));
}


/* Display loeschen */
void lcd_cls(void)
{
    lcd_write(LCD_INST, 1, 5);
}


/* Display loeschen (eine Zeile) */
void lcd_linecls(int displine, int chars)
{
    unsigned char t1;

    for(t1 = 0; t1 <= chars; t1++)
        lcd_putchar(displine, t1, 32);
}

/* E setzen */
void set_e(char status)  /* PORT C0 = Pin 6 am LCD */
{
    if(status)
        sbi(PORTC, 0);
    else
        cbi(PORTC, 0);
}

/* RS setzen */
void set_rs(char status) /* PORT C1 = Pin 4 am LCD */
{
    if(status)
        sbi(PORTC, 1);
    else
        cbi(PORTC, 1);
}

/* LCD-Display initialisieren */
void lcd_init(void)
{
    /* Grundeinstellungen: 2 Zeilen, 5x7 Matrix, 4 Bit */
    lcd_write(LCD_INST, 40, 5);
    lcd_write(LCD_INST, 40, 5);
    lcd_write(LCD_INST, 40, 5);

    lcd_write(LCD_INST, 2, 5);
    lcd_write(LCD_INST, 8, 5);

    /* Display on, Cursor off, Blink off */
    lcd_write(LCD_INST, 12, 5);

    lcd_cls();

    /* Entrymode !cursoincrease + !displayshifted */
    lcd_write(LCD_INST, 4, 5);
}


/* Eine n-stellige Zahl direkt in das LCD schreiben */
/* Parameter: Startposition und Zeile; Zahl,        */
/* darzustellende Ziffern, Position des Dezimalpunktes, (l)links- oder (r)echtsbuendig */
int lcd_putnumber(int row, int col, int num, int digits, int dec, char orientation)
{
    char cl = col, minusflag = 0;
    unsigned char cdigit[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, digitcnt = 0;
    int t1, t2, n = num, r, x = 1;

    if(num < 0)
    {
        minusflag = 1;
        n *= -1;
    }

    /* Stellenzahl automatisch bestimmen */
    if(digits == -1)
    {
        for(t1 = 1; t1 < 10 && (n / x); t1++)
            x *= 10;
        digits = t1 - 1;
    }

    if(!digits)
        digits = 1;

    for(t1 = digits - 1; t1 >= 0; t1--)
    {
        x = 1;
        for(t2 = 0; t2 < t1; t2++)
            x *= 10;
        r = n / x;
        cdigit[digitcnt++] = r + 48;

        if(t1 == dec)
            cdigit[digitcnt++] = 46;
        n -= r * x;
    }

    digitcnt--;
    t1 = 0;

    /* Ausgabe */
    switch(orientation)
    {
      case 'l':
        cl = col;
        if(minusflag)
        {
            lcd_putchar(row, cl++, '-');
            digitcnt++;
        }

        while(cl <= col + digitcnt)                       /* Linksbuendig */
            lcd_putchar(row, cl++, cdigit[t1++]);

        break;

      case 'r':
        t1 = digitcnt;                              /* Rechtsbuendig */
        for(cl = col; t1 >= 0; cl--)
            lcd_putchar(row, cl, cdigit[t1--]);
        if(minusflag)
            lcd_putchar(row, --cl, '-');
    }

    if(dec == -1)
        return digits;
    else
        return digits + 1;
}

/* Alle Daten des laufenden TG an die richtigen Stellen des LCD  */
/* schreiben: Parameter: Tiefen in m, Zeit in sec.               */
void lcd_printdiveinfo(int cdepth, int mdepth, int divetime)
{
    lcd_putnumber(0, 0, cdepth, 3, 1, 'l');
    lcd_putchar(0, 4, 'm');

    lcd_putnumber(0, 6, mdepth, 3, 1, 'l');
    lcd_putstring(0, 10, "m");

    lcd_putnumber(0, 14, divetime, -1, -1, 'r'); /* Tauchzeit rechtsbuendig 1. Zeile */
    lcd_putchar(0, 15, 39);
}


/* Temperatur anzeigen */
void showtemp()
{
    lcd_putstring(1, 12, "   ");
    lcd_putnumber(1, 14, temp, -1, -1, 'r');
    lcd_putchar(1, 15, 223); /* °-Zeichen */
}

/* Aktuelles Atemgas anzeigen */
void show_gas(int gasnum)
{
    unsigned char xpos;

    lcd_cls();
    if(gasnum < 4)
    {
        lcd_putstring(0, 0, "Gas");
        lcd_putnumber(0, 4, gasnum + 1, -1, -1, 'l');

        lcd_putstring(1, 0, "N2:");
        xpos = lcd_putnumber(1, 4, figN2[gasnum] * 100, -1, -1, 'l') + 4;
        lcd_putchar(1, xpos, '%');

        lcd_putstring(1, 8, "He:");
        xpos = lcd_putnumber(1, 12, figHe[gasnum] * 100, -1, -1, 'l') + 12;
        lcd_putchar(1, xpos, '%');
    }
    else
    {
        lcd_putstring(0, 0, "Nitrox fuer");
        lcd_putstring(1, 0, "ppO2=   bar");
        lcd_putnumber(1, 7, constppO2, 2, 1, 'r');
    }
}

/* Aktuelles Atemgas einstellen */
void set_curgas()
{
    unsigned char lcurgas = curgas;
    unsigned long lseconds = runseconds;

    show_gas(lcurgas);

    while(get_keys());

    do
    {
        if(get_keys() == 3)
        {
            lseconds = runseconds;
            lcurgas++;
            if(lcurgas > 4)
                lcurgas = 0;
            show_gas(lcurgas);
            while(get_keys() == 3);
        }
    }
    while(runseconds < lseconds  + 5);

    lcd_cls();

    if(curgas != lcurgas)
    {
        lcd_putstring(0, 0, "Wechsel zu Gas");
        lcd_putnumber(0, 15, lcurgas + 1, -1, -1, 'l');
        curgas = lcurgas;
        eeprom_store_byte(226);
        eeprom_store_byte(curgas);
    }

    wait_ms(2000);
    lcd_cls();
}


/* Tiefenwert runden auf 1 Nachkommastelle u. /= 10 */
int round_depth(int d)
{
    if(d - (d / 10) * 10 >= 5)
        return (d / 10 + 1);
    else
        return (d / 10);
}

void calc_airp_divesite(char show_mode)
{
    char xpos;
    int airp0_tmp = airp0 * 1000;

    airp0_tmp = airp0_tmp * exp(-1.2928 * 0.0981 * altitude / airp0_tmp);

    if(show_mode)
    {
        wait_ms(INITWAIT);
        lcd_cls();
        lcd_putstring(0, 0, "Luftdruck TP");
        xpos = lcd_putnumber(1, 0, airp0_tmp, -1, -1, 'l') + 1;
        lcd_putstring(1, xpos, "mbar");
    }

    airp = airp0_tmp * 0.001;
}
/* Ende LCD-Teil */

/*********/
/* USART */
/*********/
void usart_init()
{
    /* 2.4 kBaud */
    UBRRL = 220; /* Originaler Wert = 207 fuer 2.4k 215 */
    UBRRH = 0;

    /* RX Interrupt, RX und TX einschalten */
    UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

    /* 8 Datenbits, 1 Stopbit, keine Paritaet */
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);

    rx_buf_cnt = 0;
}

void usart_putc(char tx_char)
{
    while(!(UCSRA & (1<<UDRE)));

    UDR = tx_char;
}

SIGNAL(SIG_UART_RECV)
{
    unsigned char rx_char = UDR, inputlen = 2;
    unsigned int t1, byte_adr, x = 0;;

    if(rx_buf_cnt < RX_BUF_SIZE)
    {
        rx_buf[rx_buf_cnt] = rx_char;

        switch(rx_buf[0])
        {
          case 100:
            inputlen = 2; /* 1 Byte lesen */
            rx_buf_cnt++;
            break;

          case 101:
            inputlen = 4; /* 1 Byte schreiben */
            rx_buf_cnt++;
            break;

          default:   clear_rx_buf();
        }
    }
    else
        clear_rx_buf();

    if(rx_buf_cnt > inputlen)
    {
        /* Befehlsfolge quittieren */
        for(t1 = 0; t1 < rx_buf_cnt; t1++)
            usart_putc(rx_buf[t1]);

        byte_adr = rx_buf[1] + rx_buf[2] * 256;

        if(byte_adr <= MAX_EEPROM_ADR)
        {
            lcd_putnumber(1, 8, byte_adr, 4, -1, 'l');

            /* Code auswerten */
            switch(rx_buf[0])
            {
              case 100:  /* 1 Byte lesen */
                usart_putc(eeprom_rb(byte_adr));               /* Byte senden */
                usart_putc(make_crc(3, eeprom_rb(byte_adr)));  /* CRC anhaengen */
                lcd_putstring(1, 0, "Tx  ");
                lcd_putnumber(1, 13, eeprom_rb(byte_adr), 3, -1, 'l');
                break;

              case 101:  /* 1 Byte schreiben */
                for(t1 = 0; t1 < 4; t1++)  /* CRC berechnen */
                x = x ^ rx_buf[t1];

            if(x == rx_buf[4])   /* CRC ist OK */
            {
                cli();
                    while(!eeprom_is_ready());
                    eeprom_wb(rx_buf[1] + rx_buf[2] * 256, rx_buf[3]);
                    sei();
                    lcd_putstring(1, 0, "Rx  ");
                    lcd_putnumber(1, 13, rx_buf[3], 3, -1, 'l');
            }
                else
                {
                lcd_putstring(1, 0, "CRC!");
            }
            }
        }
        clear_rx_buf();
    }
}

/* CRC-Pruefsumme berechnen */
char make_crc(int buflen, int addchar)
{
    int t1, x = 0;

    for(t1 = 0; t1 < buflen; t1++) /* Puffer bis dato */
        x = x ^ rx_buf[t1];
    x = x ^ addchar;                /* Sendebyte */

    return x;
}

/* Empfangspuffer loeschen */
void clear_rx_buf()
{
    int t1;

    for(t1 = 0; t1 < RX_BUF_SIZE; t1++)
        rx_buf[t1] = 0;
    rx_buf_cnt = 0;
}

/* Hauptfunktion der Schnittstelle zwischen SBTC und PC */
void sbtc2pc()
{

    while(get_keys());
    lcd_cls();

    /* Datenuebertragung zum PC starten? */
    lcd_putstring(0, 0, "SBTC <-> PC?");
    lcd_putstring(1, 0, "(j/n)");
    do
    {
        if(get_keys() == 3)
        {
            usart_init();
            lcd_cls();
            lcd_putstring(0, 0, "Modus");
            lcd_putstring(0, 8, "ADRS VAL");

            while(get_keys() != 2);
            UCSRB = 0;
            return;
        }
    }while(get_keys() != 2);
    while(get_keys());
    lcd_cls();

}

/* Alle Tauchproile anzeigen, Auflistung der Werte in 20-sec. Schritten */
void display_profile()
{
    unsigned int t1;
   int startbyte = 55, endbyte;
   int xdepth = 0;
    unsigned char xpos, ok, p_cnt = 1;

    while(get_keys());
    lcd_cls();

    lcd_putstring(0, 0, "TG-Profil an-");
    lcd_putstring(1, 0, "zeigen? (j/n)");

    do
    {
        if(get_keys() == 3)
        {
          cli();
         while(1)
         {
            lcd_cls();

            /* Startbyte finden */
            t1 = startbyte;
            endbyte = 0;
            ok = 0;

            /* Anfang und Ende eines Profiles im EEPROM-Speicher suchen */
            while(t1 < MAX_EEPROM_ADR && !ok)
            {
               if(eeprom_rb(t1) == 229)
               {
                  startbyte = t1;
                  ok = 1;
               }
               else
                  t1++;
            }

            t1 = startbyte + 1;
            ok = 0;
            while(t1 < MAX_EEPROM_ADR && !ok)
            {
               if(eeprom_rb(t1) == 230)
               {
                  endbyte = t1;
                  ok = 1;
               }
               else
                  t1++;
            }

            if(endbyte)
            {
               lcd_cls();
               lcd_putstring(0, 0, "Profil");
               lcd_putnumber(0, 7, p_cnt++, -1, -1, 'l');
               wait_ms(1000);

               lcd_cls();
               lcd_putstring(0, 0, "Zeit");
               lcd_putstring(0, 8, "Tiefe");
               for(t1 = startbyte + 1; t1 < endbyte; t1++)
               {
                  xdepth = eeprom_rb(t1);
                  if(xdepth < 99)
                  {
                     lcd_linecls(1, 15);

                     xpos = lcd_putnumber(1, 0, (int)((t1 - startbyte) * 0.3333333), -1, -1, 'l') + 1;
                     lcd_putstring(1, xpos, "min.");


                     if(xdepth > fixmaxdepth && adg_mode) /* Bei Diveguide-Gefahr PADI-kompatible Tiefe anzeigen */
                        xpos = lcd_putnumber(1, 8, fixmaxdepth, -1, -1, 'l') + 9;
                     else
                        xpos = lcd_putnumber(1, 8, xdepth, -1, -1, 'l') + 9;

                     lcd_putchar(1, xpos, 'm');
                     wait_ms(500);

                     if(get_keys() == 3)
                     {
                        lcd_cls();
                        t1 = endbyte;
                     }
                  }
               }
            }
            else
            {
               lcd_cls();
               lcd_putstring(0, 0, "Keine (weiteren)");
               lcd_putstring(1, 0, "Profile.");
               wait_ms(2000);
               lcd_cls();
               sei();
               return;
            }
            startbyte = endbyte + 1;
            endbyte = 0;
         }
      }
   }while(get_keys() != 2);
   while(get_keys());
   lcd_cls();
}

/* Werte für Gesamttauchzeit, Max. Tiefe etc. */
void display_rcd()
{
    unsigned char xpos;
   unsigned long dminutes_t;
   unsigned int dminutes, dhours;

    lcd_putstring(0, 0, "Logwerte zeigen?");
   lcd_putstring(1, 0, "(j/n)");

    do
    {
        if(get_keys() == 3)
        {
            lcd_cls();
         lcd_putstring(0, 0, "Anzahl TG:");
         lcd_putnumber(1, 0, eeprom_rb(24) + eeprom_rb(25) * 256, -1, -1, 'l') + 1;
         while(get_keys() != 2);
         while(get_keys());

         lcd_cls();
         lcd_putstring(0, 0, "Ges. Tauchzeit:");

         dminutes_t = eeprom_rb(26) + eeprom_rb(27) * 256;
         dhours = dminutes_t / 60;
         dminutes = dminutes_t - dhours * 60;

         xpos = lcd_putnumber(1, 0, dhours, -1, -1, 'l') + 1;
         lcd_putstring(1, xpos, "Std.");
         xpos += 6;
         xpos = lcd_putnumber(1, xpos, dminutes, -1, -1, 'l') + 1;
         lcd_putstring(1, xpos, "Min.");
            while(get_keys() != 2);
         while(get_keys());

         lcd_cls();
         lcd_putstring(0, 0, "Max. Tiefe:");
         xpos = lcd_putnumber(1, 0, eeprom_rb(28) + eeprom_rb(29) * 256, 3, 1, 'l') + 1;
         lcd_putstring(1, xpos, "m");
      }
   }while(get_keys() != 2);
   while(get_keys());
   lcd_cls();
}

void display_log()
{

    unsigned int t1;
   int startbyte = 55;
    unsigned char xpos, ok, p_cnt = 1;

    while(get_keys());
    lcd_cls();

    lcd_putstring(0, 0, "TG-Daten an-");
    lcd_putstring(1, 0, "zeigen? (j/n)");

    do
    {
        if(get_keys() == 3)
        {
          cli();
         while(1)
         {
            lcd_cls();

            /* Anfang eines Datensatzes im EEPROM-Speicher suchen */
            t1 = startbyte;
            ok = 0;
            while(t1 < MAX_EEPROM_ADR && !ok)
            {
               if(eeprom_rb(t1) == 230)
               {
                  startbyte = t1;
                  ok = 1;
               }
               else
                  t1++;
            }

            if(startbyte && ok)
            {
               lcd_cls();
               lcd_putstring(0, 0, "TG Nr.");
               lcd_putnumber(0, 7, p_cnt++, -1, -1, 'l');
               wait_ms(1000);

               lcd_cls();

               lcd_putstring(0, 0, "Tauchzeit in Min.");
               lcd_putnumber(1, 0, eeprom_rb(startbyte + 1) + eeprom_rb(startbyte + 2) * 256, -1, -1, 'l');
               wait_ms(1000);
               lcd_cls();

                  lcd_putstring(0, 0, "Max. Tiefe in m");
               lcd_putnumber(1, 0, (eeprom_rb(startbyte + 3) + eeprom_rb(startbyte + 4) * 256) / 10, -1, -1, 'l');
               wait_ms(1000);
               lcd_cls();

               lcd_putstring(0, 0, "Dekostufen");

               ok = 0;
               t1 = startbyte + 5;
               xpos = 0;
               while(t1 < MAX_EEPROM_ADR && t1 < startbyte + 10 && !ok)
                {
                   if(eeprom_rb(t1++) == 231)
                   {
                      ok = 1;

                     while(t1 < MAX_EEPROM_ADR && ok && eeprom_rb(t1++) != 232)
                        xpos = lcd_putnumber(1, xpos, eeprom_rb(t1), -1, -1, 'l') + 2;
                   }
                }
            }
          }
      }
    }while(get_keys() != 2);
   while(get_keys());
   lcd_cls();
}

/* Flash-Speicher löschen 
   Parameter: 1: Nur Profilspeicher löschen, 2: kompletten Speicher löschen? */

void clear_flash(int erasemode)
{
    unsigned int t1, startadr = 0;

    while(get_keys());
    lcd_cls();

   if(erasemode == 1)
       startadr = EEPROM_PROF_START;

    /* TG-Profildaten loeschen? */
   if(startadr == EEPROM_PROF_START)
   {
        lcd_putstring(0, 0, "TG-Profile loe-");
        lcd_putstring(1, 0, "schen? (j/n)");
    }
   else
   {
        lcd_putstring(0, 0, "Flashspeicher");
        lcd_putstring(1, 0, "loeschen? (j/n)");
   }

    do
    {
        if(get_keys() == 3)
        {
            lcd_cls();
            lcd_putstring(0, 0, "Loesche Byte:");
            cli();
            for(t1 = startadr; t1 <= MAX_EEPROM_ADR; t1++)
            {
                while(!eeprom_is_ready());
                eeprom_wb(t1, 0);
                lcd_putnumber(1, 0, t1, -1, -1, 'l');
            }
            while(!eeprom_is_ready());
            eeprom_wb(30, EEPROM_PROF_START);
            while(!eeprom_is_ready());
            eeprom_wb(31, 0);
            sei();
            lcd_cls();
            return;
        }
    }while(get_keys() != 2);
    while(get_keys());
    lcd_cls();

}



/* Wartezeit in Millisekunden bei fck = 8.000 MHz */
void wait_ms(int ms)
{
    int t1, t2;

    for(t1 = 0; t1 < ms; t1++)
        for(t2 = 0; t2 < 137 * SCLOCK; t2++)
            asm volatile ("nop" ::);
}

void lcd_display_test()
{
    unsigned int t1;
    while(get_keys());
    lcd_cls();

    /* Testroutine für LCD-Anzeige */
    lcd_putstring(0, 0, "Displaytest?");
    lcd_putstring(1, 0, "(j/n)");
    do
    {
        if(get_keys() == 3)
        {
          while(get_keys());
         while(!get_keys())
         {
             for(t1 = 65; t1 < 81; t1++)
                 lcd_putchar(0, t1 - 65, t1);
             for(t1 = 97; t1 < 113; t1++)
                 lcd_putchar(1, t1 - 97, t1);
            wait_ms(1000);
            lcd_cls();
         }
            return;
        }
    }while(get_keys() != 2);
    while(get_keys());
    lcd_cls();
}


/* LEDs an PC2, 3 und 4 */
void led(char lednum, char status)
{
    if(status)
        cbi(PORTC, lednum);
    else
        sbi(PORTC, lednum);
}


/* Einstellungen durch Benutzer                */
/* Tastenentprellung per Hardware erforderlich */
int get_keys(void)
{
    char x = 1, t1;
    for(t1 = 1; t1 < 4; t1++)
    {
        if(inp(PINB) & x) /* PB0, PB1 etc. */
            return t1;
        x *= 2;
    }

    return 0;
}

/* Benutzereinstellungen */
void settings(void)
{
    int menu_sta[MENU_ITEMS] = {900, 0, 400, 10, 2, 3, 0, 0};          /* Startwerte fuer Wertepektrum */
    int menu_end[MENU_ITEMS] = {1100, 4000, 1000, 20, 16, 20, 1, 1};   /* Endwerte fuer Wertepektrum   */
    int menu_step[MENU_ITEMS] = {5, 100, 5, 1, 1, 1, 1, 1};         /* Inkrement                    */

    int menu_N2[4]; /* Temporaere Werte fuer Stickstoff */
    int menu_He[4]; /* Und Helium                       */
    int intv, t1;

    char ch, xpos;

    int menu_tmpval[MENU_ITEMS];
    menu_tmpval[0] = airp0 * 1000;   /* Luftdruck                                                     */
    menu_tmpval[1] = altitude;       /* Hoehe ueber NN                                                */
    menu_tmpval[2] = cabinp * 1000;  /* Kabinendruck Flugzeug                                         */
    menu_tmpval[3] = maxppO2;        /* Max. zul. Sauerstoffpartialdruck (10facher Wert!)             */
    menu_tmpval[4] = constppO2;      /* Konstanter Sauerstoffpartialdruck fuer CCR (10facher Wert!)   */
    menu_tmpval[5] = f_cons;         /* Multiplikationsfaktor fuer Übersaettigungstoleranzen          */
    menu_tmpval[6] = eeprom_rb(12);  /* Anti-Guide-Modus                                              */
    menu_tmpval[7] = eeprom_rb(18);  /* Anti-Guide-Modus                                              */

    for(t1 = 0; t1 < 4; t1++)
    {
        menu_N2[t1] = figN2[t1] * 100;
        menu_He[t1] = figHe[t1] * 100;
    }

    while(get_keys());
    lcd_cls();

    for(t1 = 0; t1 < MENU_ITEMS; t1++)
    {
        lcd_putstring(0, 0, menu_str[t1]);
        xpos = lcd_putnumber(1, 0, menu_tmpval[t1], menu_digits[t1], menu_dec[t1], 'l') + 1;
        lcd_putstring(1, xpos, menu_unitstr[t1]);

        do
        {
            ch = get_keys();
            if(ch == 1 || ch == 3)
            {
                lcd_linecls(1, 15);
                intv =  menu_tmpval[t1] / menu_step[t1];
                switch(ch)
                {
                  case 3:
                    menu_tmpval[t1] = intv * menu_step[t1] + menu_step[t1];
                    if(menu_tmpval[t1] > menu_end[t1])
                        menu_tmpval[t1] = menu_sta[t1] ;
                    break;

                  case 1:
                    menu_tmpval[t1]  = intv *  menu_step[t1] - menu_step[t1];
                    if(menu_tmpval[t1] < menu_sta[t1])
                        menu_tmpval[t1] = menu_end[t1];
                }
                xpos = lcd_putnumber(1, 0, menu_tmpval[t1], menu_digits[t1], menu_dec[t1], 'l') + 1;
                lcd_putstring(1, xpos, menu_unitstr[t1]);
                wait_ms(100);
            }
        }while(ch != 2);
        while(get_keys());
        lcd_cls();
    }

    /* 4 Atemgase */

    for(t1 = 0; t1 < 4; t1++)
    {
        /* N2 */
        lcd_putstring(0, 0, "Gas   N2-Anteil");
        lcd_putnumber(0, 4, t1 + 1, -1, -1, 'l');
        xpos = lcd_putnumber(1, 0, menu_N2[t1], -1, -1, 'l');
        lcd_putstring(1, xpos, "%  ");
        do
        {
            ch = get_keys();
            if(ch == 1 || ch == 3)
            {
                lcd_linecls(1, 15);
                switch(ch)
                {
                  case 3:
                    menu_N2[t1]++;
                    if(menu_N2[t1] > 79)
                        menu_N2[t1] = 0;
                    break;

                  case 1:
                    menu_N2[t1]--;
                    if(menu_N2[t1] < 0)
                        menu_N2[t1] = 79;
                }
                xpos = lcd_putnumber(1, 0, menu_N2[t1], -1, -1, 'l');
                lcd_putstring(1, xpos, "%  ");
                lcd_putstring(1, 5, "Nitrox");
                lcd_putnumber(1, 12, 100 - menu_N2[t1], -1, -1, 'l');
            }
            wait_ms(100);
        }while(ch != 2);

        lcd_linecls(1, 15);

        /* He */
        lcd_putstring(0, 0, "Gas   He-Anteil");
        lcd_putnumber(0, 4, t1 + 1, -1, -1, 'l');
        xpos = lcd_putnumber(1, 0, menu_He[t1], -1, -1, 'l');
        lcd_putstring(1, xpos, "%  ");
        do
        {
            ch = get_keys();
            if(ch == 1 || ch == 3)
            {
                lcd_linecls(1, 15);
                switch(ch)
                {
                  case 3:
                    menu_He[t1]++;
                    if(menu_He[t1] > 99)
                        menu_He[t1] = 0;
                    break;

                  case 1:
                    menu_He[t1]--;
                    if(menu_He[t1] < 0)
                        menu_He[t1] = 99;
                }
                xpos = lcd_putnumber(1, 0, menu_He[t1], -1, -1, 'l');
                lcd_putstring(1, xpos, "%  ");
            }
            wait_ms(100);
        }while(ch != 2);

        while(get_keys());
        lcd_cls();
    }

    /* Speichern? */
    lcd_putstring(0, 0, "Sichern? (j/n)");
    do
    {
        if(get_keys() == 3)
        {
            cli();
            /* Luftdruck am Tauchort */
            airp0 = menu_tmpval[0] * 0.001;
            while(!eeprom_is_ready());
            eeprom_wb(0, menu_tmpval[0] & 0x00FF);          /* LoByte */
            while(!eeprom_is_ready());
            eeprom_wb(1, (menu_tmpval[0] & 0xFF00) / 256);  /* HiByte */

            /* Hoehe ueber NN */
            altitude = menu_tmpval[1];
            while(!eeprom_is_ready());
            eeprom_wb(16, menu_tmpval[1] & 0x00FF);          /* LoByte */
            while(!eeprom_is_ready());
            eeprom_wb(17, (menu_tmpval[1] & 0xFF00) / 256);  /* HiByte */

            calc_airp_divesite(1); /* Luftdruck am Tauchort nachberechnen */
            wait_ms(2000);
            lcd_cls();

            /* Kabinendruck im Flugzeug */
            cabinp = menu_tmpval[2]* 0.001;
            while(!eeprom_is_ready());
            eeprom_wb(14, menu_tmpval[2] & 0x00FF);          /* LoByte */
            while(!eeprom_is_ready());
            eeprom_wb(15, (menu_tmpval[2] & 0xFF00) / 256);  /* HiByte */

            /* max. ppO2 */
            maxppO2 = menu_tmpval[3];
            while(!eeprom_is_ready());
            eeprom_wb(11, menu_tmpval[3]);

            /* const. ppO2 */
            constppO2 = menu_tmpval[4];
            while(!eeprom_is_ready());
            eeprom_wb(13, menu_tmpval[4]);

            /* Konservativfaktor */
         /* Anzeigen der a- und b-Werte wenn geändert */
            if(menu_tmpval[5] != f_cons)
            {
                set_ab_values(menu_tmpval[5], 1);
                while(!eeprom_is_ready());
                eeprom_wb(10, menu_tmpval[5]);
                f_cons = menu_tmpval[5];
            }

            /* ADGModus */
            adg_mode = menu_tmpval[6];
            while(!eeprom_is_ready());
            eeprom_wb(12, menu_tmpval[6]);

            /* ppN2-Anzeige nach TG */
            show_ppN2 = menu_tmpval[7];
            while(!eeprom_is_ready());
            eeprom_wb(18, menu_tmpval[7]);

            /* Gase */
            for(t1 = 0; t1 < 4; t1++)
            {
                figN2[t1] = menu_N2[t1] * 0.01;
                figHe[t1] = menu_He[t1] * 0.01;
                while(!eeprom_is_ready());
                eeprom_wb(t1 * 2 + 2, menu_N2[t1]);
                while(!eeprom_is_ready());
                eeprom_wb(t1 * 2 + 3, menu_He[t1]);
            }

            sei();

            lcd_putstring(0, 2, "Gespeichert.");
         wait_ms(1000);
         lcd_cls();
         return;
        }
    }while(get_keys() != 2);
    while(get_keys());
    lcd_cls();
}

/* Timer 2 Ereignisroutine (autom. Aufruf 1/s) */
INTERRUPT(SIG_OVERFLOW2)
{
    runseconds++;

    outp(0, TCNT2);       /* Timerregister auf 0 */
}

/* AD-Wandler Ereignisroutine */
SIGNAL(SIG_ADC)
{
    unsigned char lo, hi;

    lo = inp(ADCL);
    hi = inp(ADCH);

    adc_val = hi * 256 + lo;
    if(!adc_mode)
        depth = adc_val;
    else
        temp = adc_val * -0.077 + 50;
}

void eeprom_store_byte(char eeprom_val)
{
    if(eeprom_byte_count < EEPROM_PROF_START || eeprom_byte_count > MAX_EEPROM_ADR)
        eeprom_byte_count = EEPROM_PROF_START;

    cli();
    while(!eeprom_is_ready());
    eeprom_wb(eeprom_byte_count++, eeprom_val);
    sei();
}

int main()
{
    unsigned long seconds_old1, seconds_old2, seconds_old3;
    unsigned char do_record_depth = 0; /* Intervallschalter fuer Profilaufzeichnung */
   unsigned char info_mode = 0;       /* Definieren, was angezeigt werden soll     */
    unsigned char nft = 0;             /* Flugverbotszeit                           */
   unsigned char is_deco;
    char xpos;
   unsigned int cur_comp = 0;
   char max_info_mode;

    int t1;

    /* Ports einrichten */
    /* OUTPUT */
    /* Port D Bit 4-7 auf "Output" schalten (=Display=DB4-DB7) */
    outp(0xF0, DDRD);
    /* Port C Bit 0 bis 4 auf "Output" schalten */
    /* LCD RS, E, LEDs und BIAS Drucksensor bei niedr. Temp) */
    outp(0x3F, DDRC);

    /* Alle LEDs aus */
    for(t1 = 2; t1 < 5; t1++)
        led(t1, 0);

    /* Temperaturkompensation des Drucksensors deaktivieren */
    sbi(PORTC, 5);

    /* Mit LCD-Initialisierung 0.2 s warten bis PowerUp von MC OK */
    wait_ms(200);
    lcd_init();
    lcd_putstring(0, 5, "SBTC 2");

    /* Softwareversion */
    for(t1 = 0; t1 < 3; t1++)
    {
        if(softwareversion[t1] != eeprom_rb(21 + t1))
        {
            while(!eeprom_is_ready());
            eeprom_wb(21 + t1, softwareversion[t1]);
        }
    }

    lcd_putstring(1, 5, "V .");
    lcd_putnumber(1, 6, softwareversion[0], -1, -1, 'l');
    lcd_putnumber(1, 8, softwareversion[1], 2, -1, 'l');
    lcd_putchar(1, 10, softwareversion[2]);

    /* Watchdog aus, wird nicht gebraucht, da Software zuverlaessig ist ;-)) */
    /* Logisch '1' in WDTOE und WDE schreiben */
    WDTCR = (1<<WDTOE) | (1<<WDE);
    /* WDT abschalten */
    WDTCR = 0x00;

    /* Umgebungsluftdruck */
    wait_ms(INITWAIT);
    lcd_cls();
    airp0 = (eeprom_rb(0) + eeprom_rb(1) * 256) * 0.001;  /* Luftdruck */
    if(airp0 < 0.66 || airp0 > 1.2)
        airp0 = 1;
    lcd_putstring(0, 0, menu_str[0]);
    xpos = lcd_putnumber(1, 0, airp0 * 1000, -1, -1, 'l') + 1;
    lcd_putstring(1, xpos, menu_unitstr[0]);

    /* Hoehe ueber NN */
    wait_ms(INITWAIT);
    lcd_cls();
    altitude = (eeprom_rb(16) + eeprom_rb(17) * 256);  /* Hoehe ueber NN in m */
    if(altitude < 0 || altitude > 6000)
        altitude = 0;
    lcd_putstring(0, 0, menu_str[1]);
    xpos = lcd_putnumber(1, 0, altitude , -1, -1, 'l') + 1;
    lcd_putstring(1, xpos, menu_unitstr[1]);

    /* Luftdruck am Tauchort */
    calc_airp_divesite(1);

    /* Kabinendruck im Flugzeug */
    wait_ms(INITWAIT);
    lcd_cls();
    cabinp = (eeprom_rb(14) + eeprom_rb(15) * 256) * 0.001;  /* Wert aus EEPROM lesen */
    if(cabinp < 0.55 || cabinp > 1)
        cabinp = 0.62;
    lcd_putstring(0, 0, menu_str[2]);
    xpos = lcd_putnumber(1, 0, cabinp * 1000, -1, -1, 'l') + 1;
    lcd_putstring(1, xpos, menu_unitstr[2]);

    /* N2- und He-Anteile in den 4 Gasen */
   wait_ms(INITWAIT);
   figN2[0] = FN2;
   figHe[0] = 0;
   show_gas(0);
   wait_ms(INITWAIT);

    for(t1 = 1; t1 < 4; t1++)
    {
        figN2[t1] = eeprom_rb(t1 * 2 + 2) * 0.01;
        if(figN2[t1] < 0 || figN2[t1] > 0.79)
            figN2[t1] = 0.78;

        figHe[t1] = eeprom_rb(t1 * 2 + 3) * 0.01;
        if(figHe[t1] < 0 || figHe[t1] > 0.99)
            figHe[t1] = 0;

        show_gas(t1);
        wait_ms(INITWAIT);
    }

    curgas = 0;

    lcd_cls();

    /* maxppO2 */
    maxppO2 = eeprom_rb(11);
    if(maxppO2 > 20 || maxppO2 < 10)
        maxppO2 = 16;

    lcd_putstring(0, 0, menu_str[3]);
    lcd_putnumber(1, 0, maxppO2, 2, 1, 'l');
    lcd_putstring(1, 4, menu_unitstr[3]);

    wait_ms(INITWAIT);
    lcd_cls();

    /* constppO2 */
    constppO2 = eeprom_rb(13);
    if(constppO2 > 20 || constppO2 < 2)
        constppO2 = 12;

    lcd_putstring(0, 0, menu_str[4]);
    lcd_putnumber(1, 0, constppO2, 2, 1, 'l');
    lcd_putstring(1, 4, menu_unitstr[4]);

    wait_ms(INITWAIT);
    lcd_cls();

    /* ADG-Modus */
    adg_mode = eeprom_rb(12);
    if (adg_mode != 1 && adg_mode != 0)
        adg_mode = 1;
    lcd_putstring(0, 0, menu_str[6]);
    if(adg_mode)
        lcd_putstring(1, 0, "ein");
    else
        lcd_putstring(1, 0, "aus");

    wait_ms(INITWAIT);
    lcd_cls();

   /* ppN2 anzeigen */
    show_ppN2 = eeprom_rb(18);
    if (show_ppN2  != 1 && show_ppN2 != 0)
        show_ppN2  = 0;
    lcd_putstring(0, 0, menu_str[7]);
    if(show_ppN2 )
        lcd_putstring(1, 0, "an");
    else
        lcd_putstring(1, 0, "aus");

    wait_ms(INITWAIT);
    lcd_cls();


    /* Konservativ-Faktor auf 5 setzen (^= *= 1.2) */
    f_cons = 12;
    set_ab_values(f_cons, 0);
   lcd_putstring(0, 0, menu_str[5]);
   lcd_putnumber(1, 0, f_cons, menu_digits[5], menu_dec[5], 'l');
   wait_ms(INITWAIT);
    lcd_cls();

    /* Timer 2 fuer Sekundenzaehlung initialisieren */
    /* (asynchron getaktet durch 32.768 kHz-Quarz)  */
    TIMSK &=~((1<<TOIE2)|(1<<OCIE2));  /* Disable TC2 interrupt */
    ASSR |= (1<<AS2);                   /* Timer/Counter2 auf asynchronen Betrieb mit quarz 32,768kHz schalten */
    TCNT2 = 0x00;                        /* Startwert fuer Timer2 */
    TCCR2 = 0x05;                        /* Teiler ck/128 */
    while(ASSR & 0x07);                 /* Warten bis ASSR-Register neu geschrieben wurde */
    TIMSK |= (1<<TOIE2);                /* Interrupt ermoeglichen */

    sei();

    seconds_old1 = runseconds - 10;
    seconds_old2 = runseconds;
    seconds_old3 = runseconds;

    for(;;) /* Endlosschleife fuer period. Aufgaben (Druckmessung, Dekorechnung, etc.) Periode: 1/s */
    {
        get_dsensor();   /* Sensorabfrage Drucksensor          */
        if(curgas == 4) /* Wenn CCR mit const. ppO2 getaucht wird, dann Inertgasanteil berechnen */
            calc_figN2_for_constppO2();

        calc_ppO2(1);    /* ppO2 pruefen                       */
        check_vasc();    /* Aufstiegsgeschwindigkeit pruefen   */
        ldepth = depth;  /* Zusatzwert fuer Deltatiefe         */

        if(!depth && !surfaced && dphase)
        {
            eeprom_store_byte(227); /* "Aufgetaucht" ins Log schreiben */
            surfaced = 1;
        }

        if(temp < temp_min)
            temp_min = temp;

        if(depth > SWITCHDEPTH)
        {
            surfaced = 0;

            if(!dphase) /* TG beginnt, auf Tauchphase umschalten */
            {
                maxdepth = 0;
                diveseconds = 0;
                temp_min = 100;
                deco_minutes_total = 0;
                rcd_deco_minutes_total = 0;

            for(t1= 0; t1 < MAX_DECO_STEPS; t1++)
                rcd_decotime[t1] = 0;
                ndt_runout = 0;
                vasc_exceeded = 0;
                cns_dive = 0;
                temp_low = 0;

                lcd_cls();

                /* Neues TG-Profil im Ringspeicher anlegen, Startpunkt suchen */
                eeprom_byte_count = eeprom_rb(30) + 256 * eeprom_rb(31);

                /* Startsignal */
                eeprom_store_byte(228);

                /* Oberflaechenpause speichern */
                eeprom_store_byte((surf_seconds / 60) & 0x00FF);          /* Lo */
                eeprom_store_byte(((surf_seconds / 60) & 0xFF00) / 256);  /* Hi */

                /* Temperatur zu TG-Beginn */
                eeprom_store_byte(temp);

                /* Aufzeichnungsintervall */
                eeprom_store_byte(20);

                /* Indikator fuer den Beginn des TG-Profiles */
                eeprom_store_byte(229);

                surf_seconds = 0;
            }
            dphase = 1;

            diveseconds++;
        }
        else /* Oberflaechenmodus */
        {
            if(surf_seconds > SURF_SECONDS_MAX && !deco_minutes_total)    /* TG beendet */
            {
                if(dphase)
                {
                    /* EEPROM aktualisieren... */
                    /* TG-Zaehler um 1 erhoehen */
                    t1 = eeprom_rb(24) + 256 * eeprom_rb(25) + 1; /* Alten Wert holen */
                    cli();
                    while(!eeprom_is_ready());
                    eeprom_wb(24, t1 & 0x00FF);         /* LoByte */
                    while(!eeprom_is_ready());
                    eeprom_wb(25, (t1 & 0xFF00) / 256); /* HiByte */

                    /* Gesamttauchzeit erhoehen */
                    t1 = eeprom_rb(26) + 256 * eeprom_rb(27) + (int)(diveseconds / 60); /* Alten Wert holen und veraendern */
                    while(!eeprom_is_ready());
                    eeprom_wb(26, t1 & 0x00FF);           /* LoByte */
                    while(!eeprom_is_ready());
                    eeprom_wb(27, (t1 & 0xFF00) / 256);  /* HiByte */

                    /* Maximaltiefe evtl. erhoehen */
                    if(maxdepth > eeprom_rb(28) + 256 * eeprom_rb(29)) /* Alten Wert holen */
                    {
                        while(!eeprom_is_ready());
                        eeprom_wb(28, maxdepth & 0x00FF);         /* LoByte */
                        while(!eeprom_is_ready());
                        eeprom_wb(29, (maxdepth & 0xFF00) / 256); /* HiByte */
                    }
                    sei();

                    /* Indikator fuer Profilende */
                    eeprom_store_byte(230);

                    /* Tauchzeit in [min] */
                    eeprom_store_byte((diveseconds / 60) & 0x00FF);          /* Lo */
                    eeprom_store_byte(((diveseconds / 60) & 0xFF00) / 256);  /* Hi */

                    /* Max. Tiefe in [dm] */
                    eeprom_store_byte(maxdepth  & 0x00FF);          /* Lo */
                    eeprom_store_byte((maxdepth  & 0xFF00) / 256); /* Hi */

                    /* Min. Temperatur */
                    eeprom_store_byte(temp_min);

                    /* Temperatur auf max. Tauchtiefe */
                    eeprom_store_byte(temp_maxdepth);

                    /* Dekostufen */
                    eeprom_store_byte(231);
                    for(t1 = 0; t1 < MAX_DECO_STEPS; t1++)
                        eeprom_store_byte(rcd_decotime[t1]);
                    eeprom_store_byte(232);

                    /* Nr. des TG */
                    eeprom_store_byte(eeprom_rb(24) + 256 * eeprom_rb(25));

                    /* Tages ZNS */
                    eeprom_store_byte((int)cns_day  & 0x00FF);          /* Lo */
                    eeprom_store_byte(((int)cns_day & 0xFF00) / 256);  /* Hi */

                    /* Tauchgangs-ZNS */
                    eeprom_store_byte((int)cns_dive  & 0x00FF);        /* Lo */
                    eeprom_store_byte(((int)cns_dive & 0xFF00) / 256); /* Hi */

                    /* OTU */
                    eeprom_store_byte((int)otu  & 0x00FF);         /* Lo  */
                    eeprom_store_byte(((int)otu & 0xFF00) / 256);  /* Hi */

                    /* Sequenzende */
                    eeprom_store_byte(233);

                    /* Speichern der letzten Adresse bei Offset 30 & 31 */
                    cli();
                    while(!eeprom_is_ready());
                    eeprom_wb(30, eeprom_byte_count & 0x00FF);            /* LoByte */
                    while(!eeprom_is_ready());
                    eeprom_wb(31, (eeprom_byte_count & 0xFF00) / 256);   /* HiByte */
                    sei();

                    if(maxdepth > fixmaxdepth && adg_mode)
                        maxdepth = fixmaxdepth;
                }
                dphase = 0;
            }
            surf_seconds++;
        }

        /* Informationen der OFP alle 2 sec. wechseln */
        if(!dphase && !deco_minutes_total) /* Bei WT = 0 m, 0 Deco und 5 min. ausgetaucht umschalten */
        {                                   /* auf Anzeige der TG-Daten in der Zeile 1 */
            if(runseconds > seconds_old3 + 2)
            {
                switch(info_mode)
                {
                  case 0:
                    lcd_linecls(1, 12);
                    lcd_putstring(1, 0, "OFP: ");
                    xpos = lcd_putnumber(1, 5, surf_seconds * 0.0166667, -1, -1, 'l') + 5;
                    lcd_putstring(1, xpos, "'");
                    break;

                  case 1:
                    nft = calc_no_fly_time();
                    if(nft)
                    {
                        lcd_linecls(1, 12);
                        lcd_putstring(1, 0, "FVB: ");
                        xpos = lcd_putnumber(1, 5, nft, -1, -1, 'l') + 5;
                        lcd_putstring(1, xpos, "h");
                    }
                    break;

                  case 2:
                    if(cns_dive)
                    {
                        lcd_linecls(1, 12);
                        lcd_putstring(1, 0, "ZNS TG: ");
                        xpos = lcd_putnumber(1, 8, cns_dive, -1, -1, 'l') + 8;
                        lcd_putstring(1, xpos, "%");
                    }
                    break;

                  case 3:
                    if(cns_day)
                    {
                        lcd_linecls(1, 12);
                        lcd_putstring(1, 0, "ZNS D: ");
                        xpos = lcd_putnumber(1, 7, cns_day, -1, -1, 'l') + 7;
                        lcd_putstring(1, xpos, "%");
                    }
                    break;

                  case 4:
                    if(otu)
                    {
                        lcd_linecls(1, 12);
                        lcd_putstring(1, 0, "OTU: ");
                        xpos = lcd_putnumber(1, 5, otu, -1, -1, 'l') + 5;
                        lcd_putstring(1, xpos, "%");
                    }
                    break;

              case 5: /* Dekostufen anzeigen, wenn Kein ADG-Modus aktiv ist */
                    {
                 if(!adg_mode)
                 {
                   is_deco = 0;
                   for(t1 = MAX_DECO_STEPS - 1; t1 >= 0; t1--)
                   {
                     if(rcd_decotime[t1] > 0)
                      is_deco = 1;
                    }

                   if(is_deco)
                   {
                     lcd_linecls(1, 15);
                     lcd_putstring(1, 0, "DEC:");
                     xpos = 5;
                          for(t1 = MAX_DECO_STEPS - 1; t1 >= 0; t1--)
                     {
                       if(rcd_decotime[t1] > 0)
                        xpos += lcd_putnumber(1, xpos, rcd_decotime[t1], -1, -1, 'l') + 1;
                     }
                        }
                 }
               }
             }

            /* Anzeige ppN2 nach TG */
            if(info_mode > 5 && show_ppN2)
            {
                lcd_linecls(1, 15);
               lcd_putstring(1, 0, "ppIg");
               xpos = lcd_putnumber(1, 4, cur_comp + 1, -1, -1, 'l') + 4;
               lcd_putstring(1, xpos, ":");

               lcd_putnumber(1, xpos + 2, pig[cur_comp++] * 1000, 4, 3, 'l');
               if(cur_comp > 15)
                 cur_comp = 0;
            }

                if(show_ppN2)
                max_info_mode = 21;
            else
                    max_info_mode = 5;

                if(info_mode < max_info_mode)
                    info_mode++;
                else
                    info_mode = 0;

                seconds_old3 = runseconds;
            }
        }

        /*  Alle 10 sec. Gewebesaettigung & Dekorechnung */
        if(runseconds >= seconds_old1 + 10)
        {

         if(dphase)
         {
              lcd_cls();
         }

            get_tsensor();
            if(temp <= 8 && !temp_low && dphase)
            {
                temp_low = 1;
                set_ab_values(f_cons + 1, 0);
            }

            /* Bei kaltem Wasser Sensor nachjustieren */
            if(temp <= 10 && depth < 200)
                cbi(PORTC, 5);
            else
                sbi(PORTC, 5);

            /* Wenn CCR mit const. ppO2 getaucht wird, dann Inertgasanteil berechnen */
            if(curgas == 4 && dphase)
            {
                lcd_linecls(1, 12);
                lcd_putstring(1, 0, "N2:");
                xpos = lcd_putnumber(1, 4, figN2[4] * 100, -1, -1, 'l') + 4;
                lcd_putchar(1, xpos, '%');
                wait_ms(1000);
            }

            /* Saettigungsrechnung */
            calc_p_inert_gas(depth * 0.1);
            calc_deco();

            /* TG-Profilpunkt speichern als Absolutwert in [m] in 1 Byte alle 20s */
            if(do_record_depth >= 1)
            {
             eeprom_store_byte((unsigned char) (depth * .1));
                do_record_depth = 0;
            }
            else
                do_record_depth++;

            vasc_exceeded = 0;
            ppo2_exceeded = 0;
            decostep_skipped = 0;
            seconds_old1 = runseconds;
        }

        /* Jede Minute ZNS und OTU berechnen */
        if(runseconds > seconds_old2 + 60)
        {
            calc_cns_otu();
            seconds_old2 = runseconds;
        }

        /*  Tastaturabfrage ob Einstellungen gesetzt werden sollen */
        switch(get_keys())
        {
          case 1: /* Abfrage ob verschiedene Extrafunktionen ausgeführt werden sollen */
          sbtc2pc();
         display_profile();
            clear_flash(1); /* TG Profile loeschen ?*/
         clear_flash(2); /* kompletten Flash loeschen ?*/
         display_rcd();
         display_log();
         lcd_display_test();
            break;

          case 2: /* Einstellungen */
            settings();
            break;

          case 3:  /* Gaswechsel */
            set_curgas();
        }

        /* Mikrocontroller fuer den Rest der Sekunde in Energiesparmodus schalten */
        /* AD-Wandler aus */
        outp(0, ADCSRA);
        /* In Sleep-Mode gehen */
        set_sleep_mode (SLEEP_MODE_PWR_SAVE);
        sleep_mode();
    }
    return 0;
}