/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2023 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#include <math.h>
#include "co_cdh.h"
#include "co_dcli.h"
#include "co_string.h"
#include "co_time.h"
#include "rt_plc.h"
#include "rt_plc_arithm.h"
/* PLC RUTINER */
Sum
void sum_exec(plc_sThread* tp, pwr_sClass_sum* object)
{
#define sumsize 8
pwr_tFloat32** ptr; /* Pointer to ptr to input */
int i; /* Loopindex */
float sum; /* Result */
/* Initialize */
sum = object->Const;
ptr = &object->In1P;
/* SUM loop */
for (i = 0; i < sumsize; i++) {
if (*ptr != NULL)
sum += **ptr * object->FVect[i];
ptr = (pwr_tFloat32**)((char*)ptr + pwr_cInputOffset);
}
/* Result */
object->ActVal = sum;
}
MaxMin
void maxmin_exec(plc_sThread* tp, pwr_sClass_maxmin* object)
{
#define maxminsize 8
#define maxmin_maxfloat 1.E37
#define maxmin_minfloat -1.E37
float minval; /* Lowest value */
float maxval; /* Highest value */
int i; /* Loopcounter */
float** ptr; /* Pointer to ptr to digin */
/* Initialize */
ptr = &object->In1P;
minval = maxmin_maxfloat;
maxval = maxmin_minfloat;
/* MaxMin loop */
for (i = 0; i < maxminsize; i++) {
if (*ptr != NULL) {
if (**ptr > maxval)
maxval = **ptr;
if (**ptr < minval)
minval = **ptr;
}
ptr = (pwr_tFloat32**)((char*)ptr + pwr_cInputOffset);
}
/* Set Output */
object->MaxVal = maxval;
object->MinVal = minval;
}
Limit
void limit_exec(plc_sThread* tp, pwr_sClass_limit* object)
{
object->Max = *object->MaxP;
object->Min = *object->MinP;
object->In = *object->InP;
if (object->In > object->Max) {
object->ActVal = object->Max;
object->High = TRUE;
object->Low = FALSE;
} else if (object->In < object->Min) {
object->Low = TRUE;
if (object->Min <= object->Max) {
object->ActVal = object->Min;
object->High = FALSE;
} else {
object->ActVal = object->Max;
object->High = TRUE;
}
} else {
object->ActVal = object->In;
object->High = FALSE;
object->Low = FALSE;
}
}
Comph
void comph_exec(plc_sThread* tp, pwr_sClass_comph* object)
{
object->In = *object->InP;
object->Lim = *object->LimP;
if (object->High) {
if (object->In <= (object->Lim - object->Hysteres))
object->High = FALSE;
} else if (object->In > object->Lim)
object->High = TRUE;
}
Compl
void compl_exec(plc_sThread* tp, pwr_sClass_compl* object)
{
object->In = *object->InP;
object->Lim = *object->LimP;
if (object->Low) {
if (object->In >= (object->Lim + object->Hysteres))
object->Low = FALSE;
} else if (object->In < object->Lim)
object->Low = TRUE;
}
Select
void select_exec(plc_sThread* tp, pwr_sClass_select* object)
{
object->Control = *object->ControlP;
if (object->Control) {
object->ActVal = *object->HighP;
object->NotActVal = *object->LowP;
} else {
object->ActVal = *object->LowP;
object->NotActVal = *object->HighP;
}
}
Ramp
void ramp_init(pwr_sClass_ramp* object)
{
object->In = *object->InP;
object->ActVal = object->In;
}
/* New ramp_exec with RampUp used when absolute value is increasing */
/* and RampDown used when absolute value is decreasing */
/* New functionality will be used when new Boolean parameter 'RampUpAbs' */
/* is on. For Proview 3.0 we will use 'AccUp' not zero for new functionality */
/* If this parameter is zero the routine will workin the old way with */
/* RampUp for increasing and RampDown for decreasing */
/* 2001-03-13 Hans Werner */
void ramp_exec(plc_sThread* tp, pwr_sClass_ramp* object)
{
float limit1; /* First limit */
float limit2; /* Second limit at sign change */
float old; /* Actual start value */
float out; /* New output */
float scan; /* scantime in seconds */
/* Assume new output as unlimited as a start */
out = object->In = *object->InP; /* Get aimed value */
old = *object->FeedBP; /* Startvalue */
scan = *object->ScanTime; /* Get scantime */
if (out > old) /* Increase */
{
if (old >= 0.0) /* Positive rising even more */
{
limit1 = scan * object->RampUp;
if ((limit1 > 0.0) && (out > old + limit1))
out = old + limit1;
} else if (out <= 0.0) /* Negative rising towards zero */
{
if (object->RampUpAbs)
limit1 = scan * object->RampDown;
else
limit1 = scan * object->RampUp;
if ((limit1 > 0.0) && (out > old + limit1))
out = old + limit1;
} else /* From Neg to Pos */
{
if (object->RampUpAbs) {
limit1 = scan * object->RampDown;
limit2 = scan * object->RampUp;
} else
limit1 = limit2 = scan * object->RampUp;
if (limit1 <= 0.0) /* No limit up to zero */
{
if ((limit2 > 0.0) && (out > limit2))
out = limit2;
} else if (old <= -limit1) /* Will still not reach zero */
{
if (out > old + limit1)
out = old + limit1;
} else if (limit2 > 0) /* Use second limitation above zero */
{
if (old < -limit2)
out = 0.0;
else if (out > old + limit2)
out = old + limit2;
}
} /* End Neg to Pos */
} /* End Increasing */
else if (out < old) /* Decrease */
{
if (old <= 0.0) /* Negative falling even more */
{
if (object->RampUpAbs)
limit1 = scan * object->RampUp;
else
limit1 = scan * object->RampDown;
if ((limit1 > 0.0) && (out < old - limit1))
out = old - limit1;
} else if (out >= 0.0) /* Positive falling towards zero */
{
limit1 = scan * object->RampDown;
if ((limit1 > 0.0) && (out < old - limit1))
out = old - limit1;
} else /* From Pos to Neg */
{
if (object->RampUpAbs) {
limit1 = scan * object->RampDown;
limit2 = scan * object->RampUp;
} else
limit1 = limit2 = scan * object->RampDown;
if (limit1 <= 0.0) /* No limit down to zero */
{
if ((limit2 > 0.0) && (out < -limit2))
out = -limit2;
} else if (old >= limit1) /* Will still not reach zero */
{
if (out < old - limit1)
out = old - limit1;
} else if (limit2 > 0) /* Use second limitation below zero */
{
if (old > limit2)
out = 0.0;
else if (out < old - limit2)
out = old - limit2;
}
} /* End Neg to Pos */
} /* End Decreasing */
object->ActVal = out; /* New output */
}
Filter
void filter_init(pwr_sClass_filter* object)
{
object->In = *object->InP;
object->ActVal = object->In;
}
void filter_exec(plc_sThread* tp, pwr_sClass_filter* object)
{
float kd;
object->In = *object->InP;
if (object->FiltCon > 0.0) {
kd = 1.0 / (1.0 + *object->ScanTime / object->FiltCon);
object->ActVal
= *object->FeedBP + (object->In - *object->FeedBP) * (1.0 - kd);
} else
object->ActVal = object->In;
}
Speed
void speed_exec(plc_sThread* tp, pwr_sClass_speed* object)
{
float old;
old = object->In;
object->In = *object->InP;
object->ActVal = (object->In - old) / *object->ScanTime * object->TimFact;
}
Timint
void timint_exec(plc_sThread* tp, pwr_sClass_timint* object)
{
/* Clear ? */
if (*object->ClearP && !object->Clear) {
object->OldAcc = object->ActVal;
object->ActVal = 0;
}
object->Clear = *object->ClearP;
/* Ackumulate new value */
object->ActVal += *object->InP * *object->ScanTime / object->TimFact;
}
TimeMean
void timemean_exec(plc_sThread* tp, pwr_sClass_timemean* o)
{
if (*o->ResetP && !o->Reset) {
/* Reset */
o->ActVal = o->AccMean;
o->AccTime = 0;
}
o->Reset = *o->ResetP;
/* Calculate new value */
o->AccMean = (*o->InP * *o->ScanTime + o->AccMean * o->AccTime)
/ (*o->ScanTime + o->AccTime);
o->AccTime += *o->ScanTime;
}
Curve
void curve_exec(plc_sThread* tp, pwr_sClass_curve* object)
{
float x0 = 0.0;
float x1;
float y0 = 0.0;
float y1;
float number;
float* tabpointer;
/* Get input */
object->In = *object->InP;
if (object->TabP == NULL)
object->ActVal = object->In;
else
/* Get pointer to table, and number of pairs in table */
{
tabpointer = object->TabP;
number = *tabpointer++;
if (number <= 0)
object->ActVal = object->In;
else
/* Search in table */
{
x1 = *tabpointer++;
y1 = *tabpointer++;
if (object->In <= x1)
object->ActVal = y1;
else {
for (; (number > 1) && (object->In > x1); number--) {
x0 = x1;
x1 = *tabpointer++;
y0 = y1;
y1 = *tabpointer++;
}
if (object->In > x1)
object->ActVal = y1; /* End of table */
else
object->ActVal = y0
+ (y1 - y0) * (object->In - x0) / (x1 - x0); /* Interpollation */
}
}
}
}
Adelay
void adelay_init(pwr_sClass_adelay* object)
{
object->StoredNumbers = 0;
object->StoInd = -1;
object->Count = object->MaxCount;
object->ActVal = *object->InP;
}
void adelay_exec(plc_sThread* tp, pwr_sClass_adelay* object)
{
/* Local variables */
int maxindex;
int actindex;
int actoff;
maxindex = sizeof(object->TimVect) / 4;
/* Get input
*/
object->In = *object->InP;
object->Tim = *object->TimP;
/* Calculate average in each storeplace.
MaxCount is number of cycles before each shift
*/
object->Count++;
if (object->Count >= object->MaxCount) {
object->StoInd++;
if ((object->StoInd >= maxindex) || (object->StoInd < 0))
object->StoInd = 0;
if (object->StoredNumbers < maxindex)
object->StoredNumbers++;
object->Count = 0;
object->TimVect[object->StoInd] = object->In;
} else
object->TimVect[object->StoInd]
= (object->TimVect[object->StoInd] * object->Count + object->In)
/ (object->Count + 1);
/* Calculate position for output
*/
actoff = (object->Tim / tp->f_scan_time - object->Count) / object->MaxCount;
if (actoff >= object->StoredNumbers)
actoff = object->StoredNumbers - 1;
actindex = object->StoInd - actoff;
if (actindex < 0)
actindex += maxindex;
object->ActVal = object->TimVect[actindex];
}
PiSpeed
void pispeed_init(pwr_sClass_pispeed* object)
{
/* Read input */
object->PulsIn = *object->PulsInP;
}
void pispeed_exec(plc_sThread* tp, pwr_sClass_pispeed* object)
{
int piold; /* Old input */
/* Read input */
piold = object->PulsIn;
object->PulsIn = *object->PulsInP;
/* Calculate flow */
object->ActVal = (object->PulsIn - piold) * object->Gain * object->TimFact
/ *object->ScanTime;
}
DtoMask
void DtoMask_exec(plc_sThread* tp, pwr_sClass_DtoMask* object)
{
int i;
pwr_tBoolean *d, **dp;
pwr_tInt32 val = 0;
pwr_tInt32 m = 1;
d = &object->d1;
dp = &object->d1P;
for (i = 0; i < 32; i++) {
*d = **dp;
if (*d)
val |= m;
d = (pwr_tBoolean*)((char*)d + pwr_cInputOffset);
dp = (pwr_tBoolean**)((char*)dp + pwr_cInputOffset);
m = m << 1;
}
object->Mask = val;
}
MaskToD
void MaskToD_exec(plc_sThread* tp, pwr_sClass_MaskToD* object)
{
int i;
pwr_tInt32 m = 1;
pwr_tBoolean* d;
d = &object->od1;
object->Mask = *object->MaskP;
for (i = 0; i < 32; i++) {
if (object->Mask & m)
*d = TRUE;
else
*d = FALSE;
d++;
m = m << 1;
}
}
DtoEnum
void DtoEnum_exec(plc_sThread* tp, pwr_sClass_DtoEnum* object)
{
int i;
pwr_tBoolean *d, **dp;
pwr_tInt32 val = object->DefaultValue;
d = &object->d0;
dp = &object->d0P;
for (i = 0; i < 32; i++) {
*d = **dp;
if (*d) {
val = object->EnumValues[i];
break;
}
d = (pwr_tBoolean*)((char*)d + pwr_cInputOffset);
dp = (pwr_tBoolean**)((char*)dp + pwr_cInputOffset);
}
object->Enum = val;
}
EnumToD
void EnumToD_exec(plc_sThread* tp, pwr_sClass_EnumToD* object)
{
int i;
pwr_tBoolean* d;
d = &object->od0;
object->Enum = *object->EnumP;
for (i = 0; i < 32; i++) {
if (object->Enum == object->EnumValues[i])
*d = TRUE;
else
*d = FALSE;
d++;
}
}
Mod
void Mod_exec(plc_sThread* tp, pwr_sClass_Mod* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->ActVal = fmodf(o->In1, o->In2);
}
Equal
void Equal_exec(plc_sThread* tp, pwr_sClass_Equal* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (fabsf(o->In1 - o->In2) < FLT_EPSILON);
}
NotEqual
void NotEqual_exec(plc_sThread* tp, pwr_sClass_NotEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = !(fabsf(o->In1 - o->In2) < FLT_EPSILON);
}
GreaterEqual
void GreaterEqual_exec(plc_sThread* tp, pwr_sClass_GreaterEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 >= o->In2) || (fabsf(o->In1 - o->In2) < FLT_EPSILON);
}
GreaterThan
void GreaterThan_exec(plc_sThread* tp, pwr_sClass_GreaterThan* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 > o->In2);
}
LessEqual
void LessEqual_exec(plc_sThread* tp, pwr_sClass_LessEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 <= o->In2) || (fabsf(o->In1 - o->In2) < FLT_EPSILON);
}
LessThan
void LessThan_exec(plc_sThread* tp, pwr_sClass_LessThan* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 < o->In2);
}
IEqual
void IEqual_exec(plc_sThread* tp, pwr_sClass_IEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 == o->In2);
}
INotEqual
void INotEqual_exec(plc_sThread* tp, pwr_sClass_INotEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 != o->In2);
}
IGreaterEqual
void IGreaterEqual_exec(plc_sThread* tp, pwr_sClass_IGreaterEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 >= o->In2);
}
IGreaterThan
void IGreaterThan_exec(plc_sThread* tp, pwr_sClass_IGreaterThan* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 > o->In2);
}
ILessEqual
void ILessEqual_exec(plc_sThread* tp, pwr_sClass_ILessEqual* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 <= o->In2);
}
ILessThan
void ILessThan_exec(plc_sThread* tp, pwr_sClass_ILessThan* o)
{
o->In1 = *o->In1P;
o->In2 = *o->In2P;
o->Status = (o->In1 < o->In2);
}
IAdd
void IAdd_exec(plc_sThread* tp, pwr_sClass_IAdd* o)
{
#define IADD_SIZE 8
int i;
pwr_tInt32** inp = &o->In1P;
pwr_tInt32 sum = 0;
for (i = 0; i < IADD_SIZE; i++) {
sum += **inp;
inp = (pwr_tInt32**)((char*)inp + pwr_cInputOffset);
}
o->ActVal = sum;
}
IMul
void IMul_exec(plc_sThread* tp, pwr_sClass_IMul* o)
{
#define IMUL_SIZE 8
int i;
pwr_tInt32** inp = &o->In1P;
pwr_tInt32 result = **inp;
for (i = 1; i < IMUL_SIZE; i++) {
inp = (pwr_tInt32**)((char*)inp + pwr_cInputOffset);
result *= **inp;
}
o->ActVal = result;
}
ISub
void ISub_exec(plc_sThread* tp, pwr_sClass_ISub* o)
{
o->ActVal = *o->In1P - *o->In2P;
}
IDiv
void IDiv_exec(plc_sThread* tp, pwr_sClass_IDiv* o)
{
if (*o->In2P == 0)
o->ActVal = 0;
else
o->ActVal = *o->In1P / *o->In2P;
}
IMax
void IMax_exec(plc_sThread* tp, pwr_sClass_IMax* o)
{
#define IMAX_SIZE 8
int i;
pwr_tInt32** inp = &o->In1P;
pwr_tInt32 result = INT_MIN;
for (i = 0; i < IMAX_SIZE; i++) {
if (**inp > result)
result = **inp;
inp = (pwr_tInt32**)((char*)inp + pwr_cInputOffset);
}
o->ActVal = result;
}
IMin
void IMin_exec(plc_sThread* tp, pwr_sClass_IMin* o)
{
#define IMIN_SIZE 8
int i;
pwr_tInt32** inp = &o->In1P;
pwr_tInt32 result = INT_MAX;
for (i = 0; i < IMIN_SIZE; i++) {
if (**inp < result)
result = **inp;
inp = (pwr_tInt32**)((char*)inp + pwr_cInputOffset);
}
o->ActVal = result;
}
ISel
void ISel_exec(plc_sThread* tp, pwr_sClass_ISel* o)
{
o->Control = *o->ControlP;
if (o->Control)
o->ActVal = *o->In1P;
else
o->ActVal = *o->In2P;
}
ILimit
void ILimit_exec(plc_sThread* tp, pwr_sClass_ILimit* o)
{
o->Max = *o->MaxP;
o->Min = *o->MinP;
o->In = *o->InP;
if (o->In > o->Max) {
o->ActVal = o->Max;
o->High = TRUE;
o->Low = FALSE;
} else if (o->In < o->Min) {
o->Low = TRUE;
if (o->Min <= o->Max) {
o->ActVal = o->Min;
o->High = FALSE;
} else {
o->ActVal = o->Max;
o->High = TRUE;
}
} else {
o->ActVal = o->In;
o->High = FALSE;
o->Low = FALSE;
}
}
IMux
void IMux_exec(plc_sThread* tp, pwr_sClass_IMux* o)
{
#define IMUX_SIZE 24
int idx;
pwr_tInt32** inp = &o->In0P;
idx = o->Index = *o->IndexP;
idx = idx < 0 ? 0 : (idx > IMUX_SIZE - 1 ? IMUX_SIZE - 1 : idx);
inp = (pwr_tInt32**)((char*)inp + idx * pwr_cInputOffset);
o->ActVal = **inp;
}
Mux
void Mux_exec(plc_sThread* tp, pwr_sClass_Mux* o)
{
#define MUX_SIZE 24
int idx;
pwr_tFloat32** inp = &o->In0P;
idx = o->Index = *o->IndexP;
idx = idx < 0 ? 0 : (idx > MUX_SIZE - 1 ? MUX_SIZE - 1 : idx);
inp = (pwr_tFloat32**)((char*)inp + idx * pwr_cInputOffset);
o->ActVal = **inp;
}
Demux
void Demux_exec(plc_sThread* tp, pwr_sClass_Demux* o)
{
#define DEMUX_SIZE 24
int idx, i;
pwr_tFloat32* outp = &o->Out0;
idx = o->Index = *o->IndexP;
for (i = 0; i < DEMUX_SIZE; i++) {
if (i == idx)
*outp = *o->InP;
else
*outp = 0;
outp++;
}
}
IDemux
void IDemux_exec(plc_sThread* tp, pwr_sClass_IDemux* o)
{
#define IDEMUX_SIZE 24
int idx, i;
pwr_tInt32* outp = &o->Out0;
idx = o->Index = *o->IndexP;
for (i = 0; i < IDEMUX_SIZE; i++) {
if (i == idx)
*outp = *o->InP;
else
*outp = 0;
outp++;
}
}
Add
void Add_exec(plc_sThread* tp, pwr_sClass_Add* o)
{
#define ADD_SIZE 8
int i;
pwr_tFloat32** inp = &o->In1P;
pwr_tFloat32 sum = 0;
for (i = 0; i < ADD_SIZE; i++) {
sum += **inp;
inp = (pwr_tFloat32**)((char*)inp + pwr_cInputOffset);
}
o->ActVal = sum;
}
Mul
void Mul_exec(plc_sThread* tp, pwr_sClass_Mul* o)
{
#define MUL_SIZE 8
int i;
pwr_tFloat32** inp = &o->In1P;
pwr_tFloat32 result = **inp;
for (i = 1; i < MUL_SIZE; i++) {
inp = (pwr_tFloat32**)((char*)inp + pwr_cInputOffset);
result *= **inp;
}
o->ActVal = result;
}
Sub
void Sub_exec(plc_sThread* tp, pwr_sClass_Sub* o)
{
o->ActVal = *o->In1P - *o->In2P;
}
Div
void Div_exec(plc_sThread* tp, pwr_sClass_Div* o)
{
o->ActVal = *o->In1P / *o->In2P;
}
Max
void Max_exec(plc_sThread* tp, pwr_sClass_Max* o)
{
#define AMAX_SIZE 8
int i;
pwr_tFloat32** inp = &o->In1P;
pwr_tFloat32 result = -1E37;
for (i = 0; i < AMAX_SIZE; i++) {
if (**inp > result)
result = **inp;
inp = (pwr_tFloat32**)((char*)inp + pwr_cInputOffset);
}
o->ActVal = result;
}
Min
void Min_exec(plc_sThread* tp, pwr_sClass_Min* o)
{
#define AMIN_SIZE 8
int i;
pwr_tFloat32** inp = &o->In1P;
pwr_tFloat32 result = 1E37;
for (i = 0; i < AMIN_SIZE; i++) {
if (**inp < result)
result = **inp;
inp = (pwr_tFloat32**)((char*)inp + pwr_cInputOffset);
}
o->ActVal = result;
}
Random
void Random_exec(plc_sThread* tp, pwr_sClass_Random* o)
{
if ( o->CondP == &o->Cond)
o->ActVal = o->MinValue + (float)(rand())/RAND_MAX * (o->MaxValue - o->MinValue);
else {
if ( *o->CondP && !o->CondOld)
o->ActVal = o->MinValue + (float)(rand())/RAND_MAX * (o->MaxValue - o->MinValue);
o->CondOld = *o->CondP;
}
}
BwShiftLeft
void BwShiftLeft_exec(plc_sThread* tp, pwr_sClass_BwShiftLeft* o)
{
o->Out = ((unsigned int)*o->InP) << (*o->NumP);
}
BwShiftRight
void BwShiftRight_exec(plc_sThread* tp, pwr_sClass_BwShiftRight* o)
{
o->Out = ((unsigned int)*o->InP) >> (*o->NumP);
}
BwRotateRight
void BwRotateRight_exec(plc_sThread* tp, pwr_sClass_BwRotateRight* o)
{
o->Out = ((unsigned int)(*o->InP) << (32 - *o->NumP))
| ((unsigned int)(*o->InP) >> (*o->NumP));
}
BwRotateLeft
void BwRotateLeft_exec(plc_sThread* tp, pwr_sClass_BwRotateLeft* o)
{
o->Out = ((unsigned int)(*o->InP) >> (32 - *o->NumP))
| ((unsigned int)(*o->InP) << (*o->NumP));
}
AtSel
void AtSel_exec(plc_sThread* tp, pwr_sClass_AtSel* o)
{
o->Control = *o->ControlP;
if (o->Control)
o->ActVal = *o->In1P;
else
o->ActVal = *o->In2P;
}
DtSel
void DtSel_exec(plc_sThread* tp, pwr_sClass_DtSel* o)
{
o->Control = *o->ControlP;
if (o->Control)
o->ActVal = *o->In1P;
else
o->ActVal = *o->In2P;
}
AtMux
void AtMux_exec(plc_sThread* tp, pwr_sClass_AtMux* o)
{
#define ATMUX_SIZE 24
int idx;
pwr_tTime** inp = &o->In0P;
idx = o->Index = *o->IndexP;
idx = idx < 0 ? 0 : (idx > ATMUX_SIZE - 1 ? ATMUX_SIZE - 1 : idx);
inp = (pwr_tTime**)((char*)inp + idx * pwr_cInputOffsetAt);
o->ActVal = **inp;
}
DtMux
void DtMux_exec(plc_sThread* tp, pwr_sClass_DtMux* o)
{
#define DTMUX_SIZE 24
int idx;
pwr_tDeltaTime** inp = &o->In0P;
idx = o->Index = *o->IndexP;
idx = idx < 0 ? 0 : (idx > DTMUX_SIZE - 1 ? DTMUX_SIZE - 1 : idx);
inp = (pwr_tDeltaTime**)((char*)inp + idx * pwr_cInputOffsetDt);
o->ActVal = **inp;
}
AtMax
void AtMax_exec(plc_sThread* tp, pwr_sClass_AtMax* o)
{
#define ATMAX_SIZE 8
int i;
pwr_tTime** inp = &o->In1P;
pwr_tTime result = PWR_ATTIME_MIN;
for (i = 0; i < ATMAX_SIZE; i++) {
if (time_Acomp_NE(*inp, &result) == 1)
result = **inp;
inp = (pwr_tTime**)((char*)inp + pwr_cInputOffsetAt);
}
o->ActVal = result;
}
AtMin
void AtMin_exec(plc_sThread* tp, pwr_sClass_AtMin* o)
{
#define ATMIN_SIZE 8
int i;
pwr_tTime** inp = &o->In1P;
pwr_tTime result = PWR_ATTIME_MAX;
for (i = 0; i < ATMIN_SIZE; i++) {
if (time_Acomp_NE(*inp, &result) == -1)
result = **inp;
inp = (pwr_tTime**)((char*)inp + pwr_cInputOffsetAt);
}
o->ActVal = result;
}
DtMax
void DtMax_exec(plc_sThread* tp, pwr_sClass_DtMax* o)
{
#define DTMAX_SIZE 8
int i;
pwr_tDeltaTime** inp = &o->In1P;
pwr_tDeltaTime result = PWR_DTTIME_MIN;
for (i = 0; i < DTMAX_SIZE; i++) {
if (time_Dcomp_NE(*inp, &result) == 1)
result = **inp;
inp = (pwr_tDeltaTime**)((char*)inp + pwr_cInputOffsetDt);
}
o->ActVal = result;
}
DtMin
void DtMin_exec(plc_sThread* tp, pwr_sClass_DtMin* o)
{
#define DTMIN_SIZE 8
int i;
pwr_tDeltaTime** inp = &o->In1P;
pwr_tDeltaTime result = PWR_DTTIME_MAX;
for (i = 0; i < DTMIN_SIZE; i++) {
if (time_Dcomp_NE(*inp, &result) == -1)
result = **inp;
inp = (pwr_tDeltaTime**)((char*)inp + pwr_cInputOffsetDt);
}
o->ActVal = result;
}
AtLimit
void AtLimit_exec(plc_sThread* tp, pwr_sClass_AtLimit* o)
{
o->Max = *o->MaxP;
o->Min = *o->MinP;
o->In = *o->InP;
if (time_Acomp_NE(&o->In, &o->Max) == 1) {
o->ActVal = o->Max;
o->High = TRUE;
o->Low = FALSE;
} else if (time_Acomp_NE(&o->In, &o->Min) == -1) {
o->Low = TRUE;
if (time_Acomp_NE(&o->Min, &o->Max) <= 0) {
o->ActVal = o->Min;
o->High = FALSE;
} else {
o->ActVal = o->Max;
o->High = TRUE;
}
} else {
o->ActVal = o->In;
o->High = FALSE;
o->Low = FALSE;
}
}
DtLimit
void DtLimit_exec(plc_sThread* tp, pwr_sClass_DtLimit* o)
{
o->Max = *o->MaxP;
o->Min = *o->MinP;
o->In = *o->InP;
if (time_Dcomp_NE(&o->In, &o->Max) == 1) {
o->ActVal = o->Max;
o->High = TRUE;
o->Low = FALSE;
} else if (time_Dcomp_NE(&o->In, &o->Min) == -1) {
o->Low = TRUE;
if (time_Dcomp_NE(&o->Min, &o->Max) <= 0) {
o->ActVal = o->Min;
o->High = FALSE;
} else {
o->ActVal = o->Max;
o->High = TRUE;
}
} else {
o->ActVal = o->In;
o->High = FALSE;
o->Low = FALSE;
}
}
AtDemux
void AtDemux_exec(plc_sThread* tp, pwr_sClass_AtDemux* o)
{
#define ATDEMUX_SIZE 24
int idx, i;
pwr_tTime* outp = &o->Out0;
idx = o->Index = *o->IndexP;
for (i = 0; i < ATDEMUX_SIZE; i++) {
if (i == idx)
*outp = *o->InP;
else
*outp = pwr_cNTime;
outp++;
}
}
DtDemux
void DtDemux_exec(plc_sThread* tp, pwr_sClass_DtDemux* o)
{
int idx, i;
pwr_tDeltaTime* outp = &o->Out0;
idx = o->Index = *o->IndexP;
for (i = 0; i < ATDEMUX_SIZE; i++) {
if (i == idx)
*outp = *o->InP;
else
*outp = pwr_cNDeltaTime;
outp++;
}
}
StrSel
void StrSel_exec(plc_sThread* tp, pwr_sClass_StrSel* o)
{
o->Control = *o->ControlP;
if (o->Control)
strncpy(o->ActVal, *o->In1P, sizeof(o->ActVal));
else
strncpy(o->ActVal, *o->In2P, sizeof(o->ActVal));
}
StrMux
void StrMux_exec(plc_sThread* tp, pwr_sClass_StrMux* o)
{
#define STRMUX_SIZE 24
int idx;
pwr_tString80** inp = &o->In0P;
idx = o->Index = *o->IndexP;
idx = idx < 0 ? 0 : (idx > STRMUX_SIZE - 1 ? STRMUX_SIZE - 1 : idx);
inp = (pwr_tString80**)((char*)inp + idx * pwr_cInputOffsetStr);
strncpy(o->ActVal, **inp, sizeof(o->ActVal));
}
StrEqual
void StrEqual_exec(plc_sThread* tp, pwr_sClass_StrEqual* o)
{
if (o->CaseSensitive)
o->Status = (streq(*o->In1P, *o->In2P));
else
o->Status = (str_NoCaseStrcmp(*o->In1P, *o->In2P) == 0);
}
StrNotEqual
void StrNotEqual_exec(plc_sThread* tp, pwr_sClass_StrNotEqual* o)
{
if (o->CaseSensitive)
o->Status = (!streq(*o->In1P, *o->In2P));
else
o->Status = (str_NoCaseStrcmp(*o->In1P, *o->In2P) != 0);
}
StrAdd
void StrAdd_exec(plc_sThread* tp, pwr_sClass_StrAdd* o)
{
#define STRADD_SIZE 8
int i;
pwr_tString80** inp = &o->In1P;
pwr_tString80 sum = "";
for (i = 0; i < STRADD_SIZE; i++) {
strncat(sum, **inp, sizeof(sum) - strlen(sum) - 1);
inp = (pwr_tString80**)((char*)inp + pwr_cInputOffsetStr);
}
strncpy(o->ActVal, sum, sizeof(o->ActVal));
o->ActVal[sizeof(o->ActVal) - 1] = 0;
}
StrTrim
void StrTrim_exec(plc_sThread* tp, pwr_sClass_StrTrim* o)
{
str_trim(o->ActVal, *o->InP);
}
StrParse
void StrParse_exec(plc_sThread* tp, pwr_sClass_StrParse* o)
{
#define STRPARSE_SIZE 10
int i, tokens;
tokens = dcli_parse(*o->InP, o->Delimiter, "", o->Token1, STRPARSE_SIZE,
sizeof(o->Token1), 1);
for (i = tokens; i < STRPARSE_SIZE; i++)
*(char*)((char*)o->Token1 + i * sizeof(o->Token1)) = 0;
}