mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 13:59:19 +02:00
(uart) add serial ports enumeration and possibility to change at runtime
This commit is contained in:
@@ -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
|
||||||
);
|
);
|
||||||
|
|||||||
64
uart.cpp
64
uart.cpp
@@ -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
5
uart.h
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user