16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-17 23:39:18 +02:00

serial port input devices communication module replacement

This commit is contained in:
tmj-fstate
2018-02-06 03:03:19 +01:00
parent e8bb25454e
commit 8b74939460
19 changed files with 712 additions and 406 deletions

View File

@@ -132,6 +132,7 @@ void TButton::Update() {
if( pModelOn != nullptr ) { pModelOn->iVisible = m_state; }
if( pModelOff != nullptr ) { pModelOff->iVisible = (!m_state); }
#ifdef _WIN32
if (iFeedbackBit) {
// jeżeli generuje informację zwrotną
if (m_state) // zapalenie
@@ -139,6 +140,7 @@ void TButton::Update() {
else
Console::BitsClear(iFeedbackBit);
}
#endif
};
void TButton::AssignBool(bool const *bValue) {

View File

@@ -19,10 +19,14 @@ public:
// methods
TButton() = default;
void Clear(int const i = -1);
inline void FeedbackBitSet( int const i ) {
inline
void FeedbackBitSet( int const i ) {
iFeedbackBit = 1 << i; };
void Turn( bool const State );
inline
bool GetValue() const {
return ( m_state ? 1 : 0 ); }
inline
bool Active() {
return ( ( pModelOn != nullptr )
|| ( pModelOff != nullptr ) ); }

View File

@@ -12,7 +12,6 @@ http://mozilla.org/MPL/2.0/.
#include "Globals.h"
#include "LPT.h"
#include "Logs.h"
#include "MWD.h" // maciek001: obsluga portu COM
#include "PoKeys55.h"
#include "utilities.h"
@@ -54,31 +53,6 @@ Działanie jest następujące:
/*******************************/
/* //kod do przetrawienia:
//aby się nie włączacz wygaszacz ekranu, co jakiś czas naciska się wirtualnie ScrollLock
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
private static void PressScrollLock()
{//przyciska i zwalnia ScrollLock
const byte vkScroll = 0x91;
const byte keyeventfKeyup = 0x2;
keybd_event(vkScroll, 0x45, 0, (UIntPtr)0);
keybd_event(vkScroll, 0x45, keyeventfKeyup, (UIntPtr)0);
};
[DllImport("user32.dll")]
private static extern bool SystemParametersInfo(int uAction,int uParam,int &lpvParam,int flags);
public static Int32 GetScreenSaverTimeout()
{
Int32 value=0;
SystemParametersInfo(14,0,&value,0);
return value;
};
*/
// static class member storage allocation
TKeyTrans Console::ktTable[4 * 256];
@@ -99,7 +73,6 @@ int Console::iMode = 0;
int Console::iConfig = 0;
TPoKeys55 *Console::PoKeys55[2] = {NULL, NULL};
TLPT *Console::LPT = NULL;
TMWDComm *Console::MWDComm = NULL; // maciek001: obiekt dla MWD
int Console::iSwitch[8]; // bistabilne w kabinie, załączane z [Shift], wyłączane bez
int Console::iButton[8]; // monostabilne w kabinie, załączane podczas trzymania klawisza
@@ -111,14 +84,12 @@ Console::Console()
iSwitch[i] = 0; // bity 0..127 - bez [Ctrl], 128..255 - z [Ctrl]
iButton[i] = 0; // bity 0..127 - bez [Shift], 128..255 - z [Shift]
}
MWDComm = NULL;
};
Console::~Console()
{
delete PoKeys55[0];
delete PoKeys55[1];
delete MWDComm;
};
void Console::ModeSet(int m, int h)
@@ -166,18 +137,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;
};
@@ -190,14 +149,9 @@ void Console::Off()
SetLedState(VK_SCROLL, true); // przyciśnięty
SetLedState(VK_SCROLL, false); // zwolniony
}
delete PoKeys55[0];
PoKeys55[0] = NULL;
delete PoKeys55[1];
PoKeys55[1] = NULL;
delete LPT;
LPT = NULL;
delete MWDComm;
MWDComm = NULL;
SafeDelete( PoKeys55[0] );
SafeDelete( PoKeys55[1] );
SafeDelete( LPT );
};
void Console::BitsSet(int mask, int entry)
@@ -289,56 +243,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);
}
};
bool Console::Pressed(int x)
@@ -351,85 +255,39 @@ bool Console::Pressed(int x)
void Console::ValueSet(int x, double y)
{ // ustawienie wartości (y) na kanale analogowym (x)
if (iMode == 4)
if (PoKeys55[0])
{
x = Global.iPoKeysPWM[x];
if (Global.iCalibrateOutDebugInfo == x)
WriteLog("CalibrateOutDebugInfo: oryginal=" + std::to_string(y));
if (Global.fCalibrateOutMax[x] > 0)
{
y = clamp( y, 0.0, Global.fCalibrateOutMax[x]);
if (Global.iCalibrateOutDebugInfo == x)
WriteLog(" cutted=" + std::to_string(y));
y = y / Global.fCalibrateOutMax[x]; // sprowadzenie do <0,1> jeśli podana
// maksymalna wartość
if (Global.iCalibrateOutDebugInfo == x)
WriteLog(" fraction=" + std::to_string(y));
}
double temp = (((((Global.fCalibrateOut[x][5] * y) + Global.fCalibrateOut[x][4]) * y +
Global.fCalibrateOut[x][3]) *
y +
Global.fCalibrateOut[x][2]) *
y +
Global.fCalibrateOut[x][1]) *
y +
Global.fCalibrateOut[x][0]; // zakres <0;1>
if (Global.iCalibrateOutDebugInfo == x)
WriteLog(" calibrated=" + std::to_string(temp));
PoKeys55[0]->PWM(x, temp);
if( iMode != 4 ) { return; }
if (PoKeys55[0])
{
x = Global.iPoKeysPWM[x];
if( Global.iCalibrateOutDebugInfo == x ) {
WriteLog( "CalibrateOutDebugInfo: oryginal=" + std::to_string( y ) );
}
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
}
}
if (Global.fCalibrateOutMax[x] > 0)
{
y = clamp( y, 0.0, Global.fCalibrateOutMax[x]);
if( Global.iCalibrateOutDebugInfo == x ) {
WriteLog( " cutted=" + std::to_string( y ) );
}
// sprowadzenie do <0,1> jeśli podana maksymalna wartość
y = y / Global.fCalibrateOutMax[x];
if( Global.iCalibrateOutDebugInfo == x ) {
WriteLog( " fraction=" + std::to_string( y ) );
}
}
double temp = (((((Global.fCalibrateOut[x][5] * y) + Global.fCalibrateOut[x][4]) * y +
Global.fCalibrateOut[x][3]) *
y +
Global.fCalibrateOut[x][2]) *
y +
Global.fCalibrateOut[x][1]) *
y +
Global.fCalibrateOut[x][0]; // zakres <0;1>
if( Global.iCalibrateOutDebugInfo == x ) {
WriteLog( " calibrated=" + std::to_string( temp ) );
}
PoKeys55[0]->PWM(x, temp);
}
};
void Console::Update()
@@ -447,11 +305,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)
@@ -476,11 +329,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
};
@@ -515,6 +363,7 @@ void Console::OnKeyDown(int k)
}
}
};
void Console::OnKeyUp(int k)
{ // puszczenie klawisza w zasadzie nie ma znaczenia dla iSwitch, ale zeruje iButton
if ((k & 0x20000) == 0) // monostabilne tylko bez [Ctrl]
@@ -523,10 +372,12 @@ void Console::OnKeyUp(int k)
else
iButton[char(k) >> 5] &= ~(1 << (k & 31)); // wyłącz monostabilny podstawowy
};
int Console::KeyDownConvert(int k)
{
return int(ktTable[k & 0x3FF].iDown);
};
int Console::KeyUpConvert(int k)
{
return int(ktTable[k & 0x3FF].iUp);

View File

@@ -13,7 +13,6 @@ http://mozilla.org/MPL/2.0/.
class TConsoleDevice; // urządzenie podłączalne za pomocą DLL
class TPoKeys55;
class TLPT;
class TMWDComm; // maciek001: dodana obsluga portu COM
// klasy konwersji znaków wprowadzanych z klawiatury
class TKeyTrans
@@ -32,7 +31,6 @@ class Console
static int iBits; // podstawowy zestaw lampek
static TPoKeys55 *PoKeys55[2]; // może ich być kilka
static TLPT *LPT;
static TMWDComm *MWDComm; // maciek001: na potrzeby MWD
static void BitsUpdate(int mask);
// zmienne dla trybu "jednokabinowego", potrzebne do współpracy z pulpitem (PoKeys)
// używając klawiatury, każdy pojazd powinien mieć własny stan przełączników

View File

@@ -32,6 +32,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
#include "mouseinput.h"
#include "gamepadinput.h"
#include "Console.h"
#include "uart.h"
#include "PyInt.h"
#ifdef EU07_BUILD_STATIC
@@ -50,6 +51,7 @@ Stele, firleju, szociu, hunter, ZiomalCl, OLI_EU and others
#pragma comment( lib, "openal32.lib")
#pragma comment( lib, "setupapi.lib" )
#pragma comment( lib, "python27.lib" )
#pragma comment( lib, "libserialport-0.lib" )
#pragma comment (lib, "dbghelp.lib")
#pragma comment (lib, "version.lib")
#ifdef CAN_I_HAS_LIBPNG
@@ -68,6 +70,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_input> uart;
}
@@ -411,6 +414,9 @@ int main(int argc, char *argv[])
input::Keyboard.init();
input::Mouse.init();
input::Gamepad.init();
if( true == Global.uart_conf.enable ) {
input::uart = std::make_unique<uart_input>();
}
Global.pWorld = &World; // Ra: wskaźnik potrzebny do usuwania pojazdów
try {
@@ -443,6 +449,7 @@ int main(int argc, char *argv[])
input::Keyboard.poll();
if( true == Global.InputMouse ) { input::Mouse.poll(); }
if( true == Global.InputGamepad ) { input::Gamepad.poll(); }
if( input::uart != nullptr ) { input::uart->poll(); }
}
}
catch( std::bad_alloc const &Error ) {

View File

@@ -579,102 +579,44 @@ global_settings::ConfigParse(cParser &Parser) {
Parser.getTokens();
Parser >> 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" ) {
uart_conf.enable = true;
Parser.getTokens( 3, false );
Parser
>> uart_conf.port
>> uart_conf.baud
>> uart_conf.updatetime;
}
else if( token == "uarttune" ) {
Parser.getTokens( 14 );
Parser
>> uart_conf.mainbrakemin
>> uart_conf.mainbrakemax
>> uart_conf.localbrakemin
>> uart_conf.localbrakemax
>> uart_conf.tankmax
>> uart_conf.tankuart
>> uart_conf.pipemax
>> uart_conf.pipeuart
>> uart_conf.brakemax
>> uart_conf.brakeuart
>> uart_conf.hvmax
>> uart_conf.hvuart
>> uart_conf.currentmax
>> uart_conf.currentuart;
}
else if( token == "uartfeature" ) {
Parser.getTokens( 4 );
Parser
>> uart_conf.mainenable
>> uart_conf.scndenable
>> uart_conf.trainenable
>> uart_conf.localenable;
}
else if( token == "uartdebug" ) {
Parser.getTokens( 1 );
Parser >> uart_conf.debug;
}
} while ((token != "") && (token != "endconfig")); //(!Parser->EndOfFile)
// na koniec trochę zależności
if (!bLoadTraction) // wczytywanie drutów i słupów

View File

@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
#include "dumb3d.h"
#include "float3d.h"
#include "light.h"
#include "uart.h"
#include "utilities.h"
struct global_settings {
@@ -60,8 +61,6 @@ struct global_settings {
int iWriteLogEnabled{ 3 }; // maska bitowa: 1-zapis do pliku, 2-okienko, 4-nazwy torów
bool MultipleLogs{ false };
unsigned int DisabledLogTypes{ 0 };
bool bMWDdebugEnable{ false }; // włącz dodawanie do logu
int iMWDDebugMode{ 0 }; // co ma wyświetlać w logu
// simulation
bool RealisticControlMode{ false }; // controls ability to steer the vehicle from outside views
bool bFreeFly{ false };
@@ -159,25 +158,7 @@ struct global_settings {
0, 0, 0, 0, 0, 0, 0 };
int iCalibrateOutDebugInfo { -1 }; // numer wyjścia kalibrowanego dla którego wyświetlać informacje podczas kalibracji
int iPoKeysPWM[ 7 ] = { 0, 1, 2, 3, 4, 5, 6 }; // numery wejść dla PWM
// maciek001: konfiguracja wstępna portu COM
bool bMWDmasterEnable { false };// główne włączenie portu!
std::string sMWDPortId { "COM1" }; // nazwa portu z którego korzystamy
unsigned long int iMWDBaudrate{ 9600 }; // prędkość transmisji danych
bool bMWDInputEnable { false }; // włącz wejścia
bool bMWDBreakEnable { false }; // włącz wejścia analogowe
// wartość max potencjometru, wartość min potencjometru, rozdzielczość (max. wartość jaka może być)
double fMWDAnalogInCalib[ 4 ][ 2 ] = {
{ 0, 1023 },
{ 0, 1023 },
{ 0, 1023 },
{ 0, 1023 } };
double fMWDzg[ 2 ] = { 0.9, 1023 };
double fMWDpg[ 2 ] = { 0.8, 1023 };
double fMWDph[ 2 ] = { 0.6, 1023 };
double fMWDvolt[ 2 ] = { 4000, 1023 };
double fMWDamp[ 2 ] = { 800, 1023 };
double fMWDlowVolt[ 2 ] = { 150, 1023 };
int iMWDdivider { 5 };
uart_input::conf_t uart_conf;
// multiplayer
int iMultiplayer{ 0 }; // blokada działania niektórych eventów na rzecz kominikacji
// other

287
Train.cpp
View File

@@ -159,19 +159,23 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::mastercontrollerincreasefast, &TTrain::OnCommand_mastercontrollerincreasefast },
{ user_command::mastercontrollerdecrease, &TTrain::OnCommand_mastercontrollerdecrease },
{ user_command::mastercontrollerdecreasefast, &TTrain::OnCommand_mastercontrollerdecreasefast },
{ user_command::mastercontrollerset, &TTrain::OnCommand_mastercontrollerset },
{ user_command::secondcontrollerincrease, &TTrain::OnCommand_secondcontrollerincrease },
{ user_command::secondcontrollerincreasefast, &TTrain::OnCommand_secondcontrollerincreasefast },
{ user_command::secondcontrollerdecrease, &TTrain::OnCommand_secondcontrollerdecrease },
{ user_command::secondcontrollerdecreasefast, &TTrain::OnCommand_secondcontrollerdecreasefast },
{ user_command::secondcontrollerset, &TTrain::OnCommand_secondcontrollerset },
{ user_command::notchingrelaytoggle, &TTrain::OnCommand_notchingrelaytoggle },
{ user_command::mucurrentindicatorothersourceactivate, &TTrain::OnCommand_mucurrentindicatorothersourceactivate },
{ user_command::independentbrakeincrease, &TTrain::OnCommand_independentbrakeincrease },
{ user_command::independentbrakeincreasefast, &TTrain::OnCommand_independentbrakeincreasefast },
{ user_command::independentbrakedecrease, &TTrain::OnCommand_independentbrakedecrease },
{ user_command::independentbrakedecreasefast, &TTrain::OnCommand_independentbrakedecreasefast },
{ user_command::independentbrakeset, &TTrain::OnCommand_independentbrakeset },
{ user_command::independentbrakebailoff, &TTrain::OnCommand_independentbrakebailoff },
{ user_command::trainbrakeincrease, &TTrain::OnCommand_trainbrakeincrease },
{ user_command::trainbrakedecrease, &TTrain::OnCommand_trainbrakedecrease },
{ user_command::trainbrakeset, &TTrain::OnCommand_trainbrakeset },
{ user_command::trainbrakecharging, &TTrain::OnCommand_trainbrakecharging },
{ user_command::trainbrakerelease, &TTrain::OnCommand_trainbrakerelease },
{ user_command::trainbrakefirstservice, &TTrain::OnCommand_trainbrakefirstservice },
@@ -437,9 +441,9 @@ PyObject *TTrain::GetTrainState() {
PyDict_SetItemString( dict, "fuse", PyGetBool( mover->FuseFlag ) );
PyDict_SetItemString( dict, "epfuse", PyGetBool( mover->EpFuse ));
// induction motor state data
char* TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
char* TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
char* TXTP[ 3 ] = { "bc", "bp", "sp" };
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
char const *TXTP[ 3 ] = { "bc", "bp", "sp" };
for( int j = 0; j < 10; ++j )
PyDict_SetItemString( dict, ( std::string( "eimp_t_" ) + std::string( TXTT[ j ] ) ).c_str(), PyGetFloatS( fEIMParams[ 0 ][ j ] ) );
for( int i = 0; i < 8; ++i ) {
@@ -496,6 +500,35 @@ PyObject *TTrain::GetTrainState() {
return dict;
}
TTrain::state_t
TTrain::get_state() const {
return {
btLampkaSHP.GetValue(),
btLampkaCzuwaka.GetValue(),
btLampkaOpory.GetValue(),
btLampkaWylSzybki.GetValue(),
btLampkaNadmSil.GetValue(),
btLampkaStyczn.GetValue(),
btLampkaPoslizg.GetValue(),
btLampkaNadmPrzetw.GetValue(),
btLampkaPrzetwOff.GetValue(),
btLampkaNadmSpr.GetValue(),
btLampkaNadmWent.GetValue(),
btLampkaWysRozr.GetValue(),
btLampkaOgrzewanieSkladu.GetValue(),
btHaslerBrakes.GetValue(),
btHaslerCurrent.GetValue(),
( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ),
fTachoVelocity,
static_cast<float>( mvOccupied->Compressor ),
static_cast<float>( mvOccupied->PipePress ),
static_cast<float>( mvOccupied->BrakePress ),
fHVoltage,
{ fHCurrent[ ( mvControlled->TrainType & dt_EZT ) ? 0 : 1 ], fHCurrent[ 2 ], fHCurrent[ 3 ] }
};
}
bool TTrain::is_eztoer() const {
return
@@ -596,6 +629,17 @@ void TTrain::OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data
}
}
void TTrain::OnCommand_mastercontrollerset( TTrain *Train, command_data const &Command ) {
auto const targetposition { std::min<int>( Command.param1, Train->mvControlled->MainCtrlPosNo ) };
while( targetposition < Train->mvControlled->MainCtrlPos ) {
Train->mvControlled->DecMainCtrl( 1 );
}
while( targetposition > Train->mvControlled->MainCtrlPos ) {
Train->mvControlled->IncMainCtrl( 1 );
}
}
void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data const &Command ) {
if( Command.action != GLFW_RELEASE ) {
@@ -678,6 +722,17 @@ void TTrain::OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data
}
}
void TTrain::OnCommand_secondcontrollerset( TTrain *Train, command_data const &Command ) {
auto const targetposition { std::min<int>( Command.param1, Train->mvControlled->ScndCtrlPosNo ) };
while( targetposition < Train->mvControlled->ScndCtrlPos ) {
Train->mvControlled->DecScndCtrl( 1 );
}
while( targetposition > Train->mvControlled->ScndCtrlPos ) {
Train->mvControlled->IncScndCtrl( 1 );
}
}
void TTrain::OnCommand_independentbrakeincrease( TTrain *Train, command_data const &Command ) {
if( Command.action != GLFW_RELEASE ) {
@@ -724,6 +779,18 @@ void TTrain::OnCommand_independentbrakedecreasefast( TTrain *Train, command_data
}
}
void TTrain::OnCommand_independentbrakeset( TTrain *Train, command_data const &Command ) {
Train->mvControlled->LocalBrakePos = (
std::round(
interpolate<double>(
0.0,
LocalBrakePosNo,
clamp(
reinterpret_cast<double const &>( Command.param1 ),
0.0, 1.0 ) ) ) );
}
void TTrain::OnCommand_independentbrakebailoff( TTrain *Train, command_data const &Command ) {
if( false == FreeFlyModeFlag ) {
@@ -801,6 +868,17 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co
}
}
void TTrain::OnCommand_trainbrakeset( TTrain *Train, command_data const &Command ) {
Train->mvControlled->BrakeLevelSet(
interpolate(
Train->mvControlled->Handle->GetPos( bh_MIN ),
Train->mvControlled->Handle->GetPos( bh_MAX ),
clamp(
reinterpret_cast<double const &>( Command.param1 ),
0.0, 1.0 ) ) );
}
void TTrain::OnCommand_trainbrakecharging( TTrain *Train, command_data const &Command ) {
if( Command.action != GLFW_RELEASE ) {
@@ -1293,6 +1371,8 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvOccupied->Battery ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
// wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ
if( Train->mvOccupied->BatterySwitch( true ) ) {
// bateria potrzebna np. do zapalenia świateł
@@ -1312,6 +1392,8 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
if( Train->mvOccupied->BatterySwitch( false ) ) {
// ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
if( Train->ggBatteryButton.SubModel ) {
@@ -1334,6 +1416,8 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->PantFrontUp ) {
// turn on...
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->mvControlled->PantFrontSP = false;
if( Train->mvControlled->PantFront( true ) ) {
if( Train->mvControlled->PantFrontStart != 1 ) {
@@ -1356,6 +1440,8 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
}
else {
// ...or turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
if( ( Train->ggPantFrontButtonOff.SubModel == nullptr )
&& ( Train->ggPantSelectedDownButton.SubModel == nullptr ) ) {
@@ -1414,6 +1500,8 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->PantRearUp ) {
// turn on...
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->mvControlled->PantRearSP = false;
if( Train->mvControlled->PantRear( true ) ) {
if( Train->mvControlled->PantRearStart != 1 ) {
@@ -1436,6 +1524,8 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
}
else {
// ...or turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
if( ( Train->ggPantRearButtonOff.SubModel == nullptr )
&& ( Train->ggPantSelectedDownButton.SubModel == nullptr ) ) {
@@ -1603,6 +1693,8 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com
// press or hold...
if( Train->m_linebreakerstate == 0 ) {
// ...to close the circuit
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
if( Command.action == GLFW_PRESS ) {
// fresh press, start fresh closing delay calculation
Train->fMainRelayTimer = 0.0f;
@@ -1649,6 +1741,8 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com
}
else if( Train->m_linebreakerstate == 1 ) {
// ...to open the circuit
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
if( true == Train->mvControlled->MainSwitch( false ) ) {
Train->m_linebreakerstate = -1;
@@ -1755,6 +1849,8 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma
if( ( false == Train->mvControlled->ConverterAllow )
&& ( Train->ggConverterButton.GetValue() < 0.5 ) ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
// visual feedback
Train->ggConverterButton.UpdateValue( 1.0, Train->dsbSwitch );
/*
@@ -1782,6 +1878,8 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
// visual feedback
Train->ggConverterButton.UpdateValue( 0.0, Train->dsbSwitch );
if( Train->ggConverterOffButton.SubModel != nullptr ) {
@@ -1907,6 +2005,8 @@ void TTrain::OnCommand_compressortoggle( TTrain *Train, command_data const &Comm
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->CompressorAllow ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
// visual feedback
Train->ggCompressorButton.UpdateValue( 1.0, Train->dsbSwitch );
// impulse type switch has no effect if there's no power
@@ -1920,6 +2020,8 @@ void TTrain::OnCommand_compressortoggle( TTrain *Train, command_data const &Comm
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
if( true == Train->mvControlled->CompressorSwitch( false ) ) {
// NOTE: we don't have switch type definition for the compresor switch
// so for the time being we have hard coded "impulse" switches for all EMUs
@@ -1991,16 +2093,26 @@ void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &C
}
return;
}
command_data command = Command;
if( Train->mvControlled->StLinSwitchType == "toggle" ) {
if( ( Command.hint == command_hint::on ) && ( true == Train->mvControlled->StLinSwitchOff ) ) { return; }
if( ( Command.hint == command_hint::off ) && ( false == Train->mvControlled->StLinSwitchOff ) ) { return; }
}
else if( Command.hint == command_hint::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 ) {
if( command.action == GLFW_PRESS ) {
// button works while it's held down but we can only pay attention to initial press
if( false == Train->mvControlled->StLinSwitchOff ) {
// open the connectors
Train->mvControlled->StLinSwitchOff = true;
if( ( Train->mvControlled->TrainType == dt_ET41 )
|| ( Train->mvControlled->TrainType == dt_ET42 ) ) {
// crude implementation of the butto affecting entire unit for multi-unit engines
// crude implementation of the button affecting entire unit for multi-unit engines
// TODO: rework it into part of standard command propagation system
if( ( Train->mvControlled->Couplers[ 0 ].Connected != nullptr )
&& ( true == TestFlag( Train->mvControlled->Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
@@ -2057,10 +2169,10 @@ void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &C
}
}
}
else if( Command.action == GLFW_RELEASE ) {
else if( command.action == GLFW_RELEASE ) {
// button released
if( Train->mvControlled->StLinSwitchType != "toggle" ) {
// default button type (impulse) works on button release
// default button type (impulse) ceases its work on button release
Train->mvControlled->StLinSwitchOff = false;
if( ( Train->mvControlled->TrainType == dt_ET41 )
|| ( Train->mvControlled->TrainType == dt_ET42 ) ) {
@@ -2105,6 +2217,8 @@ void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command
( false == Train->mvControlled->ShuntMode ) :
( Train->mvControlled->Imax < Train->mvControlled->ImaxHi ) ) ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
if( true == Train->mvControlled->CurrentSwitch( true ) ) {
// visual feedback
Train->ggMaxCurrentCtrl.UpdateValue( 1.0, Train->dsbSwitch );
@@ -2112,6 +2226,8 @@ void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
if( true == Train->mvControlled->CurrentSwitch( false ) ) {
// visual feedback
Train->ggMaxCurrentCtrl.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2212,6 +2328,8 @@ void TTrain::OnCommand_headlighttoggleleft( TTrain *Train, command_data const &C
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_left ) == 0 ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_left;
// visual feedback
Train->ggLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch );
@@ -2222,6 +2340,8 @@ void TTrain::OnCommand_headlighttoggleleft( TTrain *Train, command_data const &C
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_left;
// visual feedback
Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2245,6 +2365,8 @@ void TTrain::OnCommand_headlighttoggleright( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_right ) == 0 ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_right;
// visual feedback
Train->ggRightLightButton.UpdateValue( 1.0, Train->dsbSwitch );
@@ -2255,6 +2377,8 @@ void TTrain::OnCommand_headlighttoggleright( TTrain *Train, command_data const &
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_right;
// visual feedback
Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2278,12 +2402,16 @@ void TTrain::OnCommand_headlighttoggleupper( TTrain *Train, command_data const &
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( Train->DynamicObject->iLights[ vehicleside ] & light::headlight_upper ) == 0 ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_upper;
// visual feedback
Train->ggUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch );
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
Train->DynamicObject->iLights[ vehicleside ] ^= light::headlight_upper;
// visual feedback
Train->ggUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2597,12 +2725,16 @@ void TTrain::OnCommand_headlightsdimtoggle( TTrain *Train, command_data const &C
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->DynamicObject->DimHeadlights ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->DynamicObject->DimHeadlights = true;
// visual feedback
Train->ggDimHeadlightsButton.UpdateValue( 1.0, Train->dsbSwitch );
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
Train->DynamicObject->DimHeadlights = false;
// visual feedback
Train->ggDimHeadlightsButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2654,12 +2786,16 @@ void TTrain::OnCommand_interiorlightdimtoggle( TTrain *Train, command_data const
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->bCabLightDim ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->bCabLightDim = true;
// visual feedback
Train->ggCabLightDimButton.UpdateValue( 1.0, Train->dsbSwitch );
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
Train->bCabLightDim = false;
// visual feedback
Train->ggCabLightDimButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2709,12 +2845,16 @@ void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->Heating ) {
// turn on
if( Command.hint == command_hint::off ) { return; } // caller wants the other state
Train->mvControlled->Heating = true;
// visual feedback
Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch );
}
else {
//turn off
if( Command.hint == command_hint::on ) { return; } // caller wants the other state
Train->mvControlled->Heating = false;
// visual feedback
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -2863,8 +3003,9 @@ void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Comma
void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ) {
if( true == FreeFlyModeFlag ) {
// tryb freefly
if( ( true == FreeFlyModeFlag )
&& ( Command.action == GLFW_PRESS ) ) {
// tryb freefly, press only
auto coupler { -1 };
auto *vehicle { Train->DynamicObject->ABuScanNearestObject( Train->DynamicObject->GetTrack(), 1, 1500, coupler ) };
if( vehicle == nullptr )
@@ -2884,8 +3025,9 @@ void TTrain::OnCommand_carcouplingincrease( TTrain *Train, command_data const &C
void TTrain::OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command ) {
if( true == FreeFlyModeFlag ) {
// tryb freefly
if( ( true == FreeFlyModeFlag )
&& ( Command.action == GLFW_PRESS ) ) {
// tryb freefly, press only
auto coupler { -1 };
auto *vehicle { Train->DynamicObject->ABuScanNearestObject( Train->DynamicObject->GetTrack(), 1, 1500, coupler ) };
if( vehicle == nullptr )
@@ -3451,43 +3593,27 @@ bool TTrain::Update( double const Deltatime )
fEIMParams[1 + i][8] = 0;
fEIMParams[1 + i][9] = 0;
}
if (Global.iFeedbackMode == 4)
{ // wykonywać tylko gdy wyprowadzone na pulpit
Console::ValueSet(0,
mvOccupied->Compressor); // Ra: sterowanie miernikiem: zbiornik główny
Console::ValueSet(1,
mvOccupied->PipePress); // Ra: sterowanie miernikiem: przewód główny
Console::ValueSet(2, mvOccupied->BrakePress); // Ra: sterowanie miernikiem: cylinder hamulcowy
Console::ValueSet(3, fHVoltage); // woltomierz wysokiego napięcia
Console::ValueSet(4, fHCurrent[2]); // Ra: sterowanie miernikiem: drugi amperomierz
Console::ValueSet(5,
fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1]); // pierwszy amperomierz; dla
// EZT prąd całkowity
Console::ValueSet(6, fTachoVelocity); ////Ra: prędkość na pin 43 - wyjście
/// analogowe (to nie jest PWM);
/// skakanie zapewnia mechanika
/// napędu
#ifdef _WIN32
if (Global.iFeedbackMode == 4) {
// wykonywać tylko gdy wyprowadzone na pulpit
// Ra: sterowanie miernikiem: zbiornik główny
Console::ValueSet(0, mvOccupied->Compressor);
// Ra: sterowanie miernikiem: przewód główny
Console::ValueSet(1, mvOccupied->PipePress);
// Ra: sterowanie miernikiem: cylinder hamulcowy
Console::ValueSet(2, mvOccupied->BrakePress);
// woltomierz wysokiego napięcia
Console::ValueSet(3, fHVoltage);
// Ra: sterowanie miernikiem: drugi amperomierz
Console::ValueSet(4, fHCurrent[2]);
// pierwszy amperomierz; dla EZT prąd całkowity
Console::ValueSet(5, fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1]);
// Ra: prędkość na pin 43 - wyjście analogowe (to nie jest PWM); skakanie zapewnia mechanika napędu
Console::ValueSet(6, fTachoVelocity);
}
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 ;)
}
// hunter-080812: wyrzucanie szybkiego na elektrykach gdy nie ma napiecia
// przy dowolnym ustawieniu kierunkowego
// Ra: to już jest w T_MoverParameters::TractionForce(), ale zależy od
// kierunku
#endif
// hunter-080812: wyrzucanie szybkiego na elektrykach gdy nie ma napiecia przy dowolnym ustawieniu kierunkowego
// Ra: to już jest w T_MoverParameters::TractionForce(), ale zależy od kierunku
if( ( mvControlled->Mains )
&& ( mvControlled->EngineType == ElectricSeriesMotor ) ) {
if( std::max( mvControlled->GetTrainsetVoltage(), std::fabs( mvControlled->RunningTraction.TractionVoltage ) ) < 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) {
@@ -4026,9 +4152,10 @@ bool TTrain::Update( double const Deltatime )
}
if (ggBrakeCtrl.SubModel)
{
#ifdef _WIN32
if (DynamicObject->Mechanik ?
(DynamicObject->Mechanik->AIControllFlag ? false :
(Global.iFeedbackMode == 4 || (Global.bMWDmasterEnable && Global.bMWDBreakEnable))) :
(Global.iFeedbackMode == 4 /*|| (Global.bMWDmasterEnable && Global.bMWDBreakEnable)*/)) :
false) // nie blokujemy AI
{ // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba
// Firleju: dlatego kasujemy i zastepujemy funkcją w Console
@@ -4037,7 +4164,6 @@ bool TTrain::Update( double const Deltatime )
double b = Console::AnalogCalibrateGet(0);
b = b * 8.0 - 2.0;
b = clamp<double>( 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);
}
@@ -4046,13 +4172,13 @@ bool TTrain::Update( double const Deltatime )
double b = Console::AnalogCalibrateGet(0);
b = b * 7.0 - 1.0;
b = clamp<double>( 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);
}
// else //standardowa prodedura z kranem powiązanym z klawiaturą
// ggBrakeCtrl.UpdateValue(double(mvOccupied->BrakeCtrlPos));
}
#endif
// else //standardowa prodedura z kranem powiązanym z klawiaturą
// ggBrakeCtrl.UpdateValue(double(mvOccupied->BrakeCtrlPos));
ggBrakeCtrl.UpdateValue(mvOccupied->fBrakeCtrlPos);
@@ -4060,12 +4186,12 @@ bool TTrain::Update( double const Deltatime )
}
if( ggLocalBrake.SubModel ) {
#ifdef _WIN32
if( ( DynamicObject->Mechanik != nullptr )
&& ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI
&& ( mvOccupied->BrakeLocHandle == FD1 )
&& ( ( Global.iFeedbackMode == 4 )
|| ( Global.bMWDmasterEnable && Global.bMWDBreakEnable ) ) ) {
/*|| ( Global.bMWDmasterEnable && Global.bMWDBreakEnable )*/ ) ) {
// Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba
// Firleju: dlatego kasujemy i zastepujemy funkcją w Console
auto const b = clamp<double>(
@@ -4074,12 +4200,10 @@ 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 {
else
#endif
{
// standardowa prodedura z kranem powiązanym z klawiaturą
ggLocalBrake.UpdateValue( double( mvOccupied->LocalBrakePos ) );
}
@@ -5146,6 +5270,27 @@ void TTrain::SetLights()
// clears state of all cabin controls
void TTrain::clear_cab_controls()
{
// indicators exposed to custom control devices
btLampkaSHP.Clear(0);
btLampkaCzuwaka.Clear(1);
btLampkaOpory.Clear(2);
btLampkaWylSzybki.Clear(3);
btLampkaNadmSil.Clear(4);
btLampkaStyczn.Clear(5);
btLampkaPoslizg.Clear(6);
btLampkaNadmPrzetw.Clear(((mvControlled->TrainType & dt_EZT) != 0) ? -1 : 7); // EN57 nie ma tej lampki
btLampkaPrzetwOff.Clear(((mvControlled->TrainType & dt_EZT) != 0) ? 7 : -1 ); // za to ma tę
btLampkaNadmSpr.Clear(8);
btLampkaNadmWent.Clear(9);
btLampkaWysRozr.Clear(((mvControlled->TrainType & dt_ET22) != 0) ? -1 : 10); // ET22 nie ma tej lampki
btLampkaOgrzewanieSkladu.Clear(11);
btHaslerBrakes.Clear(12); // ciśnienie w cylindrach do odbijania na haslerze
btHaslerCurrent.Clear(13); // prąd na silnikach do odbijania na haslerze
// Jeśli ustawiamy nową wartość dla PoKeys wolna jest 15
// Numer 14 jest używany dla buczka SHP w update_sounds()
// other cab controls
// TODO: arrange in more readable manner, and eventually refactor
ggMainCtrl.Clear();
ggMainCtrlAct.Clear();
ggScndCtrl.Clear();
@@ -5168,11 +5313,6 @@ void TTrain::clear_cab_controls()
ggHornLowButton.Clear();
ggHornHighButton.Clear();
ggNextCurrentButton.Clear();
/*
ggUniversal1Button.Clear();
ggUniversal2Button.Clear();
ggUniversal4Button.Clear();
*/
for( auto &universal : ggUniversals ) {
universal.Clear();
}
@@ -5215,35 +5355,19 @@ void TTrain::clear_cab_controls()
ggClockHInd.Clear();
ggEngineVoltage.Clear();
ggLVoltage.Clear();
// ggLVoltage.Output(0); //Ra: sterowanie miernikiem: niskie napięcie
// ggEnrot1m.Clear();
// ggEnrot2m.Clear();
// ggEnrot3m.Clear();
// ggEngageRatio.Clear();
ggMainGearStatus.Clear();
ggIgnitionKey.Clear();
// Jeśli ustawiamy nową wartość dla PoKeys wolna jest 15
// Numer 14 jest używany dla buczka SHP w innym miejscu
btLampkaPoslizg.Clear(6);
btLampkaStyczn.Clear(5);
btLampkaNadmPrzetw.Clear(((mvControlled->TrainType & dt_EZT) != 0) ? -1 : 7); // EN57 nie ma tej lampki
btLampkaPrzetw.Clear();
btLampkaPrzetwOff.Clear(((mvControlled->TrainType & dt_EZT) != 0) ? 7 : -1 ); // za to ma tę
btLampkaPrzetwB.Clear();
btLampkaPrzetwBOff.Clear();
btLampkaPrzekRozn.Clear();
btLampkaPrzekRoznPom.Clear();
btLampkaNadmSil.Clear(4);
btLampkaUkrotnienie.Clear();
btLampkaHamPosp.Clear();
btLampkaWylSzybki.Clear(3);
btLampkaWylSzybkiOff.Clear();
btLampkaWylSzybkiB.Clear();
btLampkaWylSzybkiBOff.Clear();
btLampkaNadmWent.Clear(9);
btLampkaNadmSpr.Clear(8);
btLampkaOpory.Clear(2);
btLampkaWysRozr.Clear(((mvControlled->TrainType & dt_ET22) != 0) ? -1 : 10); // ET22 nie ma tej lampki
btLampkaBezoporowa.Clear();
btLampkaBezoporowaB.Clear();
btLampkaMaxSila.Clear();
@@ -5254,9 +5378,6 @@ void TTrain::clear_cab_controls()
btLampkaBlokadaDrzwi.Clear();
btInstrumentLight.Clear();
btLampkaWentZaluzje.Clear();
btLampkaOgrzewanieSkladu.Clear(11);
btLampkaSHP.Clear(0);
btLampkaCzuwaka.Clear(1);
btLampkaDoorLeft.Clear();
btLampkaDoorRight.Clear();
btLampkaDepartureSignal.Clear();
@@ -5308,8 +5429,6 @@ void TTrain::clear_cab_controls()
ggRearUpperLightButton.Clear();
ggRearLeftEndLightButton.Clear();
ggRearRightEndLightButton.Clear();
btHaslerBrakes.Clear(12); // ciśnienie w cylindrach do odbijania na haslerze
btHaslerCurrent.Clear(13); // prąd na silnikach do odbijania na haslerze
}
// NOTE: we can get rid of this function once we have per-cab persistent state

34
Train.h
View File

@@ -65,9 +65,34 @@ public:
class TTrain
{
friend class TWorld; // temporary due to use of play_sound TODO: refactor this
public:
// types
struct state_t {
std::uint8_t shp;
std::uint8_t alerter;
std::uint8_t motor_resistors;
std::uint8_t line_breaker;
std::uint8_t motor_overload;
std::uint8_t motor_connectors;
std::uint8_t wheelslip;
std::uint8_t converter_overload;
std::uint8_t converter_off;
std::uint8_t compressor_overload;
std::uint8_t ventilator_overload;
std::uint8_t motor_overload_threshold;
std::uint8_t train_heating;
std::uint8_t recorder_braking;
std::uint8_t recorder_power;
std::uint8_t alerter_sound;
float velocity;
float reservoir_pressure;
float pipe_pressure;
float brake_pressure;
float hv_voltage;
std::array<float, 3> hv_current;
};
// methods
bool CabChange(int iDirection);
bool ShowNextCurrent; // pokaz przd w podlaczonej lokomotywie (ET41)
bool InitializeCab(int NewCabNo, std::string const &asFileName);
@@ -86,6 +111,7 @@ class TTrain
// McZapkie-310302: ladowanie parametrow z pliku
bool LoadMMediaFile(std::string const &asFileName);
PyObject *GetTrainState();
state_t get_state() const;
private:
// types
@@ -119,19 +145,23 @@ class TTrain
static void OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_mastercontrollerdecrease( TTrain *Train, command_data const &Command );
static void OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_mastercontrollerset( TTrain *Train, command_data const &Command );
static void OnCommand_secondcontrollerincrease( TTrain *Train, command_data const &Command );
static void OnCommand_secondcontrollerincreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_secondcontrollerdecrease( TTrain *Train, command_data const &Command );
static void OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_secondcontrollerset( TTrain *Train, command_data const &Command );
static void OnCommand_notchingrelaytoggle( TTrain *Train, command_data const &Command );
static void OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command );
static void OnCommand_independentbrakeincrease( TTrain *Train, command_data const &Command );
static void OnCommand_independentbrakeincreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_independentbrakedecrease( TTrain *Train, command_data const &Command );
static void OnCommand_independentbrakedecreasefast( TTrain *Train, command_data const &Command );
static void OnCommand_independentbrakeset( TTrain *Train, command_data const &Command );
static void OnCommand_independentbrakebailoff( TTrain *Train, command_data const &Command );
static void OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Command );
static void OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Command );
static void OnCommand_trainbrakeset( TTrain *Train, command_data const &Command );
static void OnCommand_trainbrakecharging( TTrain *Train, command_data const &Command );
static void OnCommand_trainbrakerelease( TTrain *Train, command_data const &Command );
static void OnCommand_trainbrakefirstservice( TTrain *Train, command_data const &Command );

View File

@@ -26,18 +26,22 @@ commanddescription_sequence Commands_descriptions = {
{ "mastercontrollerincreasefast", command_target::vehicle },
{ "mastercontrollerdecrease", command_target::vehicle },
{ "mastercontrollerdecreasefast", command_target::vehicle },
{ "mastercontrollerset", command_target::vehicle },
{ "secondcontrollerincrease", command_target::vehicle },
{ "secondcontrollerincreasefast", command_target::vehicle },
{ "secondcontrollerdecrease", command_target::vehicle },
{ "secondcontrollerdecreasefast", command_target::vehicle },
{ "secondcontrollerset", command_target::vehicle },
{ "mucurrentindicatorothersourceactivate", command_target::vehicle },
{ "independentbrakeincrease", command_target::vehicle },
{ "independentbrakeincreasefast", command_target::vehicle },
{ "independentbrakedecrease", command_target::vehicle },
{ "independentbrakedecreasefast", command_target::vehicle },
{ "independentbrakeset", command_target::vehicle },
{ "independentbrakebailoff", command_target::vehicle },
{ "trainbrakeincrease", command_target::vehicle },
{ "trainbrakedecrease", command_target::vehicle },
{ "trainbrakeset", command_target::vehicle },
{ "trainbrakecharging", command_target::vehicle },
{ "trainbrakerelease", command_target::vehicle },
{ "trainbrakefirstservice", command_target::vehicle },
@@ -173,7 +177,7 @@ 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, command_hint const Hint, std::uint16_t const Recipient ) const {
auto const &command = simulation::Commands_descriptions[ static_cast<std::size_t>( Command ) ];
if( ( command.target == command_target::vehicle )
@@ -190,6 +194,7 @@ command_relay::post( user_command const Command, std::uint64_t const Param1, std
Action,
Param1,
Param2,
Hint,
Timer::GetDeltaTime() },
static_cast<std::size_t>( command.target ) | Recipient );
/*

View File

@@ -20,18 +20,22 @@ enum class user_command {
mastercontrollerincreasefast,
mastercontrollerdecrease,
mastercontrollerdecreasefast,
mastercontrollerset,
secondcontrollerincrease,
secondcontrollerincreasefast,
secondcontrollerdecrease,
secondcontrollerdecreasefast,
secondcontrollerset,
mucurrentindicatorothersourceactivate,
independentbrakeincrease,
independentbrakeincreasefast,
independentbrakedecrease,
independentbrakedecreasefast,
independentbrakeset,
independentbrakebailoff,
trainbrakeincrease,
trainbrakedecrease,
trainbrakeset,
trainbrakecharging,
trainbrakerelease,
trainbrakefirstservice,
@@ -135,6 +139,12 @@ enum class user_command {
none = -1
};
enum class command_hint {
off,
on,
none = -1
};
enum class command_target {
userinterface,
@@ -163,6 +173,7 @@ struct command_data {
int action; // press, repeat or release
std::uint64_t param1;
std::uint64_t param2;
command_hint hint;
double time_delta;
};
@@ -212,7 +223,8 @@ 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, command_hint const Hint, std::uint16_t const Recipient ) const;
private:
// types
// members

View File

@@ -201,6 +201,7 @@ gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, g
reinterpret_cast<std::uint64_t const &>( turnx ),
reinterpret_cast<std::uint64_t const &>( turny ),
GLFW_PRESS,
command_hint::none,
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
0 );
@@ -218,6 +219,7 @@ gamepad_input::process_axes( glm::vec2 Leftstick, glm::vec2 const &Rightstick, g
reinterpret_cast<std::uint64_t const &>( movex ),
reinterpret_cast<std::uint64_t const &>( movez ),
GLFW_PRESS,
command_hint::none,
0 );
}
}
@@ -247,6 +249,7 @@ gamepad_input::process_mode( float const Value, std::uint16_t const Recipient )
lookup.second,
0, 0,
GLFW_RELEASE,
command_hint::none,
Recipient );
m_modeaccumulator = 0.0f;
}
@@ -260,6 +263,7 @@ gamepad_input::process_mode( float const Value, std::uint16_t const Recipient )
lookup.first,
0, 0,
GLFW_PRESS,
command_hint::none,
Recipient );
m_modeaccumulator -= 1.0f;
}
@@ -271,6 +275,7 @@ gamepad_input::process_mode( float const Value, std::uint16_t const Recipient )
lookup.first,
0, 0,
GLFW_RELEASE,
command_hint::none,
Recipient );
m_modeaccumulator = 0.0f;
}
@@ -284,6 +289,7 @@ gamepad_input::process_mode( float const Value, std::uint16_t const Recipient )
lookup.first,
0, 0,
GLFW_RELEASE,
command_hint::none,
Recipient );
m_modeaccumulator = 0.0f;
}
@@ -297,6 +303,7 @@ gamepad_input::process_mode( float const Value, std::uint16_t const Recipient )
lookup.second,
0, 0,
GLFW_PRESS,
command_hint::none,
Recipient );
m_modeaccumulator += 1.0f;
}
@@ -308,6 +315,7 @@ gamepad_input::process_mode( float const Value, std::uint16_t const Recipient )
lookup.second,
0, 0,
GLFW_RELEASE,
command_hint::none,
Recipient );
m_modeaccumulator = 0.0f;
}

View File

@@ -158,7 +158,7 @@ keyboard_input::key( int const Key, int const Action ) {
// NOTE: basic keyboard controls don't have any parameters
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( lookup->second, 0, 0, Action, 0 );
m_relay.post( lookup->second, 0, 0, Action, command_hint::none, 0 );
return true;
}
@@ -179,6 +179,8 @@ keyboard_input::default_bindings() {
{ GLFW_KEY_KP_SUBTRACT },
// mastercontrollerdecreasefast
{ GLFW_KEY_KP_SUBTRACT | keymodifier::shift },
// mastercontrollerset
{ -1 },
// secondcontrollerincrease
{ GLFW_KEY_KP_DIVIDE },
// secondcontrollerincreasefast
@@ -187,6 +189,8 @@ keyboard_input::default_bindings() {
{ GLFW_KEY_KP_MULTIPLY },
// secondcontrollerdecreasefast
{ GLFW_KEY_KP_MULTIPLY | keymodifier::shift },
// secondcontrollerset
{ -1 },
// mucurrentindicatorothersourceactivate
{ GLFW_KEY_Z | keymodifier::shift },
// independentbrakeincrease
@@ -197,12 +201,16 @@ keyboard_input::default_bindings() {
{ GLFW_KEY_KP_7 },
// independentbrakedecreasefast
{ GLFW_KEY_KP_7 | keymodifier::shift },
// independentbrakeset
{ -1 },
// independentbrakebailoff
{ GLFW_KEY_KP_4 },
// trainbrakeincrease
{ GLFW_KEY_KP_3 },
// trainbrakedecrease
{ GLFW_KEY_KP_9 },
// trainbrakeset
{ -1 },
// trainbrakecharging
{ GLFW_KEY_KP_DECIMAL },
// trainbrakerelease
@@ -481,6 +489,7 @@ keyboard_input::poll() {
reinterpret_cast<std::uint64_t const &>( movexparam ),
reinterpret_cast<std::uint64_t const &>( movezparam ),
GLFW_PRESS,
command_hint::none,
0 );
}
@@ -503,6 +512,7 @@ keyboard_input::poll() {
reinterpret_cast<std::uint64_t const &>( moveyparam ),
0,
GLFW_PRESS,
command_hint::none,
0 );
}

View File

@@ -147,9 +147,6 @@
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Console\MWD.cpp">
<Filter>Source Files\input</Filter>
</ClCompile>
<ClCompile Include="Names.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -237,6 +234,9 @@
<ClCompile Include="utilities.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="uart.cpp">
<Filter>Source Files\input</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Globals.h">
@@ -368,9 +368,6 @@
<ClInclude Include="Driver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Console\MWD.h">
<Filter>Header Files\input</Filter>
</ClInclude>
<ClInclude Include="sun.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -461,6 +458,9 @@
<ClInclude Include="utilities.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="uart.h">
<Filter>Header Files\input</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">

View File

@@ -42,6 +42,7 @@ mouse_input::move( double Mousex, double Mousey ) {
reinterpret_cast<std::uint64_t const &>( Mousex ),
reinterpret_cast<std::uint64_t const &>( Mousey ),
GLFW_PRESS,
command_hint::none,
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
0 );
@@ -60,6 +61,7 @@ mouse_input::move( double Mousex, double Mousey ) {
reinterpret_cast<std::uint64_t const &>( viewoffset.x ),
reinterpret_cast<std::uint64_t const &>( viewoffset.y ),
GLFW_PRESS,
command_hint::none,
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
0 );
@@ -102,7 +104,7 @@ mouse_input::button( int const Button, int const Action ) {
// NOTE: basic keyboard controls don't have any parameters
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( mousecommand, 0, 0, Action, 0 );
m_relay.post( mousecommand, 0, 0, Action, command_hint::none, 0 );
mousecommand = user_command::none;
}
else {
@@ -141,7 +143,7 @@ mouse_input::button( int const Button, int const Action ) {
// NOTE: basic keyboard controls don't have any parameters
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( mousecommand, 0, 0, Action, 0 );
m_relay.post( mousecommand, 0, 0, Action, command_hint::none, 0 );
m_updateaccumulator = -0.25; // prevent potential command repeat right after issuing one
switch( mousecommand ) {
@@ -192,13 +194,13 @@ mouse_input::poll() {
// NOTE: basic keyboard controls don't have any parameters
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( m_mousecommandleft, 0, 0, GLFW_REPEAT, 0 );
m_relay.post( m_mousecommandleft, 0, 0, GLFW_REPEAT, command_hint::none, 0 );
}
if( m_mousecommandright != user_command::none ) {
// NOTE: basic keyboard controls don't have any parameters
// as we haven't yet implemented either item id system or multiplayer, the 'local' controlled vehicle and entity have temporary ids of 0
// TODO: pass correct entity id once the missing systems are in place
m_relay.post( m_mousecommandright, 0, 0, GLFW_REPEAT, 0 );
m_relay.post( m_mousecommandright, 0, 0, GLFW_REPEAT, command_hint::none, 0 );
}
m_updateaccumulator -= updaterate;
}

243
uart.cpp Normal file
View File

@@ -0,0 +1,243 @@
#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");
sp_port_config *config;
if (sp_new_config(&config) != SP_OK ||
sp_set_config_baudrate(config, conf.baud) != SP_OK ||
sp_set_config_flowcontrol(config, SP_FLOWCONTROL_NONE) != SP_OK ||
sp_set_config_bits(config, 8) != SP_OK ||
sp_set_config_stopbits(config, 1) != SP_OK ||
sp_set_config_parity(config, SP_PARITY_NONE) != SP_OK ||
sp_set_config(port, config) != SP_OK)
throw std::runtime_error("uart: cannot set config");
sp_free_config(config);
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()
{
std::array<uint8_t, 31> buffer = { 0 };
sp_blocking_write(port, (void*)buffer.data(), buffer.size(), 0);
sp_drain(port);
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<float>(now - last_update).count() < conf.updatetime)
return;
last_update = now;
auto *t = Global.pWorld->train();
if (!t)
return;
sp_return ret;
if ((ret = sp_input_waiting(port)) >= 16)
{
std::array<uint8_t, 16> 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");
if (conf.debug)
{
char buf[buffer.size() * 3 + 1];
size_t pos = 0;
for (uint8_t b : buffer)
pos += sprintf(&buf[pos], "%02X ", b);
WriteLog("uart: rx: " + std::string(buf));
}
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 = ( (buffer[byte] & (1 << bit)) != 0 );
bool repeat = (type == impulse_r ||
type == impulse_r_off ||
type == impulse_r_on);
bool changed = ( (buffer[ byte ] & (1 << bit)) != (old_packet[ byte ] & (1 << bit)) );
if (!changed && !(repeat && state))
continue;
int action;
command_hint desired_state;
if (type == toggle)
{
action = GLFW_PRESS;
desired_state = ( state ? command_hint::on : command_hint::off );
}
else if (type == impulse_r_on)
{
action = ( state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE );
desired_state = command_hint::on;
}
else if (type == impulse_r_off)
{
action = ( state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE );
desired_state = command_hint::off;
}
else if (type == impulse || type == impulse_r)
{
action = ( state ? (changed ? GLFW_PRESS : GLFW_REPEAT) : GLFW_RELEASE );
desired_state = command_hint::none;
}
relay.post( std::get<1>(entry), 0, 0, action, desired_state, 0 );
}
if( true == conf.mainenable ) {
// master controller
relay.post(
user_command::mastercontrollerset,
buffer[ 6 ],
0,
GLFW_PRESS,
command_hint::none,
// TODO: pass correct entity id once the missing systems are in place
0 );
}
if( true == conf.scndenable ) {
// second controller
relay.post(
user_command::secondcontrollerset,
buffer[ 7 ],
0,
GLFW_PRESS,
command_hint::none,
// TODO: pass correct entity id once the missing systems are in place
0 );
}
if( true == conf.trainenable ) {
// train brake
double const position { (float)( ( (uint16_t)buffer[ 8 ] | ( (uint16_t)buffer[ 9 ] << 8 ) ) - conf.mainbrakemin ) / ( conf.mainbrakemax - conf.mainbrakemin ) };
relay.post(
user_command::trainbrakeset,
reinterpret_cast<std::uint64_t const &>( position ),
0,
GLFW_PRESS,
command_hint::none,
// TODO: pass correct entity id once the missing systems are in place
0 );
}
if( true == conf.localenable ) {
// independent brake
double const position { (float)( ( (uint16_t)buffer[ 10 ] | ( (uint16_t)buffer[ 11 ] << 8 ) ) - conf.localbrakemin ) / ( conf.localbrakemax - conf.localbrakemin ) };
relay.post(
user_command::independentbrakeset,
reinterpret_cast<std::uint64_t const &>( position ),
0,
GLFW_PRESS,
command_hint::none,
// TODO: pass correct entity id once the missing systems are in place
0 );
}
old_packet = buffer;
}
if (!data_pending && sp_output_waiting(port) == 0)
{
// TODO: ugly! move it into structure like input_bits
auto const trainstate = t->get_state();
uint8_t tacho = Global.iPause ? 0 : trainstate.velocity;
uint16_t tank_press = (uint16_t)std::min(conf.tankuart, trainstate.reservoir_pressure * 0.1f / conf.tankmax * conf.tankuart);
uint16_t pipe_press = (uint16_t)std::min(conf.pipeuart, trainstate.pipe_pressure * 0.1f / conf.pipemax * conf.pipeuart);
uint16_t brake_press = (uint16_t)std::min(conf.brakeuart, trainstate.brake_pressure * 0.1f / conf.brakemax * conf.brakeuart);
uint16_t hv_voltage = (uint16_t)std::min(conf.hvuart, trainstate.hv_voltage / conf.hvmax * conf.hvuart);
uint16_t current1 = (uint16_t)std::min(conf.currentuart, trainstate.hv_current[0]) / conf.currentmax * conf.currentuart;
uint16_t current2 = (uint16_t)std::min(conf.currentuart, trainstate.hv_current[1]) / conf.currentmax * conf.currentuart;
uint16_t current3 = (uint16_t)std::min(conf.currentuart, trainstate.hv_current[2]) / conf.currentmax * conf.currentuart;
std::array<uint8_t, 31> buffer {
//byte 0
tacho,
//byte 1
0,
//byte 2
(uint8_t)(
trainstate.motor_resistors << 1
| trainstate.motor_overload_threshold << 2),
//byte 3
0,
//byte 4
(uint8_t)(
trainstate.train_heating << 0
| trainstate.motor_resistors << 1
| trainstate.wheelslip << 2
| trainstate.alerter << 6
| trainstate.shp << 7),
//byte 5
(uint8_t)(
trainstate.motor_connectors << 0
| trainstate.converter_overload << 2
| trainstate.motor_overload << 4
| trainstate.line_breaker << 5
| trainstate.compressor_overload << 6),
//byte 6
(uint8_t)( trainstate.alerter_sound << 7),
SPLIT_INT16(brake_press), //byte 7-8
SPLIT_INT16(pipe_press), //byte 9-10
SPLIT_INT16(tank_press), //byte 11-12
SPLIT_INT16(hv_voltage), //byte 13-14
SPLIT_INT16(current1), //byte 15-16
SPLIT_INT16(current2), //byte 17-18
SPLIT_INT16(current3), //byte 19-20
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //byte 21-30
};
if (conf.debug)
{
char buf[buffer.size() * 3 + 1];
size_t pos = 0;
for (uint8_t b : buffer)
pos += sprintf(&buf[pos], "%02X ", b);
WriteLog("uart: tx: " + std::string(buf));
}
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;
}
}

92
uart.h Normal file
View File

@@ -0,0 +1,92 @@
#pragma once
#include <libserialport.h>
#include "command.h"
class uart_input
{
public:
// types
struct conf_t {
bool enable = false;
std::string port;
int baud;
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;
bool mainenable = true;
bool scndenable = true;
bool trainenable = true;
bool localenable = true;
bool debug = false;
};
// methods
uart_input();
~uart_input();
void poll();
private:
// types
enum input_type_t
{
toggle,
impulse,
impulse_r,
impulse_r_on,
impulse_r_off
};
std::array<std::tuple<size_t, user_command, input_type_t>, 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)
};
// members
sp_port *port = nullptr;
command_relay relay;
std::array<uint8_t, 16> old_packet;
std::chrono::time_point<std::chrono::high_resolution_clock> last_update;
conf_t conf;
bool data_pending = false;
};