/*@!Encoding:1252*/
variables
{
  // Globals for "Sensor_3" device
  BYTE gNodeId          = 28;
  char gNodeLabel[32]   = "Sensor_3_ID28";

  // Definition of debugging constants
  const int kDbgInfo    = 10;
  const int kDbgWarning = 5;
  const int kDbgError   = 1;
  const int kDbgQuiet   = 0;

  // General global variables
  int gDbgLevel         = kDbgInfo; // Set debug level for output to write window
  int gOutputLevelNL    = 10;       // output level for the NodeLayer DLL (for more information refer
                                    // to function "coSetOutputLevel()" in the online help system)

  // variables for LED handling
  msTimer runLEDTimer;           // timer for RUN LED control
  msTimer errLEDTimer;           // timer for ERR LED control
  int errLEDFlashCnt    = 0;     // flash counter for ERR LED (ON)
  int errLEDType        = 0;     // type of error signalled via ERR LED

  // constant values for LED handling
  const int kErrLEDWarning = 0x08;	// mask for ERR LED
  const int kErrLEDErrCtrl = 0x10;	// mask for ERR LED
  const int kErrLEDBusOff  = 0x80;  // mask for ERR LED
  const int kShortTime     = 200;   // timing value for LED
  const int kLongTime      = 1000;  // timing value for LED
  msTimer enableTimer;
}

on start
{
  @sysvar::GUIControls::Node28_ID = gNodeId;
}

on sysvar CANopen::CAN::Sensor_3_ID28::Control::CommunicationState
{
  int oldState;
  if (oldState != @this) {
    cancelTimer(runLEDTimer);          // stop RUN LED flashing
    oldState = @this;
  }

  switch(@this)
  {
    case 0: // Not active
      @sysvar::GUIControls::Node28_State = 0;        // set RUN LED -> OFF
      writeDbgLevel( kDbgInfo, "<%s>: Changed state to 'Not active'", gNodeLabel );
      break;
    case 4: // Prepared
      setTimer(runLEDTimer, 200);      // start first cycle for RUN LED
      @sysvar::GUIControls::Node28_State = 0;        // set RUN LED -> OFF
      writeDbgLevel( kDbgInfo, "<%s>: Changed state to 'Prepared'", gNodeLabel );
      break;
    case 5: // Operational
      @sysvar::GUIControls::Node28_State = 3;        // set RUN LED -> ON
      writeDbgLevel( kDbgInfo, "<%s>: Changed state to 'Operational'", gNodeLabel );
      break;
    case 6: // Reset Node
      @sysvar::GUIControls::Node28_State = 0;        // set RUN LED -> OFF
      errLEDType &= ~kErrLEDErrCtrl;   // reset flag
      writeDbgLevel( kDbgInfo, "<%s>: 'Reset Node' command received", gNodeLabel );
      break;
    case 7: // Reset Communication
      @sysvar::GUIControls::Node28_State = 0;        // set RUN LED -> OFF
      errLEDType &= ~kErrLEDErrCtrl;   // reset flag
      writeDbgLevel( kDbgInfo, "<%s>: 'Reset Communication' command received", gNodeLabel );
      break;
    case 127: // Preoperational
      setTimer(runLEDTimer, 200);      // start first cycle for RUN LED
      @sysvar::GUIControls::Node28_State = 0;        // set RUN LED -> OFF
      writeDbgLevel( kDbgInfo, "<%s>: Changed state to 'Preoperational'", gNodeLabel );
      break;
    default:
      @sysvar::GUIControls::Node28_State = 0;       // set RUN LED -> OFF
      writeDbgLevel( kDbgInfo, "<%s>: Changed state (?)", gNodeLabel );
      break;
  }

  // TODO: Implement additional handling here

}

on busOff
{
  coNewError(kErrLEDBusOff);
}

on errorActive
{
  errLEDType &= ~kErrLEDBusOff;  // reset flag
  errLEDType &= ~kErrLEDWarning; // reset flag
}

on warningLimit
{
  coNewError(kErrLEDWarning);
}

void EnableSensor(byte enable)
{
  if(enable == 1)
  {
    @sysvar::CANopen::CAN::Sensor_3_ID28::Control::Enabled = 1;
    setTimer(enableTimer, 1);
    @sysvar::GUIControls::Node28_ID = gNodeId;
  }
  else
  {
    @sysvar::CANopen::CAN::Sensor_3_ID28::Control::Enabled = 0;
    ShutDownLights();
  }
}

on timer enableTimer
{
  CANopenInternalNMTCommand(gNodeId, 1);
}
  
on sysVar GUIControls::Sensor3_Connected
{
  // write the actual state
  if(@sysvar::GUIControls::Sensor3_Connected == 1)
  {
    sysSetVariableString(sysvar::GUIControls::Sensor3_CnxnState,"");
  } // if
  else{
  sysSetVariableString(sysvar::GUIControls::Sensor3_CnxnState,"!! unplugged !!");
  } // else
  
  if(@sysvar::GUIControls::MainSwitch == 0){
    return;
  } // if
  
  EnableSensor(@sysvar::GUIControls::Sensor3_Connected);
}

ShutDownLights()
{
  @sysvar::GUIControls::Node28_State = 0;
  @sysvar::GUIControls::Node28_ID = 0;
}

on sysVar GUIControls::MainSwitch
{
  EnableSensor(@sysvar::GUIControls::Sensor3_Connected == 1 && @this);
}

//
// Use this function to set the error type of the error LED
//
void coNewError (int ErrType)
{
  if (errLEDType == 0)
  {
    // timer is not running
    cancelTimer(errLEDTimer);
    setTimer(errLEDTimer, 0);
  }
  if (errLEDType < ErrType)
  {
    // there is no higher priority error active
    @sysvar::GUIControls::Node28ErrLed = 1;                    // set ERR LED -> ON
    errLEDFlashCnt = 0;
  }
  errLEDType |= ErrType;                          // set flag
}

on timer errLEDTimer
{
  if (errLEDType)
  {
    // check error flags according to their priority
    if (errLEDType >= kErrLEDBusOff)
    {
      // always ON
      setTimer(errLEDTimer, kShortTime);
      return;
    }
    if (errLEDType >= kErrLEDErrCtrl)
    {
      // double flash
      if (@sysvar::GUIControls::Node28ErrLed != 0)
      {
        @sysvar::GUIControls::Node28ErrLed = 0;               // set ERR LED -> OFF
        if (errLEDFlashCnt == 1)
        {
          errLEDFlashCnt = 0;
          setTimer(errLEDTimer, kLongTime);
        }
        else
        {
          errLEDFlashCnt++;
          setTimer(errLEDTimer, kShortTime);
        }
      }
      else
      {
        @sysvar::GUIControls::Node28ErrLed = 1;               // set ERR LED -> ON
        setTimer(errLEDTimer, kShortTime);
      }
      return;
    }
    if (errLEDType >= kErrLEDWarning)
    {
      // single flash
      if (@sysvar::GUIControls::Node28ErrLed != 0)
      {
        @sysvar::GUIControls::Node28ErrLed = 0;               // set ERR LED -> OFF
        setTimer(errLEDTimer, kLongTime);
      }
      else
      {
        @sysvar::GUIControls::Node28ErrLed = 1;               // set ERR LED -> ON
        setTimer(errLEDTimer, kShortTime);
      }
      return;
    }
  }
  else
  {
    // no active error
    @sysvar::GUIControls::Node28ErrLed = 0;                   // set ERR LED -> OFF
    errLEDFlashCnt = 0;
  }
}

on timer runLEDTimer
{
  if (@sysvar::GUIControls::Node28_State == 0)
  {
    // LED is actually OFF
    setTimer(runLEDTimer, kShortTime);           // start first cycle for RUN LED
    @sysvar::GUIControls::Node28_State = 3;                    // set RUN LED -> ON
  }
  else
  {
    // LED is actually ON
   @sysvar::GUIControls::Node28_State = 0;                    // set RUN LED -> OFF
    switch (@sysvar::CANopen::CAN::Sensor_3_ID28::Control::CommunicationState)
    {
      case 4: // stopped
        setTimer(runLEDTimer, kLongTime);        // OFF cycle for RUN LED
        break;
      case 127: // pre-operational
        setTimer(runLEDTimer, kShortTime);       // OFF cycle for RUN LED
        break;
      default:
        break;
    }
  }
}
