README.md
Rendering markdown...
PROGRAM program0
VAR
CoilStatus AT %QX0.0 : BOOL := TRUE;
Output AT %QX1.2 : BOOL := TRUE;
END_VAR
IF CoilStatus THEN
Output := FALSE;
ELSE
Output := TRUE;
END_IF;
END_PROGRAM
CONFIGURATION Config0
RESOURCE Res0 ON PLC
TASK task0(INTERVAL := T#20ms,PRIORITY := 0);
PROGRAM instance0 WITH task0 : program0;
END_RESOURCE
END_CONFIGURATION
(*DBG:char md5[] = "40f2337abaef437c400ee23c19c86ce0";*)
(*DBG:/**)
(*DBG: * This file is part of OpenPLC Runtime*)
(*DBG: **)
(*DBG: * Copyright (C) 2023 Autonomy, GP Orcullo*)
(*DBG: * Based on the work by GP Orcullo on Beremiz for uC*)
(*DBG: **)
(*DBG: * This program is free software; you can redistribute it and/or*)
(*DBG: * modify it under the terms of the GNU General Public License*)
(*DBG: * as published by the Free Software Foundation; either version 2*)
(*DBG: * of the License, or (at your option) any later version.*)
(*DBG: **)
(*DBG: * This program is distributed in the hope that it will be useful,*)
(*DBG: * but WITHOUT ANY WARRANTY; without even the implied warranty of*)
(*DBG: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the*)
(*DBG: * GNU General Public License for more details.*)
(*DBG: **)
(*DBG: * You should have received a copy of the GNU General Public License*)
(*DBG: * along with this program; If not, see <http://www.gnu.org/licenses/>.*)
(*DBG: **)
(*DBG: */*)
(*DBG:*)
(*DBG:#include <stdbool.h>*)
(*DBG:*)
(*DBG:#include "iec_types_all.h"*)
(*DBG:#include "POUS.h"*)
(*DBG:*)
(*DBG:#define SAME_ENDIANNESS 0*)
(*DBG:#define REVERSE_ENDIANNESS 1*)
(*DBG:*)
(*DBG:uint8_t endianness;*)
(*DBG:*)
(*DBG:*)
(*DBG:extern PROGRAM0 RES0__INSTANCE0;*)
(*DBG:*)
(*DBG:static const struct {*)
(*DBG: void *ptr;*)
(*DBG: __IEC_types_enum type;*)
(*DBG:} debug_vars[] = {*)
(*DBG: {&(RES0__INSTANCE0.COILSTATUS), BOOL_O_ENUM},*)
(*DBG: {&(RES0__INSTANCE0.OUTPUT), BOOL_O_ENUM},*)
(*DBG:};*)
(*DBG:*)
(*DBG:#define VAR_COUNT 2*)
(*DBG:*)
(*DBG:uint16_t get_var_count(void)*)
(*DBG:{*)
(*DBG: return VAR_COUNT;*)
(*DBG:}*)
(*DBG:*)
(*DBG:size_t get_var_size(size_t idx)*)
(*DBG:{*)
(*DBG: if (idx >= VAR_COUNT)*)
(*DBG: {*)
(*DBG: return 0;*)
(*DBG: }*)
(*DBG: switch (debug_vars[idx].type) {*)
(*DBG: case BOOL_O_ENUM:*)
(*DBG: return sizeof(BOOL);*)
(*DBG: default:*)
(*DBG: return 0;*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)
(*DBG:void *get_var_addr(size_t idx)*)
(*DBG:{*)
(*DBG: void *ptr = debug_vars[idx].ptr;*)
(*DBG:*)
(*DBG: switch (debug_vars[idx].type) {*)
(*DBG: case BOOL_O_ENUM:*)
(*DBG: return (void *)((((__IEC_BOOL_p *) ptr)->flags & __IEC_FORCE_FLAG) *)
(*DBG: ? &(((__IEC_BOOL_p *) ptr)->fvalue) *)
(*DBG: : ((__IEC_BOOL_p *) ptr)->value);*)
(*DBG: default:*)
(*DBG: return 0;*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)
(*DBG:void force_var(size_t idx, bool forced, void *val)*)
(*DBG:{*)
(*DBG: void *ptr = debug_vars[idx].ptr;*)
(*DBG:*)
(*DBG: if (forced) {*)
(*DBG: size_t var_size = get_var_size(idx);*)
(*DBG: switch (debug_vars[idx].type) {*)
(*DBG: case BOOL_O_ENUM: {*)
(*DBG: memcpy((((__IEC_BOOL_p *) ptr)->value), val, var_size);*)
(*DBG: //*(((__IEC_BOOL_p *) ptr)->value) = *((BOOL *) val);*)
(*DBG: ((__IEC_BOOL_p *) ptr)->flags |= __IEC_FORCE_FLAG;*)
(*DBG: break;*)
(*DBG: }*)
(*DBG: default:*)
(*DBG: break;*)
(*DBG: }*)
(*DBG: } else {*)
(*DBG: switch (debug_vars[idx].type) {*)
(*DBG: case BOOL_O_ENUM:*)
(*DBG: ((__IEC_BOOL_p *) ptr)->flags &= ~__IEC_FORCE_FLAG;*)
(*DBG: break;*)
(*DBG: default:*)
(*DBG: break;*)
(*DBG: }*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)
(*DBG:void swap_bytes(void *ptr, size_t size) *)
(*DBG:{*)
(*DBG: uint8_t *bytePtr = (uint8_t *)ptr;*)
(*DBG: size_t i;*)
(*DBG: for (i = 0; i < size / 2; ++i) *)
(*DBG: {*)
(*DBG: uint8_t temp = bytePtr[i];*)
(*DBG: bytePtr[i] = bytePtr[size - 1 - i];*)
(*DBG: bytePtr[size - 1 - i] = temp;*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)
(*DBG:void trace_reset(void)*)
(*DBG:{*)
(*DBG: for (size_t i=0; i < VAR_COUNT; i++) *)
(*DBG: {*)
(*DBG: force_var(i, false, 0);*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)
(*DBG:void set_trace(size_t idx, bool forced, void *val)*)
(*DBG:{*)
(*DBG: if (idx >= 0 && idx < VAR_COUNT) *)
(*DBG: {*)
(*DBG: if (endianness == REVERSE_ENDIANNESS)*)
(*DBG: {*)
(*DBG: // Aaaaarghhhh... Stupid AVR is Big Endian.*)
(*DBG: swap_bytes(val, get_var_size(idx));*)
(*DBG: }*)
(*DBG:*)
(*DBG: force_var(idx, forced, val);*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)
(*DBG:void set_endianness(uint8_t value)*)
(*DBG:{*)
(*DBG: if (value == SAME_ENDIANNESS || value == REVERSE_ENDIANNESS)*)
(*DBG: {*)
(*DBG: endianness = value;*)
(*DBG: }*)
(*DBG:}*)
(*DBG:*)