-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserial.cpp
More file actions
114 lines (104 loc) · 3.42 KB
/
Copy pathserial.cpp
File metadata and controls
114 lines (104 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <serialib.h>
#include <XPLMUtilities.h>
#include <cstdint>
#include <thread>
#include <future>
#include <vector>
#include <string>
#include <format>
#include <thread>
#include <optional>
#include "main.hpp"
#include "serial.hpp"
#include "ui.hpp"
#include "remote.hpp"
#include "telemetry.hpp"
#define SCAN_TIMEOUT 3000
#define SCAN_MAXBYTES 200
namespace Serial {
serialib serial;
int Available() { return serial.available(); };
bool IsOpen() { return serial.isDeviceOpen(); };
void Error(std::string what);
void Connect(std::string port);
char ping_msg[] = "PINGHITLPINGHITLPING";
std::stop_source stop_scan;
std::future<std::optional<std::string>> port_future;
}
void Serial::StopScan() {
if (!stop_scan.stop_possible()) { return; }
stop_scan.request_stop();
}
void Serial::Scan() {
if (!port_future.valid()) {
stop_scan = std::stop_source{};
port_future = std::async(std::launch::async,
[]() -> std::optional<std::string> {
int i = 0;
while (true) {
i++;
if (i > MAX_SERIAL_PORTS) { i = 1; }
if (stop_scan.stop_requested()) { return std::optional<std::string>(); }
// Attempt connection
serialib temp_serial;
std::string device = std::format("\\\\.\\COM{}", i);
if (temp_serial.openDevice(device.c_str(), BAUD_RATE) != 1) { continue; }
temp_serial.setDTR();
temp_serial.clearRTS();
// Scan for header
char c;
int pos = 0;
int bytes_read = 0;
while (bytes_read < SCAN_MAXBYTES && temp_serial.readBytes(&c, 1, SCAN_TIMEOUT) == 1) {
bytes_read++;
if (c == ping_msg[pos]) { pos++; } else { pos = 0; };
if (pos == sizeof(ping_msg)) {
// Header found, return device name
temp_serial.closeDevice();
return std::optional<std::string>(device);
}
}
}
});
}
if (!port_future.valid()) { return; }
if (port_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready) { return; }
std::optional<std::string> port = port_future.get();
if (port.has_value()) {
Connect(port.value());
}
}
void Serial::Connect(std::string port) {
if (serial.openDevice(port.c_str(), BAUD_RATE) != 1) { return; };
serial.setDTR();
serial.clearRTS();
XPLMDebugString(std::format("HITL: Connected to {}\n", port).c_str());
Remote::UpdateDataRefs();
UI::OnSerialConnect(port);
}
void Serial::Disconnect() {
if (IsOpen()) {
serial.closeDevice();
UI::OnSerialDisconnect();
}
Remote::UpdateDataRefs();
}
void Serial::Send(void *buffer, size_t bytes) {
if (IsOpen()) {
if (serial.writeBytes(buffer, bytes) == -1) {
Error("Failed to write");
}
}
}
bool Serial::Read(uint8_t *dest) {
if (!IsOpen()) { return false; }
if (serial.readBytes(dest, 1) <= 0) {
Error("Failed to read");
return false;
}
return true;
}
void Serial::Error(std::string what) {
XPLMDebugString(std::format("HITL: Serial error {}.\n", what).c_str());
Disconnect();
}