unit uRotorIFDynamic;
{ Interface unit for J.R. Kerr NMCLIB04.DLL NOW Rotor.DLL }
// Hello Big Jim...  The entry points are  C A S E   S E N S I T I V E  // 2012-07-22 Changed pchar to pAnsichar in SioOpen and get/put

interface

uses
  Winapi.Windows, Winapi.Messages, SysUtils, uSETITypes, Dialogs;

{$REGION '-- C O N S T A N T S ----- }

Const
  AzPulsePerDeg = 628; // Rounded up to an integer
  AzVelocity = 70000; // 100000
  AzAcceleration = 100; // 20; // back to 20 2009-03-09
  // ElPulsePerDeg = 2494;
  ElPulsePerDeg = 667; // 113384 pulse / 170deg =  667 pulse/Deg, 90 deg = 53357 pulse 2018-05-31
  ElVelocity = 100000;
  ElAcceleration = 250; // was 75

{$IF Defined(NoFilterKerr) }
  CNumKerrModules = 2;
{$ELSE}
  CNumKerrModules = 3;
{$IFEND}
  FilterRelay = 2; // Channel on the Head End electronics Kerr module
{$IF Defined(NoFilterKerr) }
  ElAddr = 1;
  AzAddr = 2;
  IOAddr = 99;
{$ELSE}
  ElAddr = 2;
  AzAddr = 3;
  IOAddr = 1;
{$IFEND}
  AzPWM = 75; // For rotor homing (was 100)
  ElPWM = 150; // For rotor homing (was 250)
  ElKp = 100;
  ElKd = 1000;
  ElKi = 0;
  ElIl = 0;
  ElEl = 16000;

  ElOl = 255;
  ElCl = 0;
  ElSr = 1;
  ElDc = 0; // Dead band compensation
  ElSm = 1;

  AzMax = 360;
  AzKp = 100;
  AzKd = 1000;
  AzKi = 0;
  AzIl = 0;
  AzEl = 16000;

  AzOl = 255;
  AzCl = 0;
  AzSr = 1;
  AzDc = 0; // Dead band compensaton was 45
  AzSm = 1;

  // Module type definitions:
  SERVOMODTYPE = 0;
  ADCMODTYPE = 1;
  IOMODTYPE = 2;
  STEPMODTYPE = 3;

  // Servo Module Command set:
  RESET_POS = $00; // Reset encode counter to 0
  SET_ADDR = $01; // Set address and group address
  DEF_STAT = $02; // Define status item to return
  READ_STAT = $03; // Read value of current status items
  LOAD_TRAJ = $04; // Load trajectory data
  START_MOVE = $05; // Start pre-loaded trajectory move
  SET_GAIN = $06; // Set servo gain and contro parameters
  STOP_MOTOR = $07; // Stop motor
  IO_CTRL = $08; // Define bit directions and set output
  SET_HOMING = $09; // Define homing mode
  SET_BAUD = $0A; // Set the baud rate
  CLEAR_BITS = $0B; // Save current position in the home position register
  SAVE_AS_HOME = $0C; // Store the input bytes and timer value
  // $ 0D   Not used
  NOP = $0E; // No Op - returnes previous defined status
  HARD_RESET = $0F; // RESET - no status is returned

  // IO modules STATUSITEMS bit definitions
  SEND_AD1 = $02;
  SEND_AD2 = $04;
  SEND_AD3 = $08;

  // Servo Module STATUSITEMS bit definitions
  SEND_POS = $01;
  SEND_AD = $02;
  SEND_VEL = $04;
  SEND_AUX = $08;
  SEND_HOME = $10;
  SEND_ID = $20;
  SEND_PERROR = $40;
  SEND_NPOINTS = $80;
  // Servo Module LOAD_TRAJ control byte bit definitions
  LOAD_POS = $01;
  LOAD_VEL = $02;
  LOAD_ACC = $04;
  LOAD_PWM = $08;
  ENABLE_SERVO = $10;
  VEL_MODE = $20;
  REVERSE = $40;
  MOVE_REL = $40;
  START_NOW = $80;

  // Servo Module STOP_MOTOR control byte bit definitions:
  AMP_ENABLE = $01; // Enables the amplifier
  MOTOR_OFF = $02; // Turns the motor off
  STOP_ABRUPT = $04; // Slam on the brakes.
  STOP_SMOOTH = $08; // Decellerate smoothly
  STOP_HERE = $10; // Stop at position

  // Servo Module IO_CTRL control byte bit definitions:
  SET_OUT1 = $01; // Set limit1 output (clear other wise)
  SET_OUT2 = $02; // Set limit2 output (clear other wise)
  IO1_IN = $04; // Limit 1 is an input (otherwise its an output)
  IO2_IN = $08; // Limit 2 is an input (otherwise its an output)

  LIMSTOP_OFF = $04; // turn off motor on limit
  LIMSTOP_ABRUPT = $08; // stop abruptly on limit
  THREE_PHASE = $10; // 1 = 3-phase mode, 0 = single PWM channel
  ANTIPHASE = $20; // 1 = antiphase (0 = 50% duty cycle), 0 = PWM & dir
  FAST_PATH = $408; // 0 = 30 or 60 Hz path execution, 1 = 60 or 120 Hz
  STEP_MODE = $808; // 0 = normal operation, 1 = Step & Direction enabled

  // Servo Module SET_HOMING control byte bit definitions:
  ON_LIMIT1 = $01; // Home on change in limit1
  ON_LIMIT2 = $02; // Home on change in limit2
  HOME_MOTOR_OFF = $04; // Turn motor off when homed
  ON_INDEX = $08; // Home on change in index
  HOME_STOP_ABRUPT = $10; // Stop abruptlyh when homed
  HOME_STOP_SMOOTH = $20; // Stop smoothly when homed
  ON_POS_ERR = $40; // home on excessive position error
  ON_CUR_ERR = $80; // home on overcurrent error

  // Servo Module STATUS byte bit definitions:
  MOVE_DONE = $01; // set when move done (in Trap) when goal reached (in VEL0
  CKSUM_ERROR = $02; // checksum error received in command
  OVERCURRENT = $04; // Overcurrent detected (sticky bit)
  POWER_ON = $08; // Motor power is on
  POS_ERR = $10; // Set on excess positon error (sticky bit)
  LIMIT1 = $20; // Limit Switch 1 (on or off)
  LIMIT2 = $40; // Limit Switch 2 (on or off)
  HOME_IN_PROG = $80; // Set if searching for home.  Reset when found

  // Servo Module  Auxiliary STATUS byte bit definitions:
  INDEX = $01; // Value of the encoder index signal
  POS_WRAP = $02; // Set when 32 bit position counter wraps (sticky bit)
  SERVO_ON = $04; // Set when positon servo is operating
  ACCEL_DONE = $08; // Set when ecceleration portion of a move is done
  SLEW_DONE = $10; // Set whe slew portion of a move is done
  SERVO_OVERRUN = $20;
  // Set of servo takes longer than the specified servo period
  PATH_MODE = $40; // Set when path mode motion is in progress.
{$ENDREGION}
  //

function setErrorMsgBox(Text: String): boolean;
function setSimpleMsgBox(Text: String): boolean; // Done
function setErrorPrinting(OnOff: integer): boolean;
// function setNoOp(value: integer): boolean;
function setNmcNoOp(value: byte): byte;
function getAzMoveDone: boolean;
function getElMoveDone: boolean;
procedure setElevation(value: TDegrees);
procedure setAzimuth(value: TDegrees);
procedure setElevationTrajectory(value: Double);
procedure setAzimuthTrajectory(value: Double);
procedure setOn(value: boolean);
procedure setFilter(value: boolean);
function getFilter: boolean;
function getAzMotorPosition: integer;
function GetPError(value: byte): integer;
procedure setAzMotorPosition(value: integer);
function getElMotorPosition: integer;
procedure setElMotorPosition(value: integer);

function setHome: boolean;
function getHome: boolean;
function KerrInit(ComName: string; BaudRate: integer): boolean;
procedure SetNmcShutdown();
function NumKerrModules: integer;

function SetNmcInit(portname: PAnsiChar; BaudRate: integer): integer;
function ServoSetGain2(addr: byte; kp: smallInt; kd: smallInt; ki: smallInt; il: smallInt; ol: byte; cl: byte; el: smallInt; sr: byte; dc: byte;
  sm: byte): integer;

function ServoSetPos(addr: byte; pos: integer): boolean;

//
var

  dllHandle: cardinal;

implementation

// uses uAntenna;

var
  // FKerr: boolean;

  LastElMotorPosition: integer;
  LastAzMotorPosition: integer;
  FFilter: boolean;
  Port: PAnsiChar = 'COM2';

{$REGION 'Dynamic DLL Calls }

function setNmcNoOp(value: byte): byte;
var
  NmcNoOpFunc: TNmcNoOpFunc;
  res: boolean;
begin
  result := 0; // preset the result to error
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @NmcNoOpFunc := GetProcAddress(dllHandle, 'NmcNoOp');
    if Assigned(NmcNoOpFunc) then
      res := NmcNoOpFunc(value)
    else
      FreeLibrary(dllHandle);
  end;
end;

function setErrorPrinting(OnOff: integer): boolean;
var
  ErrorPrintingProc: TErrorPrintingProc;
begin // TErrorPrintingProcedure = procedure(f: integer)stdcall; // 1=print,0=No Print
  result := False;
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ErrorPrintingProc := GetProcAddress(dllHandle, 'ErrorPrinting');
    if Assigned(ErrorPrintingProc) then
    begin
      ErrorPrintingProc(OnOff);
      result := True;
    end
    else
      FreeLibrary(dllHandle);
  end;
end;

function setErrorMsgBox(Text: String): boolean;
var
  ErrorMsgBoxFunc: TErrorMsgBoxFunc;

begin

  result := False; // preset the result to error
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ErrorMsgBoxFunc := GetProcAddress(dllHandle, 'ErrorMsgBox');
    if Assigned(ErrorMsgBoxFunc) then
      if (ErrorMsgBoxFunc(PAnsiChar(AnsiString(Text))) <> 0) then
        result := True
      else
        FreeLibrary(dllHandle);
  end;
end;

function setSimpleMsgBox(Text: String): boolean;
var
  SimpleMsgBoxFunc: TSimpleMsgBoxFunc;

begin

  result := False; // preset the result to error
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @SimpleMsgBoxFunc := GetProcAddress(dllHandle, 'SimpleMsgBox');
    if Assigned(SimpleMsgBoxFunc) then
      if (SimpleMsgBoxFunc(PAnsiChar(AnsiString(Text))) <> 0) then
        result := True
      else
        FreeLibrary(dllHandle);
  end;
end;

function setNcmNoOp(addr: byte): byte;
var
  NmcNoOpFunc: TNmcNoOpFunc;
  res: boolean;
begin

  result := 0; // preset the results
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @NmcNoOpFunc := GetProcAddress(dllHandle, 'NmcNoOp');
  end;
  if Assigned(NmcNoOpFunc) then
  begin
    res := NmcNoOpFunc(addr);
  end
  else
  begin
    ShowMessage('Error in NmcNoOp');
    FreeLibrary(dllHandle);
  end;
end;

function NmcGetStat(addr: byte): byte;
var
  NmcGetStatFunc: TNmcGetStatFunc;
begin
  result := 0;

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @NmcGetStatFunc := GetProcAddress(dllHandle, 'NmcGetStat');
  end;
  if Assigned(NmcGetStatFunc) then
  begin
    result := NmcGetStatFunc(addr);
  end
  else
  begin
    ShowMessage('Error in NmcGetStat ');
    FreeLibrary(dllHandle);
  end;
end;

function ServoLoadTraj(addr: byte; mode: byte; pos: LongInt; vel: LongInt; acc: LongInt; pwm: byte): boolean; stdCall;
var
  ServoLoadTrajFunc: TServoLoadTrajFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoLoadTrajFunc := GetProcAddress(dllHandle, 'ServoLoadTraj');
  end;
  if Assigned(ServoLoadTrajFunc) then
  begin
    result := ServoLoadTrajFunc(addr, mode, pos, vel, acc, pwm);
  end
  else
  begin
    ShowMessage('Error in ServoLoadTraj');
    FreeLibrary(dllHandle);
  end;

end;

function ServoStopMotor(addr: byte; mode: byte): boolean;
var
  ServoStopMotorFunc: TServoStopMotorFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoStopMotorFunc := GetProcAddress(dllHandle, 'ServoStopMotor');
  end;
  if Assigned(ServoStopMotorFunc) then
  begin
    result := ServoStopMotorFunc(addr, mode);
  end
  else
  begin
    ShowMessage('Error in ServoStopMotor');
    FreeLibrary(dllHandle);
  end
end;

function IoBitDirOut(portname: byte; bitnum: integer): integer;
var
  IoBitDirOutFunc: TIoBitDirOutFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @IoBitDirOutFunc := GetProcAddress(dllHandle, 'IoBitDirOut');
  end;
  if Assigned(IoBitDirOutFunc) then
  begin
    result := IoBitDirOutFunc(portname, bitnum);
  end
  else
  begin
    ShowMessage('Error in IoBitDirOut');
    FreeLibrary(dllHandle);
  end
end;

procedure ErrorPrinting(OnOff: integer); // True =print,False=No Print
var
  ErrorPrintingProc: TErrorPrintingProc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ErrorPrintingProc := GetProcAddress(dllHandle, 'ErrorPrinting');
  end;
  if Assigned(ErrorPrintingProc) then
  begin
    ErrorPrintingProc(OnOff);
  end
  else
  begin
    ShowMessage('Error in ErrorPrinting ');
    FreeLibrary(dllHandle);
  end

end;

procedure SetNmcShutdown();
var
  NmcShutdownProcedure: TNmcShutdownProcedure;
begin

  // // Never attempt to shutdown Kerr...
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @NmcShutdownProcedure := GetProcAddress(dllHandle, 'NmcShutdown');
  end;
  if Assigned(NmcShutdownProcedure) then
  begin

    NmcShutdownProcedure();
  end
  else
  begin
    ShowMessage('Error in NmcShutdown ');
    FreeLibrary(dllHandle);
  end

end;

function IoGetPWMVal(portname: byte; Chan: byte): byte;
var
  IoGetPWMValFunc: TIoGetPWMValFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @IoGetPWMValFunc := GetProcAddress(dllHandle, 'IoGetPWMVal');
  end;
  if Assigned(IoGetPWMValFunc) then
  begin
    result := IoGetPWMValFunc(portname, Chan);
  end
  else
  begin
    ShowMessage('Error in IoGetPWMVal');
    FreeLibrary(dllHandle);
  end

end;

function IoSetPWMVal(portname: byte; Pwm1: byte; Pwm2: byte): integer;
var
  IoSetPWMValFunc: TIoSetPWMValFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @IoSetPWMValFunc := GetProcAddress(dllHandle, 'IoSetPWMVal');
  end;
  if Assigned(IoSetPWMValFunc) then
  begin
    result := IoSetPWMValFunc(portname, Pwm1, Pwm2);
  end
  else
  begin
    ShowMessage('Error in IoSetPWMVal');
    FreeLibrary(dllHandle);
  end

end;

function NmcReadStatus(addr: byte; statusitems: byte): boolean;
var
  NmcReadStatusFunc: TNmcReadStatusFunc;
begin
  dllHandle := LoadLibrary('Rotor.DLL');

  if dllHandle <> 0 then
  begin
    @NmcReadStatusFunc := GetProcAddress(dllHandle, 'NmcReadStatus');
  end;
  if Assigned(NmcReadStatusFunc) then
  begin
    result := NmcReadStatusFunc(addr, statusitems);
  end
  else
  begin
    ShowMessage('Error in NmcReadStatus ');
    FreeLibrary(dllHandle);
  end

end;

function ServoGetPos(addr: byte): LongInt;
var
  ServoGetPosFunc: TServoGetPosFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoGetPosFunc := GetProcAddress(dllHandle, 'ServoGetPos');
  end;
  if Assigned(ServoGetPosFunc) then
  begin
    result := ServoGetPosFunc(addr);
  end
  else
  begin
    ShowMessage('Error in ServoGetPos');
    FreeLibrary(dllHandle);
  end

end;

function ServoGetPError(addr: byte): integer;
var
  ServoGetPErrorFunc: TServoGetPErrorFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoGetPErrorFunc := GetProcAddress(dllHandle, 'ServoGetPError');
  end;
  if Assigned(ServoGetPErrorFunc) then
  begin
    result := ServoGetPErrorFunc(addr);
  end
  else
  begin
    ShowMessage('Error in ServoGetPError');
    FreeLibrary(dllHandle);
  end

end;

function ServoSetPos(addr: byte; pos: integer): boolean;
var
  ServoSetPosFunc: TServoSetPosFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoSetPosFunc := GetProcAddress(dllHandle, 'ServoSetPos');
  end;
  if Assigned(ServoSetPosFunc) then
  begin
    result := ServoSetPosFunc(addr, pos);
  end
  else
  begin
    ShowMessage('Error in ServoSetPos');
    FreeLibrary(dllHandle);
  end

end;

function ServoResetPos(addr: byte): boolean;
var
  ServoResetPosFunc: TServoResetPosFunc;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoResetPosFunc := GetProcAddress(dllHandle, 'ServoResetPos');
  end;
  if Assigned(ServoResetPosFunc) then
  begin
    result := ServoResetPosFunc(addr);
  end
  else
  begin
    ShowMessage('Error in ServoResetPos');
  end

end;

function ServoSetGain2(addr: byte; kp: smallInt; kd: smallInt; ki: smallInt; il: smallInt; ol: byte; cl: byte; el: smallInt; sr: byte; dc: byte;
  sm: byte): integer;
var
  ServoSetGain2Func: TServoSetGain2Func;
begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @ServoSetGain2Func := GetProcAddress(dllHandle, 'ServoSetGain2');
  end;
  if Assigned(ServoSetGain2Func) then
  begin
    result := ServoSetGain2Func(addr, kp, kd, ki, il, ol, cl, el, sr, dc, sm);
  end
  else
  begin
    ShowMessage('Error in ServoSetGain2');
    FreeLibrary(dllHandle);
  end
end;

function SetNmcInit(portname: PAnsiChar; BaudRate: integer): integer;
var
  NmcInitFunc: TNmcInitFunc;
begin
  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @NmcInitFunc := GetProcAddress(dllHandle, 'NmcInit');
  end;
  if Assigned(NmcInitFunc) then
  begin
    result := NmcInitFunc(portname, BaudRate);
  end
  else
  begin
    ShowMessage('Error in NmcInitFunc');
    FreeLibrary(dllHandle);
  end

end;

function IoGetADCVal(portname: byte; Chan: byte): byte; stdcall;
var
  IoGetADCValFunc: TIoGetADCValFunc;

begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @IoGetADCValFunc := GetProcAddress(dllHandle, 'IoGetADCVal');
  end;
  if Assigned(IoGetADCValFunc) then
  begin
    result := IoGetADCValFunc(portname, Chan);
  end
  else
  begin
    ShowMessage('Error in IoGetADCVal ');
    FreeLibrary(dllHandle);
  end;
end;

function NmcInitFunc(portname: PAnsiChar; BaudRate: integer): integer; stdCall;
var
  NmcInitFunc: TNmcInitFunc;

begin

  dllHandle := LoadLibrary('Rotor.DLL');
  if dllHandle <> 0 then
  begin
    @NmcInitFunc := GetProcAddress(dllHandle, 'NmcInit ');
  end;
  if Assigned(NmcInitFunc) then
  begin
    result := NmcInitFunc(portname, BaudRate);
  end
  else
  begin
    ShowMessage('Error in NmcInitFunc');
    FreeLibrary(dllHandle);
  end;
end;

{$ENDREGION}
//
{$REGION 'Getter/Setter }

function getAzMoveDone: boolean;
var
  current_status_byte: byte;
  move_complete: byte;

begin

  result := False;
  setNmcNoOp(AzAddr);

  current_status_byte := NmcGetStat(AzAddr);
  move_complete := current_status_byte and MOVE_DONE;
  if move_complete = MOVE_DONE then
    result := True

end;

function getElMoveDone: boolean;
var
  current_status_byte: byte;
  move_complete: byte;

begin

  result := False;
  setNmcNoOp(ElAddr);
  current_status_byte := NmcGetStat(ElAddr);
  move_complete := current_status_byte and MOVE_DONE;
  if move_complete = MOVE_DONE then
    result := True;

end;

procedure setElevation(value: TDegrees);
begin
  //
end;

procedure setAzimuth(value: TDegrees);
begin
  //
end;

procedure setElevationTrajectory(value: Double);
var
  Elevation: integer;
  res: boolean;
begin

  res := False;
  Elevation := Trunc(value) * ElPulsePerDeg;
  res := ServoLoadTraj(ElAddr, LOAD_POS or LOAD_VEL or LOAD_ACC or ENABLE_SERVO or START_NOW, Elevation, ElVelocity, ElAcceleration, ElPWM);
  if NOT res then

  begin
    ShowMessage('ElLoadTraj Failed');
  end;

end;

procedure setAzimuthTrajectory(value: Double);
var
  Azimuth: integer;
begin

  Azimuth := Trunc(value) * AzPulsePerDeg;
  ServoLoadTraj(AzAddr, LOAD_POS or LOAD_VEL or LOAD_ACC or ENABLE_SERVO or START_NOW, Azimuth, AzVelocity, AzAcceleration, AzPWM);
end;

procedure setFilter(value: boolean);
var
  CurrentFilter: byte;
begin
{$IF Defined(NoFilterKerr) }
  exit;
{$IFEND}
  CurrentFilter := IoGetPWMVal(IOAddr, FilterRelay);
  // if (value = True) then
  if (value = False) then
    IoSetPWMVal(IOAddr, CurrentFilter, 0)
  else
    IoSetPWMVal(IOAddr, CurrentFilter, 255);
  FFilter := value;
end;

function getFilter: boolean;
begin
  result := FFilter;
end;

function getAzMotorPosition: integer;
begin

  NmcReadStatus(AzAddr, SEND_POS);
  result := ServoGetPos(AzAddr);
end;

function GetPError(value: byte): integer;
var
  pos_error: byte;
begin

  pos_error := 99;
  NmcReadStatus(value, SEND_PERROR);
  pos_error := ServoGetPError(value);
  // NmcRead(
end;

procedure setAzMotorPosition(value: integer);
begin

  ServoSetPos(AzAddr, value);
end;

function getElMotorPosition: integer;

begin
  result := 0;

  NmcReadStatus(ElAddr, SEND_POS);
  result := ServoGetPos(ElAddr);
end;

procedure setElMotorPosition(value: integer);
begin

  ServoSetPos(ElAddr, value);
end;

function getHome: boolean;
var
  FElHome, FAzHome: boolean;
begin

  result := False;
  LastElMotorPosition := getElMotorPosition;
  if (LastElMotorPosition <> getElMotorPosition) then
    FElHome := False
  else
    FElHome := True;

  LastAzMotorPosition := getAzMotorPosition;
  if (LastAzMotorPosition <> getAzMotorPosition) then
    FAzHome := False
  else
    FAzHome := True;
  if (FAzHome AND FElHome) then
  begin
    setAzMotorPosition(0);
    // Set Motor Position to Zero to start
    setElMotorPosition(0);

    ServoResetPos(AzAddr);
    ServoResetPos(ElAddr);

    result := True;
  end;
end;

function setHome: boolean;
var
  message1, message2: string;
begin

  ServoLoadTraj(AzAddr, LOAD_PWM or START_NOW or REVERSE, 0, 0, 0, AzPWM);
  ServoLoadTraj(ElAddr, LOAD_PWM or START_NOW or REVERSE, 0, 0, 0, ElPWM);

  try
    ServoSetGain2(ElAddr, ElKp, ElKd, ElKi, ElIl, ElOl, ElCl, ElEl, ElSr, ElDc, ElSm);
    ServoSetGain2(AzAddr, AzKp, AzKd, AzKi, AzIl, AzOl, AzCl, AzEl, AzSr, AzDc, AzSm);
  except
    message1 := ('Exception class name = ');
    message2 := ('Exception message = ');
  end;

end;

function KerrInit(ComName: string; BaudRate: integer): boolean;
var
  nModules: integer;
begin
  result := False;

  If setErrorPrinting(0) = True then
  begin
    nModules := SetNmcInit(PAnsiChar(AnsiString(ComName)), BaudRate);
    if (nModules = CNumKerrModules) then
    begin

      result := True;
    end;
  end;
end;

function NumKerrModules: integer;
begin
  result := CNumKerrModules;
end;

function getADC1: integer;

const // IO modules STATUSITEMS bit definitions
  SEND_AD1 = $02;
  SEND_AD2 = $04;
  SEND_AD3 = $08;
var
  status_items: byte;
begin

{$IF Defined(NoFilterKerr) }
  exit;
{$IFEND}
  status_items := SEND_AD1 or SEND_AD2 or SEND_AD3;
  NmcReadStatus(IOAddr, status_items);
  result := IoGetADCVal(IOAddr, 0);
  { analog1 := IoGetADCVal(IOAddr, 1);
    analog2 := IoGetADCVal(IOAddr, 20);

    Delay(1000);
    IoGetPWMVal(AzAddr, PWMVal);
    A2DOut := IoGetADCVal(1, 1);
  }
end;

procedure setTestJack(value: integer);
var
  Show: string;
  Request: integer;
begin

  // if not Ready then

  // FTestJack := value;
  // Request := value;
  // if (Request > 4095) then
  // Request := 4095;
  //
  // Mask := $01;
  //
  // for i := 0 to 11 do
  // begin
  // if (Request and Mask) <> 0 then
  // begin
  // Show := ' 1 ' + Show;
  //
  // IoSetOutBit(AddrIO, i);
  // end
  // else
  // begin
  // Show := ' 0 ' + Show;
  //
  // IoClrOutBit(AddrIO, i);
  // end;
  // Mask := Mask shl 1;
  // end;
  // sbAntenna.Panels[csbNote].text := 'Test Jack Bits: ' + Show;
end;

procedure setOn(value: boolean);
var
  i: integer;

  test: string;
begin

  if value = True then
  begin
    ServoStopMotor(AzAddr, AMP_ENABLE or MOTOR_OFF);
    ServoStopMotor(ElAddr, AMP_ENABLE or MOTOR_OFF);
{$IF Not Defined(NoFilterKerr) }
    for i := 0 to 11 do // Set all the Kerr IO bits to output for the D-to-A
      IoBitDirOut(IOAddr, i);
{$IFEND}
  end
  else
  begin

  end;
end;

{$ENDREGION}

end.
