/*
Diplomova prace : Palubni pocitac

Hlavni aplikace

Atmega128A 10 MHz XTAL

Autor: Ondrej Lutera

2011/2012

*/

/* avrlib */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "define.h"

/* LCD */
#include "lib/dogm128.h"
/* dalsi perierie */
#include "ds18lib/ds18x20.h"
#include "ds18lib/onewire.h"
#include "uart.h"

/* knihovna SD/SDHC karty a FAT16 / FAT32 */
#include "sdlib/fat.h"
#include "sdlib/fat_config.h"
#include "sdlib/partition.h"
#include "sdlib/sd_raw.h"
#include "sdlib/sd_raw_config.h"

/* vlastni knihovny */
#include "i2clib/pcf8563.h"
#include "i2clib/pca9530.h"
#include "car_meas.h"
#include "gui.h"
#include "keys.h"
#include "storage.h"
#include "user.h"
#include "pwrctrl.h"
#include "serial_num.h"
#include "temp.h"
#include "timer.h"
#include "adc.h"
#include "backlight.h"
#include "helper_func.h"

/* globalni data pro main() atd - nevytvareji se pres zasobnik, lepsi kontrola velkych struktur vs zaplneni RAM pres avr-size */

char dText[DTEXT_MAX];      // pomocny globalni buffer pro dynamicky text
clb_t localCalibData;   // lokalni kalibracni data pro zobrazeni a bezpecnou editaci
uint16_t mV =0;         // pomocna merici promenna pro menu tank kalibrace
temp_t newSensors[MAX_SENSORS]; /* buffer pro vyhledavani a inicializaci senzoru */
uint8_t menuFoundTemp = 0;      /* pocet nove nalezenych senzoru, vyuziva se pro praci s editaci v menu */
uint8_t menuRegTemp = 0;        /* pocet nalezenych registrovanych senzoru , vyuziva se pro praci a editaci v menu */
int16_t regTemp[MAX_SENSORS];   /* pole znamych pripojenych senzoru teploty, vyuziva se pro spravu senzoru v menu */
int16_t newTemp[MAX_SENSORS];   /* pole nove pripojenych senzoru teploty, vyuziva se pro spravu senzoru v menu */
uint8_t userIndex = 0;  /* tento index slouzi jako pomocna promenna pro praci s menu a editaci uzivatelu */
user_t userData;        /* buffer - pouziva se pro ziskani a editaci a pripadne nasledne ulozeni dat uzivatele v admin rezimu */
list_t menuItems[MENU_MAX_ITEMS];   // prvky menu - jeden spolecny buffer
vscreen_t screen;
menu_t menuScr;
pcf_t localTime;    /* udrzuje lokalni info o case */
pcf_t editTime;     /* editTime se pouziva v menu a takztez pro vykresleni a prepocet udaju na screen */

avg_t menuAvg;

char * txtOk = TEXT_OK;
char * txt_  = TEXT___;
char * txtYes = TEXT_YES;
char * txtNo = TEXT_NO;

int16_t temp[MAX_SENSORS];

/* pro dynamicke vycteni adresarove a souborove struktury na SD karte potrebujeme globalni buffer textu jednotlivych adresaru.
Je to mnohem rychlejsi a bezpecnejsi nez stale dokola pri kazdem prekresleni LCD cist SD kartu

*/

char Buff[FS_TXT_SIZE];  /* tento buffer slouzi pro ruzne urychleni prace s eeprom ci s sd kartou */

struct
{

    char * fsBuff;  /* pointer na buffer Buff */
    uint8_t fsItems;
    uint8_t firstIndex; /* pouziva se pro seek v souborech - urcuje index prvni trasy v bufferu */
    /* zde si uchovame nazvy prochazeni slozek */
    char year[6];
    char month[4];
    char day[8];
    char actPath[ACT_PATH_SIZE]; /* promenna ktera udava aktualni zpracovavanou cestu na SD karte pri prochazeni logovanych dat..
                     jedna se o cestu v textove podobe.. maximalni delka cesty ve tvaru pr. /users/f8/data/2012/03/08.dat tj cca 30B + rezerva*/
} fslog;


void getScreen(vscreen_t * screen,uint32_t menu);
void getUserNames(void);
unsigned char checkLogin(void);
char * getfsBuffPtr(uint8_t index,char * fsB,uint16_t fsSize);
void getMenu(menu_t *m,uint32_t menu);
void lcdOff(void);
uint8_t checkSleep(uint8_t cond);
/* zde si osetrime nevyuzivana preruseni. tyto by nemely v zadnem pripade nastat. Ovsem pokud se neco vlivem ruseni pokazi, je dobre mit info pres seriovy port
*/
#define I(a) ISR(_VECTOR(a)){ \
                uart_putc(a); \
             }

I(1);
I(3);
I(4);
I(7);
I(9);
I(11);
I(12);
I(13);
I(15);
I(17);
I(20);
I(21);
I(22);
I(23);
I(24);
I(25);
I(26);
I(27);
I(28);
I(32);
I(33);
I(34);


/* exportuje jmena uzivatelu do globalniho bufferu */
void getUserNames(void)
{
    uint8_t i;
    for(i=0; i<MAX_USERS; i++)
    {
#if FS_TXT_SIZE < (MAX_USERS*NAME_LEN)
#warning Zvetsit FS_TXT_SIZE ! Buffer overflow..
#endif

        getUserName(i,&Buff[i*NAME_LEN]);

        if(getUserInitSet(i)!=USER_INIT_SET)strcpy_P(&Buff[i*NAME_LEN],PSTR("None"));

    }



}
/* fce volana pri nalogovani.. hleda zda je vytvoren alespon admin pripadne jej vytvori a preda rizeni logovaci funkci */
unsigned char checkLogin(void)
{
    ibutton_t ibutton1;
    ibutton_t ibutton2;
    user_t admin;
    unsigned char i;
    unsigned char compare;
    DOG_PSTR_P txtLogin=NULL;
    uint8_t mul=0xff;
    key_t k;

    if(!checkRoot())
    {
        txtLogin = DOG_PSTR(TEXT_REG_ADMIN);


        if(ibuttonFind())
        {

            ibuttonRead(&ibutton1);

            _delay_ms(100);

            ibuttonRead(&ibutton2);

            compare = 0;

            for(i=0; i<SP_SIZE; i++)
            {
                compare|=ibutton1.romCode[i]^ibutton2.romCode[i];
                mul&=(ibutton1.romCode[i]);

            }
            if(compare==0 && mul!=0xff)
            {
                memset(&admin,0,sizeof(user_t));

                /* nasel ibutton cislo */
                memcpy(&admin.iButton,&ibutton1,sizeof(ibutton_t));

                /* generovani nahodneho cisla */

                redrawLogTxt(DOG_PSTR(TEXT_PRESS_OK));

                do
                {

                    GetKeys(&k,1);
                    i++;
                    _delay_ms(1);
#ifdef CAR_WDT_EN

                    wdt_reset();
#endif


                }
                while(!(k.keys&OK) || i==0);

                redrawWaitScreen();

                admin.uid = i;
                admin.gid = G_ROOT;
                admin.init=USER_INIT_SET;

                getTimePCF(&admin.lastLogin);   // ukladany cas, se znamym letopoctem..
                getFromPCF(&admin.lastLogin);   // zpresneny o sekundy

                memset(&admin.expTime,0,sizeof(pcf_t));     /* nikdy nekoncici ucet admina */

                admin.trackDelay = 5;
                admin.suspendDelay = 5;

                strcpy_P(admin.name,DOG_PSTR("Admin"));     /* inicializuje jmeno uctu, ktere lze pak zmenit v nastavenich */

                //utoa(admin.uid,dText,16);
                snprintf_P(dText,DTEXT_MAX,PSTR("%02x"),admin.uid);

                createDir(USERS_FOLDER,dText);

                snprintf_P(dText,DTEXT_MAX,PSTR("%s/%02x"),USERS_FOLDER,admin.uid);

                createDir(dText,DATA_FOLDER);

                if(initUser(0,&admin)) redrawLogTxt(DOG_PSTR(TEXT_ADMIN_CREATED));

                resetUserScrData(0);

                _delay_ms(1000);


            }



        }

    }
    else
    {

        txtLogin = DOG_PSTR(TEXT_LOGIN);


    }

    i = userLogin();

    if(checkRoot() && i==EXP_USER) txtLogin = DOG_PSTR(TEXT_EXP_USER);

    redrawLogTxt(txtLogin);

    return i;

}
/* funkce pro naplneni ukazatelu obrazovky na data */
inline void getScreen(vscreen_t * screen,uint32_t menu)
{
    uint8_t val;
    if(menu<MAX_SCREENS)
    {

        screen->valFont = VAL_FONT;
        screen->unitFont = UNIT_FONT;
        screen->bigValFont = BIG_VAL_FONT;
        screen->textFont = TEXT_FONT;

        uint8_t i;
        scr_t * pScrData = getActiveUserScrData();

        for(i=0; i<MAX_ITEMS; i++)
        {
            item_t * p = &screen->item[i];
            val=pScrData->scr[menu][i];

            switch(val)
            {

            case 0:
                p->value.ui32 = GetAvgFuelCons();
                p->prec = FUEL_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_AVG);
                p->unit = DOG_PSTR(UNIT_LKM);

                break;
            case 1:

                if(GetActMeters()>4)    // rychlost vetsi jak 18 km/h?
                {
                    p->value.ui32 = GetCurrFuelCons();
                    p->unit = DOG_PSTR(UNIT_LKM);
                }
                else
                {
                    p->value.ui32 = GetCurrFuelConsLh();
                    p->unit = DOG_PSTR(UNIT_LH);
                }
                p->prec  = FUEL_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_ACT);



                break;

            case 2:
                p->value.ui32 = GetCurrMeters()/100;
                p->prec = KM_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_ACT);
                p->unit = DOG_PSTR(UNIT_KM);

                break;
            case 3:
                p->value.ui32 = GetCurrRpm();
                p->prec = 0;
                p->text.flash = DOG_PSTR(TEXT_RPM);
                p->unit = DOG_PSTR(UNIT_RPM);

                break;
            case 4:
                p->value.ui32 = GetMaxDis();
                p->prec = 0;
                p->text.flash = DOG_PSTR(TEXT_DISTANCE);
                p->unit = DOG_PSTR(UNIT_KM);

                break;

            case 5:

                p->value.ui32= GetCurrFuel();
                p->prec = FUEL_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_ACT);
                p->unit = DOG_PSTR(UNIT_L);

                break;

            case 7:

                p->value.ui32 = GetTripFuelCons();
                p->prec = FUEL_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_TRIP);
                p->unit = DOG_PSTR(UNIT_LKM);

                break;

            case 6:     // dlouhy format !

                p->value.pTime = getPcfFormat(GetTripTime(),&editTime);
                p->prec = FORMAT_TIME;
                p->text.flash = DOG_PSTR(TEXT_TRIP);
                p->unit = NULL;

                break;

            case 8:
                p->value.ui32 = GetTripSpeed();
                p->prec = 0;
                p->text.flash = DOG_PSTR(TEXT_TRIP);
                p->unit = DOG_PSTR(UNIT_KMH);

                break;

            case 9:
                p->value.ui32 = GetTripFuel();
                p->prec = FUEL_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_TRIP);
                p->unit = DOG_PSTR(UNIT_L);


                break;

            case 10:


                p->value.ui32 = GetTripMeters()/100;
                p->prec = KM_CONS_PREC;
                p->text.flash = DOG_PSTR(TEXT_TRIP);
                p->unit = DOG_PSTR(UNIT_KM);

                break;

            case 13:

                p->value.ui32 =GetAvgSpeed();
                p->prec = 0;
                p->text.flash = DOG_PSTR(TEXT_AVG);
                p->unit = DOG_PSTR(UNIT_KMH);


                break;

            case 12:
                p->value.ui32 = GetCurrSpeed();
                p->prec = 0;
                p->text.flash = DOG_PSTR(TEXT_ACT);
                p->unit = DOG_PSTR(UNIT_KMH);


                break;

            case 11:        // dlouhy format!

                p->value.pTime = &localTime;
                p->prec = FORMAT_TIME;
                p->text.flash = DOG_PSTR(TEXT_TIME);
                p->unit = NULL;


                break;

            case 14:

                p->value.ui32 = GetTankL();
                p->prec = 0;
                p->text.flash = DOG_PSTR(TEXT_TANK);
                p->unit = DOG_PSTR(UNIT_L);

                break;



            case 15:
                p->value.ui32 = GetV12mV()/100;
                p->prec = V12_PREC;
                p->text.flash = DOG_PSTR(TEXT_BAT);
                p->unit = DOG_PSTR(UNIT_V);

                break;

            case 16:        /* prozatim nezobrazeno, dlouhy format! */

                p->value.pTime = getPcfFormat(GetCurrTime(),&editTime);
                p->prec = FORMAT_TIME;
                p->text.flash = DOG_PSTR(TEXT_ACT);
                p->unit = NULL;


                break;

            case (MAX_VAL-1):
            case (MAX_VAL):

                // if(tempSensorCon(val-(MAX_VAL-3))){
                p->value.temp=temp[val-(MAX_VAL-1)];
                p->prec = FORMAT_TEMP;
                p->text.ram = getTempSensorText(val-(MAX_VAL-1));
                p->unit = DOG_PSTR(UNIT_C);


                break;



            default:
                break;


            }



        }


    }

}
/* pomocna funkce pro seek pres buffer ve kterem jsou za sebou ulozeny stringy navzajem oddelene '\0'
   vraci ukazatel na pocatek stringu udaneho relativnim indexem
*/
char * getfsBuffPtr(uint8_t index,char * fsB,uint16_t fsSize)
{

    uint8_t i=0;
    char * p = fsB;
    if(fsB!=NULL && fsSize)
    {

        while(i < index)
        {

            while(*p!='\0' && p < &fsB[fsSize-2])p++;

            p++; /* preskoc '\0' */
            i++;

        }

    }

    return p;
}

#define MENU_ITEM_UINT(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.val=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_UINT;       \
        MENU_PTR->list[INDEX++].prec=PREC

#define MENU_ITEM_UCHAR(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.ui8=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_UCHAR;       \
        MENU_PTR->list[INDEX++].prec=PREC

#define MENU_ITEM_TIME(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.time=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_TIME;       \
        MENU_PTR->list[INDEX++].prec=PREC

#define MENU_ITEM_DATE(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.time=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_DATE;       \
        MENU_PTR->list[INDEX++].prec=PREC

#define MENU_ITEM_TEXT(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.text=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_TEXT;       \
        MENU_PTR->list[INDEX++].prec=PREC


#define MENU_ITEM_SINT(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.sval=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_SINT;       \
        MENU_PTR->list[INDEX++].prec=PREC

#define MENU_ITEM_UI32(MENU_PTR,INDEX,TEXT,VAL,PREC) \
        MENU_PTR->list[INDEX].text=DOG_PSTR(TEXT);  \
        MENU_PTR->list[INDEX].edit.ui32=VAL;         \
        MENU_PTR->list[INDEX].mode=MODE_UI32;       \
        MENU_PTR->list[INDEX++].prec=PREC

void getMenu(menu_t *m,uint32_t menu)
{
    uint8_t i;

    uint8_t k = 0;




    if(menu>MAX_SCREENS && m->list!=NULL)
    {

        switch(menu)
        {

        case MENU_SCREEN:

            i=0;
            MENU_ITEM_UINT(m,i,TEXT_CLEAR_TRIP,NULL,0);

            MENU_ITEM_UINT(m,i,TEXT_USER_SETTINGS,NULL,0);
            MENU_ITEM_UINT(m,i,TEXT_USER_STAT,NULL,0);
            MENU_ITEM_UINT(m,i,TEXT_SETTINGS,NULL,0);
            MENU_ITEM_UINT(m,i,TEXT_SYS_LOG,NULL,0);
            strcpy_P(dText,PSTR(TEXT_MENU));
            strncat(dText,getActiveUserName(),DTEXT_MAX);
            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;
            m->font = MENU_LIST_FONT;
            m->list_size = i;

            break;
        case MENU_USER_SETTINGS:
            i=0;
            MENU_ITEM_TEXT(m,i,TEXT_USER_NAME,getActiveUserName(),0);
            MENU_ITEM_UCHAR(m,i,TEXT_USER_TRACK_DELAY,getActiveTrackDelay(),0);
            MENU_ITEM_UCHAR(m,i,TEXT_USER_SUSPEND_MIN,getActiveSuspendMin(),0);
            MENU_ITEM_UINT(m,i,TEXT_BACKLIGHT,NULL,0);
            MENU_ITEM_UINT(m,i,TEXT_CUSTOMIZE_SCR,NULL,0);
            MENU_ITEM_TIME(m,i,TEXT_USER_EXP_TIME,getActiveExpTime(),0);
            MENU_ITEM_DATE(m,i,TEXT_USER_EXP_DATE,getActiveExpTime(),0);

            strcpy_P(dText,PSTR(TEXT_USER_SETTINGS));
            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;
            m->font = MENU_LIST_FONT;
            m->list_size = i;

            break;
        case MENU_CUST_BCK:

            i=0;
            k=0;

            MENU_ITEM_UCHAR(m,i,TEXT_OPTO_0,&getActiveUserOpto()->data[k].opto,0);
            MENU_ITEM_UCHAR(m,i,TEXT_PWM_0,&getActiveUserOpto()->data[k++].pwm,0);
            MENU_ITEM_UCHAR(m,i,TEXT_OPTO_1,&getActiveUserOpto()->data[k].opto,0);
            MENU_ITEM_UCHAR(m,i,TEXT_PWM_1,&getActiveUserOpto()->data[k++].pwm,0);
            MENU_ITEM_UCHAR(m,i,TEXT_OPTO_2,&getActiveUserOpto()->data[k].opto,0);
            MENU_ITEM_UCHAR(m,i,TEXT_PWM_2,&getActiveUserOpto()->data[k++].pwm,0);
            MENU_ITEM_UCHAR(m,i,TEXT_OPTO_3,&getActiveUserOpto()->data[k].opto,0);
            MENU_ITEM_UCHAR(m,i,TEXT_PWM_3,&getActiveUserOpto()->data[k++].pwm,0);
            MENU_ITEM_UCHAR(m,i,TEXT_OPTO_4,&getActiveUserOpto()->data[k].opto,0);
            MENU_ITEM_UCHAR(m,i,TEXT_PWM_4,&getActiveUserOpto()->data[k].pwm,0);

            snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_MENU_BCK),getActOptoIx(),getActOptoPwm());

            m->titleText =dText;
            m->titleFont = MENU_TITLE_FONT;
            m->font = MENU_LIST_FONT;
            m->list_size = i;

            break;

        case MENU_SETTINGS:

            i=0;

            MENU_ITEM_TIME(m,i,TEXT_TIME,&editTime,0);
            MENU_ITEM_DATE(m,i,TEXT_DATE,&editTime,0);
            MENU_ITEM_UINT(m,i,TEXT_C_VALVE,&localCalibData.NumV,0);
            MENU_ITEM_UINT(m,i,TEXT_C_INJ,&localCalibData.InjFlow,1);
            MENU_ITEM_UINT(m,i,TEXT_C_KM,&localCalibData.Meters,0);
            MENU_ITEM_UINT(m,i,TEXT_C_RPM,&localCalibData.Rpm,0);
            MENU_ITEM_UINT(m,i,TEXT_C_L,&localCalibData.TankL,0);
            MENU_ITEM_TEXT(m,i,TEXT_TANK_INT,(localCalibData.tankInt?txtYes:txtNo),0);
            MENU_ITEM_UINT(m,i,TEXT_C_TANK,NULL,0);
            MENU_ITEM_UINT(m,i,TEXT_MANAGE_USERS,0,0);
            MENU_ITEM_UINT(m,i,TEXT_TEMP_SENSORS,0,0);
            MENU_ITEM_UINT(m,i,TEXT_FACTORY,0,0);

            strcpy_P(dText,PSTR(TEXT_SETTINGS));

            m->titleText =dText;
            m->titleFont = MENU_TITLE_FONT;

            m->font = MENU_LIST_FONT;
            m->list_size = i;

            break;

        case MENU_TANK_CALIB:

            i=0;
            k=0;
            MENU_ITEM_UINT(m,i,TEXT_CONST0_L,&localCalibData.TankCalib[k].litr,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST0_MV,&localCalibData.TankCalib[k++].mvolt,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST1_L,&localCalibData.TankCalib[k].litr,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST1_MV,&localCalibData.TankCalib[k++].mvolt,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST2_L,&localCalibData.TankCalib[k].litr,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST2_MV,&localCalibData.TankCalib[k++].mvolt,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST3_L,&localCalibData.TankCalib[k].litr,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST3_MV,&localCalibData.TankCalib[k++].mvolt,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST4_L,&localCalibData.TankCalib[k].litr,0);
            MENU_ITEM_UINT(m,i,TEXT_CONST4_MV,&localCalibData.TankCalib[k++].mvolt,0);

            snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_MENU_TANK),GetTankL(),mV);

            m->titleText =dText;
            m->titleFont = MENU_TITLE_FONT;

            m->font = MENU_LIST_FONT;
            m->list_size = i;//MENU_TANK_CALIB_CNT;

            break;

        case MENU_FIND_TEMP:

            k=0;

            MENU_ITEM_TEXT(m,k,TEXT_REG_SENSOR_CLEAR,NULL,0);

            for(i=0; i<MAX_SENSORS && i<menuRegTemp; i++)
            {
                MENU_ITEM_SINT(m,k,TEXT_REG_SENSOR,&regTemp[i],1);
                MENU_ITEM_TEXT(m,k,TEXT_REG_SENSOR_TEXT,getTempSensorText(i),0);
            }

            for(i=0; i<MAX_SENSORS && i<menuFoundTemp; i++)
            {
                MENU_ITEM_SINT(m,k,TEXT_NEW_SENSOR,&newTemp[i],1);
            }
            snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_TEMP_SENSORS));

            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;

            m->font = MENU_LIST_FONT;
            m->list_size = k;

            break;

        case MENU_MANAGE_USR:

            for(i=0; i<MAX_USERS; i++)
            {
                k=i;
                MENU_ITEM_TEXT(m,k,TEXT_MANAGE_USER,&Buff[i*NAME_LEN],0);

            }
            snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_MANAGE_USERS));
            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;
            m->font = MENU_LIST_FONT;
            m->list_size = MAX_USERS;

            break;
        case MENU_USR_EDIT:

            /* nacteme editacni menu uzivatele daneho indexem */
            i=0;

            MENU_ITEM_TEXT(m,i,TEXT_USER_NAME,userData.name,0);
            MENU_ITEM_UINT(m,i,TEXT_USER_UID,&userData.uid,0);
            MENU_ITEM_TEXT(m,i,TEXT_USER_ROOT,(userData.gid&G_ROOT)?txtYes:txtNo,0);
            MENU_ITEM_TEXT(m,i,TEXT_USER_READ,(userData.gid&G_READ)?txtYes:txtNo,0);
            MENU_ITEM_TIME(m,i,TEXT_USER_LAST_TIME,&userData.lastLogin,0);
            MENU_ITEM_DATE(m,i,TEXT_USER_LAST_DATE,&userData.lastLogin,0);
            MENU_ITEM_TIME(m,i,TEXT_USER_EXP_TIME,&userData.expTime,0);
            MENU_ITEM_DATE(m,i,TEXT_USER_EXP_DATE,&userData.expTime,0);
            MENU_ITEM_TEXT(m,i,TEXT_USER_IBUTTON,(useriButtonIsSet(&userData.iButton)?txtOk:txt_),0);
            MENU_ITEM_UCHAR(m,i,TEXT_USER_TRACK_DELAY,&userData.trackDelay,0);
            MENU_ITEM_UCHAR(m,i,TEXT_USER_SUSPEND_MIN,&userData.suspendDelay,0);

            m->font = MENU_LIST_FONT;

            snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_MANAGE_WHO),userData.name);
            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;
            m->list_size = i;


            break;
        case MENU_USR_STAT:
        case MENU_USR_STAT_M:
        case MENU_USR_STAT_D:
        case MENU_USR_STAT_MEAS:

        {
            i=0;
            char * pBuff = fslog.fsBuff;
            DOG_PSTR_P pgmText = NULL;

            switch(menu)
            {

            case MENU_USR_STAT:
                MENU_ITEM_TEXT(m,i,TEXT_AVG_YEAR,NULL,0);

                snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_YEARS_WHO),getActiveUserName());
                pgmText = DOG_PSTR(TEXT_LOG_YEAR);

                break;

            case MENU_USR_STAT_M:

                MENU_ITEM_TEXT(m,i,TEXT_AVG_MONTH,NULL,0);

                snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_MONTHS_WHO),fslog.year);
                pgmText = DOG_PSTR(TEXT_LOG_MONTH);
                break;

            case MENU_USR_STAT_D:

                MENU_ITEM_TEXT(m,i,TEXT_AVG_DAY,NULL,0);

                snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_DAYS_WHO),fslog.year,fslog.month);
                pgmText = DOG_PSTR(TEXT_LOG_DAY);

                break;
            case MENU_USR_STAT_MEAS:

                MENU_ITEM_TEXT(m,i,TEXT_AVG_ALL_MEAS,NULL,0);

                snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_MEAS_WHO),fslog.year,fslog.month,fslog.day);
                pgmText = DOG_PSTR(TEXT_LOG_MEAS);

                break;

            }

            m->font = MENU_LIST_FONT;
            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;


            /* promenna fsItems a fsBuff je inicializovana jiz od vstupu do menu!! */
            for(i=1; i<fslog.fsItems+1; i++)
            {

                m->list[i].text = pgmText;
                m->list[i].edit.text = pBuff;
                m->list[i].mode = MODE_TEXT;

                /* v ramci bufferu posuneme pointer na dalsi text */
                while(*pBuff!='\0' && pBuff!=&fslog.fsBuff[FS_TXT_SIZE-2])pBuff++;
                pBuff++;    /* preskocime null znak */

            }

            m->list_size = i;


        }

        break;

        case MENU_USR_STAT_Y_AVG:
        case MENU_USR_STAT_M_AVG:
        case MENU_USR_STAT_D_AVG:
        case MENU_USR_STAT_MEAS_AVG:
        case MENU_USR_STAT_MEAS_TRAC:

            m->font = MENU_LIST_FONT;
            m->titleText = dText;
            m->titleFont = MENU_TITLE_FONT;

            i = 0;
            MENU_ITEM_UI32(m,i,TEXT_AVG_FCONS, &menuAvg.fCons,1);
            MENU_ITEM_UI32(m,i,TEXT_AVG_LIT, &menuAvg.liters,1);
            MENU_ITEM_UINT(m,i,TEXT_AVG_KMH, &menuAvg.kmh,0);
            MENU_ITEM_UI32(m,i,TEXT_AVG_KM, &menuAvg.km,1);
            MENU_ITEM_UINT(m,i,TEXT_AVG_RPM,&menuAvg.rpm,0);
            MENU_ITEM_TIME(m,i,TEXT_AVG_TIME,&menuAvg.time,0);

            m->list_size = i;

            break;
        case MENU_SYSLOG:

            i=0;
            MENU_ITEM_UI32(m,i,TEXT_INJ_TICKS, getInjTicksPtr(),0);
            MENU_ITEM_UINT(m,i,TEXT_INJ_OVF, getInjOvfPtr(),0);
            MENU_ITEM_UI32(m,i,TEXT_IMP_TICKS, getImpTicksPtr(),0);
            MENU_ITEM_UINT(m,i,TEXT_IMP_OVF, getImpOvfPtr(),0);
            MENU_ITEM_UI32(m,i,TEXT_RPM_TICKS, getRpmTicksPtr(),0);
            MENU_ITEM_UINT(m,i,TEXT_RPM_OVF, getRpmOvfPtr(),0);

            strncpy_P(dText,PSTR(TEXT_SYS_LOG),DTEXT_MAX);


            m->titleText =dText;
            m->titleFont = MENU_TITLE_FONT;

            m->font = MENU_LIST_FONT;
            m->list_size = i;

            break;
        default:
            break;
        }

    }

}

void lcdOff(void)
{

    dog_spi_enable_client();
    dog_cmd_mode();
    dog_spi_out(0xae);

}

uint8_t checkSleep(uint8_t cond)
{
    static uint8_t SleepTime=0;
    static uint16_t state=0;

    if(cond==1)
    {

        SleepTime = RetTimer();
        state=1;
        cond++;

    }

    if(state && CompTimer(SleepTime,SLEEP_TICK) )
    {

        state++;
        SleepTime=RetTimer();

        if(state == (*getActiveSuspendMin()*(uint16_t)SLEEP_TIME) / 5)
        {
            pca_t pca;
            pca.frek1 = 152;
            pca.ls =  CH1_PWM1;
            pca.pwm1 = 20;
            setPCA(&pca);
        }
    }

    if(state == (*getActiveSuspendMin()*(uint16_t)SLEEP_TIME) || cond == 255)
    {
        /* porovnavame zda uz ubehl dany pocet minut */


        state = 0;
        cond=0;

        /* posledni synchro dat na sd kartu */
        syncData();
        closeCard();
        storagePwr(0);

        /* vypneme cistym zpusobem LCD */
        lcdOff();

        saveActiveUser();

        SetSleep() ;

    }

    SleepPoll();        // test zda prejit do sleep

    return cond;
}

int main(void)
{
    _delay_ms(10);

    wdt_reset();
    /* ZAKAZAT WATCHDOG */
    WDTCR |= (1<<WDCE) | (1<<WDE);
    WDTCR = 0x00;

    MCUCSR =0;  /* POZOR MUSIME SI VZDY ! VYNULOVAT FLAGY RESETU A HLAVNE POVOLIT JTAG ROZHRANI, KTERE JE V SUSPENDU ZAKAZANE Z DUVODU SPOTREBY */
    MCUCSR =0;  /* dvojity zapis vyzaduje JTAG */

#ifdef CAR_WDT_EN
    wdt_enable(WDTO_2S);
    wdt_reset();
#endif

    unsigned char i=0;
    uint32_t menu=0;

#ifdef MEAS_DEBUG
    uint8_t debugMeasState=0;
    char debugMessage[10];
#endif

    key_t keys;
    uint8_t t = 0;
    uint32_t old_screen=menu;
    uint16_t data;
    uint8_t firstSave=0;
//    uint8_t measTank = 0;
    uint16_t count=0;
    uint8_t readTempTime = 0;
    uint8_t tempStarted = 0;
    uint8_t editScreen=0;
    uint8_t editBox = 0;
    uint8_t blinkEdit = 0;
    uint8_t storeTime = 0;
    uint8_t storeCounter = 0;
    uint8_t foldersCheck = 0;
    uint16_t folderYear=0;
    uint8_t folderMonth=0;
    uint8_t newMeas=0;
    uint8_t NoSleep=0;
    uint8_t SleepTimeout=0;
    uint8_t state = 0;
    uint8_t okShutDwn=0;

    SetReboot();
    DisSleep();

    while(1)
    {

        if(CheckReboot())
        {

            MCUCSR =0;
            MCUCSR =0;

            i=0;
            menu=0;

#ifdef MEAS_DEBUG
            debugMeasState=0;
#endif
            t = 0;
            old_screen=menu;
            firstSave=0;
            count=0;
            readTempTime = 0;
            tempStarted = 0;
            editScreen=0;
            editBox = 0;
            blinkEdit = 0;
            storeTime = 0;
            storeCounter = 0;
            foldersCheck = 0;
            folderYear=0;
            folderMonth=0;
            newMeas=0;
            NoSleep=0;
            SleepTimeout=0;
            state = 0;

            DisSleep();

            fslog.fsBuff = Buff;

            memset(&menuScr,0,sizeof(menu_t));
            menuScr.list = menuItems;

            memset(newSensors,0,sizeof(temp_t)*MAX_SENSORS);

            DDRA = 0;       /* nevyuzite piny pullup vstupy */
            PORTA = 0xff;

            TONE_OFF;
            TONE_DDR |= 1 << TONE;

            pwrInit();

            PWR_DCDC_ON();

            LCD_PWR_ON();

            initPCF();

            dog_Init(0);

            InitCMeas();

            uart_init(BAUD_SPEED);

            keysInit();

            initOpto(NULL);
            initPCF();

            initAD();

            ibuttonLed(0);

            GetCalibData(&localCalibData);

            if((count=initTempSensors(newSensors,1)))
            {

                /* horni bajt v count udava pocet pripojenych znamych cidel zatimco spodni bajt pocet novych cidel
                Prozatim pracujeme s 2 cidly max dle MAX_SENSORS*/

                if(count&0xff && !(count&0xff00))   // pokud nejsou zadne sensory registrovane
                {
                    initTempSensorsData();

                    for(i=0; i<(count&0xff) && i < MAX_SENSORS ; i++)
                        setTempSensor(i,newSensors[i].id);

                    initTempSensors(newSensors,1);

                }

            }

            storagePwr(1);

            storageInit(USERS_FOLDER);

            ibuttonLed(1);

            InitTimer(PCF_CLK_32);

            sei();

            while(checkLogin()!=LOGIN_OK)
            {

#ifdef CAR_WDT_EN

                wdt_reset();
#endif
                if(!IsRunning())
                {

                    if(!SleepTimeout)SleepTimeout = 1;

                    SleepTimeout=checkSleep(SleepTimeout);

                    if(!SleepTimeout)
                    {

                        /* doslo k probuzeni */
                        break;
                    }


                }
                else
                {

                    SleepTimeout=0;

                }

            };

            if(CheckReboot())
            {
                SetReboot();
                continue;    /* jedeme od pocatku */
            }

            ibuttonLed(0);

            snprintf_P(dText,DTEXT_MAX,PSTR(TEXT_USER_WHO_LOGGED),getActiveUserName());

            uint8_t len = strlen(dText);

            dog_StartPage();
            do
            {
                drawFrame();
                dog_DrawStr((XMAX/2)-(len/2)*dog_GetFontBBXWidth(font_6x12),30,font_6x12,dText);

            }
            while(dog_NextPage());

#ifdef CAR_DEBUG

            uart_puts_P("User name: ");
            uart_puts(getActiveUserName());
            uart_puts_P("\n");

            uart_puts_P("User uid: ");
            uart_puthex_byte(getActiveUid());
            uart_puts_P("\n");

            uart_puts_P("User gid: ");
            uart_puthex_byte(getActiveGid());
            uart_puts_P("\n");
#endif

            if(initOpto(getActiveUserOpto()))
            {
                // pokud probehla inicializace

                saveActiveUser();       // ulozime inicializovana data do eeprom
            }
#ifdef CAR_WDT_EN
            wdt_reset();
#endif

            syncData(); /* zapiseme vsechny dosud nezapsane data na SD kartu */

            _delay_ms(1500);

#ifdef CAR_WDT_EN
            wdt_reset();
#endif

            screen.edit = 0;

            state = 0;

        }/* konec if reboot */


#ifdef CAR_WDT_EN
        wdt_reset();
#endif
        if(isNewMeas())
        {
            newMeas=1;
            if(IsRunning())activeUserPollData();
        }
        else newMeas=0;

        GetKeys(&keys,1);

        if(keys.keys || keys.key_up || keys.key_down)NoSleep=1;
        else NoSleep=0;

        if(!SleepTimeout)optoPoll(0,getActiveUserOpto());

        TankMeasPoll();
        V12MeasPoll();

        if(CompTimer(t,10))     // perioda 10/32 s
        {

            t = RetTimer();
            timePCFPoll();


            getTimePCF(&localTime);

            if(!foldersCheck)   // pokud nebyla provedena kontrola tak proved kontrolu slozek vzhledem k datu
            {

                folderYear = localTime.year;
                checkActiveUserDataYearFolder(folderYear);      // pozor tohle urcity cas potrva
                folderMonth = localTime.month;
                checkActiveUserDataMonthFolder(folderYear,folderMonth);      // pozor tohle urcity cas potrva

                foldersCheck=1;

            }
            else
            {

                if(folderYear!=localTime.year)    // pokud nesedi rok tak zkontroluj zda existuje slozka
                {

                    folderYear = localTime.year;
                    checkActiveUserDataYearFolder(folderYear);      // pozor tohle urcity cas potrva
                    // pravdepodobne nebude existovat slozka mesic to vyresime zde
                    folderMonth = localTime.month;
                    checkActiveUserDataMonthFolder(folderYear,folderMonth);      // pozor tohle urcity cas potrva

                }

                if(folderMonth!=localTime.month)        // v pripade ze nesedi slozka mesice
                {

                    folderMonth = localTime.month;
                    checkActiveUserDataMonthFolder(folderYear,folderMonth);      // pozor tohle urcity cas potrva

                }

            }

            if(menuScr.flags!=F_EDIT && menu==MENU_SETTINGS)memcpy(&editTime,&localTime,sizeof(pcf_t));

            if(menu==MENU_TANK_CALIB)
            {

                mV = RetTankmV();

            }

        }

        /* pokud z nejakeho duvodu jsme zastavili automobil a on zase jede tak testujeme stari dat a stavy */
        if(!state && IsRunning())
        {
            data_t data;

            snprintf_P(dText,DTEXT_MAX,PSTR("%s/%02x/%s"),USERS_FOLDER,getActiveUid(),DATA_FOLDER);

            if(findMeas(dText,&data,1))
            {
                getTimePCF(&localTime);
                getFromPCF(&localTime);

                uint32_t month = localTime.month;

                while(localTime.year > data.storeTime.year)
                {

                    month+=12;
                    localTime.year--;

                }

                uint32_t day=localTime.day;

                while(month>data.storeTime.month)
                {
                    day+=30;
                    localTime.month--;
                }

                uint32_t hour=localTime.hour;

                while(day>data.storeTime.day)
                {
                    hour+=24;
                    day--;
                }

                uint32_t min=localTime.min;

                while(hour>data.storeTime.hour)
                {
                    min+=60;
                    hour--;
                }

                min-=data.storeTime.min;
                /* pokud minuty po odhlaseni / prihlaseni a posledniho ulozeni po stopnuti motoru jiz ubehly danou mez, pak vyhlas novou jizdu a vynuluj prumery za jizdu */

                if(min> *getActiveTrackDelay())
                {
                    state = STATE_STARTED;
                    clearActiveUserAvgMeas();
#ifdef CAR_DEBUG
                    uart_puts_P("state=STATE_STARTED \n");
#endif
                }
                else state = STATE_NEW_RUNNING;


            }
            else state = STATE_STARTED;

        }

        if(state && !IsRunning())
        {
            state = STATE_STOPPED;
#ifdef CAR_DEBUG
            uart_puts_P("state && !IsRunning() -> state=STATE_STOPPED");
#endif
        }

        if(state)
        {

            if(CompTimer(storeTime,DELAY5S) || state==STATE_NEW_RUNNING || state==STATE_STARTED || state== STATE_STOPPED)
            {

                storeTime=RetTimer();
                storeCounter++;

                if(storeCounter==12 || state==STATE_NEW_RUNNING || state==STATE_STARTED || state==STATE_STOPPED)
                {

                    storeActiveUserMeas(state);

                    syncData();     /* synchronizujeme data SD karty, abychom o ne v pripade vypadku neprisli */

                    storeCounter=0;

                    if(state==STATE_NEW_RUNNING || state==STATE_STARTED) state = STATE_RUNNING;

                    if(state==STATE_STOPPED)state = 0;

                }


            }

        }


        if(!tempStarted)
        {


            startTempSensors();
            readTempTime = RetTimer();
            tempStarted = 1;

        }

        if(CompTimer(readTempTime,64) && tempStarted)       // perioda 2s
        {

            /* kazdou sekundu precti data cidel */
            tempStarted = 0;
            for(i=0; i<MAX_SENSORS; i++)
            {
                readTempSensor(i,&temp[i]);
            }

            if(menu==MENU_FIND_TEMP)
            {

                count = initTempSensors(newSensors,0);
                menuFoundTemp = count&0xff;
                menuRegTemp = (count>>8)&0xff;

                for(i=0; i<menuRegTemp && i<MAX_SENSORS; i++)
                    readTempSensor(i,&regTemp[i]);

                for(i=0; i<menuFoundTemp && i<MAX_SENSORS; i++)
                    DS18X20_read_decicelsius(newSensors[i].id,&newTemp[i]);

            }


        }



        if(keys.keys&MENU && !(menuScr.flags&F_EDIT))
        {
            /* provede prechod mezi menu a obrazovkami pro vykresleni mer. hodnot */

            if(menu<MAX_SCREENS)
            {
                old_screen=menu;    // zaloha aktualni obrazovky
                menu=MENU_SCREEN;
                menuScr.cursor = 0;
            }
            else
            {

                menu=old_screen;

            }

        }

        if(menu<MAX_SCREENS)
        {

            /* provadi init pro vykreslovani merenych hodnot */

            uint8_t oldmenu=menu;

            menu = checkKeys(menu,MAX_SCREENS-1,0,&keys);

            if(oldmenu!=menu || newMeas)getScreen(&screen,menu);

            key_t temp;

            memset(&temp,0,sizeof(key_t));

            GetKeys(&temp,0);
            if(temp.keys&OK)
            {

                okShutDwn++;

            }
            else okShutDwn=0;

            keys.key_up+= temp.key_up;  // abychom neprisli o nejaky ten pohyb enkoderu
            keys.key_down+=temp.key_down;


        }
        if(editScreen)  /* editace obrazovky uzivatelem */
        {

            scr_t *data = getActiveUserScrData();

            if(keys.keys&OK)
            {

                editBox++;

                if(editBox==MAX_ITEMS)
                {
                    editScreen=0;
                    screen.edit = 0;
                    saveActiveUser();
                    menu = MENU_USER_SETTINGS;
                }

            }
            if(editBox<MAX_ITEMS && data!=NULL)
            {
                uint8_t oldVal=data->scr[old_screen][editBox];

                uint8_t val = checkKeys(oldVal,MAX_VAL,0,&keys);

                // pokud je box ruzny od dlouheho a zaroven ma byt zobrazen cas tak cas preskoc
                if(editBox!=1 && (val==6 || val==11 || val==16))
                {

                    if(oldVal > val)val--;
                    else val++;

                }

                if(val>MAX_VAL)val=0;       // pro jistotu omezime podteceni

                setActiveUserScrData(old_screen,editBox,val);

                if(CompTimer(blinkEdit,BLINK_EDIT))
                {

                    if(screen.edit == 0)screen.edit = editBox+1;
                    else screen.edit = 0;

                    blinkEdit = RetTimer();

                }
                getScreen(&screen,old_screen);

            }

        }
        else if(menu>=MENU_SCREEN)      // jsme v menu takze jdeme ovladat menu
        {
//            uint8_t max = 0;

            if(keys.keys&OK && !(menuScr.flags&F_EDIT))
            {
                menuScr.editMax = 30000;

                switch(menu)
                {


                case MENU_SCREEN:



                    menu = MENU_SCREEN+ (uint32_t)100000*(menuScr.cursor+1);

                    if( !(getActiveGid()&(G_ROOT|G_READ)) && menu==MENU_SETTINGS)
                    {

                        /* pokud neni uzivatel clenem skupiny ROOT nebo READ tak musime zamezit pristup do sekce settings */
                        menu=MENU_SCREEN;

                    }
                    else menuScr.cursor=0;  /* presli jsme do submenu takze kurzor na prvni pozici */


                    /*       if(menu==MENU_CUST_BCK)  // vstupujeme do editace podsviceni?
                           {
                               // pro vetsi bezpecnost zkopirujeme do pomocne struktury userData data rizeni podsviceni
                               memcpy(&userData.opto,getActiveUserOpto(),sizeof(odat_t));

                           } */



                    if(menu==MENU_USR_STAT)
                    {
                        /* zde potrebujeme vygenerovat aktualni menu tj natahnout podmenu s polozkami dle slozek
                            v tomto pripade natahneme slozky vsech roku */
                        snprintf_P(fslog.actPath,ACT_PATH_SIZE,PSTR("%s/%02x/%s"),USERS_FOLDER,getActiveUid(),DATA_FOLDER);
                        fslog.fsItems=scanDir(fslog.actPath,FIND_DIRS,MAX_FS_LIST,fslog.fsBuff);
                        //fsItems=scanDir("/users/8a/data/2012",FIND_DIRS,MAX_YEARS_LIST,fsBuff);

                    }

                    if(menu == MENU_CLR_DATA)
                    {
                        redrawLogTxt(DOG_PSTR(TEXT_DATA_CLEARED));
                        resetActiveUserTripData();
                        _delay_ms(1000);
                        menu = MENU_SCREEN;
                    }
                    break;

                case MENU_USER_SETTINGS:

                    switch(menuScr.cursor)
                    {

                    case 0:
                        menuScr.edit_pos = 0;
                        menuScr.flags |=F_EDIT;
                        menuScr.max_edit_pos = NAME_LEN-2;      // posledni platna editacni pozice musi byt len-2 z duvodu posledniho znaku 0
                        firstSave = 1;
                        break;
                    case 1:         /* editace delky prodlevy mezi trasami */
                    case 2:         /* editace delky prodlevy pred suspendem */
                        menuScr.edit_pos = 0;
                        menuScr.flags |=F_EDIT;
                        menuScr.max_edit_pos = 1;
                        firstSave = 1;
                        break;

                    case 3:
                        menu = MENU_CUST_BCK;
                        break;
                    case 4:
                        menu= MENU_CUST_SCR;
                        editScreen=1;
                        editBox=0;
                        break;
                    default:
                        break;

                    }

                    break;

                case MENU_CLR_DATA:
                    /* nevnorujeme se do dalsiho menu */
                    break;

                case MENU_CUST_BCK:

                    menuScr.edit_pos = 0;
                    menuScr.flags|=F_EDIT;
                    menuScr.max_edit_pos = 2;

                    if(menuScr.cursor%2) menuScr.editMax = 255;
                    else menuScr.editMax = 100;

                    firstSave=1;

                    break;

                case MENU_CUST_SCR:

                    /* nic OK resi se jinde */

                    break;

                case MENU_USR_STAT:

                    /* jsme v automaticky generovanem menu s adresari roku a ted otvirame adresar s rokem nebo prumerovana data */
                {

                    if(menuScr.cursor == 0)
                    {
                        menu = MENU_USR_STAT_Y_AVG;
                        redrawWaitScreen();
                        _delay_ms(50);
                        loadAvgData(fslog.actPath,NULL,&menuAvg,0,0);

                    }
                    else if(menuScr.cursor <= fslog.fsItems)
                    {

                        /* pokud je kurzor v rozsahu bufferu nazvu adresaru tak jdeme ziskat cestu a nova data*/
                        strncpy(fslog.year,getfsBuffPtr(menuScr.cursor-1,fslog.fsBuff,FS_TXT_SIZE),6);
                        strncat_P(fslog.actPath,PSTR("/"),ACT_PATH_SIZE);
                        strncat(fslog.actPath,fslog.year,ACT_PATH_SIZE);
#ifdef CAR_DEBUG
                        uart_puts(fslog.actPath);
#endif
                        /* projdeme slozku a jeji nazvy */
                        fslog.fsItems=scanDir(fslog.actPath,FIND_DIRS,FS_TXT_SIZE,fslog.fsBuff);

                        menu=MENU_USR_STAT_M;   /* nastavime nove vnoreni menu */

                        menuScr.cursor = 0; /* nastavime kurzor na prvni pozici */



                    }


                }

                break;

                case MENU_USR_STAT_M:

                    if(menuScr.cursor == 0)
                    {

                        menu = MENU_USR_STAT_M_AVG;
                        redrawWaitScreen();
                        _delay_ms(50);
                        loadAvgData(fslog.actPath,NULL,&menuAvg,0,0);

                    }
                    else if(menuScr.cursor <= fslog.fsItems)
                    {

                        /* pokud je kurzor v rozsahu bufferu nazvu adresaru tak jdeme ziskat cestu a nova data*/
                        redrawWaitScreen();
                        _delay_ms(50);
                        strncpy(fslog.month,getfsBuffPtr(menuScr.cursor-1,fslog.fsBuff,FS_TXT_SIZE),6);
                        strncat_P(fslog.actPath,PSTR("/"),ACT_PATH_SIZE);
                        strncat(fslog.actPath,fslog.month,ACT_PATH_SIZE);
#ifdef CAR_DEBUG
                        uart_puts(fslog.actPath);
#endif
                        /* projdeme slozku a jeji nazvy */
                        fslog.fsItems=scanDir(fslog.actPath,FIND_FILES,FS_TXT_SIZE,fslog.fsBuff);

                        menu=MENU_USR_STAT_D;   /* nastavime nove vnoreni menu */

                        menuScr.cursor = 0; /* nastavime kurzor na prvni pozici */

                    }


                    break;
                case MENU_USR_STAT_D:


                    if(menuScr.cursor == 0)
                    {

                        menu = MENU_USR_STAT_D_AVG;
                        redrawWaitScreen();
                        _delay_ms(50);
                        loadAvgData(fslog.actPath,NULL,&menuAvg,0,0);

                    }
                    else if(menuScr.cursor <= fslog.fsItems)
                    {

                        redrawWaitScreen();
                        _delay_ms(50);
                        strncpy(fslog.day,getfsBuffPtr(menuScr.cursor-1,fslog.fsBuff,FS_TXT_SIZE),8);

                        fslog.fsItems=scanMeasTimes(fslog.actPath,fslog.day,fslog.fsBuff,FS_TXT_SIZE,&fslog.firstIndex);

                        menu=MENU_USR_STAT_MEAS;
                        menuScr.cursor=0;
                    }

                    break;
                case MENU_USR_STAT_MEAS:

                    if(menuScr.cursor==0)
                    {
                        redrawWaitScreen();
                        _delay_ms(50);
                        menu = MENU_USR_STAT_MEAS_AVG;

                        loadAvgData(fslog.actPath,fslog.day,&menuAvg,0,0);

                    }
                    else
                    {
                        redrawWaitScreen();
                        _delay_ms(50);
                        menu = MENU_USR_STAT_MEAS_TRAC;
                        uint8_t trackIndex = fslog.firstIndex + menuScr.cursor-1;
                        loadAvgData(fslog.actPath,fslog.day,&menuAvg,trackIndex,1);
                        menuScr.cursor=0;
                    }

                    break;

                case MENU_SETTINGS:

                    if(menuScr.cursor > 7)
                    {
                        if(getActiveGid()&(G_ROOT|G_READ))
                        {
                            menu = MENU_SETTINGS + 1000*(menuScr.cursor+1);
                            menuScr.cursor = 0;

                            /* pokud vstupujeme do menu s teplotnimi cidly, tak vyhledat cidla */

                            if(menu == MENU_FIND_TEMP)
                            {
                                count = initTempSensors(newSensors,1);
                                menuFoundTemp = count&0xff;
                                menuRegTemp = (count>>8)&0xff;

                            }

                            /* pokud se prechazi do  spravy uzivatelu, pak napln data jejich nazvu
                               zamezi se zbytecnemu opakovanemu cteni z eeprom */

                            if(menu == MENU_MANAGE_USR)
                            {
                                getUserNames();     // pokud jsme v menu uzivatelu, pak refreshuj jejich jmena kvuli pripadne editacni zmene

                            }


                        }

                        if(menu == MENU_RESET_SET && getActiveGid()&G_ROOT)
                        {
                            redrawLogTxt(DOG_PSTR(TEXT_DELETED));
                            strcpy(dText,USERS_FOLDER);
                            delFile("/",dText+1);
                            syncData();
                            closeCard();
                            storagePwr(0);
                            cli();
                            memset(&userData,0xff,sizeof(user_t));
                            memset(&localCalibData,0xff,sizeof(clb_t));
                            SetCalibData(&localCalibData);
                            initTempSensorsData();
                            for(i=0; i<MAX_USERS; i++)initUser(i,&userData);
                            SetReboot();
                            _delay_ms(1000);
                            lcdOff();
                            continue;

                        }

                    }
                    else if(getActiveGid()&G_ROOT)    /* kontrola zda ma uzivatel prava editace */
                    {
                        /* if(menuScr.cursor==5)
                         {
                             localCalibData.odo16bit ^= 1;
                             SetCalibData(&localCalibData);
                         }*/
                        if(menuScr.cursor==7)
                        {
                            localCalibData.tankInt ^=  1;
                            SetCalibData(&localCalibData);
                        }
                        else
                        {

                            menuScr.edit_pos = 0; /* init hodnoty */
                            menuScr.flags |=F_EDIT;  /* spust editacni mod */
                            if(menuScr.cursor>2)menuScr.max_edit_pos = 4;   /* tohle je editace pro ostatni konstanty */
                            else menuScr.max_edit_pos = 0;          /* tohle je editace pro pocet valcu */

                            if(menuScr.cursor ==0)
                            {
                                memcpy(&editTime,&localTime,sizeof(pcf_t));
                                menuScr.max_edit_pos = 5;
                            }
                            else if(menuScr.cursor == 1)
                            {
                                memcpy(&editTime,&localTime,sizeof(pcf_t));
                                menuScr.max_edit_pos = 7;

                            }

                            firstSave = 1;


                        }

                    }
                    break;

                case MENU_TANK_CALIB:

                    if(menuScr.cursor%2)        // liche prvky tj mereni mV
                    {
                        menuScr.max_edit_pos = 3;
                    }
                    else menuScr.max_edit_pos = 2;

                    if(getActiveGid()&G_ROOT)
                    {
                        menuScr.edit_pos = 0;
                        menuScr.flags|=F_EDIT;
                        firstSave=1;
                    }

                    break;
                case MENU_MANAGE_USR:
                    /* kontrola prav uzivatele - uzivatel s READ muze cist jen sam sebe */
                    if( (getActiveGid()&G_ROOT) || (  ( menuScr.cursor == geActiveUserIndex() )&&(getActiveGid()&G_READ) ) )
                    {

                        menu = MENU_USR_EDIT;   /* nastav spolecne vykreslovaci menu pro editaci uzivatele */
                        userIndex = menuScr.cursor; /* aktualni editovany uzivatel je specifikovan indexem dle kurzoru pri prechodu */
                        menuScr.cursor = 0;     /* budeme dale kreslit nove menu, takze nastavit kruzor na prvni pozici */

                        getUser(userIndex,&userData);

                        if(userData.init!=USER_INIT_SET)
                        {
                            memset(&userData,0,sizeof(user_t));
                            resetScrData(&userData.scrData);
                        }

                    }
                    break;

                case MENU_FIND_TEMP:
                    if((getActiveGid()&G_ROOT))
                    {
                        if(menuScr.cursor == 0)
                        {

                            initTempSensorsData();
                            count = initTempSensors(newSensors,1);
                            menuFoundTemp = count&0xff;
                            menuRegTemp = (count>>8)&0xff;
                        }
                        else if(menuScr.cursor < (menuRegTemp*2+1) )/* kurzor je v pozici registrovanych senzoru */
                        {
                            if(!(menuScr.cursor%2) && (getActiveGid()&G_ROOT) )
                            {
                                /* edituj nazev senzoru */

                                menuScr.edit_pos = 0;
                                menuScr.flags |=F_EDIT;
                                menuScr.max_edit_pos = 5;
                                firstSave = 1;

                            }
                        }
                        else
                        {
                            /* pokus se zaregistrovat na volnou pozici sensor */
                            for(i=0; i<MAX_SENSORS; i++)
                            {

                                if(!tempSensorCon(i))
                                {
                                    setTempSensor(i,newSensors[menuScr.cursor - menuRegTemp*2 -1].id);

                                }

                            }
                            count = initTempSensors(newSensors,1);
                            menuFoundTemp = count&0xff;
                            menuRegTemp = (count>>8)&0xff;
                        }
                    }
                    break;

                case MENU_RESET_SET:
                    /* zde nic nebude.. neni zadne vnoreni */
                    break;
                case MENU_USR_EDIT:

                    if(getActiveGid()&G_ROOT)
                    {

                        switch(menuScr.cursor)
                        {

                        case 0:     // editace jmena uzivatele
                            menuScr.edit_pos = 0;
                            menuScr.flags |=F_EDIT;
                            menuScr.max_edit_pos = NAME_LEN-2;      // posledni platna editacni pozice musi byt len-2 z duvodu posledniho znaku 0
                            firstSave = 1;

                            break;
                        case 1:
                            // pokud neni uid
                            if(userData.uid==0)
                            {

                                //userData.init = USER_INIT_SET;
                                _delay_ms(100);
                                do
                                {
                                    GetKeys(&keys,1);

                                }
                                while(keys.keys&OK);

                                redrawLogTxt(DOG_PSTR("Press OK Now!"));
                                i=0;

                                do
                                {
                                    i++;
                                    _delay_ms(1);
                                    GetKeys(&keys,1);
#ifdef CAR_WDT_EN
                                    wdt_reset();
#endif
                                }
                                while(!(keys.keys&OK) || i==0);

                                memset(&keys,0,sizeof(key_t));

                                userData.uid = i;

                                // kontrola zda uz takove uid neexistuje

                                for(i=0; i<MAX_USERS; i++)
                                {

                                    if(getUserInitSet(i)==USER_INIT_SET)
                                    {

                                        if(userData.uid==getUserUid(i))
                                        {
                                            userData.uid++;
                                            if(userData.uid==0)userData.uid++;
                                        }

                                    }

                                }


                                snprintf_P(dText,DTEXT_MAX,PSTR("%02x"),userData.uid);
                                createDir(USERS_FOLDER,dText);
                                snprintf_P(dText,DTEXT_MAX,PSTR("%s/%02x"),USERS_FOLDER,userData.uid);
                                createDir(dText,DATA_FOLDER);
                            }

                            break;

                        case 2:
                            // editace prav root group
                            userData.gid ^=(G_ROOT);
                            break;
                        case 3:
                            userData.gid ^=(G_READ);
                            break;
                        case 4: /* last time a last date je pouze informacni */
                        case 5:
                            break;

                        case 6:

                            // exp. time lze nastavit

                            menuScr.edit_pos = 0;
                            menuScr.flags |=F_EDIT;
                            menuScr.max_edit_pos = 5;
                            firstSave = 1;
                            break;
                        case 7: // exp date taktez editovat

                            menuScr.edit_pos = 0;
                            menuScr.flags |=F_EDIT;
                            menuScr.max_edit_pos = 7;
                            firstSave = 1;
                            break;

                        case 8: // najit ibutton cip a zaregistrovat
                        {

                            ibutton_t ibutton1,ibutton2,ibutton3;
                            uint8_t compare=0;
                            uint8_t mul = 0xff;

                            memcpy(&ibutton3,&userData.iButton,sizeof(ibutton_t));
                            memset(&userData.iButton,0xff,sizeof(ibutton_t));

                            ibuttonLed(1);

                            do
                            {

                                ibuttonRead(&ibutton1);

                                _delay_ms(200);

                                ibuttonRead(&ibutton2);

                                compare = 0;
                                mul = 0xff;

                                for(i=0; i<SP_SIZE; i++)
                                {
                                    compare|=ibutton1.romCode[i]^ibutton2.romCode[i];
                                    mul&=(ibutton1.romCode[i]);

                                }

#ifdef CAR_WDT_EN
                                wdt_reset();
#endif

                                GetKeys(&keys,1);

                                getMenu(&menuScr,menu);

                                dog_StartPage();


                                do
                                {

                                    drawMenu(&menuScr);

                                }
                                while(dog_NextPage());

                            }
                            while( (compare!=0 || mul==0xff) && !(keys.keys&ESC));

                            if(keys.keys&ESC) memcpy(&userData.iButton,&ibutton3,sizeof(ibutton_t));
                            else
                            {

                                uint8_t i;
                                uint8_t j;
                                uint8_t compare = 0;
                                for(i=0; i<MAX_USERS; i++)
                                {

                                    if(USER_INIT_SET==getUserInitSet(i))
                                    {
                                        compare = 0;
                                        getUserIbutton(i,&ibutton2);
                                        for(j=0; j<SP_SIZE; j++)
                                        {
                                            compare |=ibutton1.romCode[j]^ibutton2.romCode[j];
                                        }
                                        if(compare==0)break;
                                    }
                                }

                                if(compare==0)
                                {
                                    /* existuje jiz stejny klic u nektereho uzivatele */
                                    redrawLogTxt(DOG_PSTR(TEXT_INVALID_IBUTTON));
                                    /* vratime puvodni klic */
                                    memcpy(&userData.iButton,&ibutton3,sizeof(ibutton_t));
                                    _delay_ms(1200);

                                }
                                else
                                {
                                    /* novy klic takze ulozime */
                                    memcpy(&userData.iButton,&ibutton1,sizeof(ibutton_t));

                                }

                            }

                            ibuttonLed(0);

                        }
                        break;
                        case 9:     /* editace track delay */
                        case 10:    /* editace suspend delay */
                            menuScr.edit_pos = 0;
                            menuScr.flags |=F_EDIT;
                            menuScr.max_edit_pos = 1;
                            firstSave = 1;
                            break;

                        }




                    }

                    break;

                }

            }

            if(menuScr.flags&F_EDIT)
            {
                if(firstSave)keys.keys&=~OK;

                if(editMenuVal(&menuScr,&keys,firstSave))
                {

                    switch(menu)
                    {

                    case MENU_TANK_CALIB:

                        if( (menuScr.cursor/2) == 0)
                        {
                            if( localCalibData.TankCalib[0].mvolt!=0 && localCalibData.TankCalib[0].litr!=0 ) localCalibData.TankCalib[0].init = EE_INIT_B;
                            else localCalibData.TankCalib[0].init = 0;
                        }
                        else if( (menuScr.cursor/2) == 1)
                        {
                            if( localCalibData.TankCalib[1].mvolt!=0 && localCalibData.TankCalib[1].litr!=0 ) localCalibData.TankCalib[1].init = EE_INIT_B;
                            else localCalibData.TankCalib[1].init = 0;
                        }
                        else if( (menuScr.cursor/2) == 2)
                        {
                            if( localCalibData.TankCalib[2].mvolt!=0 && localCalibData.TankCalib[2].litr!=0 ) localCalibData.TankCalib[2].init = EE_INIT_B;
                            else localCalibData.TankCalib[2].init = 0;
                        }
                        else if( (menuScr.cursor/2) == 3)
                        {
                            if( localCalibData.TankCalib[3].mvolt!=0 && localCalibData.TankCalib[3].litr!=0 ) localCalibData.TankCalib[3].init = EE_INIT_B;
                            else localCalibData.TankCalib[3].init = 0;
                        }
                        else if( (menuScr.cursor/2) == 4)
                        {
                            if( localCalibData.TankCalib[4].mvolt!=0 && localCalibData.TankCalib[4].litr!=0 ) localCalibData.TankCalib[4].init = EE_INIT_B;
                            else localCalibData.TankCalib[4].init = 0;
                        }

                        SetCalibData(&localCalibData);

                        break;

                    case MENU_CUST_SCR:



                        break;

                    case MENU_SETTINGS:
                        /* doslo k ukonceni editace */

                        if(menuScr.cursor >1) SetCalibData(&localCalibData);
                        else
                        {
                            if(menuScr.cursor == 0)
                            {

                                /* editace casu takze nemenit datum */
                                getTimePCF(&localTime);

                                editTime.year = localTime.year;
                                editTime.month = localTime.month;
                                editTime.day = localTime.day;

                                editTime.isSet = 'Y';
                                setTimePCF(&editTime);

                            }
                            else
                            {

                                /* editace data takze nemenit cas */

                                getTimePCF(&localTime);

                                editTime.hour = localTime.hour;
                                editTime.min = localTime.min;
                                editTime.sec = localTime.sec;

                                editTime.isSet = 'Y';

                                setTimePCF(&editTime);


                            }

                        }
                        break;

                    case MENU_FIND_TEMP:

                        if(menuScr.cursor > 0 && !(menuScr.cursor%2))
                        {

                            //   strncpy(txt,getTempSensorText(menuScr.cursor/2),20);
                            //   setTempSensorText(menuScr.cursor/2,txt);
                            updateTempSensorsData();


                        }
                        break;




                    default:
                        break;

                    }
                }

                firstSave=0;

            }
            else
            {

                if(keys.keys&ESC)
                {

                    switch(menu)
                    {

                    case MENU_USR_EDIT:

                        if(strlen(userData.name)>0 && useriButtonIsSet(&userData.iButton) && userData.uid && (getActiveGid()&G_ROOT))
                        {

                            userData.init = USER_INIT_SET;

                            initUser(userIndex,&userData);

                            getUserNames();


                        }
                        break;

                    case MENU_USR_STAT_M:
                        /* pro navrat z vypisu adresaru mesicu ziskejme zpet seznam adresaru roku */
                        snprintf_P(fslog.actPath,ACT_PATH_SIZE,PSTR("%s/%02x/%s"),USERS_FOLDER,getActiveUid(),DATA_FOLDER);
                        fslog.fsItems=scanDir(fslog.actPath,FIND_DIRS,MAX_FS_LIST,fslog.fsBuff);


                        break;
                    case MENU_USR_STAT_D:
                        snprintf_P(fslog.actPath,ACT_PATH_SIZE,PSTR("%s/%02x/%s/%s"),USERS_FOLDER,getActiveUid(),DATA_FOLDER,fslog.year);
                        fslog.fsItems=scanDir(fslog.actPath,FIND_DIRS,MAX_FS_LIST,fslog.fsBuff);

                        break;
                    case MENU_USR_STAT_MEAS:
                        snprintf_P(fslog.actPath,ACT_PATH_SIZE,PSTR("%s/%02x/%s/%s/%s"),USERS_FOLDER,getActiveUid(),DATA_FOLDER,fslog.year,fslog.month);
                        fslog.fsItems=scanDir(fslog.actPath,FIND_FILES,MAX_FS_LIST,fslog.fsBuff);

                        break;


                    }



                    /* hierarchie menu je velmi jednoduse provedena pres cifry, navrat je vzdy automaticky k nizsimu cislu, ktere je zaokrouhleno vzdy na nejspodnejsi pozici na 0
                    dana omezeni co do poctu vnoreni  i menu */
                    if(menu%10)       menu=(menu/10)*10;
                    else if(menu%100) menu=(menu/100)*100;
                    else if(menu%1000)menu=(menu/1000)*1000;
                    else if(menu%10000) menu=(menu/100000)*100000;
                    else if(menu%100000) menu=(menu/100000)*100000;
                    else if(menu%1000000) menu=(menu/1000000)*1000000;
                    menuScr.cursor =0;



                }

                //if(oldMenu!=menu){
                getMenu(&menuScr,menu);
                //  oldMenu = menu;
                //}


                menuScr.cursor = checkKeys(menuScr.cursor,menuScr.list_size-1,0,&keys);


            }// end else

        }// end  else if(menu>=MENU_SCREEN)


        /*----------- vykreslovani LCD -------------------*/

        dog_StartPage();


        do
        {
            if(menu<MAX_SCREENS || editScreen)drawVscreen(&screen);
            else drawMenu(&menuScr);

        }
        while(dog_NextPage());

        /*------------------------------------------------*/


        data = uart_getc();

        while( !(data&UART_NO_DATA) )
        {
#ifdef CAR_SHELL
            if((data&0xff)=='*')simpleShell();
#endif
            /* if((data&0xff)=='S'){

             wdt_enable(CAR_WDT_TIME);
             while(1);

             }*/
#ifdef MEAS_DEBUG
            /* jednoduchy stavovy automat pro prijem prikazu - simulace provoznich hodnot motoru */
            if(debugMeasState>0 && ( ((data&0xff)>='0' && (data&0xff)<='9') || ( (data&0xff)>='A' && (data&0xff)<='F')) )
            {


                debugMessage[debugMeasState]=data&0xff;
                debugMeasState++;

                if(debugMeasState>4)
                {

                    uint16_t message = 0;
                    debugMeasState=0;
                    uint16_t val = 0;
                    for(i=1; i<5; i++)
                    {
                        val = debugMessage[i];
                        if(val>='0' && val<='9') val-='0';
                        else
                        {
                            val-='A';
                            val+=10;
                        }
                        message |=( val )<<(4*(4-i));
                    }

                    switch(debugMessage[0])
                    {

                    case 'I':
                        uart_putc('I');

                        uart_puthex_long(message);
                        setDebugInjTicks(message);
                        break;
                    case 'O':
                        uart_putc('O');
                        uart_puthex_long(message);
                        setDebugOdoTicks(message);
                        break;
                    case 'R':
                        uart_putc('R');
                        uart_puthex_long(message);
                        setDebugRpmTicks(message);
                        break;

                    }

                }

            }
            else debugMeasState=0;

            if(debugMeasState==0)
            {
                switch(data&0xff)
                {

                case 'I':
                    debugMeasState=1;
                    debugMessage[0]='I';
                    break;
                case 'O':
                    debugMeasState=1;
                    debugMessage[0]='O';
                    break;
                case 'R':
                    debugMeasState=1;
                    debugMessage[0]='R';
                    break;
                }
            }
#endif
            data = uart_getc();
        }

        if(!IsRunning() && !NoSleep && !(menuScr.flags&F_EDIT))
        {

            if(!SleepTimeout)SleepTimeout = 1;

            if(okShutDwn==30)
            {
                SleepTimeout = 255;  // prejdi ihned na spanek
                okShutDwn = 0;
            }

            SleepTimeout=checkSleep(SleepTimeout);


        }
        else
        {
            okShutDwn = 0;
            SleepTimeout=0;

        }



        _delay_ms(10);
    }

    while(1);       // sem to nidky nedojde

    return 0;
}






