Skip to content

Commit 5e7f410

Browse files
committed
Reorder
1 parent 8bfadea commit 5e7f410

42 files changed

Lines changed: 1955 additions & 490 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

source/include/fn_commons.h

Lines changed: 460 additions & 0 deletions
Large diffs are not rendered by default.

source/include/ladder_instructions.h

Lines changed: 3 additions & 312 deletions
Original file line numberDiff line numberDiff line change
@@ -30,327 +30,18 @@
3030
*
3131
*/
3232

33-
#ifndef LADDER_INSTRUCTIONS_H
34-
#define LADDER_INSTRUCTIONS_H
33+
#ifndef FN_COMMONS_H
34+
#define FN_COMMONS_H
3535

3636
#include <stdbool.h>
3737
#include <stdint.h>
3838
#include <string.h>
3939

4040
#include "ladder.h"
4141

42-
extern uint32_t basetime_factor[];
43-
44-
static inline int32_t to_integer(int32_t val, ladder_data_type_t type) {
45-
(void)type; // Unused; suppress warning (original behavior preserved)
46-
if (val == 0) {
47-
return (int32_t)(uint32_t)val; // Explicit cast as in original
48-
} else if (val == 1) {
49-
return (int32_t)val;
50-
}
51-
return 0;
52-
}
5342

5443
#define exnet(lctx) (*(*lctx).exec_network)
5544

56-
static inline int32_t safe_get_register_index(ladder_ctx_t *lctx, ladder_register_t type, int32_t raw_idx, ladder_ins_err_t *err) {
57-
if (raw_idx < 0) {
58-
*err = LADDER_INS_ERR_OUTOFRANGE;
59-
return -1;
60-
}
61-
uint32_t idx = (uint32_t) raw_idx;
62-
uint32_t qty = 0;
63-
switch (type) {
64-
case LADDER_REGISTER_M:
65-
qty = lctx->ladder.quantity.m;
66-
break;
67-
case LADDER_REGISTER_Cd:
68-
case LADDER_REGISTER_Cr:
69-
case LADDER_REGISTER_C:
70-
qty = lctx->ladder.quantity.c;
71-
break;
72-
case LADDER_REGISTER_Td:
73-
case LADDER_REGISTER_Tr:
74-
case LADDER_REGISTER_T:
75-
qty = lctx->ladder.quantity.t;
76-
break;
77-
case LADDER_REGISTER_D:
78-
qty = lctx->ladder.quantity.d;
79-
break;
80-
case LADDER_REGISTER_R:
81-
qty = lctx->ladder.quantity.r;
82-
break;
83-
default:
84-
*err = LADDER_INS_ERR_TYPEMISMATCH;
85-
return -1;
86-
}
87-
if (idx >= qty) {
88-
*err = LADDER_INS_ERR_OUTOFRANGE;
89-
return -1;
90-
}
91-
*err = LADDER_INS_ERR_OK;
92-
return (int32_t) idx;
93-
}
94-
95-
static inline bool safe_check_module_port(ladder_ctx_t *lctx, ladder_register_t type, uint32_t mod, uint8_t port, uint32_t *qty_out, ladder_ins_err_t *err) {
96-
uint32_t fn_qty = 0;
97-
switch (type) {
98-
case LADDER_REGISTER_Q:
99-
case LADDER_REGISTER_QW:
100-
fn_qty = lctx->hw.io.fn_write_qty;
101-
break;
102-
case LADDER_REGISTER_I:
103-
case LADDER_REGISTER_IW:
104-
fn_qty = lctx->hw.io.fn_read_qty;
105-
break;
106-
default:
107-
*err = LADDER_INS_ERR_TYPEMISMATCH;
108-
return false;
109-
}
110-
if (mod >= fn_qty) {
111-
*err = LADDER_INS_ERR_OUTOFRANGE;
112-
return false;
113-
}
114-
switch (type) {
115-
case LADDER_REGISTER_Q:
116-
*qty_out = lctx->output[mod].q_qty;
117-
break;
118-
case LADDER_REGISTER_QW:
119-
*qty_out = lctx->output[mod].qw_qty;
120-
break;
121-
case LADDER_REGISTER_I:
122-
*qty_out = lctx->input[mod].i_qty;
123-
break;
124-
case LADDER_REGISTER_IW:
125-
*qty_out = lctx->input[mod].iw_qty;
126-
break;
127-
default:
128-
break; // Unreachable
129-
}
130-
if (port >= *qty_out) {
131-
*err = LADDER_INS_ERR_OUTOFRANGE;
132-
return false;
133-
}
134-
*err = LADDER_INS_ERR_OK;
135-
return true;
136-
}
137-
138-
static inline int32_t ladder_get_data_value(ladder_ctx_t *lctx, uint32_t r, uint32_t c, uint32_t i) {
139-
if (lctx == NULL || lctx->exec_network == NULL) {
140-
return 0; // Safe default on invalid context
141-
}
142-
ladder_network_t *net = lctx->exec_network;
143-
if (r >= net->rows || c >= net->cols || i >= net->cells[r][c].data_qty) {
144-
return 0; // Safe default on OOB
145-
}
146-
ladder_register_t type = net->cells[r][c].data[i].type;
147-
ladder_value_t *val = &net->cells[r][c].data[i];
148-
ladder_ins_err_t err = LADDER_INS_ERR_OK;
149-
150-
switch (type) {
151-
case LADDER_REGISTER_NONE:
152-
return (int32_t) (uint32_t) val->value.i32;
153-
case LADDER_REGISTER_M:
154-
case LADDER_REGISTER_Cd:
155-
case LADDER_REGISTER_Cr:
156-
case LADDER_REGISTER_Td:
157-
case LADDER_REGISTER_Tr:
158-
case LADDER_REGISTER_C:
159-
case LADDER_REGISTER_T:
160-
case LADDER_REGISTER_D:
161-
case LADDER_REGISTER_R: {
162-
int32_t idx = safe_get_register_index(lctx, type, val->value.i32, &err);
163-
if (err != LADDER_INS_ERR_OK) {
164-
lctx->ladder.last.err = err;
165-
return 0; // Safe default on error
166-
}
167-
switch (type) {
168-
case LADDER_REGISTER_M: return (int32_t) lctx->memory.M[idx];
169-
case LADDER_REGISTER_Cd: return (int32_t) lctx->memory.Cd[idx];
170-
case LADDER_REGISTER_Cr: return (int32_t) lctx->memory.Cr[idx];
171-
case LADDER_REGISTER_Td: return (int32_t) lctx->memory.Td[idx];
172-
case LADDER_REGISTER_Tr: return (int32_t) lctx->memory.Tr[idx];
173-
case LADDER_REGISTER_C: return (int32_t) lctx->registers.C[idx];
174-
case LADDER_REGISTER_T: {
175-
uint64_t acc = lctx->timers[idx].acc;
176-
if (acc > (uint64_t) INT32_MAX) {
177-
lctx->ladder.last.err = LADDER_INS_ERR_OVERFLOW;
178-
return 0;
179-
}
180-
return (int32_t) acc;
181-
}
182-
case LADDER_REGISTER_D: return lctx->registers.D[idx];
183-
case LADDER_REGISTER_R: return (int32_t) lctx->registers.R[idx];
184-
default: return 0;
185-
}
186-
}
187-
case LADDER_REGISTER_Q:
188-
case LADDER_REGISTER_I:
189-
case LADDER_REGISTER_IW:
190-
case LADDER_REGISTER_QW: {
191-
uint32_t mod = val->value.mp.module;
192-
uint8_t port = val->value.mp.port;
193-
uint32_t qty = 0;
194-
if (!safe_check_module_port(lctx, type, mod, port, &qty, &err)) {
195-
lctx->ladder.last.err = err;
196-
return 0;
197-
}
198-
switch (type) {
199-
case LADDER_REGISTER_Q: return (int32_t) lctx->output[mod].Q[port];
200-
case LADDER_REGISTER_I: return (int32_t) lctx->input[mod].I[port];
201-
case LADDER_REGISTER_IW: return lctx->input[mod].IW[port];
202-
case LADDER_REGISTER_QW: return lctx->output[mod].QW[port];
203-
default: return 0;
204-
}
205-
}
206-
case LADDER_REGISTER_S:
207-
return 0; // Strings not numeric; default 0
208-
case LADDER_REGISTER_INV:
209-
default:
210-
return 0;
211-
}
212-
}
213-
214-
static inline int32_t ladder_get_previous_value(ladder_ctx_t *lctx, uint32_t r, uint32_t c, uint32_t i) {
215-
if (lctx == NULL || lctx->exec_network == NULL) {
216-
return 0; // Safe default on invalid context
217-
}
218-
ladder_network_t *net = lctx->exec_network;
219-
if (r >= net->rows || c >= net->cols || i >= net->cells[r][c].data_qty) {
220-
return 0; // Safe default on OOB
221-
}
222-
ladder_register_t type = net->cells[r][c].data[i].type;
223-
ladder_value_t *val = &net->cells[r][c].data[i];
224-
225-
switch (type) {
226-
case LADDER_REGISTER_M:
227-
return (int32_t) lctx->prev_scan_vals.Mh[val->value.i32];
228-
case LADDER_REGISTER_Q: {
229-
uint32_t mod = val->value.mp.module;
230-
uint8_t port = val->value.mp.port;
231-
if (mod >= lctx->hw.io.fn_write_qty) {
232-
return 0;
233-
}
234-
// Null check for Qh to prevent dereference of unallocated array
235-
if (lctx->output[mod].Qh == NULL) {
236-
return 0; // Safe default if history not allocated
237-
}
238-
// Bounds check for port to prevent OOB access
239-
if (port >= lctx->output[mod].q_qty) {
240-
return 0; // Safe default on invalid port
241-
}
242-
return (int32_t) lctx->output[mod].Qh[port];
243-
}
244-
case LADDER_REGISTER_I: {
245-
uint32_t mod = val->value.mp.module;
246-
uint8_t port = val->value.mp.port;
247-
if (mod >= lctx->hw.io.fn_read_qty) {
248-
return 0;
249-
}
250-
// Null check for Ih to prevent dereference of unallocated array
251-
if (lctx->input[mod].Ih == NULL) {
252-
return 0; // Safe default if history not allocated
253-
}
254-
// Bounds check for port to prevent OOB access
255-
if (port >= lctx->input[mod].i_qty) {
256-
return 0; // Safe default on invalid port
257-
}
258-
return (int32_t) lctx->input[mod].Ih[port];
259-
}
260-
case LADDER_REGISTER_Cd:
261-
return (int32_t) lctx->prev_scan_vals.Cdh[val->value.i32];
262-
case LADDER_REGISTER_Cr:
263-
return (int32_t) lctx->prev_scan_vals.Crh[val->value.i32];
264-
case LADDER_REGISTER_Td:
265-
return (int32_t) lctx->prev_scan_vals.Tdh[val->value.i32];
266-
case LADDER_REGISTER_Tr:
267-
return (int32_t) lctx->prev_scan_vals.Trh[val->value.i32];
268-
// For other types like IW/QW/C/T/D/R/S, previous values may not be stored (e.g., no prev for accumulators or data regs).
269-
// Default to current value or 0; adjust based on requirements (e.g., add prev for D if needed).
270-
case LADDER_REGISTER_IW: {
271-
uint32_t mod = val->value.mp.module;
272-
uint8_t port = val->value.mp.port;
273-
if (mod >= lctx->hw.io.fn_read_qty)
274-
return 0;
275-
return lctx->input[mod].IW[port]; // No prev for words; use current
276-
}
277-
case LADDER_REGISTER_QW: {
278-
uint32_t mod = val->value.mp.module;
279-
uint8_t port = val->value.mp.port;
280-
if (mod >= lctx->hw.io.fn_write_qty)
281-
return 0;
282-
return lctx->output[mod].QW[port]; // No prev for words; use current
283-
}
284-
case LADDER_REGISTER_C:
285-
return (int32_t) lctx->registers.C[val->value.i32]; // No prev; use current
286-
case LADDER_REGISTER_T:
287-
return (int32_t) lctx->timers[val->value.i32].acc; // No prev acc; use current
288-
case LADDER_REGISTER_D:
289-
return lctx->registers.D[val->value.i32]; // No prev; use current
290-
case LADDER_REGISTER_R:
291-
return (int32_t) lctx->registers.R[val->value.i32]; // No prev; use current
292-
case LADDER_REGISTER_S:
293-
return 0; // Strings not applicable for previous
294-
case LADDER_REGISTER_NONE:
295-
case LADDER_REGISTER_INV:
296-
default:
297-
return 0;
298-
}
299-
}
300-
301-
static inline int32_t ladder_get_data_int32(ladder_ctx_t *lctx, uint32_t r, uint32_t c, uint32_t i) {
302-
if (lctx == NULL || lctx->exec_network == NULL) {
303-
return 0; // Safe default on invalid context
304-
}
305-
ladder_network_t *net = lctx->exec_network;
306-
if (r >= net->rows || c >= net->cols || i >= net->cells[r][c].data_qty) {
307-
return 0; // Safe default on OOB
308-
}
309-
ladder_register_t type = net->cells[r][c].data[i].type;
310-
ladder_value_t *val = &net->cells[r][c].data[i];
311-
312-
switch (type) {
313-
case LADDER_REGISTER_NONE:
314-
return val->value.i32;
315-
case LADDER_REGISTER_M:
316-
case LADDER_REGISTER_Q:
317-
case LADDER_REGISTER_I:
318-
case LADDER_REGISTER_Cd:
319-
case LADDER_REGISTER_Cr:
320-
case LADDER_REGISTER_Td:
321-
case LADDER_REGISTER_Tr:
322-
// Bool types: Treat false=0, true=1
323-
return (int32_t) ladder_get_data_value(lctx, r, c, i);
324-
case LADDER_REGISTER_IW: {
325-
uint32_t mod = val->value.mp.module;
326-
uint8_t port = val->value.mp.port;
327-
if (mod >= lctx->hw.io.fn_read_qty)
328-
return 0;
329-
return lctx->input[mod].IW[port];
330-
}
331-
case LADDER_REGISTER_QW: {
332-
uint32_t mod = val->value.mp.module;
333-
uint8_t port = val->value.mp.port;
334-
if (mod >= lctx->hw.io.fn_write_qty)
335-
return 0;
336-
return lctx->output[mod].QW[port];
337-
}
338-
case LADDER_REGISTER_C:
339-
return (int32_t) lctx->registers.C[val->value.i32];
340-
case LADDER_REGISTER_T:
341-
return (int32_t) lctx->timers[val->value.i32].acc; // Truncate u64 to i32 if needed
342-
case LADDER_REGISTER_D:
343-
return lctx->registers.D[val->value.i32];
344-
case LADDER_REGISTER_R:
345-
return (int32_t) lctx->registers.R[val->value.i32];
346-
case LADDER_REGISTER_S:
347-
return 0; // Strings not numeric
348-
case LADDER_REGISTER_INV:
349-
default:
350-
return 0;
351-
}
352-
}
353-
35445
/**
35546
* @def ladder_cell_data_exec
35647
* @brief
@@ -810,4 +501,4 @@ ladder_ins_err_t fn_FOREIGN(ladder_ctx_t *ladder_ctx, uint32_t column, uint32_t
810501
*/
811502
ladder_ins_err_t fn_TMOVE(ladder_ctx_t *ladder_ctx, uint32_t column, uint32_t row);
812503

813-
#endif /* LADDER_INSTRUCTIONS_H */
504+
#endif /* FN_COMMONS_H */

source/instructions/fn_ADD.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
1+
/*
2+
* Copyright 2025 Emiliano Gonzalez (egonzalez . hiperion @ gmail . com))
3+
* * Project Site: https://github.com/hiperiondev/ladderlib *
4+
*
5+
* This is based on other projects:
6+
* PLsi (https://github.com/ElPercha/PLsi)
7+
*
8+
* please contact their authors for more information.
9+
*
10+
* The MIT License (MIT)
11+
*
12+
* Permission is hereby granted, free of charge, to any person obtaining
13+
* a copy of this software and associated documentation files (the
14+
* "Software"), to deal in the Software without restriction, including
15+
* without limitation the rights to use, copy, modify, merge, publish,
16+
* distribute, sublicense, and/or sell copies of the Software, and to
17+
* permit persons to whom the Software is furnished to do so, subject to
18+
* the following conditions:
19+
*
20+
* The above copyright notice and this permission notice shall be
21+
* included in all copies or substantial portions of the Software.
22+
*
23+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30+
*
31+
*/
32+
133
#include <stdbool.h>
234
#include <stdint.h>
335

36+
#include "fn_commons.h"
437
#include "ladder.h"
538
#include "ladder_internals.h"
639
#include "ladder_instructions.h"

0 commit comments

Comments
 (0)