Bugfix/lighting output low high trim fade (#1268)
* Add low and high trim fade functionality to lighting command operations * Refactor lighting command override functions and fix operating and normalized range. * Add physical range clamping function and update related clamping logic
This commit is contained in:
@@ -36,6 +36,8 @@ struct object_data {
|
|||||||
uint32_t Egress_Time_Seconds;
|
uint32_t Egress_Time_Seconds;
|
||||||
uint32_t Default_Fade_Time;
|
uint32_t Default_Fade_Time;
|
||||||
uint32_t Trim_Fade_Time;
|
uint32_t Trim_Fade_Time;
|
||||||
|
float High_End_Trim;
|
||||||
|
float Low_End_Trim;
|
||||||
float Default_Ramp_Rate;
|
float Default_Ramp_Rate;
|
||||||
float Default_Step_Increment;
|
float Default_Step_Increment;
|
||||||
BACNET_LIGHTING_TRANSITION Transition;
|
BACNET_LIGHTING_TRANSITION Transition;
|
||||||
@@ -498,6 +500,57 @@ unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
|
|||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if fade, ramp, or warn command is currently executing
|
||||||
|
* @param pObject [in] object to apply the trim values to
|
||||||
|
* @param priority [in] priority of the command
|
||||||
|
*/
|
||||||
|
static bool Lighting_Command_In_Progress(struct object_data *pObject)
|
||||||
|
{
|
||||||
|
bool in_progress = false;
|
||||||
|
|
||||||
|
if (!pObject) {
|
||||||
|
return in_progress;
|
||||||
|
}
|
||||||
|
if ((pObject->Lighting_Command.In_Progress ==
|
||||||
|
BACNET_LIGHTING_FADE_ACTIVE) ||
|
||||||
|
(pObject->Lighting_Command.In_Progress ==
|
||||||
|
BACNET_LIGHTING_RAMP_ACTIVE) ||
|
||||||
|
(pObject->Lighting_Command.Blink.Duration > 0)) {
|
||||||
|
in_progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configure the lighting command to apply low or high trim
|
||||||
|
* to the tracking value based on the priority of the command
|
||||||
|
* @param pObject [in] object to apply the trim values to
|
||||||
|
* @param priority [in] priority of the command
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
Lighting_Command_Trim_Apply(struct object_data *pObject, unsigned priority)
|
||||||
|
{
|
||||||
|
if (!pObject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* If Present_Value is commanded at priority 1 or 2,
|
||||||
|
High_End_Trim and Low_End_Trim shall not be applied and
|
||||||
|
the Tracking_Value shall not be clamped. */
|
||||||
|
if ((priority == 1) || (priority == 2)) {
|
||||||
|
/* remove any high or low trim */
|
||||||
|
pObject->Lighting_Command.High_Trim_Value = 100.0f;
|
||||||
|
pObject->Lighting_Command.Low_Trim_Value = 1.0f;
|
||||||
|
pObject->Lighting_Command.Trim_Fade_Time = 0;
|
||||||
|
} else {
|
||||||
|
/* apply high and low trim */
|
||||||
|
pObject->Lighting_Command.High_Trim_Value = pObject->High_End_Trim;
|
||||||
|
pObject->Lighting_Command.Low_Trim_Value = pObject->Low_End_Trim;
|
||||||
|
pObject->Lighting_Command.Trim_Fade_Time = pObject->Trim_Fade_Time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the lighting command if the priority is active
|
* @brief Set the lighting command if the priority is active
|
||||||
* @param object [in] BACnet object instance
|
* @param object [in] BACnet object instance
|
||||||
@@ -519,7 +572,9 @@ static void Lighting_Command_Fade_To(
|
|||||||
Present_Value_Set(pObject, value, priority);
|
Present_Value_Set(pObject, value, priority);
|
||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority <= current_priority) {
|
if (priority <= current_priority) {
|
||||||
/* we have priority - configure the Lighting Command */
|
/* we have priority */
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
|
/* configure the Lighting Command */
|
||||||
lighting_command_fade_to(&pObject->Lighting_Command, value, fade_time);
|
lighting_command_fade_to(&pObject->Lighting_Command, value, fade_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -545,7 +600,9 @@ static void Lighting_Command_Ramp_To(
|
|||||||
Present_Value_Set(pObject, value, priority);
|
Present_Value_Set(pObject, value, priority);
|
||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority <= current_priority) {
|
if (priority <= current_priority) {
|
||||||
/* we have priority - configure the Lighting Command */
|
/* we have priority */
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
|
/* configure the Lighting Command */
|
||||||
lighting_command_ramp_to(&pObject->Lighting_Command, value, ramp_rate);
|
lighting_command_ramp_to(&pObject->Lighting_Command, value, ramp_rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,6 +655,7 @@ Lighting_Command_Warn(struct object_data *pObject, unsigned priority)
|
|||||||
(Priority_Array_Active(pObject, priority - 1)) &&
|
(Priority_Array_Active(pObject, priority - 1)) &&
|
||||||
(!is_float_equal(Priority_Array_Value(pObject, priority - 1), 0.0)) &&
|
(!is_float_equal(Priority_Array_Value(pObject, priority - 1), 0.0)) &&
|
||||||
pObject->Blink_Warn_Enable) {
|
pObject->Blink_Warn_Enable) {
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
/* The blink-warn notification shall not occur
|
/* The blink-warn notification shall not occur
|
||||||
if any of the following conditions occur:
|
if any of the following conditions occur:
|
||||||
(a) The specified priority is not the highest
|
(a) The specified priority is not the highest
|
||||||
@@ -662,6 +720,7 @@ Lighting_Command_Warn_Off(struct object_data *pObject, unsigned priority)
|
|||||||
}
|
}
|
||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority <= current_priority) {
|
if (priority <= current_priority) {
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
if ((Priority_Array_Active(pObject, priority - 1)) &&
|
if ((Priority_Array_Active(pObject, priority - 1)) &&
|
||||||
(!is_float_equal(
|
(!is_float_equal(
|
||||||
Priority_Array_Value(pObject, priority - 1), 0.0)) &&
|
Priority_Array_Value(pObject, priority - 1), 0.0)) &&
|
||||||
@@ -732,6 +791,7 @@ Lighting_Command_Warn_Relinquish(struct object_data *pObject, unsigned priority)
|
|||||||
}
|
}
|
||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority <= current_priority) {
|
if (priority <= current_priority) {
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
if ((Priority_Array_Active(pObject, priority - 1)) &&
|
if ((Priority_Array_Active(pObject, priority - 1)) &&
|
||||||
(!is_float_equal(
|
(!is_float_equal(
|
||||||
Priority_Array_Value(pObject, priority - 1), 0.0)) &&
|
Priority_Array_Value(pObject, priority - 1), 0.0)) &&
|
||||||
@@ -813,6 +873,7 @@ static void Lighting_Command_Step_Up_On(
|
|||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority <= current_priority) {
|
if (priority <= current_priority) {
|
||||||
/* we have priority - configure the Lighting Command */
|
/* we have priority - configure the Lighting Command */
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
lighting_command_step(
|
lighting_command_step(
|
||||||
&pObject->Lighting_Command, operation, step_increment);
|
&pObject->Lighting_Command, operation, step_increment);
|
||||||
}
|
}
|
||||||
@@ -870,6 +931,7 @@ static void Lighting_Command_Step_Down_Off(
|
|||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority <= current_priority) {
|
if (priority <= current_priority) {
|
||||||
/* we have priority - configure the Lighting Command */
|
/* we have priority - configure the Lighting Command */
|
||||||
|
Lighting_Command_Trim_Apply(pObject, priority);
|
||||||
lighting_command_step(
|
lighting_command_step(
|
||||||
&pObject->Lighting_Command, operation, step_increment);
|
&pObject->Lighting_Command, operation, step_increment);
|
||||||
}
|
}
|
||||||
@@ -1398,11 +1460,7 @@ Lighting_Command_Stop(struct object_data *pObject, unsigned priority)
|
|||||||
}
|
}
|
||||||
current_priority = Present_Value_Priority(pObject);
|
current_priority = Present_Value_Priority(pObject);
|
||||||
if (priority == current_priority) {
|
if (priority == current_priority) {
|
||||||
if ((pObject->Lighting_Command.In_Progress ==
|
if (Lighting_Command_In_Progress(pObject)) {
|
||||||
BACNET_LIGHTING_FADE_ACTIVE) ||
|
|
||||||
(pObject->Lighting_Command.In_Progress ==
|
|
||||||
BACNET_LIGHTING_RAMP_ACTIVE) ||
|
|
||||||
(pObject->Lighting_Command.Blink.Duration > 0)) {
|
|
||||||
/* fade, ramp, or warn command is currently
|
/* fade, ramp, or warn command is currently
|
||||||
executing at the specified priority */
|
executing at the specified priority */
|
||||||
value = pObject->Lighting_Command.Tracking_Value;
|
value = pObject->Lighting_Command.Tracking_Value;
|
||||||
@@ -2552,7 +2610,7 @@ float Lighting_Output_High_End_Trim(uint32_t object_instance)
|
|||||||
|
|
||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
value = pObject->Lighting_Command.High_Trim_Value;
|
value = pObject->High_End_Trim;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -2572,8 +2630,15 @@ bool Lighting_Output_High_End_Trim_Set(uint32_t object_instance, float value)
|
|||||||
|
|
||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
|
/* High_End_Trim shall always be a positive number
|
||||||
|
in the normalized range 1.0% to 100.0%. */
|
||||||
if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) {
|
if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) {
|
||||||
pObject->Lighting_Command.High_Trim_Value = value;
|
pObject->High_End_Trim = value;
|
||||||
|
Lighting_Command_Trim_Apply(
|
||||||
|
pObject, Present_Value_Priority(pObject));
|
||||||
|
if (!Lighting_Command_In_Progress(pObject)) {
|
||||||
|
lighting_command_refresh(&pObject->Lighting_Command);
|
||||||
|
}
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2622,7 +2687,7 @@ float Lighting_Output_Low_End_Trim(uint32_t object_instance)
|
|||||||
|
|
||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
value = pObject->Lighting_Command.Low_Trim_Value;
|
value = pObject->Low_End_Trim;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -2642,8 +2707,15 @@ bool Lighting_Output_Low_End_Trim_Set(uint32_t object_instance, float value)
|
|||||||
|
|
||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
|
/* Low_End_Trim shall always be a positive number
|
||||||
|
in the normalized range 1.0% to 100.0%. */
|
||||||
if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) {
|
if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) {
|
||||||
pObject->Lighting_Command.Low_Trim_Value = value;
|
pObject->Low_End_Trim = value;
|
||||||
|
Lighting_Command_Trim_Apply(
|
||||||
|
pObject, Present_Value_Priority(pObject));
|
||||||
|
if (!Lighting_Command_In_Progress(pObject)) {
|
||||||
|
lighting_command_refresh(&pObject->Lighting_Command);
|
||||||
|
}
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2714,7 +2786,14 @@ bool Lighting_Output_Trim_Fade_Time_Set(
|
|||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
if (value <= 86400000UL) {
|
if (value <= 86400000UL) {
|
||||||
|
/* The range of allowable fade-time values
|
||||||
|
is 0 ms to 86400000 ms (1 day) inclusive. */
|
||||||
pObject->Trim_Fade_Time = value;
|
pObject->Trim_Fade_Time = value;
|
||||||
|
Lighting_Command_Trim_Apply(
|
||||||
|
pObject, Present_Value_Priority(pObject));
|
||||||
|
if (!Lighting_Command_In_Progress(pObject)) {
|
||||||
|
lighting_command_refresh(&pObject->Lighting_Command);
|
||||||
|
}
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2766,9 +2845,7 @@ bool Lighting_Output_Overridden_Set(uint32_t object_instance, float value)
|
|||||||
|
|
||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
pObject->Lighting_Command.Overridden_Momentary = false;
|
lighting_command_override_set(&pObject->Lighting_Command, value);
|
||||||
pObject->Lighting_Command.Overridden = true;
|
|
||||||
lighting_command_override(&pObject->Lighting_Command, value);
|
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2791,10 +2868,8 @@ bool Lighting_Output_Overridden_Clear(uint32_t object_instance)
|
|||||||
|
|
||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
pObject->Lighting_Command.Overridden = false;
|
|
||||||
pObject->Lighting_Command.Overridden_Momentary = false;
|
|
||||||
value = Priority_Array_Next_Value(pObject, 0);
|
value = Priority_Array_Next_Value(pObject, 0);
|
||||||
lighting_command_override(&pObject->Lighting_Command, value);
|
lighting_command_override_clear(&pObject->Lighting_Command, value);
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2818,9 +2893,7 @@ bool Lighting_Output_Overridden_Momentary(uint32_t object_instance, float value)
|
|||||||
pObject = Keylist_Data(Object_List, object_instance);
|
pObject = Keylist_Data(Object_List, object_instance);
|
||||||
if (pObject) {
|
if (pObject) {
|
||||||
/* set the override */
|
/* set the override */
|
||||||
pObject->Lighting_Command.Overridden_Momentary = true;
|
lighting_command_override_momentary(&pObject->Lighting_Command, value);
|
||||||
pObject->Lighting_Command.Overridden = true;
|
|
||||||
lighting_command_override(&pObject->Lighting_Command, value);
|
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3787,6 +3860,11 @@ uint32_t Lighting_Output_Create(uint32_t object_instance)
|
|||||||
pObject->Last_Lighting_Command.use_fade_time = false;
|
pObject->Last_Lighting_Command.use_fade_time = false;
|
||||||
pObject->Last_Lighting_Command.use_priority = false;
|
pObject->Last_Lighting_Command.use_priority = false;
|
||||||
pObject->Blink_Warn_Enable = false;
|
pObject->Blink_Warn_Enable = false;
|
||||||
|
pObject->High_End_Trim = 100.0f;
|
||||||
|
pObject->Lighting_Command.High_Trim_Value = pObject->High_End_Trim;
|
||||||
|
pObject->Low_End_Trim = 1.0f;
|
||||||
|
pObject->Lighting_Command.Low_Trim_Value = pObject->Low_End_Trim;
|
||||||
|
pObject->Trim_Fade_Time = 0;
|
||||||
pObject->Egress_Time_Seconds = 0;
|
pObject->Egress_Time_Seconds = 0;
|
||||||
pObject->Default_Fade_Time = 100;
|
pObject->Default_Fade_Time = 100;
|
||||||
pObject->Default_Ramp_Rate = 100.0;
|
pObject->Default_Ramp_Rate = 100.0;
|
||||||
|
|||||||
@@ -163,6 +163,32 @@ float lighting_command_step_increment_clamp(float step_increment)
|
|||||||
return step_increment;
|
return step_increment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clamp the value within the physical min/max range
|
||||||
|
* @details The physical output level, or non-normalized range,
|
||||||
|
* is specified as the linearized percentage (0..100%)
|
||||||
|
* of the possible light output range with 0.0% being off,
|
||||||
|
* 1.0% being dimmest, and 100.0% being brightest.
|
||||||
|
* @param value [in] value to clamp within the physical min/max range
|
||||||
|
* @return value clamped within the physical min/max range of 0.0% to 100.0%
|
||||||
|
*/
|
||||||
|
float lighting_command_physical_range_clamp(float value)
|
||||||
|
{
|
||||||
|
float physical_value;
|
||||||
|
|
||||||
|
/* clamp value within physical values, if non-zero */
|
||||||
|
if (isless(value, 1.0f)) {
|
||||||
|
/* jump target to OFF */
|
||||||
|
physical_value = 0.0f;
|
||||||
|
} else if (isgreater(value, 100.0f)) {
|
||||||
|
physical_value = 100.0f;
|
||||||
|
} else {
|
||||||
|
physical_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return physical_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculate the target value for a step down command
|
* @brief Calculate the target value for a step down command
|
||||||
* @param tracking_value [in] current tracking value
|
* @param tracking_value [in] current tracking value
|
||||||
@@ -201,6 +227,52 @@ float lighting_command_step_up_target_value(
|
|||||||
return target_value;
|
return target_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the target value for a low or high trim fade operation
|
||||||
|
* @param data - dimmer data structure
|
||||||
|
* @param value - target value for the trim fade operation
|
||||||
|
* @param trim_value - target trim value for the fade operation
|
||||||
|
* @param milliseconds - number of milliseconds elapsed since the last call
|
||||||
|
* @return calculated target value for the trim fade operation
|
||||||
|
*/
|
||||||
|
static float lighting_command_trim_fade(
|
||||||
|
struct bacnet_lighting_command_data *data,
|
||||||
|
float value,
|
||||||
|
float trim_value,
|
||||||
|
uint32_t milliseconds)
|
||||||
|
{
|
||||||
|
float new_value;
|
||||||
|
float x1, x2, x3, y1, y3;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
if (milliseconds > 0) {
|
||||||
|
/* fading */
|
||||||
|
if (milliseconds >= data->Trim_Fade_Time) {
|
||||||
|
/* end of fading */
|
||||||
|
data->Trim_Fade_Time = 0;
|
||||||
|
new_value = trim_value;
|
||||||
|
} else {
|
||||||
|
x1 = 0.0f;
|
||||||
|
x2 = (float)milliseconds;
|
||||||
|
x3 = (float)data->Trim_Fade_Time;
|
||||||
|
y1 = value;
|
||||||
|
y3 = trim_value;
|
||||||
|
new_value = linear_interpolate(x1, x2, x3, y1, y3);
|
||||||
|
data->Trim_Fade_Time -= milliseconds;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no fading */
|
||||||
|
data->Trim_Fade_Time = 0;
|
||||||
|
new_value = trim_value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no fading */
|
||||||
|
new_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clamp the value within the operating range between low and high
|
* @brief Clamp the value within the operating range between low and high
|
||||||
* end trim values.
|
* end trim values.
|
||||||
@@ -212,23 +284,68 @@ float lighting_command_step_up_target_value(
|
|||||||
* output while the Present_Value will reflect the original target value.
|
* output while the Present_Value will reflect the original target value.
|
||||||
* @param data - dimmer data structure
|
* @param data - dimmer data structure
|
||||||
* @param value the value that will be subject to clamping
|
* @param value the value that will be subject to clamping
|
||||||
|
* @param milliseconds - number of milliseconds elapsed since the last call
|
||||||
|
* @return value clamped within the operating range defined by the High_End_Trim
|
||||||
|
* and Low_End_Trim property values
|
||||||
|
*/
|
||||||
|
float lighting_command_operating_range_clamp_fade(
|
||||||
|
struct bacnet_lighting_command_data *data,
|
||||||
|
float value,
|
||||||
|
uint16_t milliseconds)
|
||||||
|
{
|
||||||
|
float high_trim, low_trim, swap_value;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
/* clamp range within physical limits */
|
||||||
|
high_trim =
|
||||||
|
lighting_command_physical_range_clamp(data->High_Trim_Value);
|
||||||
|
low_trim = lighting_command_physical_range_clamp(data->Low_Trim_Value);
|
||||||
|
/* valid range check for high and low trim values */
|
||||||
|
if (isgreater(low_trim, high_trim)) {
|
||||||
|
/* swap the trims if they are inverse */
|
||||||
|
swap_value = low_trim;
|
||||||
|
low_trim = high_trim;
|
||||||
|
high_trim = swap_value;
|
||||||
|
}
|
||||||
|
/* clamp value within trim values, if non-zero */
|
||||||
|
if (isless(value, 1.0f)) {
|
||||||
|
/* jump target to OFF if below normalized min */
|
||||||
|
value = 0.0f;
|
||||||
|
} else if (isgreater(value, high_trim)) {
|
||||||
|
value = lighting_command_trim_fade(
|
||||||
|
data, value, high_trim, milliseconds);
|
||||||
|
data->In_Progress = BACNET_LIGHTING_TRIM_ACTIVE;
|
||||||
|
} else if (isless(value, low_trim)) {
|
||||||
|
value =
|
||||||
|
lighting_command_trim_fade(data, value, low_trim, milliseconds);
|
||||||
|
data->In_Progress = BACNET_LIGHTING_TRIM_ACTIVE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no data, so just clamp value within physical limits */
|
||||||
|
value = lighting_command_physical_range_clamp(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clamp the value within the operating range between low and high
|
||||||
|
* end trim values immediately.
|
||||||
|
* @details The Operating Range is a subset of the Normalized Range,
|
||||||
|
* that represents the range of acceptable values for control of the object.
|
||||||
|
* The Operating Range is defined by the High_End_Trim and Low_End_Trim
|
||||||
|
* property values. When values are written outside of the Operating Range,
|
||||||
|
* the Tracking_Value will reflect the actual, clamped normalized light
|
||||||
|
* output while the Present_Value will reflect the original target value.
|
||||||
|
* @param data - dimmer data structure
|
||||||
|
* @param value the value that will be subject to clamping
|
||||||
|
* @return value clamped within the operating range defined by the High_End_Trim
|
||||||
|
* and Low_End_Trim property values
|
||||||
*/
|
*/
|
||||||
float lighting_command_operating_range_clamp(
|
float lighting_command_operating_range_clamp(
|
||||||
struct bacnet_lighting_command_data *data, float value)
|
struct bacnet_lighting_command_data *data, float value)
|
||||||
{
|
{
|
||||||
/* clamp value within trim values, if non-zero */
|
return lighting_command_operating_range_clamp_fade(data, value, 0);
|
||||||
if (isless(value, 1.0f)) {
|
|
||||||
/* jump target to OFF if below normalized min */
|
|
||||||
value = 0.0f;
|
|
||||||
} else if (isgreater(value, data->High_Trim_Value)) {
|
|
||||||
value = data->High_Trim_Value;
|
|
||||||
data->In_Progress = BACNET_LIGHTING_TRIM_ACTIVE;
|
|
||||||
} else if (isless(value, data->Low_Trim_Value)) {
|
|
||||||
value = data->Low_Trim_Value;
|
|
||||||
data->In_Progress = BACNET_LIGHTING_TRIM_ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,11 +367,23 @@ float lighting_command_operating_range_clamp(
|
|||||||
float lighting_command_normalized_on_range_clamp(
|
float lighting_command_normalized_on_range_clamp(
|
||||||
struct bacnet_lighting_command_data *data, float value)
|
struct bacnet_lighting_command_data *data, float value)
|
||||||
{
|
{
|
||||||
|
float min_value, max_value, swap_value;
|
||||||
|
|
||||||
|
/* clamp range within physical limits */
|
||||||
|
max_value = lighting_command_physical_range_clamp(data->Max_Actual_Value);
|
||||||
|
min_value = lighting_command_physical_range_clamp(data->Min_Actual_Value);
|
||||||
|
/* valid range check for high and low trim values */
|
||||||
|
if (isgreater(min_value, max_value)) {
|
||||||
|
/* swap the trims if they are inverse */
|
||||||
|
swap_value = min_value;
|
||||||
|
min_value = max_value;
|
||||||
|
max_value = swap_value;
|
||||||
|
}
|
||||||
/* clamp value within trim values, if non-zero */
|
/* clamp value within trim values, if non-zero */
|
||||||
if (isgreater(value, data->Max_Actual_Value)) {
|
if (isgreater(value, max_value)) {
|
||||||
value = data->Max_Actual_Value;
|
value = max_value;
|
||||||
} else if (isless(value, data->Min_Actual_Value)) {
|
} else if (isless(value, min_value)) {
|
||||||
value = data->Min_Actual_Value;
|
value = min_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -280,15 +409,26 @@ float lighting_command_normalized_range_clamp(
|
|||||||
struct bacnet_lighting_command_data *data, float value)
|
struct bacnet_lighting_command_data *data, float value)
|
||||||
{
|
{
|
||||||
float normalized_value;
|
float normalized_value;
|
||||||
|
float min_value, max_value, swap_value;
|
||||||
|
|
||||||
|
/* clamp range within physical limits */
|
||||||
|
max_value = lighting_command_physical_range_clamp(data->Max_Actual_Value);
|
||||||
|
min_value = lighting_command_physical_range_clamp(data->Min_Actual_Value);
|
||||||
|
/* valid range check for high and low trim values */
|
||||||
|
if (isgreater(min_value, max_value)) {
|
||||||
|
/* swap the trims if they are inverse */
|
||||||
|
swap_value = min_value;
|
||||||
|
min_value = max_value;
|
||||||
|
max_value = swap_value;
|
||||||
|
}
|
||||||
/* clamp value within normalized values, if non-zero */
|
/* clamp value within normalized values, if non-zero */
|
||||||
if (isless(value, 1.0f)) {
|
if (isless(value, 1.0f)) {
|
||||||
/* jump target to OFF if below normalized min */
|
/* jump target to OFF if below normalized min */
|
||||||
normalized_value = 0.0f;
|
normalized_value = 0.0f;
|
||||||
} else if (isgreater(value, data->Max_Actual_Value)) {
|
} else if (isgreater(value, max_value)) {
|
||||||
normalized_value = data->Max_Actual_Value;
|
normalized_value = max_value;
|
||||||
} else if (isless(value, data->Min_Actual_Value)) {
|
} else if (isless(value, min_value)) {
|
||||||
normalized_value = data->Min_Actual_Value;
|
normalized_value = min_value;
|
||||||
} else {
|
} else {
|
||||||
normalized_value = value;
|
normalized_value = value;
|
||||||
}
|
}
|
||||||
@@ -301,19 +441,18 @@ float lighting_command_normalized_range_clamp(
|
|||||||
* @param data - dimmer data structure
|
* @param data - dimmer data structure
|
||||||
* @param old_value - value prior to write
|
* @param old_value - value prior to write
|
||||||
* @param value - value of the write
|
* @param value - value of the write
|
||||||
|
* @param milliseconds - number of milliseconds elapsed
|
||||||
*/
|
*/
|
||||||
static void lighting_command_tracking_value_event(
|
static void lighting_command_tracking_value_event(
|
||||||
struct bacnet_lighting_command_data *data, float old_value, float value)
|
struct bacnet_lighting_command_data *data, float old_value, float value)
|
||||||
{
|
{
|
||||||
if (data->Overridden) {
|
if (data->Overridden) {
|
||||||
value = lighting_command_operating_range_clamp(data, value);
|
|
||||||
lighting_command_tracking_value_notify(data, old_value, value);
|
lighting_command_tracking_value_notify(data, old_value, value);
|
||||||
if (data->Overridden_Momentary) {
|
if (data->Overridden_Momentary) {
|
||||||
data->Overridden = false;
|
data->Overridden = false;
|
||||||
}
|
}
|
||||||
} else if (!data->Out_Of_Service) {
|
} else if (!data->Out_Of_Service) {
|
||||||
data->Overridden_Momentary = false;
|
data->Overridden_Momentary = false;
|
||||||
value = lighting_command_operating_range_clamp(data, value);
|
|
||||||
lighting_command_tracking_value_notify(data, old_value, value);
|
lighting_command_tracking_value_notify(data, old_value, value);
|
||||||
} else {
|
} else {
|
||||||
debug_printf(
|
debug_printf(
|
||||||
@@ -336,6 +475,7 @@ static void lighting_command_fade_handler(
|
|||||||
float target_value;
|
float target_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
|
/* clamp Tracking value within the Normalized ON Range */
|
||||||
target_value =
|
target_value =
|
||||||
lighting_command_normalized_on_range_clamp(data, data->Target_Level);
|
lighting_command_normalized_on_range_clamp(data, data->Target_Level);
|
||||||
if ((milliseconds >= data->Fade_Time) ||
|
if ((milliseconds >= data->Fade_Time) ||
|
||||||
@@ -365,6 +505,10 @@ static void lighting_command_fade_handler(
|
|||||||
data->Fade_Time -= milliseconds;
|
data->Fade_Time -= milliseconds;
|
||||||
data->In_Progress = BACNET_LIGHTING_FADE_ACTIVE;
|
data->In_Progress = BACNET_LIGHTING_FADE_ACTIVE;
|
||||||
}
|
}
|
||||||
|
/* clamp Tracking Value inclusively within the Operating Range */
|
||||||
|
data->Tracking_Value = lighting_command_operating_range_clamp_fade(
|
||||||
|
data, data->Tracking_Value, milliseconds);
|
||||||
|
/* notify */
|
||||||
lighting_command_tracking_value_event(
|
lighting_command_tracking_value_event(
|
||||||
data, old_value, data->Tracking_Value);
|
data, old_value, data->Tracking_Value);
|
||||||
}
|
}
|
||||||
@@ -387,9 +531,11 @@ static void lighting_command_fade_handler(
|
|||||||
static void lighting_command_ramp_handler(
|
static void lighting_command_ramp_handler(
|
||||||
struct bacnet_lighting_command_data *data, uint16_t milliseconds)
|
struct bacnet_lighting_command_data *data, uint16_t milliseconds)
|
||||||
{
|
{
|
||||||
float old_value, target_value, step_value, steps, ramp_rate;
|
float old_value, target_value, step_value, steps, ramp_rate,
|
||||||
|
operating_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
|
/* clamp Tracking value within the Normalized ON Range */
|
||||||
target_value =
|
target_value =
|
||||||
lighting_command_normalized_on_range_clamp(data, data->Target_Level);
|
lighting_command_normalized_on_range_clamp(data, data->Target_Level);
|
||||||
if (!islessgreater(data->Tracking_Value, target_value)) {
|
if (!islessgreater(data->Tracking_Value, target_value)) {
|
||||||
@@ -449,6 +595,11 @@ static void lighting_command_ramp_handler(
|
|||||||
data->In_Progress = BACNET_LIGHTING_RAMP_ACTIVE;
|
data->In_Progress = BACNET_LIGHTING_RAMP_ACTIVE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* clamp Tracking_Value inclusively within the Operating Range */
|
||||||
|
operating_value = lighting_command_operating_range_clamp_fade(
|
||||||
|
data, data->Tracking_Value, milliseconds);
|
||||||
|
data->Tracking_Value = operating_value;
|
||||||
|
/* notify */
|
||||||
lighting_command_tracking_value_event(
|
lighting_command_tracking_value_event(
|
||||||
data, old_value, data->Tracking_Value);
|
data, old_value, data->Tracking_Value);
|
||||||
}
|
}
|
||||||
@@ -465,17 +616,23 @@ static void lighting_command_ramp_handler(
|
|||||||
static void
|
static void
|
||||||
lighting_command_step_up_handler(struct bacnet_lighting_command_data *data)
|
lighting_command_step_up_handler(struct bacnet_lighting_command_data *data)
|
||||||
{
|
{
|
||||||
float old_value, target_value;
|
float old_value, target_value, operating_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
if (isgreaterequal(old_value, data->Min_Actual_Value)) {
|
if (isgreaterequal(old_value, data->Min_Actual_Value)) {
|
||||||
/* inhibit ON if the value is already OFF */
|
/* inhibit ON if the value is already OFF */
|
||||||
target_value = lighting_command_step_up_target_value(
|
target_value = lighting_command_step_up_target_value(
|
||||||
data->Tracking_Value, data->Step_Increment);
|
data->Tracking_Value, data->Step_Increment);
|
||||||
|
/* clamp Tracking value within the Normalized ON Range */
|
||||||
data->Tracking_Value =
|
data->Tracking_Value =
|
||||||
lighting_command_normalized_on_range_clamp(data, target_value);
|
lighting_command_normalized_on_range_clamp(data, target_value);
|
||||||
data->In_Progress = BACNET_LIGHTING_IDLE;
|
data->In_Progress = BACNET_LIGHTING_IDLE;
|
||||||
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
||||||
|
/* clamp Tracking value inclusively within the Operating Range */
|
||||||
|
operating_value =
|
||||||
|
lighting_command_operating_range_clamp(data, data->Tracking_Value);
|
||||||
|
data->Tracking_Value = operating_value;
|
||||||
|
/* notify */
|
||||||
lighting_command_tracking_value_event(
|
lighting_command_tracking_value_event(
|
||||||
data, old_value, data->Tracking_Value);
|
data, old_value, data->Tracking_Value);
|
||||||
}
|
}
|
||||||
@@ -493,15 +650,21 @@ lighting_command_step_up_handler(struct bacnet_lighting_command_data *data)
|
|||||||
static void
|
static void
|
||||||
lighting_command_step_down_handler(struct bacnet_lighting_command_data *data)
|
lighting_command_step_down_handler(struct bacnet_lighting_command_data *data)
|
||||||
{
|
{
|
||||||
float old_value, target_value;
|
float old_value, target_value, operating_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
target_value = lighting_command_step_down_target_value(
|
target_value = lighting_command_step_down_target_value(
|
||||||
data->Tracking_Value, data->Step_Increment);
|
data->Tracking_Value, data->Step_Increment);
|
||||||
|
/* clamp Tracking value within the Normalized ON Range */
|
||||||
data->Tracking_Value =
|
data->Tracking_Value =
|
||||||
lighting_command_normalized_on_range_clamp(data, target_value);
|
lighting_command_normalized_on_range_clamp(data, target_value);
|
||||||
data->In_Progress = BACNET_LIGHTING_IDLE;
|
data->In_Progress = BACNET_LIGHTING_IDLE;
|
||||||
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
||||||
|
/* clamp Tracking value inclusively within the Operating Range */
|
||||||
|
operating_value =
|
||||||
|
lighting_command_operating_range_clamp(data, data->Tracking_Value);
|
||||||
|
data->Tracking_Value = operating_value;
|
||||||
|
/* notify */
|
||||||
lighting_command_tracking_value_event(
|
lighting_command_tracking_value_event(
|
||||||
data, old_value, data->Tracking_Value);
|
data, old_value, data->Tracking_Value);
|
||||||
}
|
}
|
||||||
@@ -518,7 +681,7 @@ lighting_command_step_down_handler(struct bacnet_lighting_command_data *data)
|
|||||||
static void
|
static void
|
||||||
lighting_command_step_on_handler(struct bacnet_lighting_command_data *data)
|
lighting_command_step_on_handler(struct bacnet_lighting_command_data *data)
|
||||||
{
|
{
|
||||||
float old_value, target_value;
|
float old_value, target_value, operating_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
target_value = lighting_command_step_up_target_value(
|
target_value = lighting_command_step_up_target_value(
|
||||||
@@ -527,6 +690,11 @@ lighting_command_step_on_handler(struct bacnet_lighting_command_data *data)
|
|||||||
lighting_command_normalized_range_clamp(data, target_value);
|
lighting_command_normalized_range_clamp(data, target_value);
|
||||||
data->In_Progress = BACNET_LIGHTING_IDLE;
|
data->In_Progress = BACNET_LIGHTING_IDLE;
|
||||||
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
||||||
|
/* clamp Tracking value inclusively within the Operating Range */
|
||||||
|
operating_value =
|
||||||
|
lighting_command_operating_range_clamp(data, data->Tracking_Value);
|
||||||
|
data->Tracking_Value = operating_value;
|
||||||
|
/* notify */
|
||||||
lighting_command_tracking_value_event(
|
lighting_command_tracking_value_event(
|
||||||
data, old_value, data->Tracking_Value);
|
data, old_value, data->Tracking_Value);
|
||||||
}
|
}
|
||||||
@@ -543,7 +711,7 @@ lighting_command_step_on_handler(struct bacnet_lighting_command_data *data)
|
|||||||
static void
|
static void
|
||||||
lighting_command_step_off_handler(struct bacnet_lighting_command_data *data)
|
lighting_command_step_off_handler(struct bacnet_lighting_command_data *data)
|
||||||
{
|
{
|
||||||
float old_value, target_value;
|
float old_value, target_value, operating_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
target_value = lighting_command_step_down_target_value(
|
target_value = lighting_command_step_down_target_value(
|
||||||
@@ -552,6 +720,11 @@ lighting_command_step_off_handler(struct bacnet_lighting_command_data *data)
|
|||||||
lighting_command_normalized_range_clamp(data, target_value);
|
lighting_command_normalized_range_clamp(data, target_value);
|
||||||
data->In_Progress = BACNET_LIGHTING_IDLE;
|
data->In_Progress = BACNET_LIGHTING_IDLE;
|
||||||
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
data->Lighting_Operation = BACNET_LIGHTS_STOP;
|
||||||
|
/* clamp Tracking value inclusively within the Operating Range */
|
||||||
|
operating_value =
|
||||||
|
lighting_command_operating_range_clamp(data, data->Tracking_Value);
|
||||||
|
data->Tracking_Value = operating_value;
|
||||||
|
/* notify */
|
||||||
lighting_command_tracking_value_event(
|
lighting_command_tracking_value_event(
|
||||||
data, old_value, data->Tracking_Value);
|
data, old_value, data->Tracking_Value);
|
||||||
}
|
}
|
||||||
@@ -583,7 +756,7 @@ lighting_command_step_off_handler(struct bacnet_lighting_command_data *data)
|
|||||||
static void lighting_command_blink_handler(
|
static void lighting_command_blink_handler(
|
||||||
struct bacnet_lighting_command_data *data, uint16_t milliseconds)
|
struct bacnet_lighting_command_data *data, uint16_t milliseconds)
|
||||||
{
|
{
|
||||||
float old_value, target_value;
|
float old_value, target_value, operating_value;
|
||||||
|
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
/* detect 'end' operation */
|
/* detect 'end' operation */
|
||||||
@@ -635,16 +808,19 @@ static void lighting_command_blink_handler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
target_value = lighting_command_normalized_range_clamp(data, target_value);
|
target_value = lighting_command_normalized_range_clamp(data, target_value);
|
||||||
|
/* clamp Tracking value inclusively within the Operating Range */
|
||||||
|
operating_value =
|
||||||
|
lighting_command_operating_range_clamp(data, target_value);
|
||||||
/* note: The blink-warn notifications shall not be reflected
|
/* note: The blink-warn notifications shall not be reflected
|
||||||
in the tracking value. */
|
in the tracking value. */
|
||||||
if (data->In_Progress == BACNET_LIGHTING_IDLE) {
|
if (data->In_Progress == BACNET_LIGHTING_IDLE) {
|
||||||
data->Tracking_Value = target_value;
|
data->Tracking_Value = operating_value;
|
||||||
}
|
}
|
||||||
lighting_command_tracking_value_event(data, old_value, target_value);
|
lighting_command_tracking_value_event(data, old_value, operating_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Overrides the current lighting command if overridden is true
|
* @brief Overrides the current lighting command with the provided value
|
||||||
* @param data [in] dimmer data
|
* @param data [in] dimmer data
|
||||||
*/
|
*/
|
||||||
void lighting_command_override(
|
void lighting_command_override(
|
||||||
@@ -656,8 +832,63 @@ void lighting_command_override(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
old_value = data->Tracking_Value;
|
old_value = data->Tracking_Value;
|
||||||
data->Tracking_Value = value;
|
data->Tracking_Value = lighting_command_physical_range_clamp(value);
|
||||||
lighting_command_tracking_value_event(data, old_value, value);
|
lighting_command_tracking_value_event(
|
||||||
|
data, old_value, data->Tracking_Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Overrides the current lighting command with the provided value
|
||||||
|
* @param data [in] dimmer data
|
||||||
|
*/
|
||||||
|
void lighting_command_override_set(
|
||||||
|
struct bacnet_lighting_command_data *data, float value)
|
||||||
|
{
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data->Overridden = true;
|
||||||
|
data->Overridden_Momentary = false;
|
||||||
|
lighting_command_override(data, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the override of the current lighting command
|
||||||
|
* @param data [in] dimmer data
|
||||||
|
*/
|
||||||
|
void lighting_command_override_clear(
|
||||||
|
struct bacnet_lighting_command_data *data, float value)
|
||||||
|
{
|
||||||
|
float old_value, normalized_value, operating_value;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data->Overridden = false;
|
||||||
|
data->Overridden_Momentary = false;
|
||||||
|
old_value = data->Tracking_Value;
|
||||||
|
/* clamp Tracking value within the Normalized Range */
|
||||||
|
normalized_value = lighting_command_normalized_range_clamp(data, value);
|
||||||
|
/* clamp Tracking value inclusively within the Operating Range */
|
||||||
|
operating_value =
|
||||||
|
lighting_command_operating_range_clamp(data, normalized_value);
|
||||||
|
data->Tracking_Value = operating_value;
|
||||||
|
lighting_command_tracking_value_event(data, old_value, operating_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Overrides the current lighting command with the provided value
|
||||||
|
* @param data [in] dimmer data
|
||||||
|
*/
|
||||||
|
void lighting_command_override_momentary(
|
||||||
|
struct bacnet_lighting_command_data *data, float value)
|
||||||
|
{
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data->Overridden = true;
|
||||||
|
data->Overridden_Momentary = true;
|
||||||
|
lighting_command_override(data, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1009,6 +1240,7 @@ void lighting_command_init(struct bacnet_lighting_command_data *data)
|
|||||||
data->Max_Actual_Value = 100.0f;
|
data->Max_Actual_Value = 100.0f;
|
||||||
data->Low_Trim_Value = 1.0f;
|
data->Low_Trim_Value = 1.0f;
|
||||||
data->High_Trim_Value = 100.0f;
|
data->High_Trim_Value = 100.0f;
|
||||||
|
data->Trim_Fade_Time = 0;
|
||||||
data->Last_On_Value = 100.0f;
|
data->Last_On_Value = 100.0f;
|
||||||
data->Default_On_Value = 100.0f;
|
data->Default_On_Value = 100.0f;
|
||||||
data->Overridden = false;
|
data->Overridden = false;
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ typedef struct bacnet_lighting_command_data {
|
|||||||
float Max_Actual_Value;
|
float Max_Actual_Value;
|
||||||
float High_Trim_Value;
|
float High_Trim_Value;
|
||||||
float Low_Trim_Value;
|
float Low_Trim_Value;
|
||||||
|
uint32_t Trim_Fade_Time;
|
||||||
float Default_On_Value;
|
float Default_On_Value;
|
||||||
float Last_On_Value;
|
float Last_On_Value;
|
||||||
BACNET_LIGHTING_COMMAND_WARN_DATA Blink;
|
BACNET_LIGHTING_COMMAND_WARN_DATA Blink;
|
||||||
@@ -135,6 +136,15 @@ void lighting_command_toggle_default(
|
|||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
void lighting_command_override(
|
void lighting_command_override(
|
||||||
struct bacnet_lighting_command_data *data, float value);
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
void lighting_command_override_set(
|
||||||
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
void lighting_command_override_clear(
|
||||||
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
void lighting_command_override_momentary(
|
||||||
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
|
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
float lighting_command_ramp_rate_clamp(float ramp_rate);
|
float lighting_command_ramp_rate_clamp(float ramp_rate);
|
||||||
@@ -144,11 +154,18 @@ BACNET_STACK_EXPORT
|
|||||||
float lighting_command_operating_range_clamp(
|
float lighting_command_operating_range_clamp(
|
||||||
struct bacnet_lighting_command_data *data, float value);
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
|
float lighting_command_operating_range_clamp_fade(
|
||||||
|
struct bacnet_lighting_command_data *data,
|
||||||
|
float value,
|
||||||
|
uint16_t milliseconds);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
float lighting_command_normalized_range_clamp(
|
float lighting_command_normalized_range_clamp(
|
||||||
struct bacnet_lighting_command_data *data, float value);
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
float lighting_command_normalized_on_range_clamp(
|
float lighting_command_normalized_on_range_clamp(
|
||||||
struct bacnet_lighting_command_data *data, float value);
|
struct bacnet_lighting_command_data *data, float value);
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
|
float lighting_command_physical_range_clamp(float value);
|
||||||
|
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
void lighting_command_refresh(struct bacnet_lighting_command_data *data);
|
void lighting_command_refresh(struct bacnet_lighting_command_data *data);
|
||||||
|
|||||||
@@ -402,6 +402,112 @@ static void testLightingOutput(void)
|
|||||||
test_real = Lighting_Output_Tracking_Value(instance);
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
zassert_true(is_float_equal(test_real, real_value), NULL);
|
zassert_true(is_float_equal(test_real, real_value), NULL);
|
||||||
zassert_true(is_float_equal(Test_Tracking_Value, real_value), NULL);
|
zassert_true(is_float_equal(Test_Tracking_Value, real_value), NULL);
|
||||||
|
/* high-end-trim, low-end-trim, and trim-fade-time */
|
||||||
|
Lighting_Output_Present_Value_Relinquish_All(instance);
|
||||||
|
status = Lighting_Output_Transition_Set(
|
||||||
|
instance, BACNET_LIGHTING_TRANSITION_NONE);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
status = Lighting_Output_Trim_Fade_Time_Set(instance, 0);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
status = Lighting_Output_High_End_Trim_Set(instance, 90.0f);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_real = Lighting_Output_High_End_Trim(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 90.0f), NULL);
|
||||||
|
status = Lighting_Output_Low_End_Trim_Set(instance, 10.0f);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_real = Lighting_Output_Low_End_Trim(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 10.0f), NULL);
|
||||||
|
priority = 8;
|
||||||
|
status = Lighting_Output_Present_Value_Set(instance, 100.0f, priority);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
Lighting_Output_Timer(instance, 10);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_TRIM_ACTIVE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 90.0f), NULL);
|
||||||
|
Lighting_Output_Timer(instance, 10);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_IDLE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
status = Lighting_Output_Present_Value_Set(instance, 1.0f, priority);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
Lighting_Output_Timer(instance, 10);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_TRIM_ACTIVE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 10.0f), "tracking=%f", test_real);
|
||||||
|
Lighting_Output_Timer(instance, 10);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_IDLE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
Lighting_Output_Present_Value_Relinquish_All(instance);
|
||||||
|
status = Lighting_Output_Present_Value_Set(instance, 100.0f, 1);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
Lighting_Output_Timer(instance, 10);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_IDLE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 100.0f), "tracking=%f", test_real);
|
||||||
|
Lighting_Output_Present_Value_Relinquish_All(instance);
|
||||||
|
status = Lighting_Output_Present_Value_Set(instance, 80.0f, priority);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
Lighting_Output_Timer(instance, 10);
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 80.0f), NULL);
|
||||||
|
unsigned_value = 1000;
|
||||||
|
status = Lighting_Output_Trim_Fade_Time_Set(instance, unsigned_value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_unsigned = Lighting_Output_Trim_Fade_Time(instance);
|
||||||
|
zassert_equal(test_unsigned, unsigned_value, NULL);
|
||||||
|
status = Lighting_Output_Default_Fade_Time_Set(instance, 2000);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
status = Lighting_Output_Transition_Set(
|
||||||
|
instance, BACNET_LIGHTING_TRANSITION_FADE);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
status = Lighting_Output_Present_Value_Set(instance, 100.0f, priority);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
milliseconds = 500;
|
||||||
|
Lighting_Output_Timer(instance, milliseconds);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_FADE_ACTIVE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 85.0f), NULL);
|
||||||
|
Lighting_Output_Timer(instance, milliseconds);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_FADE_ACTIVE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 90.0f), NULL);
|
||||||
|
Lighting_Output_Timer(instance, milliseconds);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_TRIM_ACTIVE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 92.5f), NULL);
|
||||||
|
Lighting_Output_Timer(instance, milliseconds);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_TRIM_ACTIVE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
|
test_real = Lighting_Output_Tracking_Value(instance);
|
||||||
|
zassert_true(is_float_equal(test_real, 90.0f), NULL);
|
||||||
|
Lighting_Output_Timer(instance, milliseconds);
|
||||||
|
in_progress = Lighting_Output_In_Progress(instance);
|
||||||
|
zassert_equal(
|
||||||
|
in_progress, BACNET_LIGHTING_IDLE, "in_progress=%s",
|
||||||
|
bactext_lighting_in_progress(in_progress));
|
||||||
/* feedback value */
|
/* feedback value */
|
||||||
status = Lighting_Output_Feedback_Value_Set(instance, 55.5f);
|
status = Lighting_Output_Feedback_Value_Set(instance, 55.5f);
|
||||||
zassert_true(status, NULL);
|
zassert_true(status, NULL);
|
||||||
|
|||||||
@@ -267,7 +267,9 @@ static void test_lighting_command_unit(void)
|
|||||||
zassert_true(is_float_equal(data.Last_On_Value, 1.0f), NULL);
|
zassert_true(is_float_equal(data.Last_On_Value, 1.0f), NULL);
|
||||||
lighting_command_timer(&data, milliseconds);
|
lighting_command_timer(&data, milliseconds);
|
||||||
zassert_true(data.In_Progress == BACNET_LIGHTING_TRIM_ACTIVE, NULL);
|
zassert_true(data.In_Progress == BACNET_LIGHTING_TRIM_ACTIVE, NULL);
|
||||||
zassert_true(is_float_equal(Tracking_Value, data.Low_Trim_Value), NULL);
|
zassert_true(
|
||||||
|
is_float_equal(Tracking_Value, data.Low_Trim_Value),
|
||||||
|
"Tracking_Value=%f Low_Trim=%f", Tracking_Value, data.Low_Trim_Value);
|
||||||
target_level = 0.0f;
|
target_level = 0.0f;
|
||||||
milliseconds = 10;
|
milliseconds = 10;
|
||||||
lighting_command_fade_to(&data, target_level, 0);
|
lighting_command_fade_to(&data, target_level, 0);
|
||||||
@@ -287,13 +289,60 @@ static void test_lighting_command_unit(void)
|
|||||||
zassert_true(is_float_equal(Tracking_Value, data.High_Trim_Value), NULL);
|
zassert_true(is_float_equal(Tracking_Value, data.High_Trim_Value), NULL);
|
||||||
data.High_Trim_Value = data.Max_Actual_Value;
|
data.High_Trim_Value = data.Max_Actual_Value;
|
||||||
zassert_true(is_float_equal(data.Last_On_Value, target_level), NULL);
|
zassert_true(is_float_equal(data.Last_On_Value, target_level), NULL);
|
||||||
|
/* trim fade time */
|
||||||
|
target_level = 80.0f;
|
||||||
|
milliseconds = 10;
|
||||||
|
lighting_command_fade_to(&data, target_level, 0);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, target_level), NULL);
|
||||||
|
data.High_Trim_Value = 90.0f;
|
||||||
|
data.Trim_Fade_Time = fade_time;
|
||||||
|
lighting_command_fade_to(&data, 100.0f, fade_time * 2);
|
||||||
|
milliseconds = fade_time / 4;
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_FADE_ACTIVE, NULL);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, 82.5f), NULL);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, fade_time, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_FADE_ACTIVE, NULL);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, 85.0f), NULL);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, fade_time, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_FADE_ACTIVE, NULL);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, 87.5f), NULL);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, fade_time, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_FADE_ACTIVE, NULL);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, 90.0f), NULL);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, fade_time, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_TRIM_ACTIVE, NULL);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, 91.875f), NULL);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, 750, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_TRIM_ACTIVE, NULL);
|
||||||
|
zassert_true(
|
||||||
|
is_float_equal(Tracking_Value, 93.056f), "Tracking_Value=%f",
|
||||||
|
Tracking_Value);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, 500, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_TRIM_ACTIVE, NULL);
|
||||||
|
zassert_true(
|
||||||
|
is_float_equal(Tracking_Value, 93.264f), "Tracking_Value=%f",
|
||||||
|
Tracking_Value);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, 250, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_TRIM_ACTIVE, NULL);
|
||||||
|
zassert_true(is_float_equal(Tracking_Value, data.High_Trim_Value), NULL);
|
||||||
|
zassert_equal(data.Trim_Fade_Time, 0, NULL);
|
||||||
|
lighting_command_timer(&data, milliseconds);
|
||||||
|
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
||||||
|
data.High_Trim_Value = data.Max_Actual_Value;
|
||||||
/* override */
|
/* override */
|
||||||
override_level = 42.0f;
|
override_level = 42.0f;
|
||||||
target_level = 100.0f;
|
target_level = 100.0f;
|
||||||
milliseconds = 10;
|
milliseconds = 10;
|
||||||
data.Overridden = true;
|
lighting_command_override_set(&data, override_level);
|
||||||
data.Overridden_Momentary = false;
|
|
||||||
lighting_command_override(&data, override_level);
|
|
||||||
lighting_command_timer(&data, milliseconds);
|
lighting_command_timer(&data, milliseconds);
|
||||||
zassert_true(is_float_equal(Tracking_Value, override_level), NULL);
|
zassert_true(is_float_equal(Tracking_Value, override_level), NULL);
|
||||||
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
||||||
@@ -301,8 +350,7 @@ static void test_lighting_command_unit(void)
|
|||||||
lighting_command_timer(&data, milliseconds);
|
lighting_command_timer(&data, milliseconds);
|
||||||
zassert_true(is_float_equal(Tracking_Value, override_level), NULL);
|
zassert_true(is_float_equal(Tracking_Value, override_level), NULL);
|
||||||
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
||||||
data.Overridden = false;
|
lighting_command_override_clear(&data, target_level);
|
||||||
lighting_command_override(&data, target_level);
|
|
||||||
lighting_command_timer(&data, milliseconds);
|
lighting_command_timer(&data, milliseconds);
|
||||||
zassert_true(is_float_equal(Tracking_Value, target_level), NULL);
|
zassert_true(is_float_equal(Tracking_Value, target_level), NULL);
|
||||||
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
||||||
@@ -310,9 +358,7 @@ static void test_lighting_command_unit(void)
|
|||||||
override_level = 42.0f;
|
override_level = 42.0f;
|
||||||
target_level = 100.0f;
|
target_level = 100.0f;
|
||||||
milliseconds = 10;
|
milliseconds = 10;
|
||||||
data.Overridden = true;
|
lighting_command_override_momentary(&data, override_level);
|
||||||
data.Overridden_Momentary = true;
|
|
||||||
lighting_command_override(&data, override_level);
|
|
||||||
lighting_command_timer(&data, milliseconds);
|
lighting_command_timer(&data, milliseconds);
|
||||||
zassert_true(is_float_equal(Tracking_Value, override_level), NULL);
|
zassert_true(is_float_equal(Tracking_Value, override_level), NULL);
|
||||||
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
zassert_true(data.In_Progress == BACNET_LIGHTING_IDLE, NULL);
|
||||||
@@ -331,6 +377,24 @@ static void test_lighting_command_unit(void)
|
|||||||
target_step = lighting_command_step_increment_clamp(100.1f);
|
target_step = lighting_command_step_increment_clamp(100.1f);
|
||||||
zassert_true(is_float_equal(target_step, 100.0f), NULL);
|
zassert_true(is_float_equal(target_step, 100.0f), NULL);
|
||||||
|
|
||||||
|
/* physical range clamping */
|
||||||
|
target_level = lighting_command_physical_range_clamp(0.0f);
|
||||||
|
zassert_true(is_float_equal(target_level, 0.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(0.5f);
|
||||||
|
zassert_true(is_float_equal(target_level, 0.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(0.9f);
|
||||||
|
zassert_true(is_float_equal(target_level, 0.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(1.0f);
|
||||||
|
zassert_true(is_float_equal(target_level, 1.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(50.0f);
|
||||||
|
zassert_true(is_float_equal(target_level, 50.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(100.0f);
|
||||||
|
zassert_true(is_float_equal(target_level, 100.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(100.1f);
|
||||||
|
zassert_true(is_float_equal(target_level, 100.0f), NULL);
|
||||||
|
target_level = lighting_command_physical_range_clamp(150.0f);
|
||||||
|
zassert_true(is_float_equal(target_level, 100.0f), NULL);
|
||||||
|
|
||||||
/* step UP - inhibit ON */
|
/* step UP - inhibit ON */
|
||||||
target_step = 1.0f;
|
target_step = 1.0f;
|
||||||
target_level = 0.0f;
|
target_level = 0.0f;
|
||||||
@@ -602,7 +666,9 @@ static void test_lighting_command_unit(void)
|
|||||||
zassert_equal(data.Lighting_Operation, BACNET_LIGHTS_PROPRIETARY_MAX, NULL);
|
zassert_equal(data.Lighting_Operation, BACNET_LIGHTS_PROPRIETARY_MAX, NULL);
|
||||||
|
|
||||||
/* null check code coverage */
|
/* null check code coverage */
|
||||||
lighting_command_override(NULL, override_level);
|
lighting_command_override_set(NULL, override_level);
|
||||||
|
lighting_command_override_clear(NULL, override_level);
|
||||||
|
lighting_command_override_momentary(NULL, override_level);
|
||||||
lighting_command_fade_to(NULL, 0.0f, 0);
|
lighting_command_fade_to(NULL, 0.0f, 0);
|
||||||
lighting_command_ramp_to(NULL, 0.0f, 0.0f);
|
lighting_command_ramp_to(NULL, 0.0f, 0.0f);
|
||||||
lighting_command_step(NULL, BACNET_LIGHTS_STEP_OFF, 0.0f);
|
lighting_command_step(NULL, BACNET_LIGHTS_STEP_OFF, 0.0f);
|
||||||
|
|||||||
Reference in New Issue
Block a user