FUNCTION_BLOCK RA_PFx_ENET_STS_CMD
(*=====================================================================================================================================
	[UDFB Name]					:RA_PFx_ENET_STS_CMD (v7)     
	[Catagory]					:Communication
	[Description]				:Status & Control of a PF75x, PF52x or PF4x drive over Ethernet using Explicit Messaging (v7)
	[Author]					:Rockwell Automation
	[Created using CCW version]	:7.00
	[FeedBack]					:RASampleCode@ra.rockwell.com
	[Revison History]			:2014-October - Original Release for Version 7
	[Notes]						:Required Drive Start Source and Speed Reference parameter settings for Ethernet
									for PF755, set P545=877 for embedded Ethernet port.
									for PF75x with 20-750-ENETR, set P545=874.
									for PF525, set P046=5 and P047=15 for embedded Ethernet port.
									for PF52x with 25-COMM-E2P, set P046=4 and P047=4.
									for PF4M with 20-COMM-E, set P106=5 and P108=5.
									for PF4/40/40P/400 with 20-COMM-E, set P036=5 and P038=5.
=====================================================================================================================================*)

FBENO := FBEN;
(*-------- Initialize --------*)
FBEN_RTRIG(FBEN);
IF (__SYSVA_FIRST_SCAN AND FBEN) OR FBEN_RTRIG.Q THEN
	
	(*-------- Initialize values --------*)	
	MSGDrvType_EN	:= TRUE;
	MSGTimeOut_EN	:= FALSE;
	MSGParWrite_EN	:= FALSE;
	MSGCmd_EN		:= FALSE;
	MSGSts_EN		:= FALSE;
	MSGParRead_EN	:= FALSE;
	FBError			:= TRUE;
	CommLoss		:= TRUE;
	Ready 	  		:= FALSE;
	Active 	 		:= FALSE;
	CmdFwd 			:= FALSE;
	CmdRev 			:= FALSE;
	DriveFault  	:= FALSE;
	AtRef			:= FALSE;
	SpeedFeedback	:= 0.0;
	CmdSpeed		:= 0.0;
	OutputCurrent	:= 0.0;
	OutputVoltage	:= 0.0;
	DCBusVoltage	:= 0.0;
	FaultCode		:= 0;
	DriveType		:= '';
		
	IF UpdateRate_ms < 1000 THEN 
   		ComTriggerType 	 := 1000; (*Triggers message every 1000 ms when IN is true*)
	ELSE
		ComTriggerType 	 := ANY_TO_UDINT(UpdateRate_ms);
	END_IF;
	
	(*-------- Set Common parameter values --------*)
	ComTargetPath    := '4,'+ IPAddress;	    
	ComConMode	     := 0;              (*0-unconnected, 1-Class 3*)
	ComUcTimeOut     := ComTriggerType; (*Unconnected message time out, Set to 0 means 3000ms, range 250-10000*)
	ComConMsgTimeOut := 800;            (*Class3 time out, Set to 0 means 3000ms, range 800-10000*)
	ComConClose      := FALSE;          (*Don't close the connection upon message completion*)
	
	(*-------- Set Read Drive Type parameter values --------*)
	DrvTypeCtrlCfg.TriggerType	:= 1000;
	DrvTypeTarCfg.Path			:= ComTargetPath;
	DrvTypeTarCfg.CipConnMode	:= ComConMode;
	DrvTypeTarCfg.UcmmTimeout	:= 1000; (*Unconnected message time out, Set to 0 means 3000ms, range 250-10000*)
	DrvTypeTarCfg.ConnMsgTimeout:= 800;  (*Class3 time out, Set to 0 means 3000ms, range 800-10000*)
	DrvTypeTarCfg.ConnClose		:= ComConClose;
	DrvTypeAppCfg.Service		:= 14;	(*Read*)
	DrvTypeAppCfg.Class			:= 146; (*DPI Device object*)
	DrvTypeAppCfg.Instance		:= 0;
	DrvTypeAppCfg.Attribute		:= 1;	(*Family text*)
	
	(*-------- Set Time Out parameter values --------*) 	
	TimeOutCtrlCfg.TriggerType	:= ComTriggerType;
	TimeOutTarCfg.Path			:= ComTargetPath;
	TimeOutTarCfg.CipConnMode	:= ComConMode;
	TimeOutTarCfg.UcmmTimeout	:= ComUcTimeOut;
	TimeOutTarCfg.ConnMsgTimeout:= ComConMsgTimeOut;
	TimeOutTarCfg.ConnClose		:= ComConClose;
	IF EnetCtrlTO_sec <> 0 THEN 
   		TimeOutReqData[1]:= EnetCtrlTO_sec;	(*Set Ethernet Control Timeout value in seconds*)	
	ELSE	
		TimeOutReqData[1]:= 5; (*If 0 (invalid) set Ethernet Control Timeout to 5 seconds*)
	END_IF;	
	TimeOutAppCfg.Service	:= 16; (*Write 1 parameter*)
	TimeOutAppCfg.Class		:= 7;  (*Register object*)
	TimeOutAppCfg.Instance	:= 0;  (*Write to class*)
	TimeOutAppCfg.Attribute	:= 100;(*Attribute for Control Timeout*)
	
	(*-------- Set Scattered Parameter Write to Drive parameter values --------*)
	ParWriteReqData[1]	:= 0;
	ParWriteReqData[2]	:= 0;
	ParWriteReqData[3]	:= 0;	
	ParWriteReqData[4]	:= 0;	
	ParWriteReqData[5]	:= 0;
	ParWriteReqData[6]	:= 0;
	ParWriteReqData[7]	:= 0;	
	ParWriteReqData[8]	:= 0;	
	ParWriteReqData[9]	:= 0;
	ParWriteReqData[10]	:= 0;
	ParWriteReqData[11]	:= 0;	
	ParWriteReqData[12]	:= 0;
	ParWriteReqData[13]	:= 0;
	ParWriteReqData[14]	:= 0;
	ParWriteReqData[15]	:= 0;	
	ParWriteReqData[16]	:= 0;
	ParWriteCtrlCfg.TriggerType		:= ComTriggerType;
	ParWriteTarCfg.Path				:= ComTargetPath;
	ParWriteTarCfg.CipConnMode		:= ComConMode;
	ParWriteTarCfg.UcmmTimeout		:= ComUcTimeOut;
	ParWriteTarCfg.ConnMsgTimeout	:= ComConMsgTimeOut;
	ParWriteTarCfg.ConnClose		:= ComConClose;
	ParWriteAppCfg.Class			:= 147;	(*Class code 93h for Parameter object*)
	ParWriteAppCfg.Instance			:= 0;
	ParWriteAppCfg.Attribute		:= 0;
		
	(*-------- Set Cmd to Drive parameter values --------*)
	CmdReqData[1]	:= 0;	(*Logic Command Data*)
	CmdReqData[2]	:= 0;
	CmdReqData[3]	:= 0;
	CmdReqData[4]	:= 0;
	CmdReqData[5]	:= 0;
	CmdReqData[6]	:= 0;
	CmdReqData[7]	:= 0;
	CmdReqData[8]	:= 0;
	CmdCtrlCfg.TriggerType	:= ComTriggerType;
	CmdTarCfg.Path		    := ComTargetPath;
	CmdTarCfg.CipConnMode   := ComConMode;
	CmdTarCfg.UcmmTimeout   := ComUcTimeOut;
	CmdTarCfg.ConnMsgTimeout:= ComConMsgTimeOut;
	CmdTarCfg.ConnClose		:= ComConClose;
	CmdAppCfg.Service		:= 16;	(*Write 1 parameter*)
	CmdAppCfg.Class			:= 7;	(*Register object*)
	CmdAppCfg.Attribute		:= 4;	(*Write data*)
		
	(*-------- Set Read Status from Drive Parameter values --------*)
	StsCtrlCfg.TriggerType		:= ComTriggerType;
	StsTarCfg.Path				:= ComTargetPath;
	StsTarCfg.CipConnMode		:= ComConMode;
	StsTarCfg.UcmmTimeout		:= ComUcTimeOut;
	StsTarCfg.ConnMsgTimeout	:= ComConMsgTimeOut;
	StsTarCfg.ConnClose			:= ComConClose;
	StsAppCfg.Service		 	:= 14;  (*Read*)
	StsAppCfg.Class				:= 7;   (*Register object*)
	StsAppCfg.Attribute		 	:= 4; 	(*Read data*)
		
	(*-------- Set Scattered Parameter Read from Drive parameter values --------*)
	ParReadReqData[1]	:= 0;
	ParReadReqData[2]	:= 0;
	ParReadReqData[3]	:= 0;
	ParReadReqData[4]	:= 0;
	ParReadReqData[5]	:= 0;
	ParReadReqData[6]	:= 0;
	ParReadReqData[7]	:= 0;
	ParReadReqData[8]	:= 0;
	ParReadReqData[9]	:= 0;
	ParReadReqData[10]	:= 0;
	ParReadReqData[11]	:= 0;
	ParReadReqData[12]	:= 0;
	ParReadReqData[13]	:= 0;
	ParReadReqData[14]	:= 0;
	ParReadReqData[15]	:= 0;
	ParReadReqData[16]	:= 0;
	ParReadReqData[17]	:= 0;
	ParReadReqData[18]	:= 0;
	ParReadReqData[19]	:= 0;
	ParReadReqData[20]	:= 0;
	ParReadReqData[21]	:= 0;
	ParReadReqData[22]	:= 0;
	ParReadReqData[23]	:= 0;
	ParReadReqData[24]	:= 0;
	ParReadReqData[25]	:= 0;
	ParReadReqData[26]	:= 0;
	ParReadReqData[27]	:= 0;
	ParReadReqData[28]	:= 0;
	ParReadReqData[29]	:= 0;
	ParReadReqData[30]	:= 0;
	ParReadReqData[31]	:= 0;
	ParReadReqData[32]	:= 0;
	ParReadCtrlCfg.TriggerType		:= ComTriggerType;
	ParReadTarCfg.Path				:= ComTargetPath;
	ParReadTarCfg.CipConnMode		:= ComConMode;
	ParReadTarCfg.UcmmTimeout		:= ComUcTimeOut;
	ParReadTarCfg.ConnMsgTimeout	:= ComConMsgTimeOut;
	ParReadTarCfg.ConnClose			:= ComConClose;
	ParReadAppCfg.Class				:= 147;(*Class code 93h for Parameter object*)
	ParReadAppCfg.Instance			:= 0;
	ParReadAppCfg.Attribute			:= 0;
	
END_IF;

(*-------- Main Routine --------*)
IF FBEN THEN 
	
	IF MSGDrvType_EN THEN
		
		IF MSGDrvType_Q_RTRIG.Q THEN
			MSGTimeOut_EN	:= TRUE;
			UnknownDrv		:= FALSE;
			MSGDrvType_EN	:= FALSE;
			DrvTypeCtrlCfg.TriggerType	:= 1000;
				
			FOR Index := 1 to 16 DO
				DrvTypeChar[Index]	:= DrvTypeResData[Index];
			END_FOR;
			
			DrvTypeChar[0]	:= 16;
			COP_DrvType(TRUE,DrvTypeChar,0,DrvTypeString,0,1,FALSE);
			DriveType		:= DrvTypeString[1];
									
			IF (DriveType='PowerFlex 755   ' OR DriveType='PowerFlex 753   ') THEN
				ParWriteReqLen			:= 16; (*Write 16 bytes of data*)
				ParWriteAppCfg.Service	:= 78; (*Service code 4Eh for scattered Write*)
				ParWriteReqData[1]		:= 23; (*AccelTime1-Parameter 535(2*256+23)*)
				ParWriteReqData[2]		:= 2;  (*AccelTime1-Parameter 535(2*256+23)*)
				ParWriteReqData[9]		:= 25; (*DecelTime1-Parameter 537(2*256+25)*)
				ParWriteReqData[10]		:= 2;  (*DecelTime1-Parameter 537(2*256+25)*)
				CmdReqLen				:= 8;
				CmdAppCfg.Instance		:= 4;  (*Logic Command and Reference data (read/write)*)
				StsAppCfg.Instance		:= 3;  (*Logic Status and Feedback data (read-only)*)
				ParReadReqLen			:= 32;
				ParReadAppCfg.Service	:= 77; (*Service code 4Dh for scattered Read*)
				ParReadReqData[1]		:= 7;  (*Output Current-Parameter 7*)
				ParReadReqData[9]		:= 8;  (*Output Voltage-Parameter 8*)
				ParReadReqData[17]		:= 11; (*DC Bus Voltage-Parameter 11*)
				ParReadReqData[25]		:= 183;(*Most Recent Fault-Parameter 951(3*256+183)*)
				ParReadReqData[26]		:= 3;  (*Most Recent Fault-Parameter 951(3*256+183)*)
												
			ELSIF (DriveType='PowerFlex 525   ' OR DriveType='PowerFlex 523   ') THEN
				SpeedFeedbackDiv		:= 100.0;
				OutputCurrentDiv		:= 100.0;
				DCBusVoltageDiv			:= 1.0;
				OutputVoltageDiv		:= 10.0;
				ParWriteReqLen			:= 8;  (*Write 8 bytes of data*)
				ParWriteAppCfg.Service	:= 52; (*Service code 34h for scattered Write*)
				ParWriteReqData[1]		:= 41; (*AccelTime1-Parameter 41*)
				ParWriteReqData[5]		:= 42; (*DecelTime1-Parameter 42*)
				CmdReqLen				:= 4;
				CmdAppCfg.Instance		:= 4;  (*Logic Command and Reference data (read/write)*)
				StsAppCfg.Instance		:= 3;  (*Logic Status and Feedback data (read-only)*)
				ParReadReqLen			:= 16;
				ParReadAppCfg.Service	:= 50; (*Service code 32h for scattered Read*)
				ParReadReqData[1]		:= 3;  (*Output Current-Parameter 3*)
				ParReadReqData[5]		:= 4;  (*Output Voltage-Parameter 4*)
				ParReadReqData[9]		:= 5;  (*DC Bus Voltage-Parameter 5*)
				ParReadReqData[13]		:= 7;  (*Most Recent Fault-Parameter 7*)
				
			ELSIF (LEFT(DriveType,11)='PowerFlex 4') THEN
				ParWriteReqLen			:= 8;  (*Write 8 bytes of data*)
				ParWriteAppCfg.Service	:= 52; (*Service code 34h for scattered Write*)
				CmdReqLen				:= 4;
				CmdAppCfg.Instance		:= 3;  (*Logic Command and Reference data (read/write)*)
				StsAppCfg.Instance		:= 4;  (*Logic Status and Feedback data (read-only)*)
				ParReadReqLen			:= 16;
				ParReadAppCfg.Service	:= 50; (*Service code 32h for scattered Read*)
				ParReadReqData[1]		:= 3;  (*Output Current-Parameter 3*)
				ParReadReqData[5]		:= 4;  (*Output Voltage-Parameter 4*)
				ParReadReqData[9]		:= 5;  (*DC Bus Voltage-Parameter 5*)
				ParReadReqData[13]		:= 7;  (*Most Recent Fault-Parameter 7*)
				
				IF DriveType='PowerFlex 4M    ' THEN
					ParWriteReqData[1]	:= 109; (*AccelTime1-Parameter 109*)
					ParWriteReqData[5]	:= 110; (*DecelTime1-Parameter 110*)
				ELSE
					ParWriteReqData[1]	:= 39; (*AccelTime1-Parameter 39*)
					ParWriteReqData[5]	:= 40; (*DecelTime1-Parameter 40*)
				END_IF;
								
				IF DriveType='PowerFlex 4M    ' THEN
					SpeedFeedbackDiv	:= 10.0;
					OutputCurrentDiv	:= 100.0;
					DCBusVoltageDiv		:= 1.0;
					OutputVoltageDiv	:= 10.0;
				ELSIF DriveType='PowerFlex 4     ' THEN
					SpeedFeedbackDiv	:= 10.0;
					OutputCurrentDiv	:= 100.0;
					DCBusVoltageDiv		:= 10.0;
					OutputVoltageDiv	:= 10.0;
				ELSIF DriveType='PowerFlex 40    ' THEN
					SpeedFeedbackDiv	:= 10.0;
					OutputCurrentDiv	:= 100.0;
					DCBusVoltageDiv		:= 1.0;
					OutputVoltageDiv	:= 10.0;
				ELSIF DriveType='PowerFlex 400   ' THEN
					SpeedFeedbackDiv	:= 100.0;
					OutputCurrentDiv	:= 10.0;
					DCBusVoltageDiv		:= 1.0;
					OutputVoltageDiv	:= 1.0;
				ELSIF DriveType='PowerFlex 40P   ' THEN
					SpeedFeedbackDiv	:= 100.0;
					OutputCurrentDiv	:= 100.0;
					DCBusVoltageDiv		:= 1.0;
					OutputVoltageDiv	:= 10.0;
				ELSE
					SpeedFeedbackDiv	:= 1.0;
					OutputCurrentDiv	:= 1.0;
					DCBusVoltageDiv		:= 1.0;
					OutputVoltageDiv	:= 1.0;
				END_IF;
								
			ELSE
				DriveType					:= 'Unknown Drive   ';
				MSGTimeOut_EN				:= FALSE;
				UnknownDrv					:= TRUE;
				MSGDrvType_EN				:= TRUE;
				DrvTypeCtrlCfg.TriggerType	:= 10000;
			END_IF;
			
		END_IF;
				
	ELSIF MSGTimeOut_EN THEN
		
		IF MSGTimeOut_Q_RTRIG.Q THEN
			MSGSts_EN		:= TRUE;
			MSGParRead_EN	:= TRUE;
			MSGTimeOut_EN	:= FALSE;
		END_IF;
	
	ELSE
		IF (DriveType='PowerFlex 755   ' OR DriveType='PowerFlex 753   ') THEN
			IF ABS(AccelTime1)>3600.0 THEN
				AccelTime1Array[1]	:= 3600.0;
			ELSE
				AccelTime1Array[1]	:= ABS(AccelTime1);
			END_IF;
	
			COP_AccelTime(TRUE,AccelTime1Array,0,AccelTimeArray,0,4,TRUE);
	
			IF ABS(DecelTime1)>3600.0 THEN
				DecelTime1Array[1]	:= 3600.0;
			ELSE
				DecelTime1Array[1]	:= ABS(DecelTime1);
			END_IF;
	
			COP_DecelTime(TRUE,DecelTime1Array,0,DecelTimeArray,0,4,TRUE);
	
			IF (MSGTimeOut_Q_RTRIG.Q OR AccelTimeArray[3]<>ParWriteReqData[7] OR AccelTimeArray[4]<>ParWriteReqData[8] OR DecelTimeArray[3]<>ParWriteReqData[15] OR DecelTimeArray[4]<>ParWriteReqData[16]) 
			THEN
				MSGParWrite_EN		:= TRUE;
				ParWriteReqData[5]	:= AccelTimeArray[1];
				ParWriteReqData[6]	:= AccelTimeArray[2];
				ParWriteReqData[7]	:= AccelTimeArray[3];
				ParWriteReqData[8]	:= AccelTimeArray[4];
				ParWriteReqData[13]	:= DecelTimeArray[1];
				ParWriteReqData[14]	:= DecelTimeArray[2];
				ParWriteReqData[15]	:= DecelTimeArray[3];
				ParWriteReqData[16]	:= DecelTimeArray[4];
			END_IF;
		ELSE
			IF ABS(AccelTime1)>600.0 THEN
				AccelTime	:= ANY_TO_DINT(600.0 * SpeedFeedbackDiv);
			ELSE
				AccelTime	:= ANY_TO_DINT(ABS(AccelTime1) * SpeedFeedbackDiv);
			END_IF;
		
			AccelTimeLow	:= ANY_TO_USINT(AND_MASK(AccelTime, 2#0000_0000_1111_1111));
			AccelTimeHi		:= ANY_TO_USINT(SHR(AccelTime, 8));
	
			IF ABS(DecelTime1)>600.0 THEN
				DecelTime	:= ANY_TO_DINT(600.0 * SpeedFeedbackDiv);
			ELSE
				DecelTime	:= ANY_TO_DINT(ABS(DecelTime1) * SpeedFeedbackDiv);
			END_IF;
		
			DecelTimeLow	:= ANY_TO_USINT(AND_MASK(DecelTime, 2#0000_0000_1111_1111));
			DecelTimeHi		:= ANY_TO_USINT(SHR(DecelTime, 8));
				
			IF (MSGTimeOut_Q_RTRIG.Q OR AccelTimeLow<>ParWriteReqData[3] OR AccelTimeHi<>ParWriteReqData[4] OR DecelTimeLow<>ParWriteReqData[7] OR DecelTimeHi<>ParWriteReqData[8]) 
			THEN
				MSGParWrite_EN		:= TRUE;
				ParWriteReqData[3]	:= AccelTimeLow;
				ParWriteReqData[4]	:= AccelTimeHi;
				ParWriteReqData[7]	:= DecelTimeLow;
				ParWriteReqData[8]	:= DecelTimeHi;
			END_IF;
			
		END_IF;
	
		IF MSGParWrite_Q_RTRIG.Q THEN
			MSGParWrite_EN	:= FALSE;
		END_IF;
	
		IF Stop THEN	
			CmdReqData1.0	:= TRUE;
			CmdReqData1.1	:= FALSE;
		ELSIF Start THEN 
			CmdReqData1.0	:= FALSE;
			CmdReqData1.1	:= TRUE;
		ELSE
			CmdReqData1.0	:= FALSE;
			CmdReqData1.1	:= FALSE;
		END_IF;
	
		CmdReqData1.2	:= Jog;
		CmdReqData1.3	:= ClrFault;
				IF SetFwd THEN 
			CmdReqData1.4	:= TRUE;
			CmdReqData1.5	:= FALSE;
		ELSIF SetRev THEN
			CmdReqData1.4	:= FALSE;
			CmdReqData1.5	:= TRUE;
		ELSE
			CmdReqData1.4	:= FALSE;
			CmdReqData1.5	:= FALSE;
		END_IF;
	
		IF (DriveType='PowerFlex 755   ' OR DriveType='PowerFlex 753   ') THEN
			IF ABS(SpeedRef)>500.0 THEN
				SpeedRefArray[1] := 500.0;
			ELSE
				SpeedRefArray[1] := ABS(SpeedRef);
			END_IF;
	
			COP_SpeedRef(TRUE, SpeedRefArray, 0, InputHzArray, 0, 4, TRUE);
				
			IF (CmdReqData1<>CmdReqData[1] OR InputHzArray[3]<>CmdReqData[7] OR InputHzArray[4]<>CmdReqData[8])
			THEN
				MSGCmd_EN		:= TRUE;
				CmdReqData[1]	:= CmdReqData1;
				CmdReqData[5]	:= InputHzArray[1];
				CmdReqData[6]	:= InputHzArray[2];
				CmdReqData[7]	:= InputHzArray[3];
				CmdReqData[8]	:= InputHzArray[4];
			END_IF;
		ELSE
			IF ABS(SpeedRef)>500.0 THEN
				InputHz	:= ANY_TO_DINT(500.0 * SpeedFeedbackDiv);
			ELSE
				InputHz	:= ANY_TO_DINT(ABS(SpeedRef) * SpeedFeedbackDiv);
			END_IF;
		
			InputHzLow	:= ANY_TO_USINT(AND_MASK(InputHz, 2#0000_0000_1111_1111));
			InputHzHigh	:= ANY_TO_USINT(SHR(InputHz, 8)); 
				
			IF (CmdReqData1<>CmdReqData[1] OR InputHzLow<>CmdReqData[3] OR InputHzHigh<>CmdReqData[4])
			THEN
				MSGCmd_EN		:= TRUE;
				CmdReqData[1]	:= CmdReqData1;
				CmdReqData[3]	:= InputHzLow;
				CmdReqData[4]	:= InputHzHigh;
			END_IF;
		END_IF;
	
		IF MSGCmd_Q_RTRIG.Q THEN
			MSGCmd_EN	:= FALSE;
			CmdSpeed	:= SpeedRef;
		END_IF;
			
		IF MSGSts_Q_RTRIG.Q THEN
			Ready 	  		:= StsResData[1].0;
			Active 	 		:= StsResData[1].1;
			CmdFwd 			:= StsResData[1].3;
			CmdRev 			:= NOT StsResData[1].3;
			DriveFault  	:= StsResData[1].7;
			AtRef			:= StsResData[2].0;
		
			IF (DriveType='PowerFlex 755   ' OR DriveType='PowerFlex 753   ') THEN
				COP_SpeedFbk(TRUE, StsResData, 4, SpeedFbkArray, 0, 1, TRUE);
				SpeedFeedback	:= SpeedFbkArray[1];
			ELSE
				SpeedFeedback	:= ANY_TO_REAL(SHL(ANY_TO_DINT(StsResData[4]),8)+ ANY_TO_DINT(StsResData[3])) / SpeedFeedbackDiv;
			END_IF;
		
		END_IF;
			IF MSGParRead_Q_RTRIG.Q THEN
	
			IF (DriveType='PowerFlex 755   ' OR DriveType='PowerFlex 753   ') THEN
				COP_OutputCurrent(TRUE,ParReadResData,4,OutputCurrentArray,0,1,TRUE);
				OutputCurrent	:= OutputCurrentArray[1];
				COP_OutputVoltage(TRUE,ParReadResData,12,OutputVoltageArray,0,1,TRUE);
				OutputVoltage	:= OutputVoltageArray[1];
				COP_DCBusVoltage(TRUE,ParReadResData,20,DCBusVoltageArray,0,1,TRUE);
				DCBusVoltage	:= DCBusVoltageArray[1];
				IF DriveFault THEN
					COP_FaultCode(TRUE,ParReadResData,28,FaultCodeArray,0,1,TRUE);
					FaultCode	:= ANY_TO_UINT(FaultCodeArray[1]);
				ELSE
					FaultCode	:= 0;
				END_IF;
			ELSE
				OutputCurrent	:= ANY_TO_REAL(SHL(ANY_TO_DINT(ParReadResData[4]),8)+ ANY_TO_DINT(ParReadResData[3])) / OutputCurrentDiv;
				OutputVoltage	:= ANY_TO_REAL(SHL(ANY_TO_DINT(ParReadResData[8]),8)+ ANY_TO_DINT(ParReadResData[7])) / OutputVoltageDiv;
				DCBusVoltage	:= ANY_TO_REAL(SHL(ANY_TO_DINT(ParReadResData[12]),8)+ ANY_TO_DINT(ParReadResData[11])) / DCBusVoltageDiv;
				IF DriveFault THEN
					FaultCode	:= ANY_TO_UINT(ParReadResData[15]);
				ELSE
					FaultCode	:= 0;
				END_IF;
			END_IF;
				
		END_IF;
					
	END_IF;
(*------ Comms Loss Detection ----*)
	MSGDrvType_Err_RTRIG(MSG_DrvType.Status.Error);
	MSGTimeOut_Err_RTRIG(MSG_TimeOut.Status.Error);
	MSGParWrite_Err_RTRIG(MSG_ParWrite.Status.Error);
	MSGCmd_Err_RTRIG(MSG_Cmd.Status.Error);
	MSGSts_Err_RTRIG(MSG_Sts.Status.Error);
	MSGParRead_Err_RTRIG(MSG_ParRead.Status.Error);
	
	IF MSGDrvType_Err_RTRIG.Q THEN
	
		IF (MSG_DrvType.Status.ErrorID=55 AND MSG_DrvType.Status.SubErrorID=115) THEN(*No Connect Error*)
			DrvTypeCtrlCfg.TriggerType	:= 10000;
		ELSE
			DrvTypeCtrlCfg.TriggerType	:= 1000;
		END_IF;
		
	END_IF;
		
	IF MSGTimeOut_Err_RTRIG.Q OR MSGParWrite_Err_RTRIG.Q OR MSGCmd_Err_RTRIG.Q OR MSGSts_Err_RTRIG.Q OR MSGParRead_Err_RTRIG.Q THEN 
		
		MSGParWrite_EN	:= FALSE;
		MSGCmd_EN		:= FALSE;
		MSGSts_EN		:= FALSE;
		MSGParRead_EN	:= FALSE;

		(*-------- Retrigger Write TimeOut MSG if CIPStatus returns Device State Conflict SubErrorID=16 --------*)
		IF (MSGParWrite_Err_RTRIG.Q AND MSG_ParWrite.Status.ErrorID=224 AND MSG_ParWrite.Status.SubErrorID=16)
		OR (MSGCmd_Err_RTRIG.Q AND MSG_Cmd.Status.ErrorID=224 AND MSG_Cmd.Status.SubErrorID=16) THEN
			MSGDrvType_EN	:= FALSE;
			MSGTimeOut_EN	:= TRUE;
			CommLoss		:= FALSE;
		ELSE (*-------- Otherwise re-initialize communications by attempting to read Drive Type --------*)
			MSGDrvType_EN	:= TRUE;
			MSGTimeOut_EN	:= FALSE;
			CommLoss		:= TRUE;
			Ready 	  		:= FALSE;
			Active 	 		:= FALSE;
			CmdFwd 			:= FALSE;
			CmdRev 			:= FALSE;
			DriveFault  	:= FALSE;
			AtRef			:= FALSE;
			SpeedFeedback	:= 0.0;
			CmdSpeed		:= 0.0;
			OutputCurrent	:= 0.0;
			OutputVoltage	:= 0.0;
			DCBusVoltage	:= 0.0;
			FaultCode		:= 0;
			DriveType		:= '';
		END_IF;
		
	END_IF;
	
	MSGDrvType_Q_RTRIG(MSG_DrvType.Q);
	MSGTimeOut_Q_RTRIG(MSG_TimeOut.Q);
	MSGParWrite_Q_RTRIG(MSG_ParWrite.Q);
	MSGCmd_Q_RTRIG(MSG_Cmd.Q);
	MSGSts_Q_RTRIG(MSG_Sts.Q);
	MSGParRead_Q_RTRIG(MSG_ParRead.Q);
	
	IF MSGDrvType_Q_RTRIG.Q OR MSGTimeOut_Q_RTRIG.Q OR MSGParWrite_Q_RTRIG.Q OR MSGCmd_Q_RTRIG.Q OR MSGSts_Q_RTRIG.Q OR MSGParRead_Q_RTRIG.Q THEN 
		CommLoss	:= FALSE;
	END_IF;
	
	(*-------- Diagnostics --------*)
	IF UnknownDrv OR CommLoss THEN
		FBError		:= TRUE;
	ELSE
		FBError		:= FALSE;
	END_IF;

ELSE
	(*-------- Comms disabled --------*)
	MSGDrvType_EN	:= FALSE;
	MSGTimeOut_EN	:= FALSE;
	MSGParWrite_EN	:= FALSE;
	MSGCmd_EN		:= FALSE;
	MSGSts_EN		:= FALSE;
	MSGParRead_EN	:= FALSE;
	CommLoss		:= TRUE;
	Ready 	  		:= FALSE;
	Active 	 		:= FALSE;
	CmdFwd 			:= FALSE;
	CmdRev 			:= FALSE;
	DriveFault  	:= FALSE;
	AtRef			:= FALSE;
	SpeedFeedback	:= 0.0;
	CmdSpeed		:= 0.0;
	OutputCurrent	:= 0.0;
	OutputVoltage	:= 0.0;
	DCBusVoltage	:= 0.0;
	FaultCode		:= 0;
	DriveType		:= '';
END_IF;

(*-------- Always scan message instructions whether enabled or not --------*)
MSG_DrvType(MSGDrvType_EN, DrvTypeCtrlCfg, DrvTypeAppCfg, DrvTypeTarCfg,,, DrvTypeResData);
MSG_TimeOut(MSGTimeOut_EN, TimeOutCtrlCfg, TimeOutAppCfg, TimeOutTarCfg, TimeOutReqData, 2,);
MSG_ParWrite(MSGParWrite_EN, ParWriteCtrlCfg, ParWriteAppCfg, ParWriteTarCfg, ParWriteReqData, ParWriteReqLen, ParWriteResData);
MSG_Cmd(MSGCmd_EN, CmdCtrlCfg, CmdAppCfg, CmdTarCfg, CmdReqData, CmdReqLen,);
MSG_Sts(MSGSts_EN, StsCtrlCfg, StsAppCfg, StsTarCfg,,, StsResData);
MSG_ParRead(MSGParRead_EN, ParReadCtrlCfg, ParReadAppCfg, ParReadTarCfg, ParReadReqData, ParReadReqLen, ParReadResData);
END_FUNCTION_BLOCK