From f2a57dda638a14f2d41dd634bbe9ef3ebc9a1aac Mon Sep 17 00:00:00 2001 From: milek7 Date: Thu, 21 Sep 2017 19:33:48 +0200 Subject: [PATCH] uart experiments windows build fix log uart write error uart changes uart changes uart changes uart changes uart changes uart works uart changes verbose uart log uart changes uart changes uart logging uart logging uart changes changes uart changes --- Button.h | 1 + CMakeLists.txt | 8 +- CMake_modules/Findlibserialport.cmake | 9 + Console.cpp | 127 ----- Console/MWD.cpp | 763 -------------------------- Console/MWD.h | 98 ---- EU07.cpp | 9 +- Globals.cpp | 142 +---- Globals.h | 42 +- Train.cpp | 255 ++++++--- Train.h | 14 + builds/cmake_win32.bat | 4 +- builds/cmake_win64.bat | 4 +- builds/download_windeps.bat | 2 +- command.cpp | 6 +- command.h | 11 +- uart.cpp | 173 ++++++ uart.h | 58 ++ 18 files changed, 537 insertions(+), 1189 deletions(-) create mode 100644 CMake_modules/Findlibserialport.cmake delete mode 100644 Console/MWD.cpp delete mode 100644 Console/MWD.h create mode 100644 uart.cpp create mode 100644 uart.h diff --git a/Button.h b/Button.h index c468d7ff..3080aff0 100644 --- a/Button.h +++ b/Button.h @@ -49,6 +49,7 @@ class TButton Turn( !m_state ); }; inline bool Active() { return (pModelOn) || (pModelOff); }; + inline uint8_t b() { return m_state ? 1 : 0; }; void Update(); void Init(std::string const &asName, TModel3d *pModel, bool bNewOn = false); void Load(cParser &Parser, TModel3d *pModel1, TModel3d *pModel2 = NULL); diff --git a/CMakeLists.txt b/CMakeLists.txt index 151cc2d4..77d13adc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.0) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake_modules/") project("eu07++ng") +set(CMAKE_CXX_STANDARD 14) include_directories("." "Console" "McZapkie") file(GLOB HEADERS "*.h" "Console/*.h" "McZapkie/*.h") @@ -66,11 +67,12 @@ set(SOURCES "translation.cpp" "material.cpp" "lua.cpp" +"uart.cpp" ) if (WIN32) add_definitions(-DHAVE_ROUND) # to make pymath to not redefine round - set(SOURCES ${SOURCES} "windows.cpp" "Console.cpp" "Console/LPT.cpp" "Console/MWD.cpp" "Console/PoKeys55.cpp" "wavread.cpp") + set(SOURCES ${SOURCES} "windows.cpp" "Console.cpp" "Console/LPT.cpp" "Console/PoKeys55.cpp" "wavread.cpp") endif() if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) @@ -130,6 +132,10 @@ find_package(LuaJIT REQUIRED) include_directories(${LUAJIT_INCLUDE_DIR}) target_link_libraries(${PROJECT_NAME} ${LUAJIT_LIBRARIES}) +find_package(libserialport REQUIRED) +include_directories(${libserialport_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} ${libserialport_LIBRARY}) + if (UNIX) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -g") endif() diff --git a/CMake_modules/Findlibserialport.cmake b/CMake_modules/Findlibserialport.cmake new file mode 100644 index 00000000..08548e8a --- /dev/null +++ b/CMake_modules/Findlibserialport.cmake @@ -0,0 +1,9 @@ +find_path(libserialport_INCLUDE_DIR libserialport.h) +find_library(libserialport_LIBRARY serialport) +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(libserialport DEFAULT_MSG libserialport_LIBRARY libserialport_INCLUDE_DIR) +if(libserialport_FOUND) + set(libserialport_LIBRARIES ${libserialport_LIBRARY}) + set(libserialport_INCLUDE_DIRS ${libserialport_INCLUDE_DIR}) +endif() + diff --git a/Console.cpp b/Console.cpp index 0f8775c5..886f2656 100644 --- a/Console.cpp +++ b/Console.cpp @@ -13,7 +13,6 @@ http://mozilla.org/MPL/2.0/. #include "McZapkie/mctools.h" #include "LPT.h" #include "Logs.h" -#include "MWD.h" // maciek001: obsluga portu COM #include "PoKeys55.h" //--------------------------------------------------------------------------- @@ -118,7 +117,6 @@ Console::~Console() { delete PoKeys55[0]; delete PoKeys55[1]; - delete MWDComm; }; void Console::ModeSet(int m, int h) @@ -166,18 +164,6 @@ int Console::On() break; } - if (Global::bMWDmasterEnable) - { - WriteLog("Opening ComPort"); - MWDComm = new TMWDComm(); - if (!(MWDComm->Open())) // jeżeli nie otwarł portu - { - WriteLog("ERROR: ComPort is NOT OPEN!"); - delete MWDComm; - MWDComm = NULL; - } - } - return 0; }; @@ -196,8 +182,6 @@ void Console::Off() PoKeys55[1] = NULL; delete LPT; LPT = NULL; - delete MWDComm; - MWDComm = NULL; }; void Console::BitsSet(int mask, int entry) @@ -289,56 +273,6 @@ void Console::BitsUpdate(int mask) } break; } - if (Global::bMWDmasterEnable) - { - // maciek001: MWDComm lampki i kontrolki - // out3: ogrzewanie sk?adu, opory rozruchowe, poslizg, zaluzjewent, -, -, czuwak, shp - // out4: stycz.liniowe, pezekaznikr??nicobwpomoc, nadmiarprzetw, roznicowy obw. g?, nadmiarsilniki, wylszybki, zanikpr?duprzyje?dzienaoporach, nadmiarsprezarki - // out5: HASLER */ - if (mask & 0x0001) if (iBits & 1) { - MWDComm->WriteDataBuff[4] |= 1 << 7; // SHP HASLER też - if (!MWDComm->bSHPstate) { - MWDComm->bSHPstate = true; - MWDComm->bPrzejazdSHP = true; - } - else MWDComm->bPrzejazdSHP = false; - } - else { - MWDComm->WriteDataBuff[4] &= ~(1 << 7); - MWDComm->bPrzejazdSHP = false; - MWDComm->bSHPstate = false; - } - if (mask & 0x0002) if (iBits & 2) MWDComm->WriteDataBuff[4] |= 1 << 6; // CA - else MWDComm->WriteDataBuff[4] &= ~(1 << 6); - if (mask & 0x0004) if (iBits & 4) MWDComm->WriteDataBuff[4] |= 1 << 1; // jazda na oporach rozruchowych - else MWDComm->WriteDataBuff[4] &= ~(1 << 1); - if (mask & 0x0008) if (iBits & 8) MWDComm->WriteDataBuff[5] |= 1 << 5; // wyłącznik szybki - else MWDComm->WriteDataBuff[5] &= ~(1 << 5); - if (mask & 0x0010) if (iBits & 0x10) MWDComm->WriteDataBuff[5] |= 1 << 4; // nadmiarowy silników trakcyjnych - else MWDComm->WriteDataBuff[5] &= ~(1 << 4); - if (mask & 0x0020) if (iBits & 0x20) MWDComm->WriteDataBuff[5] |= 1 << 0; // styczniki liniowe - else MWDComm->WriteDataBuff[5] &= ~(1 << 0); - if (mask & 0x0040) if (iBits & 0x40) MWDComm->WriteDataBuff[4] |= 1 << 2; // poślizg - else MWDComm->WriteDataBuff[4] &= ~(1 << 2); - if (mask & 0x0080) if (iBits & 0x80) MWDComm->WriteDataBuff[5] |= 1 << 2; // (nadmiarowy) przetwornicy? ++ - else MWDComm->WriteDataBuff[5] &= ~(1 << 2); - if (mask & 0x0100) if (iBits & 0x100) MWDComm->WriteDataBuff[5] |= 1 << 7; // nadmiarowy sprężarki - else MWDComm->WriteDataBuff[5] &= ~(1 << 7); - if (mask & 0x0200) if (iBits & 0x200) MWDComm->WriteDataBuff[2] |= 1 << 1; // wentylatory i opory - else MWDComm->WriteDataBuff[2] &= ~(1 << 1); - if (mask & 0x0400) if (iBits & 0x400) MWDComm->WriteDataBuff[2] |= 1 << 2; // wysoki rozruch - else MWDComm->WriteDataBuff[2] &= ~(1 << 2); - if (mask & 0x0800) if (iBits & 0x800) MWDComm->WriteDataBuff[4] |= 1 << 0; // ogrzewanie pociągu - else MWDComm->WriteDataBuff[4] &= ~(1 << 0); - if (mask & 0x1000) if (iBits & 0x1000) MWDComm->bHamowanie = true; // hasler: ciśnienie w hamulcach HASLER rysik 2 - else MWDComm->bHamowanie = false; - if (mask & 0x2000) if (iBits & 0x2000) MWDComm->WriteDataBuff[6] |= 1 << 4; // hasler: prąd "na" silnikach - HASLER rysik 3 - else MWDComm->WriteDataBuff[6] &= ~(1 << 4); - if (mask & 0x4000) if (iBits & 0x4000) MWDComm->WriteDataBuff[6] |= 1 << 7; // brzęczyk SHP/CA - else MWDComm->WriteDataBuff[6] &= ~(1 << 7); - //if(mask & 0x8000) if(iBits & 0x8000) MWDComm->WriteDataBuff[1] |= 1<<7; (puste) - //else MWDComm->WriteDataBuff[0] &= ~(1<<7); - } }; void Console::ValueSet(int x, double y) @@ -371,57 +305,6 @@ void Console::ValueSet(int x, double y) WriteLog(" calibrated=" + std::to_string(temp)); PoKeys55[0]->PWM(x, temp); } - if (Global::bMWDmasterEnable) - { - unsigned int iliczba; - switch (x) - { - case 0: iliczba = (unsigned int)floor((y / (Global::fMWDzg[0] * 10) * Global::fMWDzg[1]) + 0.5); // zbiornik główny - MWDComm->WriteDataBuff[12] = (unsigned char)(iliczba >> 8); - MWDComm->WriteDataBuff[11] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Main tank press " + to_string(MWDComm->WriteDataBuff[12]) + " " + to_string(MWDComm->WriteDataBuff[11])); - break; - case 1: iliczba = (unsigned int)floor((y / (Global::fMWDpg[0] * 10) * Global::fMWDpg[1]) + 0.5); // przewód główny - MWDComm->WriteDataBuff[10] = (unsigned char)(iliczba >> 8); - MWDComm->WriteDataBuff[9] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Main pipe press " + to_string(MWDComm->WriteDataBuff[10]) + " " + to_string(MWDComm->WriteDataBuff[9])); - break; - case 2: iliczba = (unsigned int)floor((y / (Global::fMWDph[0] * 10) * Global::fMWDph[1]) + 0.5); // cylinder hamulcowy - MWDComm->WriteDataBuff[8] = (unsigned char)(iliczba >> 8); - MWDComm->WriteDataBuff[7] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Break press " + to_string(MWDComm->WriteDataBuff[8]) + " " + to_string(MWDComm->WriteDataBuff[7])); - break; - case 3: iliczba = (unsigned int)floor((y / Global::fMWDvolt[0] * Global::fMWDvolt[1]) + 0.5); // woltomierz WN - MWDComm->WriteDataBuff[14] = (unsigned char)(iliczba >> 8); - MWDComm->WriteDataBuff[13] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Hi Volt meter " + to_string(MWDComm->WriteDataBuff[14]) + " " + to_string(MWDComm->WriteDataBuff[13])); - break; - case 4: iliczba = (unsigned int)floor((y / Global::fMWDamp[0] * Global::fMWDamp[1]) + 0.5); // amp WN 1 - MWDComm->WriteDataBuff[16] = (unsigned char)(iliczba >> 8); - MWDComm->WriteDataBuff[15] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Apm meter1 " + to_string(MWDComm->WriteDataBuff[16]) + " " + to_string(MWDComm->WriteDataBuff[15])); - break; - case 5: iliczba = (unsigned int)floor((y / Global::fMWDamp[0] * Global::fMWDamp[1]) + 0.5); // amp WN 2 - MWDComm->WriteDataBuff[18] = (unsigned char)(iliczba >> 8); - MWDComm->WriteDataBuff[17] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Apm meter2 " + to_string(MWDComm->WriteDataBuff[18]) + " " + to_string(MWDComm->WriteDataBuff[17])); - break; - case 6: iliczba = (unsigned int)floor((y / Global::fMWDamp[0] * Global::fMWDamp[1]) + 0.5); // amp WN 3 - MWDComm->WriteDataBuff[20] = (unsigned int)(iliczba >> 8); - MWDComm->WriteDataBuff[19] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Apm meter3 " + to_string(MWDComm->WriteDataBuff[20]) + " " + to_string(MWDComm->WriteDataBuff[19])); - break; - case 7: if (Global::iPause) MWDComm->WriteDataBuff[0] = 0; //skoro pauza to hasler stoi i nie nabija kilometrów CHYBA NIE DZIAŁA! - else MWDComm->WriteDataBuff[0] = (unsigned char)floor(y); // prędkość dla np haslera - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Speed: " + to_string(MWDComm->WriteDataBuff[0])); - break; - case 8: iliczba = (unsigned int)floor((y / Global::fMWDlowVolt[0] * Global::fMWDlowVolt[1]) + 0.5); // volt NN - MWDComm->WriteDataBuff[22] = (unsigned int)(iliczba >> 8); - MWDComm->WriteDataBuff[21] = (unsigned char)iliczba; - if (Global::bMWDmasterEnable && Global::iMWDDebugMode & 8) WriteLog("Low Volt meter " + to_string(MWDComm->WriteDataBuff[22]) + " " + to_string(MWDComm->WriteDataBuff[21])); - break; // przygotowane do wdrożenia, jeszcze nie wywoływane - } - } }; void Console::Update() @@ -439,11 +322,6 @@ void Console::Update() Global::iPause |= 8; // tak??? PoKeys55[0]->Connect(); // próba ponownego podłączenia } - if (Global::bMWDmasterEnable) - { - if (MWDComm->GetMWDState()) MWDComm->Run(); - else MWDComm->Close(); - } }; float Console::AnalogGet(int x) @@ -468,11 +346,6 @@ float Console::AnalogCalibrateGet(int x) if (x == 1) return b/10; else return b; } - if (Global::bMWDmasterEnable && Global::bMWDBreakEnable) - { - float b = (float)MWDComm->uiAnalog[x]; - return (b - Global::fMWDAnalogInCalib[x][0]) / (Global::fMWDAnalogInCalib[x][1] - Global::fMWDAnalogInCalib[x][0]); - } return -1.0; // odcięcie }; diff --git a/Console/MWD.cpp b/Console/MWD.cpp deleted file mode 100644 index 67b63bdd..00000000 --- a/Console/MWD.cpp +++ /dev/null @@ -1,763 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -/* - Program obsługi portu COM i innych na potrzeby sterownika MWDevice - (oraz innych wykorzystujących komunikację przez port COM) - dla Symulatora Pojazdów Szynowych MaSzyna - author: Maciej Witek 2016 - Autor nie ponosi odpowiedzialności za niewłaciwe używanie lub działanie programu! -*/ -#include "stdafx.h" -#include "MWD.h" -#include "Globals.h" -#include "Logs.h" -#include "World.h" - -#include - -HANDLE hComm; - -TMWDComm::TMWDComm() // konstruktor -{ - MWDTime = 0; - bSHPstate = false; - bPrzejazdSHP = false; - bKabina1 = true; // pasuje wyciągnąć dane na temat kabiny - bKabina2 = false; // i ustawiać te dwa parametry! - bHamowanie = false; - bCzuwak = false; - - bRysik1H = false; - bRysik1L = false; - bRysik2H = false; - bRysik2L = false; - - bocznik = 0; - nastawnik = 0; - kierunek = 0; - bnkMask = 0; - - int i = 6; - - while (i) - { - i--; - lastStateData[i] = 0; - maskData[i] = 0; - maskSwitch[i] = 0; - bitSwitch[i] = 0; - } - - i = 0; - while (i 0) - return 1; - else - return 0; -} - -bool TMWDComm::ReadData() // odbieranie danych + odczyta danych analogowych i zapis do zmiennych -{ - DWORD bytes_read; - ReadFile(hComm, &ReadDataBuff[0], BYTETOREAD, &bytes_read, NULL); - if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog("Data receive. Checking data..."); - if (Global::bMWDBreakEnable) - { - uiAnalog[0] = (ReadDataBuff[9] << 8) + ReadDataBuff[8]; - uiAnalog[1] = (ReadDataBuff[11] << 8) + ReadDataBuff[10]; - uiAnalog[2] = (ReadDataBuff[13] << 8) + ReadDataBuff[12]; - uiAnalog[3] = (ReadDataBuff[15] << 8) + ReadDataBuff[14]; - if (Global::bMWDdebugEnable && (Global::iMWDDebugMode & 1)) - { - WriteLog("Main Break = " + to_string(uiAnalog[0])); - WriteLog("Locomotiv Break = " + to_string(uiAnalog[1])); - } - if (Global::bMWDdebugEnable && (Global::iMWDDebugMode & 2)) - { - WriteLog("Analog input 1 = " + to_string(uiAnalog[2])); - WriteLog("Analog imput 2 = " + to_string(uiAnalog[3])); - } - } - if (Global::bMWDInputEnable) CheckData(); - return TRUE; -} - -bool TMWDComm::SendData() // wysyłanie danych -{ - DWORD bytes_write; - - WriteFile(hComm, &WriteDataBuff[0], BYTETOWRITE, &bytes_write, NULL); - - return TRUE; -} - -bool TMWDComm::Run() // wywoływanie obsługi MWD + generacja większego opóźnienia -{ - if (GetMWDState()) - { - MWDTime++; - if (!(MWDTime % Global::iMWDdivider)) - { - MWDTime = 0; - if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog("Sending data..."); - SendData(); - if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog(" complet!\nReceiving data..."); - ReadData(); - if (Global::bMWDdebugEnable && Global::iMWDDebugMode == 128) WriteLog(" complet!"); - return 1; - } - } - else - { - WriteLog("Port COM: connection ERROR!"); - Close(); - // może spróbować się połączyć znowu? - return 0; - } - return 1; -} - -void TMWDComm::CheckData() // sprawdzanie wejść cyfrowych i odpowiednie sterowanie maszyną -{ - int i = 0; - while (i < 6) - { - maskData[i] = ReadDataBuff[i] ^ lastStateData[i]; - lastStateData[i] = ReadDataBuff[i]; - i++; - } - /* - Rozpiska portów! - Port0: 0 NC odblok. przek. sprężarki i wentyl. oporów - 1 M wyłącznik wył. szybkiego - 2 Shift+M impuls załączający wył. szybki - 3 N odblok. przekaźników nadmiarowych - i różnicowego obwodu głównegoMMm - 4 NC rezerwa - 5 Ctrl+N odblok. przek. nadmiarowych - przetwornicy, ogrzewania pociągu i różnicowych obw. pomocniczych - 6 L wył. styczników liniowych - 7 SPACE kasowanie czuwaka - - Port1: 0 NC - 1 (Shift) X przetwornica - 2 (Shift) C sprężarka - 3 S piasecznice - 4 (Shift) H ogrzewanie składu - 5 przel. hamowania Shift+B - pspbpwy Ctrl+B pospieszny B towarowy - 6 przel. hamowania - 7 (Shift) F rozruch w/n - - Port2: 0 (Shift) P pantograf przedni - 1 (Shift) O pantograf tylni - 2 ENTER przyhamowanie przy poślizgu - 3 () przyciemnienie świateł - 4 () przyciemnienie świateł - 5 NUM6 odluźniacz - 6 a syrena lok W - 7 A syrena lok N - - Port3: 0 Shift+J bateria - 1 - 2 - 3 - 4 - 5 - 6 - 7 - */ - - /* po przełączeniu bistabilnego najpierw wciskamy klawisz i przy następnym - wejściu w pętlę MWD puszczamy bo inaczej nie działa - */ - - // wciskanie przycisków klawiatury - /*PORT0*/ - if (maskData[0] & 0x02) if (lastStateData[0] & 0x02) - KeyBoard('M', 1); // wyłączenie wyłącznika szybkiego - else KeyBoard('M', 0); // monostabilny - if (maskData[0] & 0x04) if (lastStateData[0] & 0x04) // impuls załączający wyłącznik szybki - { - KeyBoard(0x10, 1); // monostabilny - KeyBoard('M', 1); - } - else - { - KeyBoard('M', 0); - KeyBoard(0x10, 0); - } - if (maskData[0] & 0x08) if (lastStateData[0] & 0x08) - KeyBoard('N', 1); // odblok nadmiarowego silników trakcyjnych - else KeyBoard('N', 0); // monostabilny - if (maskData[0] & 0x20) if (lastStateData[0] & 0x20) - { // odblok nadmiarowego przetwornicy, ogrzewania poc. - KeyBoard(0x11, 1); // różnicowego obwodów pomocniczych - KeyBoard('N', 1); // monostabilny - } - else - { - KeyBoard('N', 0); - KeyBoard(0x11, 0); - } - if (maskData[0] & 0x40) if (lastStateData[0] & 0x40) KeyBoard('L', 1); // wył. styczników liniowych - else KeyBoard('L', 0); // monostabilny - if (maskData[0] & 0x80) if (lastStateData[0] & 0x80) KeyBoard(0x20, 1); // kasowanie czuwaka/SHP - else KeyBoard(0x20, 0); // kasowanie czuwaka/SHP - - /*PORT1*/ - - // puszczanie przycisku bistabilnego klawiatury - if (maskSwitch[1] & 0x02) - { - if (bitSwitch[1] & 0x02) - { - KeyBoard('X', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('X', 0); - maskSwitch[1] &= ~0x02; - } - if (maskSwitch[1] & 0x04) { - if (bitSwitch[1] & 0x04) { - KeyBoard('C', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('C', 0); - maskSwitch[1] &= ~0x04; - } - if (maskSwitch[1] & 0x10) { - if (bitSwitch[1] & 0x10) { - KeyBoard('H', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('H', 0); - maskSwitch[1] &= ~0x10; - } - if (maskSwitch[1] & 0x20 || maskSwitch[1] & 0x40) { - if (maskSwitch[1] & 0x20) KeyBoard(0x10, 0); - if (maskSwitch[1] & 0x40) KeyBoard(0x11, 0); - KeyBoard('B', 0); - maskSwitch[1] &= ~0x60; - } - if (maskSwitch[1] & 0x80) { - if (bitSwitch[1] & 0x80) { - KeyBoard('F', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('F', 0); - maskSwitch[1] &= ~0x80; - } - - // przetwornica - if (maskData[1] & 0x02) if (lastStateData[1] & 0x02) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('X', 1); - maskSwitch[1] |= 0x02; - bitSwitch[1] |= 0x02; - } - else - { - maskSwitch[1] |= 0x02; - bitSwitch[1] &= ~0x02; - KeyBoard('X', 1); - } - // sprężarka - if (maskData[1] & 0x04) if (lastStateData[1] & 0x04) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('C', 1); - maskSwitch[1] |= 0x04; - bitSwitch[1] |= 0x04; - } - else - { - maskSwitch[1] |= 0x04; - bitSwitch[1] &= ~0x04; - KeyBoard('C', 1); - } - // piasecznica - if (maskData[1] & 0x08) if (lastStateData[1] & 0x08) - KeyBoard('S', 1); - else - KeyBoard('S', 0); // monostabilny - // ogrzewanie składu - if (maskData[1] & 0x10) if (lastStateData[1] & 0x10) - { - KeyBoard(0x11, 1); // bistabilny - KeyBoard('H', 1); - maskSwitch[1] |= 0x10; - bitSwitch[1] |= 0x10; - } - else - { - maskSwitch[1] |= 0x10; - bitSwitch[1] &= ~0x10; - KeyBoard('H', 1); - } - // przełącznik hamowania - if (maskData[1] & 0x20 || maskData[1] & 0x40) - { - if (lastStateData[1] & 0x20) - { // Shift+B - KeyBoard(0x10, 1); - maskSwitch[1] |= 0x20; - } - else if (lastStateData[1] & 0x40) - { // Ctrl+B - KeyBoard(0x11, 1); - maskSwitch[1] |= 0x40; - } - KeyBoard('B', 1); - } - // rozruch wysoki/niski - if (maskData[1] & 0x80) if (lastStateData[1] & 0x80) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('F', 1); - maskSwitch[1] |= 0x80; - bitSwitch[1] |= 0x80; - } - else - { - maskSwitch[1] |= 0x80; - bitSwitch[1] &= ~0x80; - KeyBoard('F', 1); - } - - - //PORT2 - if (maskSwitch[2] & 0x01) - { - if (bitSwitch[2] & 0x01) - { - KeyBoard('P', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('P', 0); - maskSwitch[2] &= ~0x01; - } - if (maskSwitch[2] & 0x02) - { - if (bitSwitch[2] & 0x02) - { - KeyBoard('O', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('O', 0); - maskSwitch[2] &= ~0x02; - } - - // pantograf przedni - if (maskData[2] & 0x01) if (lastStateData[2] & 0x01) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('P', 1); - maskSwitch[2] |= 0x01; - bitSwitch[2] |= 0x01; - } - else - { - maskSwitch[2] |= 0x01; - bitSwitch[2] &= ~0x01; - KeyBoard('P', 1); - } - // pantograf tylni - if (maskData[2] & 0x02) if (lastStateData[2] & 0x02) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('O', 1); - maskSwitch[2] |= 0x02; - bitSwitch[2] |= 0x02; - } - else - { - maskSwitch[2] |= 0x02; - bitSwitch[2] &= ~0x02; - KeyBoard('O', 1); - } - // przyhamowanie przy poślizgu - if (maskData[2] & 0x04) if (lastStateData[2] & 0x04) { - KeyBoard(0x10, 1); // monostabilny - KeyBoard(0x0D, 1); - } - else - { - KeyBoard(0x0D, 0); - KeyBoard(0x10, 0); - } - /*if(maskData[2] & 0x08) if (lastStateData[2] & 0x08){ // przyciemnienie świateł - KeyBoard(' ',0); // bistabilny - KeyBoard(0x10,1); - KeyBoard(' ',1); - }else{ - KeyBoard(' ',0); - KeyBoard(0x10,0); - KeyBoard(' ',1); - } - if(maskData[2] & 0x10) if (lastStateData[2] & 0x10) { // przyciemnienie świateł - KeyBoard(' ',0); // bistabilny - KeyBoard(0x11,1); - KeyBoard(' ',1); - }else{ - KeyBoard(' ',0); - KeyBoard(0x11,0); - KeyBoard(' ',1); - }*/ - // odluźniacz - if (maskData[2] & 0x20) if (lastStateData[2] & 0x20) - KeyBoard(0x66, 1); - else - KeyBoard(0x66, 0); // monostabilny - // syrena wysoka - if (maskData[2] & 0x40) if (lastStateData[2] & 0x40) - { - KeyBoard(0x10, 1); // monostabilny - KeyBoard('A', 1); - } - else - { - KeyBoard('A', 0); - KeyBoard(0x10, 0); - } - if (maskData[2] & 0x80) if (lastStateData[2] & 0x80) - KeyBoard('A', 1); // syrena niska - else - KeyBoard('A', 0); // monostabilny - - - //PORT3 - - if (maskSwitch[3] & 0x01) - { - if (bitSwitch[3] & 0x01) - { - KeyBoard('J', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('J', 0); - maskSwitch[3] &= ~0x01; - } - if (maskSwitch[3] & 0x02) - { - if (bitSwitch[3] & 0x02) - { - KeyBoard('Y', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('Y', 0); - maskSwitch[3] &= ~0x02; - } - if (maskSwitch[3] & 0x04) - { - if (bitSwitch[3] & 0x04) - { - KeyBoard('U', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('U', 0); - maskSwitch[3] &= ~0x04; - } - if (maskSwitch[3] & 0x08) - { - if (bitSwitch[3] & 0x08) - { - KeyBoard('I', 0); - KeyBoard(0x10, 0); - } - else KeyBoard('I', 0); - maskSwitch[3] &= ~0x08; - } - - - // bateria - if (maskData[3] & 0x01) if (lastStateData[3] & 0x01) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('J', 1); - maskSwitch[3] |= 0x01; - bitSwitch[3] |= 0x01; - } - else - { - maskSwitch[3] |= 0x01; - bitSwitch[3] &= ~0x01; - KeyBoard('J', 1); - } - //Światło lewe - if (maskData[3] & 0x02) if (lastStateData[3] & 0x02) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('Y', 1); - maskSwitch[3] |= 0x02; - bitSwitch[3] |= 0x02; - }else - { - maskSwitch[3] |= 0x02; - bitSwitch[3] &= ~0x02; - KeyBoard('Y', 1); - } - //światło górne - if (maskData[3] & 0x04) if (lastStateData[3] & 0x04) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('U', 1); - maskSwitch[3] |= 0x04; - bitSwitch[3] |= 0x04; - } - else - { - maskSwitch[3] |= 0x04; - bitSwitch[3] &= ~0x04; - KeyBoard('U', 1); - } - //światło prawe - if (maskData[3] & 0x08) if (lastStateData[3] & 0x08) - { - KeyBoard(0x10, 1); // bistabilny - KeyBoard('I', 1); - maskSwitch[3] |= 0x08; - bitSwitch[3] |= 0x08; - } - else - { - maskSwitch[3] |= 0x08; - bitSwitch[3] &= ~0x08; - KeyBoard('I', 1); - } - - - - /* NASTAWNIK, BOCZNIK i KIERUNEK */ - - if (bnkMask & 1) - { // puszczanie klawiszy - KeyBoard(0x6B, 0); - bnkMask &= ~1; - } - if (bnkMask & 2) - { - KeyBoard(0x6D, 0); - bnkMask &= ~2; - } - if (bnkMask & 4) - { - KeyBoard(0x6F, 0); - bnkMask &= ~4; - } - if (bnkMask & 8) - { - KeyBoard(0x6A, 0); - bnkMask &= ~8; - } - - if (nastawnik < ReadDataBuff[6]) - { - bnkMask |= 1; - nastawnik++; - KeyBoard(0x6B, 1); // wciśnij + i dodaj 1 do nastawnika - } - if (nastawnik > ReadDataBuff[6]) - { - bnkMask |= 2; - nastawnik--; - KeyBoard(0x6D, 1); // wciśnij - i odejmij 1 do nastawnika - } - if (bocznik < ReadDataBuff[7]) - { - bnkMask |= 4; - bocznik++; - KeyBoard(0x6F, 1); // wciśnij / i dodaj 1 do bocznika - } - if (bocznik > ReadDataBuff[7]) - { - bnkMask |= 8; - bocznik--; - KeyBoard(0x6A, 1); // wciśnij * i odejmij 1 do bocznika - } - - /* Obsługa HASLERA */ - if (ReadDataBuff[0] & 0x80) - bCzuwak = true; - - if (bKabina1) - { // logika rysika 1 - bRysik1H = true; - bRysik1L = false; - if (bPrzejazdSHP) - bRysik1H = false; - } - else if (bKabina2) - { - bRysik1L = true; - bRysik1H = false; - if (bPrzejazdSHP) - bRysik1L = false; - } - else - { - bRysik1H = false; - bRysik1L = false; - } - - if (bHamowanie) - { // logika rysika 2 - bRysik2H = false; - bRysik2L = true; - } - else - { - if (bCzuwak) - bRysik2H = true; - else - bRysik2H = false; - bRysik2L = false; - } - bCzuwak = false; - if (bRysik1H) - WriteDataBuff[6] |= 1 << 0; - else - WriteDataBuff[6] &= ~(1 << 0); - if (bRysik1L) - WriteDataBuff[6] |= 1 << 1; - else - WriteDataBuff[6] &= ~(1 << 1); - if (bRysik2H) - WriteDataBuff[6] |= 1 << 2; - else - WriteDataBuff[6] &= ~(1 << 2); - if (bRysik2L) - WriteDataBuff[6] |= 1 << 3; - else - WriteDataBuff[6] &= ~(1 << 3); -} - -void TMWDComm::KeyBoard(int key, bool s) // emulacja klawiatury -{ - INPUT ip; - // Set up a generic keyboard event. - ip.type = INPUT_KEYBOARD; - ip.ki.wScan = 0; // hardware scan code for key - ip.ki.time = 0; - ip.ki.dwExtraInfo = 0; - - ip.ki.wVk = key; // virtual-key code for the "a" key - - if (s) - { // Press the "A" key - ip.ki.dwFlags = 0; // 0 for key press - SendInput(1, &ip, sizeof(INPUT)); - } - else - { - ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release - SendInput(1, &ip, sizeof(INPUT)); - } - - // return 1; -} diff --git a/Console/MWD.h b/Console/MWD.h deleted file mode 100644 index 93f2dab4..00000000 --- a/Console/MWD.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -This Source Code Form is subject to the -terms of the Mozilla Public License, v. -2.0. If a copy of the MPL was not -distributed with this file, You can -obtain one at -http://mozilla.org/MPL/2.0/. -*/ - -/* - Program obsługi portu COM i innych na potrzeby sterownika MWDevice - (oraz innych wykorzystujących komunikację przez port COM) - dla Symulatora Pojazdów Szynowych MaSzyna - author: Maciej Witek 2016 - Autor nie ponosi odpowiedzialności za niewłaciwe używanie lub działanie programu! -*/ - -#ifndef MWDH -#define MWDH -//--------------------------------------------------------------------------- - -#define BYTETOWRITE 31 // ilość bajtów przesyłanych z MaSzyny -#define BYTETOREAD 16 // ilość bajtów przesyłanych do MaSzyny - -typedef unsigned char BYTE; -typedef unsigned long DWORD; - -class TMWDComm -{ -private: - int MWDTime; // - char lastStateData[6], maskData[6], maskSwitch[6], bitSwitch[6]; - int bocznik, nastawnik, kierunek; - char bnkMask; - - bool ReadData(); //BYTE *pReadDataBuff); - bool SendData(); //BYTE *pWriteDataBuff); - void CheckData(); //sprawdzanie zmian wejść i kontrola mazaków HASLERA - void KeyBoard(int key, bool s); - - //void CheckData2(); - - bool bRysik1H; - bool bRysik1L; - bool bRysik2H; - bool bRysik2L; - -public: - bool Open(); // Otwarcie portu - bool Close(); // Zamknięcie portu - bool Run(); // Obsługa portu - bool GetMWDState(); // sprawdź czy port jest otwarty, 0 zamknięty, 1 otwarty - - // zmienne do rysików HASLERA - bool bSHPstate; - bool bPrzejazdSHP; - bool bKabina1; - bool bKabina2; - bool bHamowanie; - bool bCzuwak; - - unsigned int uiAnalog[4]; // trzymanie danych z wejść analogowych - - BYTE ReadDataBuff[BYTETOREAD+2]; //17]; // bufory danych - BYTE WriteDataBuff[BYTETOWRITE+2]; //31]; - - TMWDComm(); // konstruktor - ~TMWDComm(); // destruktor -}; -#endif - -/* -INFO - wpisy do eu07.ini: - -mwdmasterenable yes // włącz MWD (master MWD Enable) -mwddebugenable yes // włącz logowanie -mwddebugmode 4 // tryb debugowania (które logi) - -mwdcomportname COM3 // nazwa portu -mwdbaudrate 500000 // prędkość transmisji - -mwdinputenable yes // włącz wejścia (przyciski, przełączniki) -mwdbreakenable yes // włącz hamulce (wejścia analogowe) - -mwdmainbreakconfig 0 1023 // konfiguracja kranu zespolonego -> min, max (położenie kranu - odczyt z ADC) -mwdlocbreakconfig 0 1023 // konfiguracja kranu maszynisty -> min, max (położenie kranu - odczyt z ADC) -mwdanalogin2config 0 1023 -mwdanalogin2config 0 1023 - -mwdmaintankpress 0.9 1023 // max ciśnienie w zbiorniku głownym i rozdzielczość -mwdmainpipepress 0.7 1023 // max ciśnienie w przewodzie głównym i rozdzielczość -mwdbreakpress 0.5 1023 // max ciśnienie w cylindrach hamulcowych i rozdzielczość - -mwdhivoltmeter 4000 1023 // max napięcie na woltomierzu WN -mwdhiampmeter 800 1023 // max prąd amperomierza WN - -mwddivider 5 // dzielnik - czym większy tym rzadziej czyta diwajs -*/ diff --git a/EU07.cpp b/EU07.cpp index be631e0f..ce4cd222 100644 --- a/EU07.cpp +++ b/EU07.cpp @@ -33,6 +33,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others #include "Timer.h" #include "resource.h" #include "uilayer.h" +#include "uart.h" #pragma comment (lib, "glu32.lib") #pragma comment (lib, "dsound.lib") @@ -50,7 +51,7 @@ keyboard_input Keyboard; mouse_input Mouse; gamepad_input Gamepad; glm::dvec2 mouse_pickmodepos; // stores last mouse position in control picking mode - +std::unique_ptr uart; } void screenshot_save_thread( char *img ) @@ -350,9 +351,13 @@ int main(int argc, char *argv[]) sound_man = std::make_unique(); + Global::pWorld = &World; + input::Keyboard.init(); input::Mouse.init(); input::Gamepad.init(); + if (Global::uart_conf.enable) + input::uart = std::make_unique(); if( false == World.Init( window ) ) { ErrorLog( "Simulation setup failed" ); @@ -393,6 +398,8 @@ int main(int argc, char *argv[]) && ( true == GfxRenderer.Render() ) ) { glfwPollEvents(); input::Keyboard.poll(); + if (input::uart) + input::uart->poll(); if( true == Global::InputMouse ) { input::Mouse.poll(); } if( true == Global::InputGamepad ) { input::Gamepad.poll(); } } diff --git a/Globals.cpp b/Globals.cpp index a8de9723..9621a627 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -166,24 +166,11 @@ int Global::iPoKeysPWM[7] = {0, 1, 2, 3, 4, 5, 6}; bool Global::bnewAirCouplers = true; double Global::fTimeSpeed = 1.0; // przyspieszenie czasu, zmienna do testów bool Global::bHideConsole = false; // hunter-271211: ukrywanie konsoli + +Global::uart_conf_t Global::uart_conf; + //randomizacja std::mt19937 Global::random_engine = std::mt19937(std::time(NULL)); -// maciek001: konfiguracja wstępna portu COM -bool Global::bMWDmasterEnable = false; // główne włączenie portu! -bool Global::bMWDdebugEnable = false; // włącz dodawanie do logu -int Global::iMWDDebugMode = 0; // co ma wyświetlać w logu -std::string Global::sMWDPortId = "COM1"; // nazwa portu z którego korzystamy -unsigned long int Global::iMWDBaudrate = 9600; // prędkość transmisji danych -bool Global::bMWDInputEnable = false; // włącz wejścia -bool Global::bMWDBreakEnable = false; // włącz wejścia analogowe -double Global::fMWDAnalogInCalib[4][2] = { { 0, 1023 },{ 0, 1023 },{ 0, 1023 },{ 0, 1023 } }; // wartość max potencjometru, wartość min potencjometru, rozdzielczość (max. wartość jaka może być) -double Global::fMWDzg[2] = { 0.9, 1023 }; -double Global::fMWDpg[2] = { 0.8, 1023 }; -double Global::fMWDph[2] = { 0.6, 1023 }; -double Global::fMWDvolt[2] = { 4000, 1023 }; -double Global::fMWDamp[2] = { 800, 1023 }; -double Global::fMWDlowVolt[2] = { 150, 1023 }; -int Global::iMWDdivider = 5; opengl_light Global::DayLight; Global::soundmode_t Global::soundpitchmode = Global::linear; @@ -756,102 +743,33 @@ void Global::ConfigParse(cParser &Parser) Parser.getTokens(); Parser >> Global::InputGamepad; } - // maciek001: ustawienia MWD - else if (token == "mwdmasterenable") { // główne włączenie maszyny! - Parser.getTokens(); - Parser >> bMWDmasterEnable; - if (bMWDdebugEnable) WriteLog("SerialPort Master Enable"); - } - else if (token == "mwddebugenable") { // logowanie pracy - Parser.getTokens(); - Parser >> bMWDdebugEnable; - if (bMWDdebugEnable) WriteLog("MWD Debug Mode On"); - } - else if (token == "mwddebugmode") { // co ma być debugowane? - Parser.getTokens(1, false); - Parser >> iMWDDebugMode; - if (bMWDdebugEnable) WriteLog("Debug Mode = " + to_string(iMWDDebugMode)); - } - else if (token == "mwdcomportname") { // nazwa portu COM - Parser.getTokens(); - Parser >> sMWDPortId; - if (bMWDdebugEnable) WriteLog("PortName " + sMWDPortId); - } - else if (token == "mwdbaudrate") { // prędkość transmisji danych - Parser.getTokens(1, false); - Parser >> iMWDBaudrate; - if (bMWDdebugEnable) WriteLog("Baud rate = " + to_string((int)(iMWDBaudrate / 1000)) + (" kbps")); - } - else if (token == "mwdinputenable") { // włącz wejścia - Parser.getTokens(); - Parser >> bMWDInputEnable; - if (bMWDdebugEnable && bMWDInputEnable) WriteLog("MWD Input Enable"); - } - else if (token == "mwdbreakenable") { // włącz obsługę hamulców - Parser.getTokens(); - Parser >> bMWDBreakEnable; - if (bMWDdebugEnable && bMWDBreakEnable) WriteLog("MWD Break Enable"); - } - else if (token == "mwdmainbreakconfig") { // ustawienia hamulca zespolonego - Parser.getTokens(2, false); - Parser >> fMWDAnalogInCalib[0][0] >> fMWDAnalogInCalib[0][1]; - if (bMWDdebugEnable) WriteLog("Main break settings: " + to_string(fMWDAnalogInCalib[0][0]) + (" ") + to_string(fMWDAnalogInCalib[0][1])); - } - else if (token == "mwdlocbreakconfig") { // ustawienia hamulca lokomotywy - Parser.getTokens(2, false); - Parser >> fMWDAnalogInCalib[1][0] >> fMWDAnalogInCalib[1][1]; - if (bMWDdebugEnable) WriteLog("Locomotive break settings: " + to_string(fMWDAnalogInCalib[1][0]) + (" ") + to_string(fMWDAnalogInCalib[1][1])); - } - else if (token == "mwdanalogin1config") { // ustawienia hamulca zespolonego - Parser.getTokens(2, false); - Parser >> fMWDAnalogInCalib[2][0] >> fMWDAnalogInCalib[2][1]; - if (bMWDdebugEnable) WriteLog("Analog input 1 settings: " + to_string(fMWDAnalogInCalib[2][0]) + (" ") + to_string(fMWDAnalogInCalib[2][1])); - } - else if (token == "mwdanalogin2config") { // ustawienia hamulca lokomotywy - Parser.getTokens(2, false); - Parser >> fMWDAnalogInCalib[3][0] >> fMWDAnalogInCalib[3][1]; - if (bMWDdebugEnable) WriteLog("Analog input 2 settings: " + to_string(fMWDAnalogInCalib[3][0]) + (" ") + to_string(fMWDAnalogInCalib[3][1])); - } - else if (token == "mwdmaintankpress") { // max ciśnienie w zbiorniku głownym i rozdzielczość - Parser.getTokens(2, false); - Parser >> fMWDzg[0] >> fMWDzg[1]; - if (bMWDdebugEnable) WriteLog("MainAirTank settings: " + to_string(fMWDzg[0]) + (" ") + to_string(fMWDzg[1])); - } - else if (token == "mwdmainpipepress") { // max ciśnienie w przewodzie głownym i rozdzielczość - Parser.getTokens(2, false); - Parser >> fMWDpg[0] >> fMWDpg[1]; - if (bMWDdebugEnable) WriteLog("MainAirPipe settings: " + to_string(fMWDpg[0]) + (" ") + to_string(fMWDpg[1])); - } - else if (token == "mwdbreakpress") { // max ciśnienie w hamulcach i rozdzielczość - Parser.getTokens(2, false); - Parser >> fMWDph[0] >> fMWDph[1]; - if (bMWDdebugEnable) WriteLog("AirPipe settings: " + to_string(fMWDph[0]) + (" ") + to_string(fMWDph[1])); - } - else if (token == "mwdhivoltmeter") { // max napięcie na woltomierzu WN - Parser.getTokens(2, false); - Parser >> fMWDvolt[0] >> fMWDvolt[1]; - if (bMWDdebugEnable) WriteLog("VoltMeter settings: " + to_string(fMWDvolt[0]) + (" ") + to_string(fMWDvolt[1])); - } - else if (token == "mwdhiampmeter") { - Parser.getTokens(2, false); - Parser >> fMWDamp[0] >> fMWDamp[1]; - if (bMWDdebugEnable) WriteLog("Amp settings: " + to_string(fMWDamp[0]) + (" ") + to_string(fMWDamp[1])); - } - else if (token == "mwdlowvoltmeter") { - Parser.getTokens(2, false); - Parser >> fMWDlowVolt[0] >> fMWDlowVolt[1]; - if (bMWDdebugEnable) WriteLog("Low VoltMeter settings: " + to_string(fMWDlowVolt[0]) + (" ") + to_string(fMWDlowVolt[1])); - } - else if (token == "mwddivider") { - Parser.getTokens(1, false); - Parser >> iMWDdivider; - if (iMWDdivider == 0) - { - WriteLog("Dzielnik nie może być równy ZERO! Ustawiam na 1!"); - iMWDdivider = 1; - } - if (bMWDdebugEnable) WriteLog("Divider = " + to_string(iMWDdivider)); - } + else if (token == "uart") + { + Parser.getTokens(3, false); + Global::uart_conf.enable = true; + Parser >> Global::uart_conf.port; + Parser >> Global::uart_conf.baud; + Parser >> Global::uart_conf.interval; + Parser >> Global::uart_conf.updatetime; + } + else if (token == "uarttune") + { + Parser.getTokens(14); + Parser >> Global::uart_conf.mainbrakemin + >> Global::uart_conf.mainbrakemax + >> Global::uart_conf.localbrakemin + >> Global::uart_conf.localbrakemax + >> Global::uart_conf.tankmax + >> Global::uart_conf.tankuart + >> Global::uart_conf.pipemax + >> Global::uart_conf.pipeuart + >> Global::uart_conf.brakemax + >> Global::uart_conf.brakeuart + >> Global::uart_conf.hvmax + >> Global::uart_conf.hvuart + >> Global::uart_conf.currentmax + >> Global::uart_conf.currentuart; + } } while ((token != "") && (token != "endconfig")); //(!Parser->EndOfFile) // na koniec trochę zależności if (!bLoadTraction) // wczytywanie drutów i słupów diff --git a/Globals.h b/Globals.h index 92013019..8848ffc6 100644 --- a/Globals.h +++ b/Globals.h @@ -293,6 +293,31 @@ class Global //randomizacja static std::mt19937 random_engine; + struct uart_conf_t + { + bool enable = false; + std::string port; + int baud; + int interval; + float updatetime; + + float mainbrakemin = 0.0f; + float mainbrakemax = 65535.0f; + float localbrakemin = 0.0f; + float localbrakemax = 65535.0f; + float tankmax = 10.0f; + float tankuart = 65535.0f; + float pipemax = 10.0f; + float pipeuart = 65535.0f; + float brakemax = 10.0f; + float brakeuart = 65535.0f; + float hvmax = 100000.0f; + float hvuart = 65535.0f; + float currentmax = 10000.0f; + float currentuart = 65535.0f; + }; + static uart_conf_t uart_conf; + // metody static void TrainDelete(TDynamicObject *d); static void ConfigParse(cParser &parser); @@ -303,23 +328,6 @@ class Global static std::string Bezogonkow(std::string str, bool _ = false); static double Min0RSpeed(double vel1, double vel2); - // maciek001: zmienne dla MWD - static bool bMWDmasterEnable; // główne włączenie portu COM - static bool bMWDdebugEnable; // logowanie pracy - static int iMWDDebugMode; - static std::string sMWDPortId; // nazwa portu COM - static unsigned long int iMWDBaudrate; // prędkość transmisji - static bool bMWDInputEnable; // włącz wejścia - static bool bMWDBreakEnable; // włącz wejścia analogowe (hamulce) - static double fMWDAnalogInCalib[4][2]; // ustawienia kranów hamulca zespolonego i dodatkowego - min i max - static double fMWDzg[2]; // max wartość wskazywana i max wartość generowana (rozdzielczość) - static double fMWDpg[2]; - static double fMWDph[2]; - static double fMWDvolt[2]; - static double fMWDamp[2]; - static double fMWDlowVolt[2]; - static int iMWDdivider; - static opengl_light DayLight; enum soundmode_t diff --git a/Train.cpp b/Train.cpp index 585466a5..9800f0bc 100644 --- a/Train.cpp +++ b/Train.cpp @@ -824,8 +824,7 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co if( ( Train->mvOccupied->BrakeCtrlPos == -1 ) && ( Train->mvOccupied->BrakeHandle == FVel6 ) && ( Train->DynamicObject->Controller != AIdriver ) - && ( Global::iFeedbackMode != 4 ) - && ( !( Global::bMWDmasterEnable && Global::bMWDBreakEnable ) ) ) { + && ( Global::iFeedbackMode != 4 ) ) { // Odskakiwanie hamulce EP Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPos + 1 ); Train->keybrakecount = 0; @@ -856,8 +855,7 @@ void TTrain::OnCommand_trainbrakecharging( TTrain *Train, command_data const &Co if( ( Train->mvOccupied->BrakeCtrlPos == -1 ) && ( Train->mvOccupied->BrakeHandle == FVel6 ) && ( Train->DynamicObject->Controller != AIdriver ) - && ( Global::iFeedbackMode != 4 ) - && ( !( Global::bMWDmasterEnable && Global::bMWDBreakEnable ) ) ) { + && ( Global::iFeedbackMode != 4 ) ) { // Odskakiwanie hamulce EP Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPos + 1 ); Train->keybrakecount = 0; @@ -1248,7 +1246,12 @@ void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Co } } -void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) { +void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command ) +{ + if (Command.desired_state == command_data::ON && Train->mvOccupied->Battery) + return; + if (Command.desired_state == command_data::OFF && !Train->mvOccupied->Battery) + return; if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down @@ -1289,7 +1292,19 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command } } -void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &Command ) { +void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &cmd ) +{ + command_data Command = cmd; + + if (Train->mvOccupied->PantSwitchType != "impulse") + { + if (Command.desired_state == Command.ON && Train->mvControlled->PantFrontUp) + return; + if (Command.desired_state == Command.OFF && !Train->mvControlled->PantFrontUp) + return; + } + else if (Command.desired_state == Command.OFF) + Command.action = GLFW_RELEASE; if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down @@ -1369,7 +1384,18 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const } } -void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &Command ) { +void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &cmd ) { + command_data Command = cmd; + + if (Train->mvOccupied->PantSwitchType != "impulse") + { + if (Command.desired_state == Command.ON && Train->mvControlled->PantRearUp) + return; + if (Command.desired_state == Command.OFF && !Train->mvControlled->PantRearUp) + return; + } + else if (Command.desired_state == Command.OFF) + Command.action = GLFW_RELEASE; if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down @@ -1562,7 +1588,8 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com if( Command.action != GLFW_RELEASE ) { // press or hold... - if( Train->m_linebreakerstate == 0 ) { + if ((Command.desired_state == command_data::TOGGLE && Train->m_linebreakerstate == 0) + || Command.desired_state == command_data::ON) { // ...to close the circuit if( Command.action == GLFW_PRESS ) { // fresh press, start fresh closing delay calculation @@ -1609,39 +1636,26 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com } } } - else if( Train->m_linebreakerstate == 1 ) { + else if ((Command.desired_state == command_data::TOGGLE && Train->m_linebreakerstate == 1) + || Command.desired_state == command_data::OFF) { // ...to open the circuit - if( true == Train->mvControlled->MainSwitch( false ) ) { + Train->mvControlled->MainSwitch( false ); - Train->m_linebreakerstate = -1; + Train->m_linebreakerstate = -1; - if( Train->ggMainOffButton.SubModel != nullptr ) { - // two separate switches to close and break the circuit + if( Train->ggMainOffButton.SubModel != nullptr ) { + // two separate switches to close and break the circuit + // visual feedback + Train->ggMainOffButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else if( Train->ggMainButton.SubModel != nullptr ) { + // single two-state switch + { // visual feedback - Train->ggMainOffButton.UpdateValue( 1.0, Train->dsbSwitch ); - } - else if( Train->ggMainButton.SubModel != nullptr ) { - // single two-state switch -/* - // NOTE: we don't have switch type definition for the line breaker switch - // so for the time being we have hard coded "impulse" switches for all EMUs - // TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz - if( Train->mvControlled->TrainType == dt_EZT ) { - // audio feedback - if( Command.action == GLFW_PRESS ) { - Train->play_sound( Train->dsbSwitch ); - } - // visual feedback - Train->ggMainButton.UpdateValue( 1.0 ); - } - else -*/ - { - // visual feedback - Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch ); - } + Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch ); } } + // play sound immediately when the switch is hit, not after release if( Train->fMainRelayTimer > 0.0f ) { Train->play_sound( Train->dsbRelay ); @@ -1713,6 +1727,11 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma return; } + if (Train->mvControlled->ConverterAllow && Command.desired_state == command_data::ON) + return; + if (!Train->mvControlled->ConverterAllow && Command.desired_state == command_data::OFF) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down if( ( false == Train->mvControlled->ConverterAllow ) @@ -1866,6 +1885,11 @@ void TTrain::OnCommand_compressortoggle( TTrain *Train, command_data const &Comm return; } + if (Train->mvControlled->CompressorAllow && Command.desired_state == command_data::ON) + return; + if (!Train->mvControlled->CompressorAllow && Command.desired_state == command_data::OFF) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down if( false == Train->mvControlled->CompressorAllow ) { @@ -1945,8 +1969,8 @@ void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const } } -void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command ) { - +void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &cmd ) { + command_data Command = cmd; // TODO: don't rely on presense of 3d model to determine presence of the switch if( Train->ggStLinOffButton.SubModel == nullptr ) { if( Command.action == GLFW_PRESS ) { @@ -1954,6 +1978,17 @@ void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &C } return; } + + if (Train->mvControlled->StLinSwitchType == "toggle") + { + if (Command.desired_state == Command.ON && Train->mvControlled->StLinSwitchOff) + return; + if (Command.desired_state == Command.OFF && !Train->mvControlled->StLinSwitchOff) + return; + } + else if (Command.desired_state == Command.OFF) + Command.action = GLFW_RELEASE; + // NOTE: because we don't have modeled actual circuits this is a simplification of the real mechanics // namely, pressing the button will flip it in the entire unit, which isn't exactly physically possible if( Command.action == GLFW_PRESS ) { @@ -2064,7 +2099,12 @@ void TTrain::OnCommand_motordisconnect( TTrain *Train, command_data const &Comma } } -void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command_data const &Command ) { +void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command_data const &Command ) +{ + if (Train->mvControlled->Imax < Train->mvControlled->ImaxHi && Command.desired_state == command_data::OFF) + return; + if (!(Train->mvControlled->Imax < Train->mvControlled->ImaxHi) && Command.desired_state == command_data::ON) + return; if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down @@ -2119,9 +2159,16 @@ void TTrain::OnCommand_headlighttoggleleft( TTrain *Train, command_data const &C 0 : 1 ); + bool current_state = (bool)(Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_left); + + if (Command.desired_state == command_data::ON && current_state) + return; + if (Command.desired_state == command_data::OFF && !current_state) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_left ) == 0 ) { + if( !current_state ) { // turn on Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_left; // visual feedback @@ -2152,9 +2199,16 @@ void TTrain::OnCommand_headlighttoggleright( TTrain *Train, command_data const & 0 : 1 ); + bool current_state = (bool)(Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_right); + + if (Command.desired_state == command_data::ON && current_state) + return; + if (Command.desired_state == command_data::OFF && !current_state) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_right ) == 0 ) { + if( !current_state ) { // turn on Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_right; // visual feedback @@ -2185,9 +2239,16 @@ void TTrain::OnCommand_headlighttoggleupper( TTrain *Train, command_data const & 0 : 1 ); + bool current_state = (bool)(Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_upper); + + if (Command.desired_state == command_data::ON && current_state) + return; + if (Command.desired_state == command_data::OFF && !current_state) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_upper ) == 0 ) { + if( !current_state ) { // turn on Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_upper; // visual feedback @@ -2452,6 +2513,11 @@ void TTrain::OnCommand_headlightsdimtoggle( TTrain *Train, command_data const &C return; } + if (Train->DynamicObject->DimHeadlights && Command.desired_state == command_data::ON) + return; + if (!Train->DynamicObject->DimHeadlights && Command.desired_state == command_data::OFF) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down if( false == Train->DynamicObject->DimHeadlights ) { @@ -2509,6 +2575,11 @@ void TTrain::OnCommand_interiorlightdimtoggle( TTrain *Train, command_data const return; } + if (Train->bCabLightDim && Command.desired_state == command_data::ON) + return; + if (!Train->bCabLightDim && Command.desired_state == command_data::OFF) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down if( false == Train->bCabLightDim ) { @@ -2564,6 +2635,11 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command return; } + if (Train->mvControlled->Heating && Command.desired_state == command_data::ON) + return; + if (!Train->mvControlled->Heating && Command.desired_state == command_data::OFF) + return; + if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down if( false == Train->mvControlled->Heating ) { @@ -3719,20 +3795,6 @@ bool TTrain::Update( double const Deltatime ) /// skakanie zapewnia mechanika /// napędu } - - if (Global::bMWDmasterEnable) // pobieranie danych dla pulpitu port (COM) - { - Console::ValueSet(0, mvOccupied->Compressor); // zbiornik główny - Console::ValueSet(1, mvOccupied->PipePress); // przewód główny - Console::ValueSet(2, mvOccupied->BrakePress); // cylinder hamulcowy - Console::ValueSet(3, fHVoltage); // woltomierz wysokiego napięcia - Console::ValueSet(4, fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1]); - // pierwszy amperomierz; dla EZT prąd całkowity - Console::ValueSet(5, fHCurrent[2]); // drugi amperomierz 2 - Console::ValueSet(6, fHCurrent[3]); // drugi amperomierz 3 - Console::ValueSet(7, fTachoVelocity); - //Console::ValueSet(8, mvControlled->BatteryVoltage); // jeszcze nie pora ;) - } #endif // hunter-080812: wyrzucanie szybkiego na elektrykach gdy nie ma napiecia @@ -4654,7 +4716,7 @@ bool TTrain::Update( double const Deltatime ) #ifdef _WIN32 if (DynamicObject->Mechanik ? (DynamicObject->Mechanik->AIControllFlag ? false : - (Global::iFeedbackMode == 4 || (Global::bMWDmasterEnable && Global::bMWDBreakEnable))) : + (Global::iFeedbackMode == 4)) : false) // nie blokujemy AI { // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba // Firleju: dlatego kasujemy i zastepujemy funkcją w Console @@ -4663,7 +4725,6 @@ bool TTrain::Update( double const Deltatime ) double b = Console::AnalogCalibrateGet(0); b = b * 8.0 - 2.0; b = clamp( b, -2.0, mvOccupied->BrakeCtrlPosNo ); // przycięcie zmiennej do granic - if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FV4a break position = " + to_string(b)); ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia mvOccupied->BrakeLevelSet(b); } @@ -4672,7 +4733,6 @@ bool TTrain::Update( double const Deltatime ) double b = Console::AnalogCalibrateGet(0); b = b * 7.0 - 1.0; b = clamp( b, -1.0, mvOccupied->BrakeCtrlPosNo ); // przycięcie zmiennej do granic - if (Global::bMWDdebugEnable && Global::iMWDDebugMode & 4) WriteLog("FVel6 break position = " + to_string(b)); ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia mvOccupied->BrakeLevelSet(b); } @@ -4690,8 +4750,7 @@ bool TTrain::Update( double const Deltatime ) if( ( DynamicObject->Mechanik != nullptr ) && ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI && ( mvOccupied->BrakeLocHandle == FD1 ) - && ( ( Global::iFeedbackMode == 4 ) - || ( Global::bMWDmasterEnable && Global::bMWDBreakEnable ) ) ) { + && ( ( Global::iFeedbackMode == 4 ) ) ) { // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba // Firleju: dlatego kasujemy i zastepujemy funkcją w Console auto const b = clamp( @@ -4700,10 +4759,6 @@ bool TTrain::Update( double const Deltatime ) ManualBrakePosNo ); ggLocalBrake.UpdateValue( b ); // przesów bez zaokrąglenia mvOccupied->LocalBrakePos = int( 1.09 * b ); // sposób zaokrąglania jest do ustalenia - if( ( true == Global::bMWDdebugEnable ) - && ( ( Global::iMWDDebugMode & 4 ) != 0 ) ) { - WriteLog( "FD1 break position = " + to_string( b ) ); - } } else // standardowa prodedura z kranem powiązanym z klawiaturą #endif @@ -7419,3 +7474,75 @@ TTrain::play_sound( sound* Sound, sound* Fallbacksound, float gain ) { play_sound( Fallbacksound, gain ); } +float TTrain::get_tacho() +{ + return fTachoVelocity; +} + +float TTrain::get_tank_pressure() +{ + return mvOccupied->Compressor; +} + +float TTrain::get_pipe_pressure() +{ + return mvOccupied->PipePress; +} + +float TTrain::get_brake_pressure() +{ + return mvOccupied->BrakePress; +} + +float TTrain::get_hv_voltage() +{ + return fHVoltage; +} + +std::array TTrain::get_current() +{ + return { fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1], fHCurrent[2], fHCurrent[3] }; +} + +bool TTrain::get_alarm() +{ + return (TestFlag(mvOccupied->SecuritySystem.Status, s_CAalarm) || + TestFlag(mvOccupied->SecuritySystem.Status, s_SHPalarm)); +} + +void TTrain::set_mainctrl(int pos) +{ + if (pos < mvControlled->MainCtrlPos) + mvControlled->DecMainCtrl(1); + else if (pos > mvControlled->MainCtrlPos) + mvControlled->IncMainCtrl(1); +} + +void TTrain::set_scndctrl(int pos) +{ + if (pos < mvControlled->ScndCtrlPos) + mvControlled->DecScndCtrl(1); + else if (pos > mvControlled->ScndCtrlPos) + mvControlled->IncScndCtrl(1); +} + +void TTrain::set_trainbrake(float val) +{ + val = std::min(1.0f, std::max(0.0f, val)); + float min = mvControlled->Handle->GetPos(bh_MIN); + float max = mvControlled->Handle->GetPos(bh_MAX); + mvControlled->BrakeLevelSet(min + val * (max - min)); +} + +void TTrain::set_localbrake(float val) +{ + val = std::min(1.0f, std::max(0.0f, val)); + float min = 0.0f; + float max = (float)LocalBrakePosNo; + mvControlled->LocalBrakePos = std::round(min + val * (max - min)); +} + +int TTrain::get_drive_direction() +{ + return mvOccupied->ActiveDir * mvOccupied->CabNo; +} diff --git a/Train.h b/Train.h index dc05a1e8..194937d6 100644 --- a/Train.h +++ b/Train.h @@ -493,5 +493,19 @@ public: // reszta może by?publiczna inline TMoverParameters *Controlled() { return mvControlled; }; void DynamicSet(TDynamicObject *d); void Silence(); + + float get_tacho(); + float get_tank_pressure(); + float get_pipe_pressure(); + float get_brake_pressure(); + float get_hv_voltage(); + std::array get_current(); + bool get_alarm(); + int get_drive_direction(); + + void set_mainctrl(int); + void set_scndctrl(int); + void set_trainbrake(float); + void set_localbrake(float); }; //--------------------------------------------------------------------------- diff --git a/builds/cmake_win32.bat b/builds/cmake_win32.bat index 05d0c7b62..fdefe6c4 100644 --- a/builds/cmake_win32.bat +++ b/builds/cmake_win32.bat @@ -17,5 +17,7 @@ cmake ../.. -T v140_xp ^ -DLIBSNDFILE_INCLUDE_DIR=%DEPS_DIR%/libsndfile/include ^ -DLIBSNDFILE_LIBRARY=%DEPS_DIR%/libsndfile/lib/win32/libsndfile-1.lib ^ -DLUAJIT_INCLUDE_DIR=%DEPS_DIR%/luajit/include ^ --DLUAJIT_LIBRARIES=%DEPS_DIR%/luajit/lib/win32/lua51.lib +-DLUAJIT_LIBRARIES=%DEPS_DIR%/luajit/lib/win32/lua51.lib ^ +-Dlibserialport_INCLUDE_DIR=%DEPS_DIR%/libserialport/include ^ +-Dlibserialport_LIBRARY=%DEPS_DIR%/libserialport/lib/win32/libserialport-0.lib popd \ No newline at end of file diff --git a/builds/cmake_win64.bat b/builds/cmake_win64.bat index 4294b1a2..96d2dc6b 100644 --- a/builds/cmake_win64.bat +++ b/builds/cmake_win64.bat @@ -17,5 +17,7 @@ cmake ../.. -A x64 ^ -DLIBSNDFILE_INCLUDE_DIR=%DEPS_DIR%/libsndfile/include ^ -DLIBSNDFILE_LIBRARY=%DEPS_DIR%/libsndfile/lib/win64/libsndfile-1.lib ^ -DLUAJIT_INCLUDE_DIR=%DEPS_DIR%/luajit/include ^ --DLUAJIT_LIBRARIES=%DEPS_DIR%/luajit/lib/win64/lua51.lib +-DLUAJIT_LIBRARIES=%DEPS_DIR%/luajit/lib/win64/lua51.lib ^ +-Dlibserialport_INCLUDE_DIR=%DEPS_DIR%/libserialport/include ^ +-Dlibserialport_LIBRARY=%DEPS_DIR%/libserialport/lib/win64/libserialport-0.lib popd \ No newline at end of file diff --git a/builds/download_windeps.bat b/builds/download_windeps.bat index ee15b44c..24fd4428 100644 --- a/builds/download_windeps.bat +++ b/builds/download_windeps.bat @@ -1,2 +1,2 @@ -powershell "$wc = New-Object System.Net.WebClient; $wc.DownloadFile(\"https://milek7.pl/.stuff/eu07exe/builddep3.zip\", \"%cd%\deps_win.zip\")" +powershell "$wc = New-Object System.Net.WebClient; $wc.DownloadFile(\"https://milek7.pl/.stuff/eu07exe/builddep4.zip\", \"%cd%\deps_win.zip\")" powershell "$s = New-Object -ComObject shell.application; $z = $s.Namespace(\"%cd%\deps_win.zip\"); foreach ($i in $z.items()) { $s.Namespace(\"%cd%\").CopyHere($i) }" diff --git a/command.cpp b/command.cpp index 06e74454..91455a31 100644 --- a/command.cpp +++ b/command.cpp @@ -174,7 +174,9 @@ command_queue::pop( command_data &Command, std::size_t const Recipient ) { } void -command_relay::post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, int const Action, std::uint16_t const Recipient ) const { +command_relay::post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, + int const Action, std::uint16_t const Recipient, + command_data::desired_state_t state) const { auto const &command = simulation::Commands_descriptions[ static_cast( Command ) ]; if( ( command.target == command_target::vehicle ) @@ -191,7 +193,7 @@ command_relay::post( user_command const Command, std::uint64_t const Param1, std Action, Param1, Param2, - Timer::GetDeltaTime() }, + state, Timer::GetDeltaTime() }, static_cast( command.target ) | Recipient ); /* #ifdef _DEBUG diff --git a/command.h b/command.h index a06509e5..9b4e23cf 100644 --- a/command.h +++ b/command.h @@ -169,6 +169,13 @@ struct command_data { int action; // press, repeat or release std::uint64_t param1; std::uint64_t param2; + enum desired_state_t + { + TOGGLE, + OFF, + ON + }; + desired_state_t desired_state; double time_delta; }; @@ -218,7 +225,9 @@ public: // posts specified command for the specified recipient // TODO: replace uint16_t with recipient handle, based on item id void - post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, int const Action, std::uint16_t const Recipient ) const; + post( user_command const Command, std::uint64_t const Param1, std::uint64_t const Param2, + int const Action, std::uint16_t const Recipient, + command_data::desired_state_t state = command_data::TOGGLE ) const; private: // types // members diff --git a/uart.cpp b/uart.cpp new file mode 100644 index 00000000..e3c70c23 --- /dev/null +++ b/uart.cpp @@ -0,0 +1,173 @@ +#include "stdafx.h" +#include "uart.h" +#include "Globals.h" +#include "World.h" +#include "Train.h" +#include "Logs.h" + +uart_input::uart_input() +{ + conf = Global::uart_conf; + + if (sp_get_port_by_name(conf.port.c_str(), &port) != SP_OK) + throw std::runtime_error("uart: cannot find specified port"); + + if (sp_open(port, SP_MODE_READ_WRITE) != SP_OK) + throw std::runtime_error("uart: cannot open port"); + + if (sp_set_baudrate(port, conf.baud) != SP_OK) + throw std::runtime_error("uart: cannot set baudrate"); + + if (sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE) != SP_OK) + throw std::runtime_error("uart: cannot set flowcontrol"); + + if (sp_flush(port, SP_BUF_BOTH) != SP_OK) + throw std::runtime_error("uart: cannot flush"); + + old_packet.fill(0); + last_update = std::chrono::high_resolution_clock::now(); +} + +uart_input::~uart_input() +{ + sp_close(port); + sp_free_port(port); +} + +#define SPLIT_INT16(x) (uint8_t)x, (uint8_t)(x >> 8) + +void uart_input::poll() +{ + auto now = std::chrono::high_resolution_clock::now(); + if (std::chrono::duration(now - last_update).count() < conf.updatetime) + return; + last_update = now; + + TTrain *t = Global::pWorld->train(); + + sp_return ret; + + if (sp_input_waiting(port) >= 16) + { + std::array buffer; + ret = sp_blocking_read(port, (void*)buffer.data(), buffer.size(), 0); + if (ret < 0) + throw std::runtime_error("uart: failed to read from port"); + + sp_drain(port); + data_pending = false; + + for (auto entry : input_bits) + { + input_type_t type = std::get<2>(entry); + + size_t byte = std::get<0>(entry) / 8; + size_t bit = std::get<0>(entry) % 8; + + bool state = (bool)(buffer[byte] & (1 << bit)); + + bool repeat = (type == impulse_r || + type == impulse_r_off || + type == impulse_r_on); + + bool changed = (state != (bool)(old_packet[byte] & (1 << bit))); + + if (!changed && !(repeat && state)) + continue; + + int action; + command_data::desired_state_t desired_state; + + if (type == toggle) + { + action = GLFW_PRESS; + desired_state = state ? command_data::ON : command_data::OFF; + } + else if (type == impulse_r_on) + { + action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE; + desired_state = command_data::ON; + } + else if (type == impulse_r_off) + { + action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE; + desired_state = command_data::OFF; + } + else if (type == impulse || type == impulse_r) + { + action = state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE; + desired_state = command_data::TOGGLE; + } + + relay.post(std::get<1>(entry), 0, 0, action, 0, desired_state); + } + + int mainctrl = buffer[6]; + int scndctrl = buffer[7]; + float trainbrake = (float)(((uint16_t)buffer[8] | ((uint16_t)buffer[9] << 8)) - conf.mainbrakemin) / (conf.mainbrakemax - conf.mainbrakemin); + float localbrake = (float)(((uint16_t)buffer[10] | ((uint16_t)buffer[11] << 8)) - conf.mainbrakemin) / (conf.localbrakemax - conf.localbrakemin); + + t->set_mainctrl(mainctrl); + t->set_scndctrl(scndctrl); + t->set_trainbrake(trainbrake); + t->set_localbrake(localbrake); + + old_packet = buffer; + } + + if (!data_pending && sp_output_waiting(port) == 0) + { + // TODO: ugly! move it into structure like input_bits + + uint8_t buzzer = (uint8_t)t->get_alarm(); + uint8_t tacho = (uint8_t)t->get_tacho(); + uint16_t tank_press = (uint16_t)std::min(conf.tankuart, t->get_tank_pressure() / conf.tankmax * conf.tankuart); + uint16_t pipe_press = (uint16_t)std::min(conf.pipeuart, t->get_pipe_pressure() / conf.pipemax * conf.pipeuart); + uint16_t brake_press = (uint16_t)std::min(conf.brakeuart, t->get_brake_pressure() / conf.brakemax * conf.brakeuart); + uint16_t hv_voltage = (uint16_t)std::min(conf.hvuart, t->get_hv_voltage() / conf.hvmax * conf.hvuart); + auto current = t->get_current(); + uint16_t current1 = (uint16_t)std::min(conf.currentuart, current[0]) / conf.currentmax * conf.currentuart; + uint16_t current2 = (uint16_t)std::min(conf.currentuart, current[1]) / conf.currentmax * conf.currentuart; + uint16_t current3 = (uint16_t)std::min(conf.currentuart, current[2]) / conf.currentmax * conf.currentuart; + + std::array buffer = + { + 0, 0, //byte 0-1 + tacho, //byte 2 + 0, 0, 0, 0, 0, 0, //byte 3-8 + SPLIT_INT16(brake_press), //byte 9-10 + SPLIT_INT16(pipe_press), //byte 11-12 + SPLIT_INT16(tank_press), //byte 13-14 + SPLIT_INT16(hv_voltage), //byte 15-16 + SPLIT_INT16(current1), //byte 17-18 + SPLIT_INT16(current2), //byte 19-20 + SPLIT_INT16(current3), //byte 21-22 + 0, 0, 0, 0, 0, 0, 0, 0 //byte 23-30 + }; + + buffer[4] |= t->btLampkaOpory.b() << 1; + buffer[4] |= t->btLampkaWysRozr.b() << 2; + + buffer[6] |= t->btLampkaOgrzewanieSkladu.b() << 0; + buffer[6] |= t->btLampkaOpory.b() << 1; + buffer[6] |= t->btLampkaPoslizg.b() << 2; + buffer[6] |= t->btLampkaCzuwaka.b() << 6; + buffer[6] |= t->btLampkaSHP.b() << 7; + + buffer[7] |= t->btLampkaStyczn.b() << 0; + buffer[7] |= t->btLampkaNadmPrzetw.b() << 2; + buffer[7] |= t->btLampkaNadmSil.b() << 4; + buffer[7] |= t->btLampkaWylSzybki.b() << 5; + buffer[7] |= t->btLampkaNadmSpr.b() << 6; + + buffer[8] |= buzzer << 7; + + sp_flush(port, SP_BUF_INPUT); // flush input buffer in preparation for reply packet + + ret = sp_blocking_write(port, (void*)buffer.data(), buffer.size(), 0); + if (ret != buffer.size()) + throw std::runtime_error("uart: failed to write to port"); + + data_pending = true; + } +} diff --git a/uart.h b/uart.h new file mode 100644 index 00000000..e58faff4 --- /dev/null +++ b/uart.h @@ -0,0 +1,58 @@ +#pragma once +#include +#include "command.h" +#include "Globals.h" + +class uart_input +{ + enum input_type_t + { + toggle, + impulse, + impulse_r, + impulse_r_on, + impulse_r_off + }; + + std::array, 23> input_bits = + { + std::make_tuple(1, user_command::linebreakertoggle, impulse_r_off), + std::make_tuple(2, user_command::linebreakertoggle, impulse_r_on), + std::make_tuple(3, user_command::motoroverloadrelayreset, impulse), + std::make_tuple(5, user_command::converteroverloadrelayreset, impulse), + std::make_tuple(6, user_command::motorconnectorsopen, toggle), + std::make_tuple(7, user_command::alerteracknowledge, impulse_r), + + std::make_tuple(9, user_command::convertertoggle, toggle), + std::make_tuple(10, user_command::compressortoggle, toggle), + std::make_tuple(11, user_command::sandboxactivate, impulse), + std::make_tuple(12, user_command::heatingtoggle, toggle), + + std::make_tuple(15, user_command::motoroverloadrelaythresholdtoggle, toggle), + std::make_tuple(16, user_command::pantographtogglefront, toggle), + std::make_tuple(17, user_command::pantographtogglerear, toggle), + std::make_tuple(18, user_command::wheelspinbrakeactivate, impulse), + std::make_tuple(19, user_command::headlightsdimtoggle, toggle), + std::make_tuple(20, user_command::interiorlightdimtoggle, toggle), + std::make_tuple(21, user_command::independentbrakebailoff, impulse), + std::make_tuple(22, user_command::hornhighactivate, impulse), + std::make_tuple(23, user_command::hornlowactivate, impulse), + + std::make_tuple(24, user_command::batterytoggle, toggle), + std::make_tuple(25, user_command::headlighttoggleleft, toggle), + std::make_tuple(26, user_command::headlighttoggleupper, toggle), + std::make_tuple(27, user_command::headlighttoggleright, toggle) + }; + + sp_port *port = nullptr; + command_relay relay; + std::array old_packet; + std::chrono::time_point last_update; + Global::uart_conf_t conf; + bool data_pending = false; + +public: + uart_input(); + ~uart_input(); + void poll(); +};