TEST2

Dependencies:   LCD_DISCO_F746NG QSPI_DISCO_F746NG TS_DISCO_F746NG

main.cpp

Committer:
tribal91
Date:
2017-12-14
Revision:
3:4c554633a76a
Parent:
0:011a309655b5

File content as of revision 3:4c554633a76a:

#include "main.h"

//поток на работу с Eth
void workEth(){
    int test = 0;
    time_t unixtime; //unix-время из udp-пакета
    tm tmu; //для unix-времени
    int stat_b; //№ пути
    
    idThread2 = osThreadGetId(); //получаем id потока
    //настройка соединения
    eth.set_network(ip, Mask, Gateway);
    //иниц. eth
    eth.connect();
    //иниц. udp
    sock9003.open(&eth);
    sock9003.bind(9003);
    sock9003.set_blocking(false); //неблокир. режим
    sock9006.open(&eth);
    sock9006.bind(9006);
    sock9006.set_blocking(false);
    //таймер таймаута связи с сервером
    tickerConn.attach(&workConn, 30);
    
    char ppp[46];
    time_t create_message_t, train_start_t; //время формирования сообщения, время отправления
    
    while(1)
    {        
        //пакет со временем
        if(sock9003.recvfrom(&sockAddr, ppp, LEN_PACK_9003) == LEN_PACK_9003 && ppp[3] == 143)
        {
            flEth = 1; //флаг подтверждения связи
            tickerConn.detach(); //перезапускаем таймер
            tickerConn.attach(&workConn, 30);
            unixtime = (ppp[7]<<24) + (ppp[6]<<16) + (ppp[5]<<8) + ppp[4];
            //конвертация unix-времени в нормальный вид
            tmu = *localtime(&unixtime);
            if((abs(tmu.tm_sec - t.tm_sec) > 1) || (tmu.tm_min != t.tm_min) || ((tmu.tm_hour) != t.tm_hour)) //сравниваем времена
            {
                //устанавливаем новое время
                t.tm_hour = tmu.tm_hour;
                t.tm_min = tmu.tm_min;
                t.tm_sec = tmu.tm_sec;
                sTime = mktime(&t);
                sTime = sTime - (7 * 3600);
                set_time(sTime);
            }
            memset(ppp, 0, LEN_PACK_9003);
        }
        
        //пакет с инфой для ПУИ
        if(sock9006.recvfrom(&sockAddr, ppp, LEN_PACK_9006) == LEN_PACK_9006)
        {
            create_message_t = (ppp[7]<<24) + (ppp[6]<<16) + (ppp[5]<<8) + ppp[4];
            train_start_t = (ppp[30]<<24) + (ppp[29]<<16) + (ppp[28]<<8) + ppp[27];
            stat_b = ppp[14];
            
            if(train_start_t > create_message_t)
            {
                train_start_t = train_start_t - create_message_t;
                tmuPui = *localtime(&train_start_t);
                
                switch(stat_b)
                {
                    case 1:
                        //время
                        sec1 = tmuPui.tm_min * 60 + tmuPui.tm_sec; //получаем секунды до отправления
                        flMut.lock();
                        flRecT1 = 1;
                        flMut.unlock();
                        flWorkT1 = fl1NP = 1;
                        pui1SetTime(train_start_t);
                        //станция
                        numStat1 = (ppp[25] / 16) * 16 * 16 * 16 + (ppp[25] % 16) * 16 * 16 + (ppp[26] / 16) * 16 + ppp[26] % 16;
                        flMut.lock();
                        flRec1 = 1;
                        flMut.unlock();
                        sendStatPui1(numStat1);
                        break;
                    
                    case 2:
                        //время
                        sec2 = tmuPui.tm_min * 60 + tmuPui.tm_sec; //получаем секунды до отправления
                        flMut.lock();
                        flRecT2 = 1;
                        flMut.unlock();
                        fl2NP = flWorkT2 = 1;
                        pui2SetTime(train_start_t);
                        //станция
                        numStat2 = (ppp[25] / 16) * 16 * 16 * 16 + (ppp[25] % 16) * 16 * 16 + (ppp[26] / 16) * 16 + ppp[26] % 16;
                        flMut.lock();
                        flRec2 = 1;
                        flMut.unlock();
                        sendStatPui2(numStat2);
                        break;
                }
            }
            memset(ppp, 0, LEN_PACK_9006);
        }
    }
}

int main(){
    StartIWDG(5000); //иниц. и запуск. wdt
    //эмблема
    logo();
    //иниц. тачпада
    ts.Init(lcd.GetXSize(), lcd.GetYSize());
    //иниц. qspi
    qspi.Init();    
    //загрузка ip из флеш
    qspi.Read((uint8_t*)readBuf, WRITE_READ_ADDR, 16);
    readBuf[15] = '\0';
    //формируем буфер на отображение
    int len = strlen(readBuf)+1;
    r = new char[len];
    for(int i=0; i<len; i++)
        r[i] = readBuf[i];
    r[len] = 0;
    //проверка ip
    if(checkIP(r)) //если есть
        threadEth.start(workEth); //заводим второй поток
    
    lcd.SetFont(&FontNum);
    //установка часов RTC
    setClock();
    //отправка яркости на экран
    brightness1 = !brightness1;
    brightness2 = !brightness2;
    //сохр. отправленные пакеты
    bufSend1[0] = 32;
    bufSend1[1] = 15;
    bufSend1[2] = '\0';
    memmove(bufSend2, bufSend1, 2);
    //ожидание ответа от ПУИ1/ПУИ2
    ansPui1();
    ansPui2();
    //отрисовка главного окна
    mainWindow();

    short st1 = 0, st2 = 0; //для анализа очистки полей станций
    
    while(1)
    {
        HAL_IWDG_Refresh(&IwdgHandle); //сброс wdt
        wait_ms(50);
        
        if(flWdtTh) //опрос флага зависания дочернего потока
        {
            flWdtTh = 0;
            if(osThreadGetState(idThread2) < 0)
                NVIC_SystemReset();
        }
        
        //мониторим флаги flEth, flRec1, flRec2
        if(fl1 != flEth) //если есть связь по eth
        {
            fl1 = flEth;
            lcd.Clear(LCD_COLOR_BLACK);
            mainWindow();
        }
        
        if(flRecT1) //если отобразить секунды1
        {
            flRecT1 = 0;
            flSec1 = 1;   
        }
        
        if(flRecT2) //если отобразить секунды2
        {
            flRecT2 = 0;
            if(visible) //только для 2 пути, т.к. накладывается на меню
                flSec2 = 1;  
        }
        
        if(flRec1) //если отобразить название станции1
        {
            flRec1 = 0;
            flWork1 = 1;
            if(st1 != numStat1) //чистим строку экрана
            {
                lcd.SetTextColor(LCD_COLOR_BLACK);
                lcd.FillRect(5, 250, 235, 20);
                lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
                st1 = numStat1;
            }
            viewStation(numStat1, 0);
        }
        
        if(flRec2) //если отобразить название станции2
        {
            flRec2 = 0;
            flWork2 = 1;
            if(st2 != numStat2) //чистим строку экрана
            {
                lcd.SetTextColor(LCD_COLOR_BLACK);
                lcd.FillRect(241, 250, 236, 20);
                lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
                st2 = numStat2;
                if(!visible)
                    settingBut();
            }
            if(visible)
                viewStation(numStat2, 1);
        }
        
        ts.GetState(&TS_State);
        if(TS_State.touchDetected)
        {
            wait_ms(50);
            
            for(uint8_t ind = 0; ind < TS_State.touchDetected; ind++)
            {
                uint16_t x = TS_State.touchX[ind];
                uint16_t y = TS_State.touchY[ind];
                if((x >= 434 && x <= 479) && (y >= 1 && y <= 45)) //второй экран
                {
                    if(flTest)
                    {
                        flTest = flSec1 = flSec2 = 0;
                        fl1NP = fl2NP = 1;
                        sec1 = sec2 = 0;
                        //зачищаем старую кнопку
                        lcd.SetTextColor(LCD_COLOR_BLACK);
                        lcd.FillRect(434, 0, 45, 45);
                        lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
                        mainWindow();
                        break;
                    }
                    
                    if(visible)
                    {
                        flSec2 = 0;
                        settingBut();
                    }
                    else
                    {
                        if(flTest || flWorkT2)
                            flSec2 = 1;
                        lcd.Clear(LCD_COLOR_BLACK);
                        mainWindow();
                    }
                    visible = !visible;
                    wait_ms(80);
                }
                
                if((x >= 319 && x <= 476) && (y >= 49 && y <= 119) && !visible) //тест
                {
                    flWork1 = flWork2 = 0; //перекрываем отображ. станций
                    flWorkT1 = flWorkT2 = 0; //останавливаем рабочий режим
                    //отправка команд на уст-во
                    bufSend1[0] = 64;
                    bufSend1[1] = 10;
                    memmove(bufSend2, bufSend1, 3);
                    //1-ая команда
                    ansPui1();
                    ansPui2();
                    wait_ms(80);
                    
                    bufSend1[0] = 128;
                    bufSend1[1] = 31;
                    memmove(bufSend2, bufSend1, 3);
                    //2-ая команда
                    ansPui1();
                    ansPui2();
                    wait_ms(80); //?????????
                    
                    //запуск у себя
                    fl2NP = fl1NP = 1;
                    sec2 = sec1 = 30; //выставляем кол-во тестовых секунд
                    flTest = flTime = flSec1 = flSec2 = 1; //уст-ка флагов таймеров
                    visible = 1;
                    lcd.Clear(LCD_COLOR_BLACK);
                    lcd.SetTextColor(LCD_COLOR_YELLOW);
                    mainWindow();
                }
                
                if((x >= 319 && x <= 476) && (y >= 120 && y <= 190) && !visible) //яркость
                    drawSelector();
                
                if((x >= 319 && x <= 476) && (y >= 191 && y <= 261) && !visible) //конфигурация
                    configWindow();
            }
        }
    }
}

//отрисовка главного окна
void mainWindow(){
    //рамка
    lcd.DrawRect(0, 0, 479, 271);
    lcd.DrawRect(1, 1, 477, 269);
    lcd.DrawRect(2, 2, 475, 267);
    //разделители
    lcd.DrawHLine(0, 100, 479);
    lcd.DrawVLine(240, 100, 171);
    
    if(flTest || flWorkT1 || flWorkT2)
    {
        lcd.SetFont(&FontNum);
        strftime(buf, 10, "%H:%M:%S", localtime(&sTime));
        lcd.DisplayStringAt(38, 50, (uint8_t *)buf, LEFT_MODE);
        //отрисовка секундомеров
        if(fl1NP)
            strftime(buf1, 10, "%M:%S ", localtime(&s1Time)); //пробел ОБЯЗАТЕЛЕН
        else
            strftime(buf1, 10, "-%M:%S", localtime(&s1Time));
        
        if(fl2NP)
            strftime(buf2, 10, " %M:%S", localtime(&s2Time));
        else
            strftime(buf2, 10, "-%M:%S", localtime(&s2Time));
        lcd.DisplayStringAt(50, 180, (uint8_t *)buf1, LEFT_MODE);
        lcd.DisplayStringAt(60, 180, (uint8_t *)buf2, RIGHT_MODE);
    }
    else
    {
        if(!flSec1)
        {
            flSec1 = 1;
            viewTimerSec();
            flSec1 = 0;
        }
        if(!flSec2)
        {
            flSec2 = 1;
            viewTimerSec();
            flSec2 = 0;    
        }
    }
    
    //вывод названий станций
    if(flWork1)
        viewStation(numStat1, 0);
    if(flWork2)
        viewStation(numStat2, 1);
    //главные служебные значки
    lcd.DisplayStringAt(10, 10, (uint8_t *)"\"", LEFT_MODE);
    if(flEth)
        lcd.DisplayStringAt(38, 10, (uint8_t *)"&", LEFT_MODE); //если есть связь
    else
        lcd.DisplayStringAt(38, 10, (uint8_t *)"%", LEFT_MODE); //если нет связи

    //путь 1
    if(brightness1)
        lcd.DisplayStringAt(10, 115, (uint8_t *)"#", LEFT_MODE); //если ярче
    else
        lcd.DisplayStringAt(10, 115, (uint8_t *)"$", LEFT_MODE); //если тусклее
    if(flCon1)
        lcd.DisplayStringAt(38, 115, (uint8_t *)"'", LEFT_MODE); //если есть связь
    else
        lcd.DisplayStringAt(38, 115, (uint8_t *)"%", LEFT_MODE); //если нет связи
    //путь 2
    if(brightness2)
        lcd.DisplayStringAt(210, 115, (uint8_t *)"#", RIGHT_MODE); //если ярче
    else
        lcd.DisplayStringAt(210, 115, (uint8_t *)"$", RIGHT_MODE); //если тусклее
    if(flCon2)
        lcd.DisplayStringAt(182, 115, (uint8_t *)"'", RIGHT_MODE); //если есть связь
    else
        lcd.DisplayStringAt(182, 115, (uint8_t *)"%", RIGHT_MODE); //если нет связи
    //подписи путей
    lcd.SetFont(&FontRus);
    lcd.DisplayStringAt(170, 115, (uint8_t *)"1 PTSc", LEFT_MODE); //1 путь
    lcd.DisplayStringAt(15, 115, (uint8_t *)"2 PTSc", RIGHT_MODE); //2 путь
    
    if(flTest)
    {
        //кнопка "Назад"
        lcd.SetFont(&FontBigRus);
        lcd.DisplayStringAt(0, 5, (uint8_t *)"SFRS", CENTER_MODE);
        lcd.SetFont(&FontRus);
        Point pt_[3];
        pt_[0] = (Point){441, 22};
        pt_[1] = (Point){472, 10};
        pt_[2] = (Point){472, 35};
        lcd.FillPolygon(pt_, 3);
    }
    else
    {
        //кнопка "Настройки"
        lcd.SetFont(&FontBigRus);
        lcd.DisplayStringAt(0, 5, (uint8_t *)"QABOSA", CENTER_MODE);
        lcd.SetFont(&FontRus);
        lcd.FillRect(440, 7, 33, 3); //линия 1 //4
        lcd.FillRect(440, 21, 33, 3); //линия 2
        lcd.FillRect(440, 36,33, 3); //линия 3
    }
}

//меню настроек
void settingBut(){
    lcd.SetFont(&FontBigRus);
    lcd.DrawRect(315, 46, 164, 218);
    lcd.FillRect(319, 49, 157, 70); //кнопка 1
    lcd.FillRect(319, 120, 157, 70); //кнопка 2
    lcd.FillRect(319, 191, 157, 70); //кнопка 3
    //надписи на кнопках
    lcd.SetBackColor(LCD_COLOR_LIGHTGREEN); //white
    lcd.SetTextColor(LCD_COLOR_BLACK);
    
    lcd.DisplayChar(362, 74, 0x53); //T
    lcd.DisplayChar(379, 74, 0x46); //E
    lcd.DisplayChar(396, 74, 0x52); //S
    lcd.DisplayChar(413, 74, 0x53); //T
    //
    lcd.DisplayChar(337, 144, 0x66); //Я
    lcd.DisplayChar(354, 144, 0x51); //Р
    lcd.DisplayChar(371, 144, 0x4B); //К
    lcd.DisplayChar(388, 144, 0x4F); //О
    lcd.DisplayChar(405, 144, 0x52); //С
    lcd.DisplayChar(422, 144, 0x53); //Т
    lcd.DisplayChar(439, 144, 0x63); //Ь
    //
    lcd.DisplayChar(362, 214, 0x52); //O
    lcd.DisplayChar(379, 214, 0x46); //N
    lcd.DisplayChar(396, 214, 0x53); //F
    lcd.DisplayChar(413, 214, 0x63); //I
    
    lcd.SetBackColor(LCD_COLOR_BLACK);
    lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
    lcd.SetFont(&FontNum);
}

//окно настройки сети
void configWindow(){
    flNetW = 1;
    visible = 1;
    flTime = 0;
    if(flSec1)
        flSec1 = 0;
    if(flSec2)
        flSec2 = 0;
    bool done = 0; //флаг выхода из фун-ии
    lcd.Clear(LCD_COLOR_BLACK);
    lcd.SetTextColor(LCD_COLOR_RED);
    //рамка
    lcd.DrawRect(0, 0, 479, 271);
    lcd.DrawRect(1, 1, 477, 269);
    lcd.DrawRect(2, 2, 475, 267);
    //главные служебные значки
    lcd.SetFont(&FontNum);
    lcd.DisplayStringAt(10, 10, (uint8_t *)"\"", LEFT_MODE);
    if(flEth)
        lcd.DisplayStringAt(38, 10, (uint8_t *)"&", LEFT_MODE); //если есть связь
    else
        lcd.DisplayStringAt(38, 10, (uint8_t *)"%", LEFT_MODE); //если нет связи
    //заголовок
    lcd.SetFont(&FontBigRus);
    lcd.DisplayStringAt(0, 5, (uint8_t *)"RFSc", CENTER_MODE);
    lcd.SetFont(&Font24);
    wait_ms(80); //100
    //IP адрес + кнопки
    drawIP();
    //кнопка "назад"
    Point pt_[3];
    pt_[0] = (Point){441, 22};
    pt_[1] = (Point){472, 10};
    pt_[2] = (Point){472, 35};
    lcd.FillPolygon(pt_, 3);
    
    while(!done)
    {
        HAL_IWDG_Refresh(&IwdgHandle); //сброс wdt
        wait_ms(50);
        
        if(fl1 != flEth) //если есть связь по eth
        {
            fl1 = flEth;
            lcd.SetTextColor(LCD_COLOR_BLACK);
            lcd.FillRect(38, 10, 19, 29);
            lcd.SetTextColor(LCD_COLOR_RED);
            lcd.SetFont(&FontNum);
            if(flEth)
                lcd.DisplayStringAt(38, 10, (uint8_t *)"&", LEFT_MODE); //если есть связь
            else
                lcd.DisplayStringAt(38, 10, (uint8_t *)"%", LEFT_MODE); //если нет связи
            lcd.SetFont(&Font24);
        }
        
        ts.GetState(&TS_State);
        if(TS_State.touchDetected)
        {
            wait_ms(50);
            for(uint8_t ind = 0; ind < TS_State.touchDetected; ind++)
            {
                uint16_t x = TS_State.touchX[ind];
                uint16_t y = TS_State.touchY[ind];
                
                if((x >= 300 && x<=459) && (y>=50 && y<= 258)) //набор ip-адреса //+-10
                {
                    wait_ms(80);
                    viewSymbol(defSymbol(x, y));
                }
                
                if((x >= 434 && x <= 479) && (y >= 1 && y <= 45)) //назад
                {
                    backFunc();
                    done = 1;
                }
            }
        }
    }
    flNetW = 0;
}

//выбор яркости
void drawSelector(){
    bool done = 0;
    flLight = 1;
    
    lcd.SetFont(&FontBigRus);
    lcd.DrawRect(171, 79, 144, 145);
    lcd.FillRect(175, 82, 137, 70); //кнопка 1
    lcd.FillRect(175, 153, 137, 70); //кнопка 2
    //надписи на кнопках
    lcd.SetBackColor(LCD_COLOR_LIGHTGREEN); //white
    lcd.SetTextColor(LCD_COLOR_BLACK);
    //1
    lcd.DisplayChar(200, 107, 0x50); //П
    lcd.DisplayChar(217, 107, 0x54); //У
    lcd.DisplayChar(234, 107, 0x49); //И
    lcd.DisplayChar(268, 107, 0x31); //1
    //2
    lcd.DisplayChar(200, 177, 0x50); //П
    lcd.DisplayChar(217, 177, 0x54); //У
    lcd.DisplayChar(234, 177, 0x49); //И
    lcd.DisplayChar(268, 177, 0x32); //2
    lcd.SetBackColor(LCD_COLOR_BLACK);
    lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
    lcd.SetFont(&FontNum);
    
    while(!done)
    {
        HAL_IWDG_Refresh(&IwdgHandle); //сброс wdt
        wait_ms(50);
        
        ts.GetState(&TS_State);
        if(TS_State.touchDetected)
        {
            wait_ms(50);
            for(uint8_t ind = 0; ind < TS_State.touchDetected; ind++)
            {
                uint16_t x = TS_State.touchX[ind];
                uint16_t y = TS_State.touchY[ind];
                
                if((x >= 175 && x <= 312) && (y >= 82 && y <= 152)) //пуи 1
                {
                    //пеепрключаем состояние
                    brightness1 = !brightness1;
                    //отправляем в com-порт
                    bufSend1[0] = 32;
                    if(brightness1) //если ярче
                        bufSend1[1] = 15;
                    else //если тусклее
                        bufSend1[1] = 1;
                    ansPui1();
                    wait_ms(80); //?????????
                    if(flWorkT2)
                        flSec2 = 1;
                    visible = 1;
                    lcd.Clear(LCD_COLOR_BLACK);
                    mainWindow();
                    done = 1;
                }
                
                if((x >= 175 && x <= 312) && (y >= 153 && y <= 223)) //пуи 2
                {
                    //переключаем состояние
                    brightness2 = !brightness2;
                    //отправка в com-порт
                    bufSend2[0] = 32;
                    if(brightness2) //если ярче
                        bufSend2[1] = 15;
                    else //если тусклее
                        bufSend2[1] = 1;
                    ansPui2();
                    wait_ms(80);
                    if(flWorkT2)
                        flSec2 = 1;
                    visible = 1;
                    lcd.Clear(LCD_COLOR_BLACK);
                    mainWindow();
                    done = 1;
                }
                
                if((x >= 319 && x <= 476) && (y >= 120 && y <= 190)) //выход из под-меню
                {
                    lcd.Clear(LCD_COLOR_BLACK);
                    mainWindow();
                    settingBut();
                    done = 1;
                }
            }
        }
    }
    flLight = 0;
}

//отрисовка эл-ов управления в меню "Сеть"
void drawIP(){   
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.DrawRect(10, 85, 275, 130);
    lcd.DisplayStringAt(20, 142, (uint8_t *)&bufX, LEFT_MODE); //вспомогат. надпись
    lcd.SetTextColor(LCD_COLOR_RED);
    lcd.DisplayStringAt(20, 97, (uint8_t *)ip, LEFT_MODE);
    lcd.DisplayStringAt(20, 187, (uint8_t *)"9003/9006", LEFT_MODE);
    
    //квадратики
    lcd.SetFont(&FontNum);
    uint16_t tX = 310;
    uint16_t tY = 60;
    
    for(int i=0, k=0; i<3; i++)
    {
        for(int v=0; v<3; v++)
        {
            lcd.DisplayChar(tX, tY, 0x31+k);
            tX = tX + 60;
            k++;
        }
        tX = 310;
        tY = tY + 50;
    }
    lcd.DisplayChar(tX + 60, tY, 0x30);
    lcd.DisplayChar(tX, tY, 0x28);
    tX = tX + 120; //60
    lcd.DisplayChar(tX, tY, 0x21);
    lcd.SetFont(&Font24);
}

//определяем выбранный символ в меню "Сеть"
int defSymbol(uint16_t x, uint16_t y){
    uint16_t tX = 297;
    uint16_t tY = 53;
    
    //первая строчка
    for(int i=0; i<3; i++)
    {
        if((x > (tX + i * 59)) && (x < (tX + 45 + i * 59)) && (y > tY) && (y <= (tY + 45)))
            return(i + 1);
    }
    tY = tY + 48;
    //вторая строчка
    for(int i=0; i<3; i++)
    {
        if((x > (tX + i * 59)) && (x < (tX + 45 + i * 59)) && (y > tY) && (y <= (tY + 45)))
            return(4 + i);
    }
    tY = tY + 48;
    //третья строчка
    for(int i=0; i<3; i++)
    {
        if((x > (tX + i * 59)) && (x < (tX + 45 + i * 59)) && (y > tY) && (y <= (tY + 45)))
            return(7 + i);
    }
    tY = tY + 48;
    //четвёртая строчка
    for(int i=0; i<3; i++)
    {
        if((x > (tX + i * 59)) && (x < (tX + 45 + i * 59)) && (y > tY) && (y <= (tY + 45)))
        {
            if(i == 0)
                return('=');
            if(i == 1)
                return(0);
            if(i == 2)
                return('x');
        }
    }
    
    return(255);
}

//отображаем выбранный символ в меню "Сеть"
void viewSymbol(short aaa){
    if(aaa == 255)
        return;
    
    if(ind < 15 && aaa != 120 && aaa != 61)
    {
        switch(aaa)
        {
            case 0:
                bufX[ind] = '0';
                break;
                
            case 1:
                bufX[ind] = '1';
                break;
                
            case 2:
                bufX[ind] = '2';
                break;
                
            case 3:
                bufX[ind] = '3';
                break;
                
            case 4:
                bufX[ind] = '4';
                break;
                
            case 5:
                bufX[ind] = '5';
                break;
                
            case 6:
                bufX[ind] = '6';
                break;
                
            case 7:
                bufX[ind] = '7';
                break;
                
            case 8:
                bufX[ind] = '8';
                break;
                
            case 9:
                bufX[ind] = '9';
                break;
        }
        
        if(ind==2 || ind==6 || ind==10)
            ind += 2;
        else
            ind++;
        sprintf((char*)bufX, "%c%c%c.%c%c%c.%c%c%c.%c%c%c", bufX[0], bufX[1], bufX[2], bufX[4], bufX[5], bufX[6], bufX[8], bufX[9], bufX[10], bufX[12], bufX[13], bufX[14]);
    }
    
    if(aaa == 120)
    {
        if(ind == 4 || ind == 8 || ind == 12)
            ind -= 2;
        else
        {
            if(ind > 0)
                ind--;
        }
        bufX[ind] = 'X';
        sprintf((char*)bufX, "%c%c%c.%c%c%c.%c%c%c.%c%c%c", bufX[0], bufX[1], bufX[2], bufX[4], bufX[5], bufX[6], bufX[8], bufX[9], bufX[10], bufX[12], bufX[13], bufX[14]);
    }
    
    if(aaa == 61 && ind == 15)
    {
        //формируем буфер отображения
        int len = strlen(bufX)+1;
        r = new char[len];
        for(int i=0; i<len; i++)
            r[i] = bufX[i];
        r[len] = 0;
        //проверка введённого ip
        if(checkIP(r)) //если верно
        {
            ind = 0;
            //запись во флеш нового ip
            qspi.Erase_Block(WRITE_READ_ADDR); //очистка флеш
            qspi.Write((uint8_t*)r, WRITE_READ_ADDR, 16); //запись во флеш
            //перезапуск eth
            sock9003.close();
            sock9006.close();
            eth.disconnect();
            flEth = 0;
            //переназначаем новые настройки сети
            wait_ms(50);
            eth.set_network(ip, Mask, Gateway);
            //иниц. eth
            eth.connect();
            sock9003.open(&eth);
            sock9003.bind(9003);
            sock9003.set_blocking(false); //неблокир. режим
            sock9006.open(&eth);
            sock9006.bind(9006);
            sock9006.set_blocking(false); //неблокир. режим
            //убиваем eth-поток
            //int e = threadEth.terminate();
            //wait_ms(/*50*/1000); //?????????????????
            //запускаем новый поток
            //threadEth.start(workEth);
            //перерисовка окна
            lcd.SetTextColor(LCD_COLOR_BLACK);
            lcd.DisplayStringAt(20, 97, (uint8_t *)"255.255.255.255", LEFT_MODE);
            lcd.SetTextColor(LCD_COLOR_RED);
            //конец перерисовки окна
            lcd.DisplayStringAt(20, 97, (uint8_t *)ip, LEFT_MODE);
            sprintf((char*)bufX, "%c%c%c.%c%c%c.%c%c%c.%c%c%c", 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X');
        }
    }
    
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.DisplayStringAt(20, 142, (uint8_t *)&bufX, LEFT_MODE);
    lcd.SetTextColor(LCD_COLOR_RED);
}

//проверка правильности ввода IP-адреса
bool checkIP(const char *str){
    char *p;
    int n;
    char num[4];

    for(int i=0; i<4; i++)
    {
        if(!isdigit((unsigned char) *str))
            return 0;
        n = strtol(str, &p, 10);
        if(n < 0 || n > 255)
            return 0;
        if(i + 1 < 4 && *p != '.')
            return 0;
        num[i] = n;
        str = p + (i + 1 < 4);
    }
    sprintf(r, "%d.%d.%d.%d", num[0], num[1], num[2], num[3]);
    
    if(!strcmp(r, "000.000.000.000")) //если ip = 0.0.0.0
        ip = "10.114.48.13"; //то дефолтный адрес
    else
        ip = r;
    return 1;
}

//возврат в основное меню
void backFunc(){
    lcd.SetFont(&FontNum);
    lcd.Clear(LCD_COLOR_BLACK);
    lcd.SetTextColor(LCD_COLOR_LIGHTGREEN);
    flTime = 1;
    if(flTest) //если режим теста
        flSec1 = flSec2 = 1;
    if(flWorkT1) //если работает ПУИ1
        flSec1 = 1;
    if(flWorkT2) //если работает ПУИ2
        flSec2 = 1;
    mainWindow();
}

//секундомер для путей
void viewTimerSec(){
    sTime = time(NULL) + (7 * 3600);
    s1Time = sec1;
    s2Time = sec2;
    
    checkTh++;
    
    if(flTime) //часы RTC
    {
        lcd.SetFont(&FontNum);
        strftime(buf, 10, "%H:%M:%S", localtime(&sTime));
        lcd.DisplayStringAt(38, 50, (uint8_t *)buf, LEFT_MODE);
    }
    //отрисовка секундомеров
    if(flSec1) //таймер ПУИ1
    {
        if(fl1NP)
            strftime(buf1, 10, "%M:%S ", localtime(&s1Time)); //пробел ОБЯЗАТЕЛЕН
        else
            strftime(buf1, 10, "-%M:%S", localtime(&s1Time));
        lcd.DisplayStringAt(50, 180, (uint8_t *)buf1, LEFT_MODE);
    }
    if(flSec2) //таймер ПУИ2
    {
        if(fl2NP)
            strftime(buf2, 10, " %M:%S", localtime(&s2Time));
        else
            strftime(buf2, 10, "-%M:%S", localtime(&s2Time));
        lcd.DisplayStringAt(60, 180, (uint8_t *)buf2, RIGHT_MODE);
    }
    
    //режим "Тест"
    if(flTest)
    {
        if(sec1 > 0 && fl1NP)
            sec1--;
        else
        {
            fl2NP = fl1NP = 0;            
            sec1++;
            if(sec1 > 30) //конец теста
            {
                flTest = flSec2 = flSec1 = 0;
                fl2NP = fl1NP = 1;
                sec1 = sec2 = 0;
                //зачищаем старую кнопку
                lcd.SetTextColor(LCD_COLOR_BLACK);
                lcd.FillRect(434, 0, 45, 45);
                lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
                mainWindow();
            }
        }
        sec2 = sec1;
    }
    
    //рабочий режим ПУИ1
    if(flWorkT1)
    {
        if(sec1 > 0 && fl1NP)
            sec1--;
        else
        {
            fl1NP = 0;
            sec1++;
            if(sec1 > TIMEOUT_MINUS) //тайм-аут 10 мин.
            {
                flSec1 = flWorkT1 = 0;
                fl1NP = 1;
                sec1 = 0;
            }
        }        
    }
    
    //рабочий режим ПУИ2
    if(flWorkT2)
    {
        if(sec2 > 0 && fl2NP)
            sec2--;
        else
        {
            fl2NP = 0;
            sec2++;
            if(sec2 > TIMEOUT_MINUS) //тайм-аут 10 мин
            {
                flSec2 = flWorkT2 = 0;
                fl2NP = 1;
                sec2 = 0;
            }
        }
    }
    
    //надо ли делать проверку дочернего потока
    if(checkTh == 5)
    {
        checkTh = 0;
        flWdtTh = 1;
    }
}

//установка часов
void setClock(){
    t.tm_year = 2017;
    t.tm_mon = 11;
    t.tm_mday = 15;
    t.tm_hour = 13;
    t.tm_min = 27;
    t.tm_sec = 0;
    t.tm_year = t.tm_year - 1900;
    t.tm_mon = t.tm_mon - 1;    
    sTime = mktime(&t);
    sTime = sTime - (7 * 3600);
    set_time(sTime);
    //таймер на прерывание
    tickerIrqSec.attach(&viewTimerSec, 1);
}

//ответ от ПУИ1
void ansPui1(){
    char cntTry1 = 0;
    lcd.SetFont(&FontNum);
    flCon1 = 0;
    while(!flCon1 && cntTry1 < 3)
    {
        cntTry1++;      
        //отправляем пакет
        pc1.putc(bufSend1[0]);
        wait_ms(8);
        pc1.putc(bufSend1[1]);

        //получаем ответ
        wait_ms(10);
        while(pc1.readable())
        {
            bufPc1[0] = pc1.getc();
            bufPc1[1] = pc1.getc();
        }
        //сравниваем полученное с отправленным
        if(!strcmp(bufSend1, bufPc1)) //если равно
            flCon1 = 1;
        else //если не равно
            flCon1 = 0;
    }
    //выводим на экран резалт
    if(!flNetW) //если не в меню "СЕТЬ"
    {
        lcd.SetTextColor(LCD_COLOR_BLACK);
        lcd.FillRect(38, 115, 19, 29);
        lcd.SetTextColor(LCD_COLOR_LIGHTGREEN);
        if(flCon1)
            lcd.DisplayStringAt(38, 115, (uint8_t *)"'", LEFT_MODE); //есть связь
        else
            lcd.DisplayStringAt(38, 115, (uint8_t *)"%", LEFT_MODE); //нет связи
    }   
    lcd.SetFont(&FontRus);
}

//ответ от ПУИ2
void ansPui2(){
    char cntTry2 = 0;
    lcd.SetFont(&FontNum);
    flCon2 = 0;
    while(!flCon2 && cntTry2 < 3)
    {
        cntTry2++;      
        //отправляем пакет
        pc2.putc(bufSend2[0]);
        wait_ms(8);
        pc2.putc(bufSend2[1]);
        
        //получаем ответ
        wait_ms(10);
        while(pc2.readable())
        {
            bufPc2[0] = pc2.getc();
            bufPc2[1] = pc2.getc();
        }
        //сравниваем полученное с отправленным
        if(!strcmp(bufSend2, bufPc2)) //если равно
            flCon2 = 1;
        else //если не равно
            flCon2 = 0;
    }
    //выводим на экран резалт
    if(!flNetW && !flLight) //если не в меню "СЕТЬ" и не в "ЯРКОСТЬ"
    {
        lcd.SetTextColor(LCD_COLOR_BLACK);
        lcd.FillRect(297, 115, 19, 29);
        lcd.SetTextColor(LCD_COLOR_LIGHTGREEN);
        if(flCon2)
            lcd.DisplayStringAt(182, 115, (uint8_t *)"'", RIGHT_MODE); //есть связь
        else
            lcd.DisplayStringAt(182, 115, (uint8_t *)"%", RIGHT_MODE); //нет связи
    }   
    lcd.SetFont(&FontRus);
    /*cntB2 = 0;
    while(pc2.readable())
    {
        bufPc2[cntB2] = pc2.getc();
        bufPc2[cntB2+1] = pc2.getc();
    }
    lcd.SetFont(&FontNum);
    if(!flLight && !flNetW)
    {
        lcd.SetTextColor(LCD_COLOR_BLACK);
        lcd.FillRect(297, 115, 19, 29);
        lcd.SetTextColor(LCD_COLOR_LIGHTGREEN);
    }
    if(!strcmp(bufSend2, bufPc2))
    {
        flCon2 = 1; //если равны
        if(!flLight && !flNetW)
            lcd.DisplayStringAt(182, 115, (uint8_t *)"'", RIGHT_MODE);
    }
    else
    {
        flCon2 = 0; //если не равны
        if(!flLight && !flNetW)
            lcd.DisplayStringAt(182, 115, (uint8_t *)"%", RIGHT_MODE);
    }
    lcd.SetFont(&FontRus);*/
}

//отправка времени на ПУИ1
void pui1SetTime(int n){
    if ((n > 0) && (n < 255))
    {
        bufSend1[0] = 128;
        bufSend1[1] = n;
    }
    else if ((n > 256) && (n < 511))
    {
        bufSend1[0] = 121;
        bufSend1[1] = n - 256;
    }
    else if ((n > 512) && (n < 767))
    {
        bufSend1[0] = 130;
        bufSend1[1] = n - 512;
    }
    else if ((n > 768) && (n < 961))
    {
        bufSend1[0] = 131;
        bufSend1[1] = n - 768;
    }
    ansPui1();
}

//отправка времени на ПУИ2
void pui2SetTime(int n){
    if ((n > 0) && (n < 255))
    {
        bufSend2[0] = 128;
        bufSend2[1] = n + 1;
    }
    else if ((n > 256) && (n < 511))
    {        
        bufSend2[0] = 129;
        bufSend2[1] = n - 255;
    }
    else if ((n > 512) && (n < 767))
    {
        bufSend2[0] = 130;
        bufSend2[1] = n - 511;
    }
    else if ((n > 768) && (n < 961))
    {
        bufSend2[0] = 131;
        bufSend2[1] = n - 767;
    }
    ansPui2();
}

//отправка станции на ПУИ1
void sendStatPui1(short stat){
     bufSend1[0] = 64;
     switch(stat)
     {
        case 114:
          // ABTOBO;
          bufSend1[1] = 1;
          break;
        case 115:
          // НАРВСКАЯ
          bufSend1[1] = 3;
          break;
        case 117:
          // ТЕХНОЛОГИЧЕСКИЙ ИНСТИТУТ
          bufSend1[1] = 7;
          break;
        case 120:
          // ПЛОЩАДЬ ВОССТАНИЯ
          bufSend1[1] = 6;
          break;
        case 122:
          // ПЛОЩАДЬ ЛЕНИНА
          bufSend1[1] = 4;
          break;
        case 127:
          // АКАДЕМИЧЕСКАЯ
          bufSend1[1] = 2;
          break;
    
        case 218:
          // САДОВАЯ
          bufSend1[1] = 22;
          break;
    
        case 319:
          //ОБУХОВО
          bufSend1[1] = 11;
          break;
        case 317:
          //ЛОМОНОСОВСКАЯ
          bufSend1[1] = 12;
          break;
        case 315:
          // ПЛ. АЛЕКСАНДРА НЕВСКОГО I
          bufSend1[1] = 13;
          break;
        case 314:
          // МАЯКОВСКАЯ
          bufSend1[1] = 14;
          break;
        case 312:
          // ВАСИЛЕОСТРОВСКАЯ
          bufSend1[1] = 16;
          break;
    
        case 416:
          // ПЛ. АЛЕКСАНДРА НЕВСКОГО II
          bufSend1[1] = 21;
          break;
          
        case 522:
          // ЧКАЛОВСКАЯ
          bufSend1[1] = 23;
          break;
        case 524:
          // СТАРАЯ ДЕРЕВНЯ
          bufSend1[1] = 24;
          break;
    }
    ansPui1();
}

//отправка станции на ПУИ2
void sendStatPui2(short stat){
     bufSend2[0] = 64;
     switch(stat)
     {
        case 114:
          // ABTOBO;
          bufSend2[1] = 1;
          break;
        case 115:
          // НАРВСКАЯ
            bufSend2[1] = 3;
          break;
        case 117:
          // ТЕХНОЛОГИЧЕСКИЙ ИНСТИТУТ
          bufSend2[1] = 7;
          break;
        case 120:
          // ПЛОЩАДЬ ВОССТАНИЯ
          bufSend2[1] = 6;
          break;
        case 122:
          // ПЛОЩАДЬ ЛЕНИНА
          bufSend2[1] = 4;
          break;
        case 127:
          // АКАДЕМИЧЕСКАЯ
          bufSend2[1] = 2;
          break;
    
        case 218:
          // САДОВАЯ
          bufSend2[1] = 22;
          break;
    
        case 319:
          //ОБУХОВО
          bufSend2[1] = 11;
          break;
        case 317:
          //ЛОМОНОСОВСКАЯ
          bufSend2[1] = 12;
          break;
        case 315:
          // ПЛ. АЛЕКСАНДРА НЕВСКОГО I
          bufSend2[1] = 13;
          break;
        case 314:
          // МАЯКОВСКАЯ
          bufSend2[1] = 14;
          break;
        case 312:
          // ВАСИЛЕОСТРОВСКАЯ
          bufSend2[1] = 16;
          break;
    
        case 416:
          // ПЛ. АЛЕКСАНДРА НЕВСКОГО II
          bufSend2[1] = 21;
          break;
        case 522:
          // ЧКАЛОВСКАЯ
          bufSend2[1] = 23;
          break;
        case 524:
          // СТАРАЯ ДЕРЕВНЯ
          bufSend2[1] = 24;
          break;
    }
    ansPui2();
}

//вывод станции на экран
void viewStation(short stat, bool fl){
    char station[25];
    lcd.SetFont(&FontRus);
    strcpy(&station[0], getStation(stat));
    if(!fl)
        lcd.DisplayStringAt(10, 250, (uint8_t *)&station, LEFT_MODE);
    else
        lcd.DisplayStringAt(10, 250, (uint8_t *)&station, RIGHT_MODE);
    lcd.SetFont(&FontNum);
}

//определение названия станции
char* getStation(short stat){
    switch(stat)
    {
        case 0:
            return "[]";
        case 112:
          return "P-KS CFSFQANOC"; //Проспект Ветеранов
        case 113:
          return "LFNINRKIJ P-KS"; //Ленинский Проспект
        case 114:
          return "ACSOCO"; //Автово
        case 115:
          return "NAQCRKAf"; //Нарвская
        case 116:
          return "BALSIJRKAf"; //Балтийская
        case 117:
          return "SFVNOLODIXFRKIJ I."; //Технологический Институт
        case 118:
          return "PTYKINRKAf"; //Пушкинская
        case 119:
          return "CLAEIMIQRKAf"; //Владимирская
        case 120:
          return "P-Ec CORRSANIf"; //Площадь Восстания
        case 121:
          return "XFQNbYFCRKAf"; //Чернышевская
        case 122:
          return "P-Ec LFNINA"; //Площадь Ленина
        case 123:
          return "CbBOQDRKAf"; //Выборгская
        case 124:
          return "LFRNAf"; //Лесная
        case 125:
          return "P-Ec MTGFRSCA"; //Площадь Мужества
        case 126:
          return "POLISFVNIXFRKAf"; //Политехническая
        case 127:
          return "AKAEFMIXFRKAf"; //Академическая
        case 128:
          return "DQAGEANRKIJ P-KS"; //Гражданский Проспект
        case 129:
          return "EFCfSKINO"; //Девяткино
    
        case 211:
          return "KTPXINO"; //Купчино
        case 212:
          return "HCFHENAf"; //Звёздная
        case 213:
          return "MORKOCRKAf"; //Московская
        case 214:
          return "PAQK POBFEb"; //Парк Победы
        case 215:
          return "dLFKSQORILA"; //Электросила
        case 216:
          return "UQTNHFNRKAf"; //Фрунзенская
        case 217:
          return "SFVNOLODIXFRKIJ I.2"; //Технологический Институт 2
        case 218:
          return "RAEOCAf"; //Садовая
    
        case 220:
          return "NFCRKIJ P-KS"; //Невский Проспект
        case 221:
          return "DOQcKOCRKAf"; //Горьковская
        case 222:
          return "PFSQODQAERKAf"; //Петроградская
        case 223:
          return "XFQNAf QFXKA"; //Чёрная Речка
        case 224:
          return "PIONFQRKAf"; //Пионерская
        case 225:
          return "TEFLcNAf"; //Удельная
        case 226:
          return "OHFQKI"; //Озерки
        case 227:
          return "P-KS PQORCFZFNIf"; //Проспект Просвещения
        case 228:
          return "PAQNAR"; //Парнас
    
        case 320:
          return "QbBASRKOF"; //Рыбатское
        case 319:
          return "OBTVOCO"; //Обухово
        case 318:
          return "PQOLFSAQRKAf"; //Пролетарская
        case 317:
          return "LOMONOROCRKAf"; //Ломоносовская
        case 316:
          return "FLIHAQOCRKAf"; //Елизаровская
        case 315:
          return "P-Ec A. NFCRKODO 1"; //Площадь Александра Невского 1
        case 314:
          return "MAfKOCRKAf"; //Маяковская
        case 313:
          return "DORSINbJ ECOQ"; //Гостиный Двор
        case 312:
          return "CARILFORSQOCRKAf"; //Василеостровская
        case 311:
          return "PQIMOQRKAf"; //Приморская
    
        case 412:
          return "EbBFNKO"; //Дыбенко
        case 413:
          return "P-KS BOLcYFCIKOC"; //Проспект Большевиков
        case 414:
          return "LAEOGRKAf"; //Ладожская
        case 415:
          return "NOCOXFQKARRKAf"; //Новочеркасская
        case 416:
          return "P-Ec A. NFCRKODO 2"; //Площадь Александра Невского 2
        case 417:
          return "LIDOCRKIJ P-KS"; //Лиговский Проспект
        case 418:
          return "RPARRKAf"; //Спасская
    
        case 514:
          return "MFGETNAQOENAf"; //Международная
        case 515:
          return "BTVAQFRSRKAf"; //Бухарестская
        case 516:
          return "COLKOCRKAf"; //Волковская
        case 517:
          return "OBCOENbJ KANAL"; //Обводный Канал
        case 518:
          return "HCFNIDOQOERKAf"; //Звенигородская
        case 519:
          return "RFNNAf P-Ec"; //Сенная Площадь
        case 520:
          return "AEMIQALSFJRKAf"; //Адмиралтейская
        case 521:
          return "RPOQSICNAf"; //Спортивная
        case 522:
          return "XKALOCRKAf"; //Чкаловская
        case 523:
          return "KQFRSOCRKIJ ORSQOC"; //Крестовский Остров
        case 524:
          return "RSAQAf EFQFCNf"; //Старая Деревня
        case 525:
          return "KOMFNEANSRKIJ P-KS"; //Комендантский Проспект
    }
    return "";//'\0';
}

//эмблема нии тм
void logo(){
    lcd.Clear(LCD_COLOR_BLACK);
    lcd.SetTextColor(LCD_COLOR_BLUE);
    //круги
    for(int i=0; i<3; i++)
        lcd.DrawCircle(240, 136, 75 + i);
    lcd.DrawCircle(240, 136, 80);
    //Т
    lcd.FillRect(214, 81, 52, 7);
    lcd.DrawHLine(214, 88, 18);
    lcd.DrawHLine(214, 89, 17);
    lcd.DrawHLine(215, 90, 15);
    lcd.DrawHLine(216, 91, 12);
    lcd.DrawHLine(217, 92, 10);
    lcd.DrawHLine(218, 93, 9);
    lcd.DrawHLine(219, 94, 7);
    lcd.DrawHLine(220, 95, 5);
    lcd.DrawHLine(246, 88, 20);
    lcd.DrawHLine(247, 89, 19);
    lcd.DrawHLine(248, 90, 17);
    lcd.DrawHLine(250, 91, 14);
    lcd.DrawHLine(251, 92, 12);
    lcd.DrawHLine(251, 93, 11);
    lcd.DrawHLine(253, 94, 8);
    lcd.DrawHLine(254, 95, 6);
    lcd.FillRect(235, 88, 8, 75);
    //M
    lcd.FillRect(194, 96, 12, 76);
    lcd.FillRect(275, 96, 12, 76);
    lcd.DrawHLine(195, 172, 11);
    lcd.DrawHLine(196, 173, 10);
    lcd.DrawHLine(197, 174, 9);
    lcd.DrawHLine(198, 175, 8);
    lcd.DrawHLine(199, 176, 7);
    lcd.DrawHLine(200, 177, 6);
    lcd.DrawHLine(201, 178, 5);
    lcd.DrawHLine(202, 179, 4);
    lcd.DrawHLine(203, 180, 3);
    lcd.DrawHLine(204, 181, 2);
    lcd.DrawHLine(275, 172, 11);
    lcd.DrawHLine(275, 173, 10);
    lcd.DrawHLine(275, 174, 9);
    lcd.DrawHLine(275, 175, 8);
    lcd.DrawHLine(275, 176, 7);
    lcd.DrawHLine(275, 177, 6);
    lcd.DrawHLine(275, 178, 5);
    lcd.DrawHLine(275, 179, 4);
    lcd.DrawHLine(275, 180, 3);
    lcd.DrawHLine(275, 181, 2);
    for(int i=0; i<15; i++)
    {
        lcd.DrawLine(206, 97 + i, 238, 177 + i);
        lcd.DrawLine(275, 97 + i, 238, 177 + i);
    }
    //прямоугольник
    lcd.FillRect(226, 148, 27, 15);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    //Н
    lcd.DrawVLine(228, 151, 10);
    lcd.DrawHLine(228, 155, 7);
    lcd.DrawVLine(235, 151, 10);
    //И
    lcd.DrawVLine(238, 151, 10);
    lcd.DrawLine(238, 161, 243, 151);
    lcd.DrawVLine(243, 151, 10);
    //И
    lcd.DrawVLine(246, 151, 10);
    lcd.DrawLine(246, 161, 251, 151);
    lcd.DrawVLine(251, 151, 10);
    
    wait(2);
    lcd.Clear(LCD_COLOR_BLACK);
    lcd.SetBackColor(LCD_COLOR_BLACK);
    lcd.SetTextColor(LCD_COLOR_LIGHTGREEN); //white
}

//уст-ка флага отсутствия связи с сервером
void workConn(){
    flEth = 0;   
}

//watchdog-таймер
void StartIWDG(int interval_ms)
{
    if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET)
        __HAL_RCC_CLEAR_RESET_FLAGS();
 
    /* IWDG counter clock Frequency = LsiFreq/256 = LSI_VALUE
       Counter Reload Value = 250ms/IWDG counter clock period
       256/32.000 = 8 ms per cycle (prescaler/LSI)
       reload = interval_ms / 8;
       LSI_VALUE = 32000 on the L4 */
    int reload_ms = (256 * 1000) / LSI_VALUE; //~ 8 мс
    int reload_val = interval_ms / reload_ms;
    if (reload_val <= 0)
        reload_val = 8;
    if (reload_val > (1 << 12) - 1) //> 12-битн. счётчик
        reload_val = (1 << 12) - 1;
 
    IwdgHandle.Instance = IWDG;
    IwdgHandle.Init.Prescaler = IWDG_PRESCALER_256;
    IwdgHandle.Init.Reload = reload_val;
    IwdgHandle.Init.Window = IWDG_WINDOW_DISABLE;
 
    HAL_IWDG_Init(&IwdgHandle);
    HAL_IWDG_Refresh(&IwdgHandle);  
}