ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
fins.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file fins.cpp
6 * @brief Omron FINS command/response builder + parser (pure, host-tested).
7 */
8
10
11#if PC_ENABLE_FINS
12
13#include <string.h>
14
15static size_t write_header(uint8_t *buf, const FinsHeader *h)
16{
17 buf[0] = h->icf;
18 buf[1] = h->rsv;
19 buf[2] = h->gct;
20 buf[3] = h->dna;
21 buf[4] = h->da1;
22 buf[5] = h->da2;
23 buf[6] = h->sna;
24 buf[7] = h->sa1;
25 buf[8] = h->sa2;
26 buf[9] = h->sid;
27 return FINS_HEADER_SIZE;
28}
29
30static void read_header(const uint8_t *buf, FinsHeader *h)
31{
32 h->icf = buf[0];
33 h->rsv = buf[1];
34 h->gct = buf[2];
35 h->dna = buf[3];
36 h->da1 = buf[4];
37 h->da2 = buf[5];
38 h->sna = buf[6];
39 h->sa1 = buf[7];
40 h->sa2 = buf[8];
41 h->sid = buf[9];
42}
43
44size_t pc_fins_build_command(uint8_t *buf, size_t cap, const FinsHeader *h, uint8_t mrc, uint8_t src,
45 const uint8_t *params, size_t params_len)
46{
47 if (!buf || !h || (params_len && !params))
48 {
49 return 0;
50 }
51 size_t total = FINS_HEADER_SIZE + 2 + params_len;
52 if (total > cap)
53 {
54 return 0;
55 }
56 size_t p = write_header(buf, h);
57 buf[p++] = mrc;
58 buf[p++] = src;
59 if (params_len)
60 {
61 memcpy(buf + p, params, params_len);
62 p += params_len;
63 }
64 return p;
65}
66
67size_t pc_fins_build_memory_area_read(uint8_t *buf, size_t cap, const FinsHeader *h, uint8_t area, uint16_t address,
68 uint8_t bit, uint16_t count)
69{
70 uint8_t params[6];
71 params[0] = area;
72 params[1] = (uint8_t)(address >> 8);
73 params[2] = (uint8_t)(address & 0xFF);
74 params[3] = bit;
75 params[4] = (uint8_t)(count >> 8);
76 params[5] = (uint8_t)(count & 0xFF);
77 return pc_fins_build_command(buf, cap, h, FINS_MRC_MEMORY_AREA, FINS_SRC_MEMORY_AREA_READ, params, sizeof(params));
78}
79
80size_t pc_fins_build_memory_area_write(uint8_t *buf, size_t cap, const FinsHeader *h, uint8_t area, uint16_t address,
81 uint8_t bit, uint16_t count, const uint8_t *data, size_t data_len)
82{
83 if (data_len && !data)
84 {
85 return 0;
86 }
87 uint8_t prefix[6];
88 prefix[0] = area;
89 prefix[1] = (uint8_t)(address >> 8);
90 prefix[2] = (uint8_t)(address & 0xFF);
91 prefix[3] = bit;
92 prefix[4] = (uint8_t)(count >> 8);
93 prefix[5] = (uint8_t)(count & 0xFF);
94 // The command builder lays down header + MRC + SRC + the 6-octet prefix; the write data follows it.
95 size_t n =
96 pc_fins_build_command(buf, cap, h, FINS_MRC_MEMORY_AREA, FINS_SRC_MEMORY_AREA_WRITE, prefix, sizeof(prefix));
97 if (!n)
98 {
99 return 0; // header + prefix did not fit
100 }
101 if (data_len)
102 {
103 if (n + data_len > cap)
104 {
105 return 0; // the write data does not fit
106 }
107 memcpy(buf + n, data, data_len);
108 }
109 return n + data_len;
110}
111
112size_t pc_fins_build_run(uint8_t *buf, size_t cap, const FinsHeader *h, FinsRunMode mode)
113{
114 uint8_t params[3];
115 params[0] = 0xFF; // program number 0xFFFF (all programs)
116 params[1] = 0xFF; //
117 params[2] = (uint8_t)mode; // wire byte: 0x02 MONITOR / 0x04 RUN
118 return pc_fins_build_command(buf, cap, h, FINS_MRC_OPERATING_MODE, FINS_SRC_RUN, params, sizeof(params));
119}
120
121size_t pc_fins_build_stop(uint8_t *buf, size_t cap, const FinsHeader *h)
122{
123 return pc_fins_build_command(buf, cap, h, FINS_MRC_OPERATING_MODE, FINS_SRC_STOP, nullptr, 0);
124}
125
126bool pc_fins_parse_command(const uint8_t *buf, size_t len, FinsCommand *out)
127{
128 if (!buf || !out || len < FINS_HEADER_SIZE + 2)
129 {
130 return false;
131 }
132 read_header(buf, &out->header);
133 out->mrc = buf[FINS_HEADER_SIZE];
134 out->src = buf[FINS_HEADER_SIZE + 1];
135 out->params = buf + FINS_HEADER_SIZE + 2;
136 out->params_len = len - (FINS_HEADER_SIZE + 2);
137 return true;
138}
139
140bool pc_fins_parse_response(const uint8_t *buf, size_t len, FinsResponse *out)
141{
142 if (!buf || !out || len < FINS_HEADER_SIZE + 4) // header + MRC + SRC + MRES + SRES
143 {
144 return false;
145 }
146 read_header(buf, &out->header);
147 out->mrc = buf[FINS_HEADER_SIZE];
148 out->src = buf[FINS_HEADER_SIZE + 1];
149 out->mres = buf[FINS_HEADER_SIZE + 2];
150 out->sres = buf[FINS_HEADER_SIZE + 3];
151 out->data = buf + FINS_HEADER_SIZE + 4;
152 out->data_len = len - (FINS_HEADER_SIZE + 4);
153 return true;
154}
155
156#endif // PC_ENABLE_FINS
Omron FINS frame codec (PC_ENABLE_FINS) - zero-heap command/response builder + parser for the Factory...