ether2ser 0.1.0
Ethernet <-> synchronous V.24 bridge firmware for RP2040 + W5500
Loading...
Searching...
No Matches
event_dispatch.c
Go to the documentation of this file.
1/*
2 * ether2ser - Ethernet <-> synchronous V.24 (RS-232/V.28) bridge
3 *
4 * File: src/system/event_dispatch.c
5 * Purpose: Event dispatcher handlers for CLI, status, and configuration events.
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Copyright (c) 2026 Florian <f.leuze@outlook.de>
10 */
11
12// Related headers
14
15// Standard library headers
16#include <inttypes.h>
17#include <stdbool.h>
18#include <stdint.h>
19#include <stdio.h>
20#include <string.h>
21
22// Library Headers
23#include "pico/time.h"
24#include "wizchip_conf.h"
25#include "wizchip_qspi_pio.h"
26
27// Project Headers
29#include "drivers/tx_queue.h"
30#include "drivers/v24_config.h"
32#include "platform/watchdog.h"
35#include "protocol/hdlc_sync.h"
36#include "system/app_context.h"
37#include "system/cli_commands.h"
38#include "system/cli_usb_cdc.h"
39#include "system/common.h"
40#include "system/error.h"
41#include "system/event_queue.h"
43
44// Generated headers
45
46static void print_v24_polarities(const V24_POLARITIES_T* polarities)
47{
48 if (polarities == NULL)
49 {
50 LOG_PLAIN("polarities: <null>\r\n");
51 return;
52 }
53
54 LOG_PLAIN("polarities: ");
55 bool first = true;
56#define ADD(name, flag) \
57 do \
58 { \
59 if (flag) \
60 { \
61 LOG_PLAIN("%s%s", first ? "" : ",", name); \
62 first = false; \
63 } \
64 } while (0)
65
66 ADD("txd", polarities->tx_polarities.txd_inverted);
67 ADD("txc", polarities->tx_polarities.txc_inverted);
68 ADD("cts", polarities->tx_polarities.cts_inverted);
69 ADD("rts", polarities->tx_polarities.rts_inverted);
70 ADD("dtr", polarities->tx_polarities.dtr_inverted);
71 ADD("rxd", polarities->rx_polarities.rxd_inverted);
72 ADD("rxc", polarities->rx_polarities.rxc_inverted);
73 ADD("dcd", polarities->rx_polarities.dcd_inverted);
74
75 if (first)
76 {
77 LOG_PLAIN("<none>");
78 }
79 LOG_PLAIN("\r\n");
80}
81
83{
84 switch (event_id)
85 {
86 case NET_IP_REMOTE:
87 return "NET_IP_REMOTE";
88 case NET_IP_GATEWAY:
89 return "NET_GATEWAY";
90 case NET_IP_LOCAL:
91 return "NET_IP_LOCAL";
92 case NET_IP_MASK:
93 return "NET_IP_MASK";
94 case NET_PORT_LOCAL:
95 return "NET_PORT_LOCAL";
96 case NET_PORT_REMOTE:
97 return "NET_PORT_REMOTE";
98 default:
99 return "NET_UNKNOWN";
100 }
101}
102
104{
105 switch (state)
106 {
108 return "HUNTING";
110 return "SYNCING";
112 return "SYNCED";
113 default:
114 return "UNKNOWN";
115 }
116}
117
118static void print_net_settings_event(const event_t* event)
119{
120 if (event == NULL)
121 {
122 return;
123 }
124
125 const event_queue_data_t* payload = NULL;
126 if (!event_get_payload_ptr(event, sizeof(*payload), (const void**)&payload))
127 {
128 return;
129 }
130
131 LOG_DEBUG("EV_NET_SETTINGS: id=%s\r\n", net_setting_id_name(payload->id));
132 switch (payload->id)
133 {
134 case NET_IP_REMOTE:
135 case NET_IP_LOCAL:
136 case NET_IP_GATEWAY:
137 LOG_DEBUG(" ip=%u.%u.%u.%u\r\n", payload->value.ip[0], payload->value.ip[1],
138 payload->value.ip[2], payload->value.ip[3]);
139 break;
140 case NET_IP_MASK:
141 LOG_DEBUG(" subnetmask=%u.%u.%u.%u\r\n", payload->value.ip[0], payload->value.ip[1],
142 payload->value.ip[2], payload->value.ip[3]);
143 break;
144 case NET_PORT_LOCAL:
145 case NET_PORT_REMOTE:
146 LOG_DEBUG(" port=%u\r\n", payload->value.port);
147 break;
148 default:
149 LOG_DEBUG(" raw: %02X %02X %02X %02X %02X %02X\r\n", payload->value.ip[0],
150 payload->value.ip[1], payload->value.ip[2], payload->value.ip[3],
151 (uint8_t)(payload->value.port >> 8), (uint8_t)(payload->value.port & 0xFF));
152 break;
153 }
154}
155
156static void request_save_config(void)
157{
158 event_t save_event = {
160 .data.ptr = NULL,
161 .data_len = 0,
162 .is_inline = false,
163 };
164 event_queue_push(&save_event);
165}
166
167typedef struct
168{
172
173static bool ev_set_net_settings(const event_queue_data_t* payload, app_ctx_t* app)
174{
175 bool changed = false;
176 e2s_error_t err;
177 switch (payload->id)
178 {
179 case NET_IP_REMOTE:
180 if (memcmp(app->destination_config.ip_address, payload->value.ip, 4) != 0)
181 {
182 memcpy(app->destination_config.ip_address, payload->value.ip, 4);
183 changed = true;
184 }
185 break;
186 case NET_IP_LOCAL:
187 {
188 wiz_NetInfo net_info;
189 wizchip_getnetinfo(&net_info);
190 if (memcmp(net_info.ip, payload->value.ip, 4) != 0)
191 {
192 memcpy(app->local_config.ip_address, payload->value.ip, 4);
193 memcpy(net_info.ip, payload->value.ip, 4);
194 wizchip_setnetinfo(&net_info);
195 changed = true;
196 }
197 break;
198 }
199 case NET_IP_MASK:
200 {
201 wiz_NetInfo net_info;
202 wizchip_getnetinfo(&net_info);
203 if (memcmp(net_info.sn, payload->value.ip, 4) != 0)
204 {
205 memcpy(net_info.sn, payload->value.ip, 4);
206 wizchip_setnetinfo(&net_info);
207 changed = true;
208 }
209 break;
210 }
211 case NET_IP_GATEWAY:
212 {
213 wiz_NetInfo net_info;
214 wizchip_getnetinfo(&net_info);
215 if (memcmp(net_info.gw, payload->value.ip, 4) != 0)
216 {
217 memcpy(net_info.gw, payload->value.ip, 4);
218 wizchip_setnetinfo(&net_info);
219 changed = true;
220 }
221 break;
222 }
223 case NET_PORT_LOCAL:
224 if (app->local_config.port != payload->value.port)
225 {
226 app->local_config.port = payload->value.port;
228 {
229 fatal_panic(err);
230 }
231 changed = true;
232 }
233 break;
234 case NET_PORT_REMOTE:
235 if (app->destination_config.port != payload->value.port)
236 {
237 app->destination_config.port = payload->value.port;
239 {
240 fatal_panic(err);
241 }
242 changed = true;
243 }
244 break;
245 default:
246 break;
247 }
248 app->need_prompt = true;
249 return changed;
250}
251
252static void ev_get_net_settings(const event_queue_data_t* payload, const app_ctx_t* app)
253{
254 switch (payload->id)
255 {
256 case NET_IP_REMOTE:
257 LOG_PLAIN("NET_IP_REMOTE: %d.%d.%d.%d\r\n", app->destination_config.ip_address[0],
260 break;
261 case NET_IP_LOCAL:
262 case NET_IP_MASK:
263 case NET_IP_GATEWAY:
264 {
265 wiz_NetInfo net_info;
266 wizchip_getnetinfo(&net_info);
267 LOG_PLAIN("ip=%u.%u.%u.%u sn=%u.%u.%u.%u gw=%u.%u.%u.%u\r\n", net_info.ip[0],
268 net_info.ip[1], net_info.ip[2], net_info.ip[3], net_info.sn[0], net_info.sn[1],
269 net_info.sn[2], net_info.sn[3], net_info.gw[0], net_info.gw[1], net_info.gw[2],
270 net_info.gw[3]);
271 break;
272 }
273 case NET_PORT_LOCAL:
274 LOG_PLAIN("NET_PORT_LOCAL: %d\r\n", app->local_config.port);
275 break;
276 case NET_PORT_REMOTE:
277 LOG_PLAIN("NET_PORT_REMOTE: %d\r\n", app->destination_config.port);
278 break;
279 default:
280 break;
281 }
282}
283
285{
286 apply_result_t result = {0};
287 switch (payload->id)
288 {
289 case V24_BAUDRATE:
290 if (app->v24_config.baudrate != payload->value.baudrate)
291 {
294 result.changed = true;
295 }
296 app->need_prompt = true;
297 break;
298 case V24_POLARITIES:
299 if (memcmp(&app->v24_config.polarities, &payload->value.polarities,
300 sizeof(V24_POLARITIES_T)) != 0)
301 {
302 memcpy(&app->v24_config.polarities, &payload->value.polarities,
303 sizeof(V24_POLARITIES_T));
306 result.changed = true;
307 }
308 app->need_prompt = true;
309 break;
310 case V24_CLOCK_MODE:
311 {
312 bool external_clock = payload->value.v24_clock_mode;
313
314 if (app->v24_config.external_clock != external_clock)
315 {
316 if (!tx_queue_is_empty(&app->tx_queue))
317 {
318 LOG_ERROR("Cannot change clock mode during ongoing transmission!\r\n");
319 break;
320 }
321 LOG_PLAIN("Switching to %s mode.\r\n", external_clock ? "external" : "internal");
322 app->v24_config.external_clock = external_clock;
323 result.changed = true;
324 result.reboot_required = true;
325 }
326 else
327 {
328 LOG_INFO("Already in %s mode.\r\n", external_clock ? "external" : "internal");
329 break;
330 }
331 app->need_prompt = true;
332 break;
333 }
334 default:
335 break;
336 }
337 return result;
338}
339
340static void ev_get_v24_settings(const event_queue_data_t* payload, app_ctx_t* app)
341{
342 switch (payload->id)
343 {
344 case V24_BAUDRATE:
345 LOG_PLAIN("V24_BAUDRATE: %d\r\n", app->v24_config.baudrate);
346 app->need_prompt = true;
347 break;
348 case V24_POLARITIES:
350 app->need_prompt = true;
351 break;
352 case V24_CLOCK_MODE:
353 LOG_PLAIN("V24 TX Clock: %s\r\n", app->v24_config.external_clock ? "external (XCK Pin 15)"
354 : "internal (TCK Pin 17)");
355 app->need_prompt = true;
356 break;
357 default:
358 break;
359 }
360}
361
362typedef struct
363{
364 uint64_t frame_gap;
365 uint64_t tx_gap;
372
373static void ev_status(app_ctx_t* app, ev_status_stats_t* status_stats)
374{
375 status_stats->frame_gap = 0;
377 {
378 status_stats->frame_gap = app->stats.hdlc_tx_frames - app->stats.hdlc_frame_ready;
379 }
380 status_stats->tx_gap = 0;
382 {
383 status_stats->tx_gap = app->stats.hdlc_frame_ready - app->stats.udp_tx_frames;
384 }
385
386 static uint64_t prev_udp_rx_frames = 0U;
387 static uint64_t prev_hdlc_frame_ready = 0U;
388 static uint64_t prev_udp_tx_frames = 0U;
389 static uint64_t prev_hdlc_decode_fail = 0U;
390 static uint64_t prev_serial_rx_bytes = 0U;
391 uint32_t report_now_ms = to_ms_since_boot(get_absolute_time());
392 uint32_t elapsed_ms = 0U;
393 if (app->stats.last_report_ms != 0U)
394 {
395 elapsed_ms = report_now_ms - app->stats.last_report_ms;
396 }
397 if (elapsed_ms == 0U)
398 {
399 elapsed_ms = 1U;
400 }
401
402 uint64_t d_udp_rx_frames = app->stats.udp_rx_frames - prev_udp_rx_frames;
403 uint64_t d_hdlc_frame_ready = app->stats.hdlc_frame_ready - prev_hdlc_frame_ready;
404 uint64_t d_udp_tx_frames = app->stats.udp_tx_frames - prev_udp_tx_frames;
405 uint64_t d_decode_fail = app->stats.hdlc_decode_fail - prev_hdlc_decode_fail;
406 uint64_t d_serial_rx_bytes = app->stats.serial_rx_bytes - prev_serial_rx_bytes;
407
408 status_stats->udp_rx_rate_fps = (d_udp_rx_frames * 1000U) / elapsed_ms;
409 status_stats->hdlc_rx_rate_fps = (d_hdlc_frame_ready * 1000U) / elapsed_ms;
410 status_stats->udp_tx_rate_fps = (d_udp_tx_frames * 1000U) / elapsed_ms;
411 status_stats->decode_fail_rate = (d_decode_fail * 1000U) / elapsed_ms;
412 status_stats->serial_rx_rate_bps = (d_serial_rx_bytes * 1000U) / elapsed_ms;
413
414 prev_udp_rx_frames = app->stats.udp_rx_frames;
415 prev_hdlc_frame_ready = app->stats.hdlc_frame_ready;
416 prev_udp_tx_frames = app->stats.udp_tx_frames;
417 prev_hdlc_decode_fail = app->stats.hdlc_decode_fail;
418 prev_serial_rx_bytes = app->stats.serial_rx_bytes;
419 app->stats.last_report_ms = report_now_ms;
420}
421
422static void print_status_event(app_ctx_t* app, ev_status_stats_t* status_stats)
423{
424
425 LOG_PLAIN("status: ok\r\n");
426 LOG_PLAIN("Current Baudrate estimation on pin %d: %.1f Hz\r\n", V24_RXC,
428 if (app->v24_config.external_clock)
429 {
430 LOG_PLAIN("Current Baudrate estimation on pin %d: %.1f Hz\r\n", V24_TXC_DCE,
432 }
433 LOG_PLAIN("PIPE STATS\r\n");
434 LOG_PLAIN(" Traffic\r\n");
435 LOG_PLAIN(" Frames : udp_rx=%" PRIu64 " hdlc_tx=%" PRIu64 " hdlc_rx=%" PRIu64
436 " udp_tx=%" PRIu64 "\r\n",
438 app->stats.udp_tx_frames);
439 LOG_PLAIN(" Backlog : tx->ready_gap=%" PRIu64 " ready->udp_gap=%" PRIu64 "\r\n",
440 status_stats->frame_gap, status_stats->tx_gap);
441 LOG_PLAIN(" Serial : rx_bytes=%" PRIu64 " tx_bytes=%" PRIu64 "\r\n",
443 LOG_PLAIN(" Rates : udp_rx=%" PRIu64 "/s hdlc_rx=%" PRIu64 "/s udp_tx=%" PRIu64
444 "/s fail=%" PRIu64 "/s rx_bytes=%" PRIu64 "/s\r\n",
445 status_stats->udp_rx_rate_fps, status_stats->hdlc_rx_rate_fps,
446 status_stats->udp_tx_rate_fps, status_stats->decode_fail_rate,
447 status_stats->serial_rx_rate_bps);
448
449 LOG_PLAIN(" Decode / Sync\r\n");
450 LOG_PLAIN(" Decode : frame_ready=%" PRIu64 " ok=%" PRIu64 " fail=%" PRIu64 "\r\n",
452 LOG_PLAIN(" FailReason: invalid=%" PRIu64 " short=%" PRIu64 " long=%" PRIu64
453 " unstuff=%" PRIu64 " crc=%" PRIu64 "\r\n",
457 LOG_PLAIN(" SyncState : %s\r\n", hdlc_sync_state_name(app->accumulator.state));
458 LOG_PLAIN(" SyncWait : syncing=%" PRIu64 " synced=%" PRIu64 "\r\n",
460 LOG_PLAIN(" SyncMaint : consume=%" PRIu64 " hardcap_events=%" PRIu64
461 " hardcap_bytes=%" PRIu64 "\r\n",
464 LOG_PLAIN(" Resync : idle=%" PRIu64 " hard=%" PRIu64 " no_progress=%" PRIu64 "\r\n",
467 LOG_PLAIN(
468 " Accum : pos=%zu proc=%zu state=%d off=%u cand_valid=%d cand_end=%zu\r\n",
472 LOG_PLAIN(" RX Health : acc_pos_max=%" PRIu64 " rx_fifo_stall=%" PRIu64
473 " rx_drop_acc_full=%" PRIu64 " hunt_idle_drop=%" PRIu64 "\r\n",
476
477 LOG_PLAIN(" Buffers\r\n");
478 LOG_PLAIN(" TX Queue : used=%zu/%zu active=%d\r\n", app->tx_queue.queue_buffer.count,
481 : 0);
482 LOG_PLAIN(" HighWater : tx=%" PRIu64 " event=%" PRIu64 " log=%" PRIu64 "\r\n",
485 LOG_PLAIN(" W5500 Buf : rx_no_room_events=%" PRIu64 " tx_full_events=%" PRIu64 "\r\n",
487 LOG_PLAIN(" Drops : tx=%" PRIu64 " event=%" PRIu64 " log=%" PRIu64 "\r\n",
489 app->stats.log_drop_lines);
490 LOG_PLAIN(" Recons : len=%zu\r\n", app->reconstructed_frame.length);
491 LOG_PLAIN(" Throttle : udp_rx_enter=%" PRIu64 " udp_rx_skips=%" PRIu64 "\r\n",
493
495 LOG_PLAIN(
496 " PIO TX : stalled=%" PRIu32 "\r\n",
498 ? ((v24_runtime->tx_pio->fdebug >>
499 (PIO_FDEBUG_TXSTALL_LSB + v24_runtime->tx_sm)) & // NOLINT(misc-include-cleaner)
500 1U)
501 : 0);
502}
503
504void event_dispatch(const event_t* event, app_ctx_t* app)
505{
506 switch (event->type)
507 {
508 case EV_REBOOT:
509 {
510 reboot();
511 break; // Compiler wants break because dosnt detect trap in reboot
512 }
513 case EV_STATUS:
514 {
515 ev_status_stats_t status_stats = {0};
516 ev_status(app, &status_stats);
517 print_status_event(app, &status_stats);
518 app->need_prompt = true;
519 }
520 break;
521 case EV_MEM:
524 app->need_prompt = true;
525 break;
526 case EV_CLI_LINE:
527 {
528 const char* cli_line = NULL;
529 if (event_get_payload_ptr(event, 1, (const void**)&cli_line))
530 {
531 handle_cli_line(cli_line);
532 }
533 app->need_prompt = true;
534 break;
535 }
536 case EV_UDP_RX:
537 LOG_DEBUG("tx_queue_enqueue_udp_frame: %d\r\n",
539 memset(app->rx_frame_buffer.payload, 0, app->rx_frame_buffer.length);
540 app->rx_frame_buffer.length = 0;
541 app->need_prompt = true;
542 break;
543 case EV_UDP_TX:
544 {
545 const UDP_FRAME_T* tx_frame = NULL;
546 if (event_get_payload_ptr(event, sizeof(*tx_frame), (const void**)&tx_frame))
547 {
548 w5500_udp_tx(&app->destination_config, tx_frame);
549 }
550 app->need_prompt = true;
551 break;
552 }
553 case EV_HDLC_DECODE:
554 {
555 const HDLC_FRAME_T* hdlc_frame = NULL;
556 if (event_get_payload_ptr(event, sizeof(*hdlc_frame), (const void**)&hdlc_frame))
557 {
558 app->tx_frame_buffer.length = 0;
559 PRINT_FRAME_HEX("Frame: ", hdlc_frame->payload, hdlc_frame->length);
560 if (hdlc_decode(hdlc_frame, app->tx_frame_buffer.payload, TX_BUF_SIZE,
561 &(app->tx_frame_buffer.length), true))
562 {
563 event_t hdlc_frame_event = {.type = EV_UDP_TX,
564 .data.ptr = &app->tx_frame_buffer,
565 .data_len = sizeof(app->tx_frame_buffer)};
566 event_queue_push(&hdlc_frame_event);
567 }
568 memset(hdlc_frame->payload, 0, hdlc_frame->length);
570 }
571 break;
572 }
573 case EV_SAVE_CONFIG:
574 LOG_PLAIN("Storing persistent config in flash.\r\n");
575 wizchip_getnetinfo(&(app->net_config.net_info));
582 LOG_PLAIN("Config stored. Dumping for checking:\r\n");
583 dump_config();
584 app->need_prompt = true;
585 break;
586 case EV_WIPE_CONFIG:
587 LOG_PLAIN("Wiping persistent config in flash.\r\n");
588 config_wipe();
589 LOG_PLAIN("Config wiped. Dumping for checking:\r\n");
590 dump_config();
591 app->need_prompt = true;
592 break;
594 {
596 {
598 }
599 const event_queue_data_t* payload = NULL;
600 if (!event_get_payload_ptr(event, sizeof(*payload), (const void**)&payload))
601 {
602 break;
603 }
604 if (ev_set_net_settings(payload, app))
605 {
607 }
608 break;
609 }
611 {
613 {
615 }
616 const event_queue_data_t* payload = NULL;
617 if (!event_get_payload_ptr(event, sizeof(*payload), (const void**)&payload))
618 {
619 break;
620 }
621
622 ev_get_net_settings(payload, app);
623 break;
624 }
626 {
627 const event_queue_data_t* payload = NULL;
628 if (!event_get_payload_ptr(event, sizeof(*payload), (const void**)&payload))
629 {
630 break;
631 }
632 apply_result_t set_result = ev_set_v24_settings(payload, app);
633 if (set_result.changed)
634 {
636 }
637 if (set_result.reboot_required)
638 {
639 event_t reboot_event = {
640 .type = EV_REBOOT,
641 .data.ptr = NULL,
642 .data_len = 0,
643 .is_inline = false,
644 };
645 event_queue_push(&reboot_event);
646 }
647 break;
648 }
650 {
651 const event_queue_data_t* payload = NULL;
652 if (!event_get_payload_ptr(event, sizeof(*payload), (const void**)&payload))
653 {
654 break;
655 }
656 ev_get_v24_settings(payload, app);
657 break;
658 }
659 default:
660 break;
661 }
662}
float baudrate_estimator_get_current_estimation(V24_PIN_T pin)
Get latest baudrate estimate.
void handle_cli_line(const char *line)
Parse and execute one CLI input line.
log_level_t get_loglevel(void)
Get current global log level.
Definition log.c:61
#define LOG_INFO(...)
Definition common.h:164
#define LOG_DEBUG(...)
Definition common.h:165
#define PRINT_FRAME_HEX(label, payload_ptr, length)
Definition common.h:168
#define LOG_PLAIN(...)
Definition common.h:162
@ LOG_LEVEL_DEBUG
Definition common.h:91
#define PRIu32
Definition common.h:64
#define PRIu64
Definition common.h:73
#define LOG_ERROR(...)
Definition common.h:163
void fatal_panic(e2s_error_t reason)
Print error message and panic.
Definition error.c:30
e2s_error_t
Common error codes returned by ether2ser modules.
Definition error.h:27
@ E2S_OK
Definition error.h:28
static apply_result_t ev_set_v24_settings(const event_queue_data_t *payload, app_ctx_t *app)
static const char * hdlc_sync_state_name(HDLC_SYNC_STATE_T state)
static void print_net_settings_event(const event_t *event)
static const char * net_setting_id_name(event_queue_data_types_t event_id)
static void print_status_event(app_ctx_t *app, ev_status_stats_t *status_stats)
#define ADD(name, flag)
static void ev_get_v24_settings(const event_queue_data_t *payload, app_ctx_t *app)
static void ev_status(app_ctx_t *app, ev_status_stats_t *status_stats)
void event_dispatch(const event_t *event, app_ctx_t *app)
Dispatch one event to the corresponding handler.
static bool ev_set_net_settings(const event_queue_data_t *payload, app_ctx_t *app)
static void print_v24_polarities(const V24_POLARITIES_T *polarities)
static void ev_get_net_settings(const event_queue_data_t *payload, const app_ctx_t *app)
static void request_save_config(void)
bool event_queue_push(const event_t *event_entry)
Enqueue an event.
Definition event_queue.c:49
bool event_get_payload_ptr(const event_t *event, size_t required_size, const void **out)
Resolve payload pointer and validate minimum payload size.
event_queue_data_types_t
Typed payload selector for configuration-oriented events.
Definition event_queue.h:56
@ NET_PORT_REMOTE
Definition event_queue.h:62
@ NET_IP_MASK
Definition event_queue.h:60
@ V24_POLARITIES
Definition event_queue.h:64
@ V24_CLOCK_MODE
Definition event_queue.h:65
@ V24_BAUDRATE
Definition event_queue.h:63
@ NET_PORT_LOCAL
Definition event_queue.h:61
@ NET_IP_LOCAL
Definition event_queue.h:59
@ NET_IP_REMOTE
Definition event_queue.h:57
@ NET_IP_GATEWAY
Definition event_queue.h:58
@ EV_STATUS
Definition event_queue.h:42
@ EV_CLI_LINE
Definition event_queue.h:37
@ EV_SET_V24_SETTINGS
Definition event_queue.h:47
@ EV_GET_NET_SETTINGS
Definition event_queue.h:46
@ EV_MEM
Definition event_queue.h:43
@ EV_WIPE_CONFIG
Definition event_queue.h:44
@ EV_SET_NET_SETTINGS
Definition event_queue.h:45
@ EV_GET_V24_SETTINGS
Definition event_queue.h:48
@ EV_REBOOT
Definition event_queue.h:49
@ EV_SAVE_CONFIG
Definition event_queue.h:41
@ EV_HDLC_DECODE
Definition event_queue.h:40
@ EV_UDP_TX
Definition event_queue.h:39
@ EV_UDP_RX
Definition event_queue.h:38
#define HDLC_FLAG_BYTE
Definition hdlc_common.h:29
bool hdlc_decode(const HDLC_FRAME_T *frame, uint8_t *payload, const size_t out_capacity, size_t *payload_length, bool lsb_first)
Decode an HDLC bit-stuffed frame.
void hdlc_sync_acc_init(HDLC_SYNC_ACCUMULATOR_T *accumulator, uint8_t sync_byte)
Initialize HDLC sync accumulator state.
Definition hdlc_sync.c:507
HDLC_SYNC_STATE_T
HDLC synchronizer state machine states.
Definition hdlc_sync.h:41
@ HDLC_SYNC_STATE_HUNTING
Definition hdlc_sync.h:43
@ HDLC_SYNC_STATE_SYNCED
Definition hdlc_sync.h:47
@ HDLC_SYNC_STATE_SYNCING
Definition hdlc_sync.h:45
void print_flash_usage(void)
Print flash usage statistics.
void dump_config(void)
Print current configuration to console/log output.
void config_write(const config_t *cfg)
Write configuration to flash.
void print_memory_usage(void)
Print RAM usage statistics.
void config_wipe(void)
Erase persistent configuration sector.
#define V24_RXC
Definition pinmap.h:28
#define V24_TXC_DCE
Definition pinmap.h:27
void reinit_v24_config(V24_CONFIG_T *config, V24_BAUDRATE_T baudrate)
Reinitialize V.24 runtime configuration and derived timing values.
const v24_runtime_t * get_v24_runtime(void)
Returns a pointer to the v24 runtime.
v24_runtime_t v24_runtime
void rx_clock_update_settings(V24_RX_POLARITIES_T *polarities)
Apply RX runtime settings to an already configured RX PIO SM. Take note that this function relies on ...
void tx_clock_update_settings(V24_CONFIG_T *config)
Apply TX runtime settings to an already configured TX PIO SM. Take note that this function relies on ...
Generic HDLC frame buffer descriptor.
Definition hdlc_common.h:38
size_t length
Definition hdlc_common.h:42
uint8_t * payload
Definition hdlc_common.h:40
HDLC_SYNC_STATE_T state
Definition hdlc_sync.h:71
wiz_NetInfo net_info
size_t capacity
Definition ringbuffer.h:34
size_t count
Definition ringbuffer.h:36
size_t offset
Definition tx_queue.h:66
HDLC_FRAME_T frame
Definition tx_queue.h:64
TX_QUEUE_ENTRY_T current_entry
Definition tx_queue.h:75
uint64_t tx_wire_bytes
Definition tx_queue.h:81
Ringbuffer queue_buffer
Definition tx_queue.h:77
uint8_t ip_address[4]
uint16_t port
UDP payload container.
size_t length
uint8_t * payload
V24_POLARITIES_T polarities
Definition v24_config.h:91
V24_BAUDRATE_T baudrate
Definition v24_config.h:89
bool external_clock
Definition v24_config.h:97
Combined TX and RX polarity configuration.
Definition v24_config.h:78
V24_RX_POLARITIES_T rx_polarities
Definition v24_config.h:80
V24_TX_POLARITIES_T tx_polarities
Definition v24_config.h:79
Global application context shared across modules.
Definition app_context.h:98
UDP_FRAME_T tx_frame_buffer
bool need_prompt
UDP_FRAME_T rx_frame_buffer
HDLC_SYNC_ACCUMULATOR_T accumulator
TX_QUEUE_T tx_queue
payload_statistics_t stats
NETWORK_CONFIG_T net_config
UDP_CONFIG_T local_config
V24_CONFIG_T v24_config
config_t persistent_config
Definition app_context.h:99
UDP_CONFIG_T destination_config
HDLC_FRAME_T reconstructed_frame
UDP_CONFIG_T local_config
NETWORK_CONFIG_T net_config
V24_CONFIG_T v24_config
log_level_t log_level
UDP_CONFIG_T remote_config
uint64_t serial_rx_rate_bps
Generic event payload wrapper for network/V.24 config operations.
Definition event_queue.h:73
V24_BAUDRATE_T baudrate
Definition event_queue.h:82
V24_POLARITIES_T polarities
Definition event_queue.h:81
event_queue_data_types_t id
Definition event_queue.h:75
union event_queue_data_t::@0 value
Event queue entry.
Definition event_queue.h:91
event_type_t type
Definition event_queue.h:93
uint64_t rx_fifo_stall_events
Definition app_context.h:87
uint64_t sync_candidate_consume
Definition app_context.h:65
uint64_t hdlc_decode_fail
Definition app_context.h:56
uint64_t tx_queue_used_max
Definition app_context.h:79
uint64_t resync_no_progress_count
Definition app_context.h:77
uint64_t decode_fail_crc_mismatch
Definition app_context.h:73
uint64_t sync_hardcap_drop_events
Definition app_context.h:66
uint64_t udp_rx_throttle_enter
Definition app_context.h:58
uint64_t tx_queue_drop_frames
Definition app_context.h:80
uint64_t accumulator_pos_max
Definition app_context.h:86
uint64_t hunt_idle_drop_bytes
Definition app_context.h:89
uint64_t event_queue_drop_events
Definition app_context.h:82
uint64_t decode_fail_unstuff_error
Definition app_context.h:72
uint64_t udp_rx_throttle_skips
Definition app_context.h:59
uint64_t log_queue_used_max
Definition app_context.h:84
uint64_t hdlc_frame_ready
Definition app_context.h:54
uint64_t serial_rx_drop_acc_full
Definition app_context.h:88
uint64_t decode_fail_invalid_frame
Definition app_context.h:69
uint64_t event_queue_used_max
Definition app_context.h:81
uint64_t decode_fail_too_short
Definition app_context.h:70
uint64_t sync_hardcap_drop_bytes
Definition app_context.h:67
uint64_t resync_idle_timeout_count
Definition app_context.h:75
uint64_t sync_lookahead_wait_syncing
Definition app_context.h:63
uint64_t resync_hard_fail_count
Definition app_context.h:76
uint64_t udp_tx_buffer_full_counts
Definition app_context.h:61
uint64_t decode_fail_payload_too_long
Definition app_context.h:71
uint64_t sync_lookahead_wait_synced
Definition app_context.h:64
uint64_t udp_rx_buffer_full_counts
Definition app_context.h:60
bool tx_queue_is_empty(TX_QUEUE_T *queue)
Check whether queue and active entry are fully drained.
Definition tx_queue.c:122
e2s_error_t tx_queue_enqueue_udp_frame(TX_QUEUE_T *queue, const UDP_FRAME_T *frame)
Encode UDP frame to HDLC and append it to TX queue.
Definition tx_queue.c:201
void w5500_udp_tx(UDP_CONFIG_T *send_config, const UDP_FRAME_T *frame)
Send one UDP frame through W5500.
e2s_error_t w5500_reconfigure_udp_socket(UDP_CONFIG_T *config)
Reconfigure UDP socket with new endpoint settings.
#define TX_BUF_SIZE
void reboot(void)
Reboots by resetting the watchdog.
Definition watchdog.c:28