424 lines
10 KiB
C
424 lines
10 KiB
C
/**
|
|
* @file GoDigital.c
|
|
*
|
|
* @internal
|
|
* Copyright (C) 2016-2021 by LMI Technologies Inc.
|
|
* Licensed under the MIT License.
|
|
* Redistributed files must retain the above copyright notice.
|
|
*/
|
|
#include <GoSdk/Outputs/GoDigital.h>
|
|
#include <GoSdk/GoUtils.h>
|
|
#include <GoSdk/GoSensor.h>
|
|
|
|
kBeginClassEx(Go, GoDigital)
|
|
kAddVMethod(GoDigital, kObject, VRelease)
|
|
kEndClassEx()
|
|
|
|
GoFx(kStatus) GoDigital_Construct(GoDigital* digital, kObject sensor, kAlloc allocator)
|
|
{
|
|
kAlloc alloc = kAlloc_Fallback(allocator);
|
|
kStatus status;
|
|
|
|
kCheck(kAlloc_GetObject(alloc, kTypeOf(GoDigital), digital));
|
|
|
|
if (!kSuccess(status = GoDigital_Init(*digital, kTypeOf(GoDigital), sensor, alloc)))
|
|
{
|
|
kAlloc_FreeRef(alloc, digital);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_Init(GoDigital digital, kType type, kObject sensor, kAlloc alloc)
|
|
{
|
|
kObjR(GoDigital, digital);
|
|
kStatus exception;
|
|
|
|
kCheck(kObject_Init(digital, type, alloc));
|
|
kZero(obj->xml);
|
|
kZero(obj->xmlItem);
|
|
kZero(obj->decisionOptions);
|
|
kZero(obj->decisionSources);
|
|
obj->passMode = GO_DIGITAL_PASS_TRUE;
|
|
obj->scheduleEnabled = kFALSE;
|
|
obj->signalType = GO_DIGITAL_SIGNAL_PULSED;
|
|
obj->delay = 0;
|
|
obj->delayDomain = GO_OUTPUT_DELAY_DOMAIN_TIME;
|
|
obj->event = 0;
|
|
kZero(obj->pulseWidth);
|
|
obj->invertOutput = kFALSE;
|
|
obj->outputUsed = kFALSE;
|
|
|
|
obj->sensor = sensor;
|
|
|
|
kTry
|
|
{
|
|
kTest(kArrayList_Construct(&obj->decisionOptions, kTypeOf(k32u), 0, alloc));
|
|
kTest(kArrayList_Construct(&obj->decisionSources, kTypeOf(k32u), 0, alloc));
|
|
}
|
|
kCatch(&exception)
|
|
{
|
|
GoDigital_VRelease(digital);
|
|
kEndCatch(exception);
|
|
}
|
|
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_VRelease(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
kCheck(kDestroyRef(&obj->decisionOptions));
|
|
kCheck(kDestroyRef(&obj->decisionSources));
|
|
|
|
kCheck(kObject_VRelease(digital));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_Read(GoDigital digital, kXml xml, kXmlItem item)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
kChar* text = kNULL;
|
|
kXmlItem tempItem = kNULL;
|
|
kSize textCapacity = GO_OUTPUT_SOURCE_TEXT_CAPACITY;
|
|
k32u temp32u;
|
|
|
|
obj->xml = xml;
|
|
obj->xmlItem = item;
|
|
|
|
kTry
|
|
{
|
|
kTest(kObject_GetMemZero(digital, sizeof(kChar) * textCapacity, &text));
|
|
|
|
kTest(GoConfig_ReadAttrBoolOptional(xml, item, "used", kTRUE, &obj->outputUsed));;
|
|
|
|
tempItem = kXml_Child(xml, item, "Measurements");
|
|
if (!kIsNull(tempItem))
|
|
{
|
|
kTest(kXml_AttrText(xml, tempItem, "options", text, textCapacity));
|
|
kTest(GoOptionList_ParseList32u(text, obj->decisionOptions));
|
|
kTest(kXml_ItemText(xml, tempItem, text, textCapacity));
|
|
kTest(GoOptionList_ParseList32u(text, obj->decisionSources));
|
|
}
|
|
|
|
kTest(kXml_Child32u(xml, item, "Event", &temp32u));
|
|
obj->event = (k32s)temp32u;
|
|
kTest(kXml_Child32u(xml, item, "SignalType", &temp32u));
|
|
obj->signalType = (k32s)temp32u;
|
|
kTest(kXml_Child32s(xml, item, "ScheduleEnabled", &obj->scheduleEnabled));
|
|
|
|
tempItem = kXml_Child(xml, item, "PulseWidth");
|
|
if (!kIsNull(tempItem))
|
|
{
|
|
kTest(kXml_Item32u(xml, tempItem, &obj->pulseWidth.value));
|
|
kTest(kXml_Attr32u(xml, tempItem, "min", &obj->pulseWidth.min));
|
|
kTest(kXml_Attr32u(xml, tempItem, "max", &obj->pulseWidth.max));
|
|
}
|
|
|
|
kTest(kXml_Child32s(xml, item, "PassMode", &obj->passMode));
|
|
kTest(kXml_Child64s(xml, item, "Delay", &obj->delay));
|
|
kTest(kXml_Child32s(xml, item, "DelayDomain", &obj->delayDomain));
|
|
|
|
if (kXml_ChildExists(xml, item, "Inverted"))
|
|
{
|
|
kTest(kXml_ChildBool(xml, item, "Inverted", &obj->invertOutput));
|
|
}
|
|
}
|
|
kFinally
|
|
{
|
|
kObject_FreeMem(digital, text);
|
|
kEndFinally();
|
|
}
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_Write(GoDigital digital, kXml xml, kXmlItem item)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
kChar* text = kNULL;
|
|
kSize textCapacity = GO_OUTPUT_SOURCE_TEXT_CAPACITY;
|
|
|
|
kTry
|
|
{
|
|
kTest(kObject_GetMemZero(digital, sizeof(kChar) * textCapacity, &text));
|
|
|
|
kTest(GoOptionList_Format32u(kArrayList_DataT(obj->decisionSources, k32u), kArrayList_Count(obj->decisionSources), text, textCapacity));
|
|
kTest(kXml_SetChildText(xml, item, "Measurements", text));
|
|
|
|
kTest(kXml_SetChild32u(xml, item, "Event", obj->event));
|
|
kTest(kXml_SetChild32u(xml, item, "SignalType", obj->signalType));
|
|
kTest(kXml_SetChild32u(xml, item, "ScheduleEnabled", obj->scheduleEnabled));
|
|
kTest(kXml_SetChild32u(xml, item, "PulseWidth", obj->pulseWidth.value));
|
|
kTest(kXml_SetChild32s(xml, item, "PassMode", obj->passMode));
|
|
kTest(kXml_SetChild64s(xml, item, "Delay", obj->delay));
|
|
kTest(kXml_SetChild32s(xml, item, "DelayDomain", obj->delayDomain));
|
|
kTest(kXml_SetChildBool(xml, item, "Inverted", obj->invertOutput));
|
|
}
|
|
kFinally
|
|
{
|
|
kObject_FreeMem(digital, text);
|
|
kEndFinally();
|
|
}
|
|
|
|
//Forwards Compatibility
|
|
kCheck(GoUtils_XmlMerge(obj->xml, obj->xmlItem, xml, item));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetEvent(GoDigital digital, GoDigitalEvent event)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->event = event;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(GoDigitalEvent) GoDigital_Event(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->event;
|
|
}
|
|
|
|
GoFx(kArrayList) GoDigital_OptionList(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->decisionOptions;
|
|
}
|
|
|
|
GoFx(kSize) GoDigital_OptionCount(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return kArrayList_Count(obj->decisionOptions);
|
|
}
|
|
|
|
GoFx(k32u) GoDigital_OptionAt(GoDigital digital, kSize index)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
kAssert(index < GoDigital_OptionCount(digital));
|
|
|
|
return kArrayList_AsT(obj->decisionOptions, index, k32u);
|
|
}
|
|
|
|
GoFx(kSize) GoDigital_SourceCount(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return kArrayList_Count(obj->decisionSources);
|
|
}
|
|
|
|
GoFx(k32u) GoDigital_SourceAt(GoDigital digital, kSize index)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
kAssert(index < GoDigital_SourceCount(digital));
|
|
|
|
return kArrayList_AsT(obj->decisionSources, index, k32u);
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_AddSource(GoDigital digital, k32u sourceId)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
kArrayList options = GoDigital_OptionList(digital);
|
|
|
|
kCheck(GoOptionList_Check32u(kArrayList_DataT(options, const k32u), kArrayList_Count(options), sourceId));
|
|
kCheck(kArrayList_AddT(obj->decisionSources, &sourceId));
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_RemoveSource(GoDigital digital, kSize index)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
kCheck(kArrayList_Discard(obj->decisionSources, index));
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_ClearSources(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
kCheck(kArrayList_Clear(obj->decisionSources));
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetPassMode(GoDigital digital, GoDigitalPass pass)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->passMode = pass;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(GoDigitalPass) GoDigital_PassMode(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->passMode;
|
|
}
|
|
|
|
GoFx(k32u) GoDigital_PulseWidthLimitMin(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->pulseWidth.min;
|
|
}
|
|
|
|
GoFx(k32u) GoDigital_PulseWidthLimitMax(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->pulseWidth.max;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetPulseWidth(GoDigital digital, k32u width)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
kCheckArgs(GoUtils_MinMax_(width, GoDigital_PulseWidthLimitMin(digital), GoDigital_PulseWidthLimitMax(digital)));
|
|
|
|
obj->pulseWidth.value = width;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(k32u) GoDigital_PulseWidth(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->pulseWidth.value;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetSignalType(GoDigital digital, GoDigitalSignal signal)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->signalType = signal;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(GoDigitalSignal) GoDigital_SignalType(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->signalType;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetDelay(GoDigital digital, k64s delay)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->delay = delay;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(k64s) GoDigital_Delay(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->delay;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetDelayDomain(GoDigital digital, GoOutputDelayDomain delayDomain)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->delayDomain = delayDomain;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(GoOutputDelayDomain) GoDigital_DelayDomain(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->delayDomain;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_EnableSchedule(GoDigital digital, kBool enabled )
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->scheduleEnabled = enabled;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|
|
|
|
GoFx(kBool) GoDigital_ScheduleEnabled(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->scheduleEnabled;
|
|
}
|
|
|
|
GoFx(kBool) GoDigital_IsOutputInverted(GoDigital digital)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
GoSensor_SyncConfig(obj->sensor);
|
|
|
|
return obj->invertOutput;
|
|
}
|
|
|
|
GoFx(kStatus) GoDigital_SetOutputInverted(GoDigital digital, kBool invert)
|
|
{
|
|
kObj(GoDigital, digital);
|
|
|
|
obj->invertOutput = invert;
|
|
kCheck(GoSensor_SetConfigModified(obj->sensor));
|
|
|
|
return kOK;
|
|
}
|