MC Protocol Serial C++ 0.2.3
MC protocol serial library for MCU-oriented environments
Loading...
Searching...
No Matches
mcu_async_batch_read.cpp
Go to the documentation of this file.
1#include <array>
2#include <cstddef>
3#include <cstdint>
4#include <cstdio>
5#include <cstring>
6
9
10namespace {
11
23
24struct ExampleApp {
25 MelsecSerialClient client;
26 std::array<std::uint16_t, 2> out_words {};
27 std::array<std::byte, mcprotocol::serial::kMaxResponseFrameBytes> rx_chunk {};
28 std::size_t rx_chunk_size = 0;
29 bool tx_started = false;
30 bool tx_completed = false;
31 bool rx_ready = false;
32 bool request_done = false;
33 Status completion_status {};
34};
35
36ProtocolConfig make_protocol() {
37 ProtocolConfig config;
38 config.frame_kind = FrameKind::C4;
39 config.code_mode = CodeMode::Ascii;
40 config.ascii_format = AsciiFormat::Format4;
41 config.target_series = PlcSeries::Q_L;
42 config.sum_check_enabled = false;
43 config.route = RouteConfig {
44 .kind = RouteKind::HostStation,
45 .station_no = 0x00,
46 .network_no = 0x00,
47 .pc_no = 0xFF,
48 .request_destination_module_io_no = 0x03FF,
49 .request_destination_module_station_no = 0x00,
50 .self_station_enabled = false,
51 .self_station_no = 0x00,
52 };
53 return config;
54}
55
56void on_request_complete(void* user, Status status) {
57 auto* app = static_cast<ExampleApp*>(user);
58 app->request_done = true;
59 app->completion_status = status;
60}
61
62void uart_start_tx_async(ExampleApp& app, std::span<const std::byte> frame) {
63 (void)frame;
64 app.tx_started = true;
65}
66
67void simulate_plc_response(ExampleApp& app, const ProtocolConfig& config) {
68 const std::array<std::uint8_t, 8> response_data {'1', '2', '3', '4', '5', '6', '7', '8'};
69 std::array<std::uint8_t, mcprotocol::serial::kMaxResponseFrameBytes> response_frame {};
70 std::size_t response_frame_size = 0;
71 const Status status = FrameCodec::encode_success_response(
72 config,
73 std::span<const std::uint8_t>(response_data.data(), response_data.size()),
74 response_frame,
75 response_frame_size);
76 if (!status.ok()) {
77 app.request_done = true;
78 app.completion_status = status;
79 return;
80 }
81
82 std::memcpy(app.rx_chunk.data(), response_frame.data(), response_frame_size);
83 app.rx_chunk_size = response_frame_size;
84 app.rx_ready = true;
85}
86
87} // namespace
88
89int main() {
90 ExampleApp app;
91 const ProtocolConfig config = make_protocol();
92
93 Status status = app.client.configure(config);
94 if (!status.ok()) {
95 std::fprintf(stderr, "configure failed: %s\n", status.message);
96 return 1;
97 }
98
99 status = app.client.async_batch_read_words(
100 0,
101 BatchReadWordsRequest {
102 .head_device = {.code = mcprotocol::serial::DeviceCode::D, .number = 100},
103 .points = static_cast<std::uint16_t>(app.out_words.size()),
104 },
105 std::span<std::uint16_t>(app.out_words.data(), app.out_words.size()),
106 on_request_complete,
107 &app);
108 if (!status.ok()) {
109 std::fprintf(stderr, "request start failed: %s\n", status.message);
110 return 1;
111 }
112
113 uart_start_tx_async(app, app.client.pending_tx_frame());
114
115 for (std::uint32_t tick = 1; tick <= 4 && !app.request_done; ++tick) {
116 if (app.tx_started && !app.tx_completed) {
117 status = app.client.notify_tx_complete(tick);
118 if (!status.ok()) {
119 std::fprintf(stderr, "notify_tx_complete failed: %s\n", status.message);
120 return 1;
121 }
122 app.tx_completed = true;
123 simulate_plc_response(app, config);
124 }
125
126 if (app.rx_ready) {
127 app.client.on_rx_bytes(
128 tick,
129 std::span<const std::byte>(app.rx_chunk.data(), app.rx_chunk_size));
130 app.rx_ready = false;
131 }
132
133 app.client.poll(tick);
134 }
135
136 if (!app.request_done || !app.completion_status.ok()) {
137 std::fprintf(stderr, "request did not complete successfully\n");
138 return 1;
139 }
140
141 if (app.out_words[0] != 0x1234U || app.out_words[1] != 0x5678U) {
142 std::fprintf(stderr, "unexpected read data: %04X %04X\n", app.out_words[0], app.out_words[1]);
143 return 1;
144 }
145
146 std::printf("example read ok: D100=0x%04X D101=0x%04X\n", app.out_words[0], app.out_words[1]);
147 return 0;
148}
Frame-level encode/decode helper for complete serial MC frames.
Definition codec.hpp:80
Asynchronous MC protocol client for UART / serial integrations.
Definition client.hpp:37
Asynchronous request-execution state machine for serial MC protocol traffic.
int main()
RouteKind
Route layout inside the request header.
Definition types.hpp:190
FrameKind
MC protocol frame family used on the serial link.
Definition types.hpp:147
CodeMode
Request/response payload encoding.
Definition types.hpp:161
AsciiFormat
ASCII formatting variant for C4 / C3 / C2 serial frames.
Definition types.hpp:169
PlcSeries
PLC family selection used for subcommand and device-layout differences.
Definition types.hpp:181
Top-level protocol configuration shared by codecs and client requests.
Definition types.hpp:323
Route header fields for serial MC requests.
Definition types.hpp:296
Result object returned by most public APIs.
Definition status.hpp:26