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(); +};