type
 TRamping = record t0,t1,v0,v1:real; end;
var
 RampVolt : TRamping; // Demo
 //
 // Ramping routines.
 //
 procedure RampingClear(var R:TRamping);
 begin
  R.t0:=0; R.t1:=0; R.v0:=0; R.v1:=0;
 end;
 procedure RampingStart(var R:TRamping; v0,v1,rate:Real);
 begin
  RampingClear(R);
  R.t0:=mSecNow; R.t1:=R.t0; R.v0:=v0; R.v1:=v1;
  if (rate>0) then R.t1:=R.t1+1000*abs((v1-v0)/rate);
 end;
 function RampingGoing(var R:TRamping):Boolean;
 begin
  RampingGoing:=(R.t0>0);
 end;
 function RampingComplete(var R:TRamping):Boolean;
 begin
  RampingComplete:=(mSecNow>R.t1);
 end;
 function RampingValue(var R:TRamping):Real;
 var v,ms:Real;
 begin
  ms:=mSecNow;
  if (ms>R.t1) or (R.t0=0) then v:=R.v1
  else v:=R.v0+(R.v1-R.v0)*(ms-R.t0)/(R.t1-R.t0);
  RampingValue:=v;
 end;
 //
 // User code: apply ramping
 //
 procedure RampingHandler;                                     // User polling for Ramping
 var v:Real;
 begin
  if SysTimer_Pulse(PollPeriod)>0 then begin                   // On polling timer:
   if RampingGoing(RampVolt) then begin                        // If ramping is in progress
    v:=RampingValue(RampVolt);                                 // Get current ramping value
    ApplyRampingVoltage(v);                                    // Apply User code to set RampVolt
    if RampingComplete(RampVolt) then RampingClear(RampVolt);  // Reset if ramping completed
   end;
   bNul(iSetTag(tagRampVolt,Ord(RampingGoing(RampVolt))));     // Update ramping state tag
  end;
 end;
 procedure ClearApplication;
 begin
  RampingClear(RampVolt);
 end;
 procedure PollApplication;
 begin
  // v0/v1=start/stop Voltage, rate - ramping speed Volt/sec.
  if SomethingHappened then RampingStart(RampVolt,v0,v1,rate);
  RampingHandler;
 end;
