mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
Merge pull request #15 from marcinn/feature/milek7-uart
Usprawnienia UART
This commit is contained in:
@@ -13,6 +13,9 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "PyInt.h"
|
||||
#include "network/manager.h"
|
||||
#include "headtrack.h"
|
||||
#ifdef WITH_UART
|
||||
#include "uart.h"
|
||||
#endif
|
||||
|
||||
class eu07_application {
|
||||
const int MAX_NETWORK_PER_FRAME = 1000;
|
||||
|
||||
@@ -140,7 +140,7 @@ driver_mode::drivermode_input::command_fallback( user_command const Command ) co
|
||||
if( lookup == commandfallbacks.end() ) {
|
||||
return { user_command::none, user_command::none };
|
||||
}
|
||||
|
||||
|
||||
return lookup->second;
|
||||
}
|
||||
|
||||
@@ -600,7 +600,7 @@ driver_mode::update_camera( double const Deltatime ) {
|
||||
// debug camera
|
||||
DebugCamera.Update();
|
||||
}
|
||||
|
||||
|
||||
// reset window state, it'll be set again if applicable in a check below
|
||||
Global.CabWindowOpen = false;
|
||||
|
||||
@@ -801,7 +801,7 @@ driver_mode::OnKeyDown(int cKey) {
|
||||
switch (cKey) {
|
||||
|
||||
case GLFW_KEY_F4: {
|
||||
if( Global.shiftState ) { ExternalView(); } // with Shift, cycle through external views
|
||||
if( Global.shiftState ) { ExternalView(); } // with Shift, cycle through external views
|
||||
else { InOutKey(); } // without, step out of the cab or return to it
|
||||
break;
|
||||
}
|
||||
@@ -826,7 +826,7 @@ driver_mode::OnKeyDown(int cKey) {
|
||||
}
|
||||
case GLFW_KEY_F6: {
|
||||
// przyspieszenie symulacji do testowania scenerii... uwaga na FPS!
|
||||
if( DebugModeFlag ) {
|
||||
if( DebugModeFlag ) {
|
||||
|
||||
if( Global.ctrlState ) { Global.fTimeSpeed = ( Global.shiftState ? 60.0 : 20.0 ); }
|
||||
else { Global.fTimeSpeed = ( Global.shiftState ? 5.0 : Global.default_timespeed ); }
|
||||
@@ -883,7 +883,7 @@ driver_mode::DistantView( bool const Near ) {
|
||||
( simulation::Train != nullptr ) ?
|
||||
simulation::Train->Dynamic() :
|
||||
pDynamicNearest ) };
|
||||
|
||||
|
||||
if( vehicle == nullptr ) { return; }
|
||||
|
||||
auto const cab =
|
||||
@@ -1049,7 +1049,7 @@ driver_mode::CabView() {
|
||||
m_externalview = false;
|
||||
|
||||
// likwidacja obrotów - patrzy horyzontalnie na południe
|
||||
Camera.Reset();
|
||||
Camera.Reset();
|
||||
|
||||
// bind camera with the vehicle
|
||||
Camera.m_owner = train->Dynamic();
|
||||
|
||||
@@ -116,7 +116,7 @@ driver_ui::on_key( int const Key, int const Action ) {
|
||||
}
|
||||
|
||||
switch (Key) {
|
||||
|
||||
|
||||
case GLFW_KEY_TAB: {
|
||||
m_mappanel.is_open = !m_mappanel.is_open;
|
||||
|
||||
@@ -130,7 +130,7 @@ driver_ui::on_key( int const Key, int const Action ) {
|
||||
( m_aidpanel.is_expanded == false ) ? 1 :
|
||||
2 );
|
||||
state = clamp_circular( ++state, 3 );
|
||||
|
||||
|
||||
m_aidpanel.is_open = ( state > 0 );
|
||||
m_aidpanel.is_expanded = ( state > 1 );
|
||||
|
||||
@@ -144,7 +144,7 @@ driver_ui::on_key( int const Key, int const Action ) {
|
||||
( m_timetablepanel.is_expanded == false ) ? 1 :
|
||||
2 );
|
||||
state = clamp_circular( ++state, 3 );
|
||||
|
||||
|
||||
m_timetablepanel.is_open = ( state > 0 );
|
||||
m_timetablepanel.is_expanded = ( state > 1 );
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ http://mozilla.org/MPL/2.0/.
|
||||
#define DRIVER_HINT_CONTENT
|
||||
#include "driverhints.h"
|
||||
|
||||
#ifdef WITH_UART
|
||||
#include "uart.h"
|
||||
#endif
|
||||
|
||||
void
|
||||
drivingaid_panel::update() {
|
||||
|
||||
@@ -548,6 +552,9 @@ debug_panel::update() {
|
||||
m_powergridlines.clear();
|
||||
m_cameralines.clear();
|
||||
m_rendererlines.clear();
|
||||
#ifdef WITH_UART
|
||||
m_uartlines.clear();
|
||||
#endif
|
||||
|
||||
update_section_vehicle( m_vehiclelines );
|
||||
update_section_engine( m_enginelines );
|
||||
@@ -558,6 +565,9 @@ debug_panel::update() {
|
||||
update_section_powergrid( m_powergridlines );
|
||||
update_section_camera( m_cameralines );
|
||||
update_section_renderer( m_rendererlines );
|
||||
#ifdef WITH_UART
|
||||
update_section_uart(m_uartlines);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -610,6 +620,18 @@ debug_panel::render() {
|
||||
render_section( "Camera", m_cameralines );
|
||||
render_section( "Gfx Renderer", m_rendererlines );
|
||||
render_section_settings();
|
||||
#ifdef WITH_UART
|
||||
if(true == render_section( "UART", m_uartlines)) {
|
||||
int ports_num = UartStatus.available_ports.size();
|
||||
char **avlports = new char*[ports_num];
|
||||
for (int i=0; i < ports_num; i++) {
|
||||
avlports[i] = (char *) UartStatus.available_ports[i].c_str();
|
||||
}
|
||||
ImGui::Combo("Port", &UartStatus.selected_port_index, avlports, ports_num);
|
||||
ImGui::Combo("Baud", &UartStatus.selected_baud_index, uart_baudrates_list, uart_baudrates_list_num);
|
||||
ImGui::Checkbox("Enabled", &UartStatus.enabled);
|
||||
}
|
||||
#endif
|
||||
// toggles
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox( "Debug Mode", &DebugModeFlag );
|
||||
@@ -1213,6 +1235,35 @@ debug_panel::update_section_scantable( std::vector<text_line> &Output ) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_UART
|
||||
void
|
||||
debug_panel::update_section_uart( std::vector<text_line> &Output ) {
|
||||
uart_status *status = &UartStatus;
|
||||
|
||||
Output.emplace_back(
|
||||
("Port: " + status->port_name).c_str(),
|
||||
Global.UITextColor
|
||||
);
|
||||
Output.emplace_back(
|
||||
("Baud: " + std::to_string(status->baud)).c_str(),
|
||||
Global.UITextColor
|
||||
);
|
||||
if(status->is_connected) {
|
||||
std::string synctext = status->is_synced ? "SYNCED" : "NOT SYNCED";
|
||||
Output.emplace_back(("CONNECTED, " + synctext).c_str(), Global.UITextColor);
|
||||
} else {
|
||||
Output.emplace_back("* NOT CONNECTED *", Global.UITextColor);
|
||||
}
|
||||
Output.emplace_back(
|
||||
(
|
||||
"Packets sent: "+std::to_string(status->packets_sent)
|
||||
+" Packets received: "+std::to_string(status->packets_received)
|
||||
).c_str(),
|
||||
Global.UITextColor
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
debug_panel::update_section_scenario( std::vector<text_line> &Output ) {
|
||||
|
||||
|
||||
@@ -89,6 +89,9 @@ private:
|
||||
void update_section_powergrid( std::vector<text_line> &Output );
|
||||
void update_section_camera( std::vector<text_line> &Output );
|
||||
void update_section_renderer( std::vector<text_line> &Output );
|
||||
#ifdef WITH_UART
|
||||
void update_section_uart( std::vector<text_line> &Output );
|
||||
#endif
|
||||
// section update helpers
|
||||
std::string update_vehicle_coupler( int const Side );
|
||||
std::string update_vehicle_brake() const;
|
||||
@@ -97,6 +100,9 @@ private:
|
||||
bool render_section( std::vector<text_line> const &Lines );
|
||||
bool render_section_scenario();
|
||||
bool render_section_eventqueue();
|
||||
#ifdef WITH_UART
|
||||
bool render_section_uart();
|
||||
#endif
|
||||
bool render_section_settings();
|
||||
// members
|
||||
std::array<char, 1024> m_buffer;
|
||||
@@ -111,7 +117,8 @@ private:
|
||||
m_scenariolines,
|
||||
m_eventqueuelines,
|
||||
m_powergridlines,
|
||||
m_rendererlines;
|
||||
m_rendererlines,
|
||||
m_uartlines;
|
||||
|
||||
double last_time = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
|
||||
186
uart.cpp
186
uart.cpp
@@ -7,33 +7,121 @@
|
||||
#include "parser.h"
|
||||
#include "Logs.h"
|
||||
#include "simulationtime.h"
|
||||
#include "application.h"
|
||||
|
||||
const char* uart_baudrates_list[] = {
|
||||
"300",
|
||||
"1200",
|
||||
"2400",
|
||||
"4800",
|
||||
"9600",
|
||||
"19200",
|
||||
"38400",
|
||||
"57600",
|
||||
"74880",
|
||||
"115200",
|
||||
"230400",
|
||||
"250000",
|
||||
"500000",
|
||||
"1000000",
|
||||
"2000000"
|
||||
};
|
||||
|
||||
const size_t uart_baudrates_list_num = (
|
||||
sizeof(uart_baudrates_list)/sizeof(uart_baudrates_list[0])
|
||||
);
|
||||
|
||||
void uart_status::reset_stats() {
|
||||
packets_sent = 0;
|
||||
packets_received = 0;
|
||||
}
|
||||
|
||||
uart_status UartStatus;
|
||||
|
||||
uart_input::uart_input()
|
||||
{
|
||||
conf = Global.uart_conf;
|
||||
uart_status *status = &UartStatus;
|
||||
|
||||
if (!setup_port())
|
||||
throw std::runtime_error("uart: cannot open port");
|
||||
status->enabled = conf.enable;
|
||||
status->port_name = conf.port;
|
||||
status->baud = conf.baud;
|
||||
|
||||
const std::string baudStr = std::to_string(status->baud);
|
||||
|
||||
for(int i=0;i<uart_baudrates_list_num;i++) {
|
||||
if(baudStr == uart_baudrates_list[i]) {
|
||||
status->selected_baud_index = i;
|
||||
status->active_port_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
old_packet.fill(0);
|
||||
last_update = std::chrono::high_resolution_clock::now();
|
||||
last_setup = std::chrono::high_resolution_clock::now();
|
||||
|
||||
find_ports();
|
||||
}
|
||||
|
||||
void uart_input::find_ports() {
|
||||
uart_status *status = &UartStatus;
|
||||
|
||||
struct sp_port **ports;
|
||||
if (sp_list_ports(&ports) == SP_OK) {
|
||||
status->available_ports.clear();
|
||||
status->active_port_index = -1;
|
||||
status->selected_port_index = -1;
|
||||
for (int i=0; ports[i]; i++) {
|
||||
std::string newport = std::string(sp_get_port_name(ports[i]));
|
||||
status->available_ports.emplace_back(newport);
|
||||
if(newport == status->port_name) {
|
||||
status->active_port_index = i;
|
||||
status->selected_port_index = i;
|
||||
}
|
||||
}
|
||||
if(status->selected_port_index > status->available_ports.size()) {
|
||||
status->selected_port_index = -1;
|
||||
}
|
||||
sp_free_port_list(ports);
|
||||
} else {
|
||||
WriteLog("uart: cannot read serial ports list");
|
||||
}
|
||||
last_port_find = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
bool uart_input::setup_port()
|
||||
{
|
||||
uart_status *status = &UartStatus;
|
||||
|
||||
if(!port) {
|
||||
find_ports();
|
||||
}
|
||||
if (port) {
|
||||
sp_close(port);
|
||||
sp_free_port(port);
|
||||
port = nullptr;
|
||||
}
|
||||
|
||||
if (sp_get_port_by_name(conf.port.c_str(), &port) != SP_OK) {
|
||||
ErrorLog("uart: cannot find specified port");
|
||||
last_setup = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (sp_get_port_by_name(status->port_name.c_str(), &port) != SP_OK) {
|
||||
if(!error_notified) {
|
||||
status->is_connected = false;
|
||||
ErrorLog("uart: cannot find specified port '"+conf.port+"'");
|
||||
find_ports();
|
||||
}
|
||||
error_notified = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sp_open(port, (sp_mode)(SP_MODE_READ | SP_MODE_WRITE)) != SP_OK) {
|
||||
ErrorLog("uart: cannot open port");
|
||||
if(!error_notified) {
|
||||
status->is_connected = false;
|
||||
ErrorLog("uart: cannot open port '"+status->port_name+"'");
|
||||
find_ports();
|
||||
}
|
||||
error_notified = true;
|
||||
port = nullptr;
|
||||
return false;
|
||||
}
|
||||
@@ -41,25 +129,43 @@ bool uart_input::setup_port()
|
||||
sp_port_config *config;
|
||||
|
||||
if (sp_new_config(&config) != SP_OK ||
|
||||
sp_set_config_baudrate(config, conf.baud) != SP_OK ||
|
||||
sp_set_config_baudrate(config, status->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) {
|
||||
ErrorLog("uart: cannot set config");
|
||||
if(!error_notified) {
|
||||
status->is_connected = false;
|
||||
ErrorLog("uart: cannot set config");
|
||||
}
|
||||
error_notified = true;
|
||||
port = nullptr;
|
||||
find_ports();
|
||||
return false;
|
||||
}
|
||||
|
||||
sp_free_config(config);
|
||||
|
||||
if (sp_flush(port, SP_BUF_BOTH) != SP_OK) {
|
||||
ErrorLog("uart: cannot flush");
|
||||
if(!error_notified) {
|
||||
status->is_connected = false;
|
||||
ErrorLog("uart: cannot flush");
|
||||
}
|
||||
error_notified = true;
|
||||
port = nullptr;
|
||||
find_ports();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(error_notified || ! status->is_connected) {
|
||||
error_notified = false;
|
||||
ErrorLog("uart: connected to '"+status->port_name+"'");
|
||||
status->reset_stats();
|
||||
status->is_connected = true;
|
||||
data_pending = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -158,11 +264,55 @@ uart_input::recall_bindings() {
|
||||
|
||||
void uart_input::poll()
|
||||
{
|
||||
uart_status *status = &UartStatus;
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
/* handle baud change */
|
||||
if(status->active_baud_index != status->selected_baud_index) {
|
||||
status->baud = std::stoul(uart_baudrates_list[status->selected_baud_index]);
|
||||
status->active_baud_index = status->selected_baud_index;
|
||||
status->reset_stats();
|
||||
status->is_connected = false;
|
||||
setup_port();
|
||||
}
|
||||
|
||||
/* handle port change */
|
||||
if(status->available_ports.size() > 0 && status->selected_port_index >= 0 && status->active_port_index != status->selected_port_index) {
|
||||
status->port_name = status->available_ports[status->selected_port_index];
|
||||
status->active_port_index = status->selected_port_index;
|
||||
status->reset_stats();
|
||||
status->is_connected = false;
|
||||
setup_port();
|
||||
}
|
||||
|
||||
if (
|
||||
(!port && std::chrono::duration<float>(now - last_port_find).count() > 1.0)
|
||||
|| (port && std::chrono::duration<float>(now - last_port_find).count() > 5.0)
|
||||
) {
|
||||
find_ports();
|
||||
}
|
||||
|
||||
if(!status->enabled) {
|
||||
if(port) {
|
||||
sp_close(port);
|
||||
sp_free_port(port);
|
||||
port = nullptr;
|
||||
}
|
||||
status->is_connected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::chrono::duration<float>(now - last_update).count() < conf.updatetime)
|
||||
return;
|
||||
last_update = now;
|
||||
|
||||
|
||||
/* if connection error occured, slow down reconnection tries */
|
||||
if (!port && error_notified && std::chrono::duration<float>(now - last_setup).count() < 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!port) {
|
||||
setup_port();
|
||||
return;
|
||||
@@ -173,29 +323,31 @@ void uart_input::poll()
|
||||
return;
|
||||
|
||||
sp_return ret;
|
||||
|
||||
|
||||
if ((ret = sp_input_waiting(port)) >= 20)
|
||||
{
|
||||
std::array<uint8_t, 20> tmp_buffer; // TBD, TODO: replace with vector of configurable size?
|
||||
ret = sp_blocking_read(port, (void*)tmp_buffer.data(), tmp_buffer.size(), 0);
|
||||
|
||||
|
||||
if (ret < 0) {
|
||||
setup_port();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool sync;
|
||||
if (tmp_buffer[0] != 0xEF || tmp_buffer[1] != 0xEF || tmp_buffer[2] != 0xEF || tmp_buffer[3] != 0xEF) {
|
||||
UartStatus.is_synced = false;
|
||||
if (conf.debug)
|
||||
WriteLog("uart: bad sync");
|
||||
sync = false;
|
||||
}
|
||||
else {
|
||||
UartStatus.is_synced = true;
|
||||
if (conf.debug)
|
||||
WriteLog("uart: sync ok");
|
||||
sync = true;
|
||||
}
|
||||
|
||||
|
||||
if (!sync) {
|
||||
int sync_cnt = 0;
|
||||
int sync_fail = 0;
|
||||
@@ -231,9 +383,10 @@ void uart_input::poll()
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::array<uint8_t, 16> buffer;
|
||||
memmove(&buffer[0], &tmp_buffer[4], 16);
|
||||
UartStatus.packets_received++;
|
||||
|
||||
if (conf.debug)
|
||||
{
|
||||
@@ -456,7 +609,12 @@ void uart_input::poll()
|
||||
setup_port();
|
||||
return;
|
||||
}
|
||||
UartStatus.packets_sent++;
|
||||
|
||||
data_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool uart_input::is_connected() {
|
||||
return (port != nullptr);
|
||||
}
|
||||
|
||||
31
uart.h
31
uart.h
@@ -3,6 +3,27 @@
|
||||
#include <libserialport.h>
|
||||
#include "command.h"
|
||||
|
||||
extern const char* uart_baudrates_list[];
|
||||
extern const size_t uart_baudrates_list_num;
|
||||
|
||||
class uart_status {
|
||||
public:
|
||||
std::string port_name = "";
|
||||
std::vector<std::string> available_ports = {};
|
||||
int selected_port_index = -1;
|
||||
int selected_baud_index = -1;
|
||||
int active_port_index = -1;
|
||||
int active_baud_index = -1;
|
||||
int baud = 0;
|
||||
bool enabled = false;
|
||||
bool is_connected = false;
|
||||
bool is_synced = false;
|
||||
unsigned long packets_sent = 0;
|
||||
unsigned long packets_received = 0;
|
||||
|
||||
void reset_stats();
|
||||
};
|
||||
|
||||
class uart_input
|
||||
{
|
||||
public:
|
||||
@@ -52,6 +73,8 @@ public:
|
||||
recall_bindings();
|
||||
void
|
||||
poll();
|
||||
bool
|
||||
is_connected();
|
||||
|
||||
private:
|
||||
// types
|
||||
@@ -64,8 +87,9 @@ private:
|
||||
|
||||
using input_pin_t = std::tuple<std::size_t, input_type_t, user_command, user_command>;
|
||||
using inputpin_sequence = std::vector<input_pin_t>;
|
||||
|
||||
|
||||
bool setup_port();
|
||||
void find_ports();
|
||||
|
||||
// members
|
||||
sp_port *port = nullptr;
|
||||
@@ -73,7 +97,12 @@ private:
|
||||
command_relay relay;
|
||||
std::array<std::uint8_t, 16> old_packet; // TBD, TODO: replace with vector of configurable size?
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> last_update;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> last_setup;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> last_port_find;
|
||||
conf_t conf;
|
||||
bool data_pending = false;
|
||||
bool error_notified = false;
|
||||
std::uint8_t m_trainstatecab { 0 }; // helper, keeps track of last active cab. 0: front cab, 1: rear cab
|
||||
};
|
||||
|
||||
extern uart_status UartStatus;
|
||||
|
||||
Reference in New Issue
Block a user