/// This FB can be used to implement a Soft PWM, based
/// on the scheduler of a Linux system.
///
/// Note, that this function block should be used in a
/// a high priority task. The interval of the task will
/// constantly change.
FUNCTION_BLOCK SoftPWM
VAR_INPUT
dwFrequ : DWORD;
rDutyCycle : REAL;
END_VAR
VAR_OUTPUT
xPWM : BOOL;
VAR
hTask : SysTask.RTS_IEC_HANDLE := SysTask.RTS_INVALID_HANDLE;
ulInterval: DWORD;
(* If current task is not, yet, determined, get it *)
IF hTask = SysTask.RTS_INVALID_HANDLE THEN
SysTask.SysTaskGetCurrent(ADR(hTask));
END_IF
(* if task is determined, adjust next cycle *)
IF hTask <> SysTask.RTS_INVALID_HANDLE THEN
IF xPWM THEN
ulInterval := LREAL_TO_DWORD(dwFrequ * (LREAL#1000000 / DWORD_TO_LREAL(dwFrequ)) * (LREAL#1 - rDutyCycle));
END_IF
SysTask.SysTaskSetInterval(hTask, ulInterval);
xPWM := NOT xPWM;