16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 12:49:18 +02:00

(uart) add serial ports enumeration and possibility to change at runtime

This commit is contained in:
Marcin Nowak
2021-10-16 22:58:04 +02:00
parent 3f308cf812
commit 0138aa2f41
3 changed files with 81 additions and 10 deletions

View File

@@ -614,6 +614,14 @@ debug_panel::render() {
render_section_settings(); render_section_settings();
#ifdef WITH_UART #ifdef WITH_UART
if(true == render_section( "UART", m_uartlines)) { if(true == render_section( "UART", m_uartlines)) {
int ports_num = Application.uart_status.available_ports.size();
if(ports_num > 0) {
char **avlports = new char*[ports_num];
for (int i=0; i < ports_num; i++) {
avlports[i] = (char *) Application.uart_status.available_ports[i].c_str();
}
ImGui::ListBox("Port", &Application.uart_status.selected_port_index, avlports, ports_num);
}
ImGui::Checkbox("Enabled", &Application.uart_status.enabled); ImGui::Checkbox("Enabled", &Application.uart_status.enabled);
} }
#endif #endif
@@ -1230,24 +1238,26 @@ debug_panel::update_section_scantable( std::vector<text_line> &Output ) {
#ifdef WITH_UART #ifdef WITH_UART
void void
debug_panel::update_section_uart( std::vector<text_line> &Output ) { debug_panel::update_section_uart( std::vector<text_line> &Output ) {
UartStatus *status = &Application.uart_status;
Output.emplace_back( Output.emplace_back(
("Port: " + Application.uart_status.port_name).c_str(), ("Port: " + status->port_name).c_str(),
Global.UITextColor Global.UITextColor
); );
Output.emplace_back( Output.emplace_back(
("Baud: " + std::to_string(Application.uart_status.baud)).c_str(), ("Baud: " + std::to_string(status->baud)).c_str(),
Global.UITextColor Global.UITextColor
); );
if(Application.uart_status.is_connected) { if(status->is_connected) {
std::string synctext = Application.uart_status.is_synced ? "SYNCED" : "NOT SYNCED"; std::string synctext = status->is_synced ? "SYNCED" : "NOT SYNCED";
Output.emplace_back(("CONNECTED, " + synctext).c_str(), Global.UITextColor); Output.emplace_back(("CONNECTED, " + synctext).c_str(), Global.UITextColor);
} else { } else {
Output.emplace_back("* NOT CONNECTED *", Global.UITextColor); Output.emplace_back("* NOT CONNECTED *", Global.UITextColor);
} }
Output.emplace_back( Output.emplace_back(
( (
"Packets sent: "+std::to_string(Application.uart_status.packets_sent) "Packets sent: "+std::to_string(status->packets_sent)
+" Packets received: "+std::to_string(Application.uart_status.packets_received) +" Packets received: "+std::to_string(status->packets_received)
).c_str(), ).c_str(),
Global.UITextColor Global.UITextColor
); );

View File

@@ -23,8 +23,39 @@ uart_input::uart_input()
last_setup = std::chrono::high_resolution_clock::now(); last_setup = std::chrono::high_resolution_clock::now();
} }
void uart_input::enumerate_ports() {
UartStatus *status = &Application.uart_status;
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 enumerate serial ports");
}
last_enumeration = std::chrono::high_resolution_clock::now();
}
bool uart_input::setup_port() bool uart_input::setup_port()
{ {
UartStatus *status = &Application.uart_status;
if(!port) {
enumerate_ports();
}
if (port) { if (port) {
sp_close(port); sp_close(port);
sp_free_port(port); sp_free_port(port);
@@ -32,12 +63,17 @@ bool uart_input::setup_port()
} }
last_setup = std::chrono::high_resolution_clock::now(); last_setup = std::chrono::high_resolution_clock::now();
UartStatus *status = &Application.uart_status;
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;
}
if (sp_get_port_by_name(status->port_name.c_str(), &port) != SP_OK) { if (sp_get_port_by_name(status->port_name.c_str(), &port) != SP_OK) {
if(!error_notified) { if(!error_notified) {
status->is_connected = false; status->is_connected = false;
ErrorLog("uart: cannot find specified port '"+conf.port+"'"); ErrorLog("uart: cannot find specified port '"+conf.port+"'");
enumerate_ports();
} }
error_notified = true; error_notified = true;
return false; return false;
@@ -47,6 +83,7 @@ bool uart_input::setup_port()
if(!error_notified) { if(!error_notified) {
status->is_connected = false; status->is_connected = false;
ErrorLog("uart: cannot open port '"+status->port_name+"'"); ErrorLog("uart: cannot open port '"+status->port_name+"'");
enumerate_ports();
} }
error_notified = true; error_notified = true;
port = nullptr; port = nullptr;
@@ -68,6 +105,7 @@ bool uart_input::setup_port()
} }
error_notified = true; error_notified = true;
port = nullptr; port = nullptr;
enumerate_ports();
return false; return false;
} }
@@ -80,6 +118,7 @@ bool uart_input::setup_port()
} }
error_notified = true; error_notified = true;
port = nullptr; port = nullptr;
enumerate_ports();
return false; return false;
} }
@@ -187,26 +226,43 @@ uart_input::recall_bindings() {
void uart_input::poll() void uart_input::poll()
{ {
if(!Application.uart_status.enabled) { UartStatus *status = &Application.uart_status;
auto now = std::chrono::high_resolution_clock::now();
if(status->selected_port_index >= 0 && status->active_port_index != status->selected_port_index) {
status->port_name = status->available_ports[status->selected_port_index];
setup_port();
}
if (
(!port && std::chrono::duration<float>(now - last_enumeration).count() > 1.0)
|| (port && std::chrono::duration<float>(now - last_enumeration).count() > 5.0)
) {
enumerate_ports();
}
if(!status->enabled) {
if(port) { if(port) {
sp_close(port); sp_close(port);
sp_free_port(port); sp_free_port(port);
port = nullptr; port = nullptr;
} }
Application.uart_status.is_connected = false; status->is_connected = false;
return; return;
} }
auto now = std::chrono::high_resolution_clock::now();
if (std::chrono::duration<float>(now - last_update).count() < conf.updatetime) if (std::chrono::duration<float>(now - last_update).count() < conf.updatetime)
return; return;
last_update = now; last_update = now;
/* if connection error occured, slow down reconnection tries */ /* if connection error occured, slow down reconnection tries */
if (!port && error_notified && std::chrono::duration<float>(now - last_setup).count() < 1.0) { if (!port && error_notified && std::chrono::duration<float>(now - last_setup).count() < 1.0) {
return; return;
} }
if (!port) { if (!port) {
setup_port(); setup_port();
return; return;

5
uart.h
View File

@@ -6,6 +6,9 @@
class UartStatus { class UartStatus {
public: public:
std::string port_name = ""; std::string port_name = "";
std::vector<std::string> available_ports = {};
int selected_port_index = -1;
int active_port_index = -1;
int baud = 0; int baud = 0;
bool enabled = false; bool enabled = false;
bool is_connected = false; bool is_connected = false;
@@ -79,6 +82,7 @@ private:
using inputpin_sequence = std::vector<input_pin_t>; using inputpin_sequence = std::vector<input_pin_t>;
bool setup_port(); bool setup_port();
void enumerate_ports();
// members // members
sp_port *port = nullptr; sp_port *port = nullptr;
@@ -87,6 +91,7 @@ private:
std::array<std::uint8_t, 16> old_packet; // TBD, TODO: replace with vector of configurable size? 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_update;
std::chrono::time_point<std::chrono::high_resolution_clock> last_setup; std::chrono::time_point<std::chrono::high_resolution_clock> last_setup;
std::chrono::time_point<std::chrono::high_resolution_clock> last_enumeration;
conf_t conf; conf_t conf;
bool data_pending = false; bool data_pending = false;
bool error_notified = false; bool error_notified = false;