TEST2

Dependencies:   LCD_DISCO_F746NG QSPI_DISCO_F746NG TS_DISCO_F746NG

Revision:
0:011a309655b5
Child:
2:1d503ae10977
Child:
3:4c554633a76a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Dec 14 09:40:28 2017 +0000
@@ -0,0 +1,1518 @@
+#include "main.h"
+
+//поток на работу с Eth
+void workEth(){
+    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);  
+}
\ No newline at end of file