<?xml version="1.0" encoding="utf-8"?>---
FUNCTION_BLOCK IoDrvMCP3008 EXTENDS IoDrvBase
VAR
_IIoDrv: ICmpIoDrv;
_IIoDrvParameter: ICmpIoDrvParameter;
_MCP3008: MCP3008;
_dwInUse: DWORD;
_xBackGroundDiagStarted: BOOL;
_bDeactivated: BOOL;
END_VAR
VAR
CLASSID_CCmpIoDrvTemplate: DWORD;
END_VAR
METHOD FB_Exit: BOOL
VAR_INPUT
bInCopyCode: BOOL;
END_VAR
FB_Exit_Count := FB_Exit_Count + 1;
FB_Exit := TRUE;
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL;
bInCopyCode: BOOL;
END_VAR
VAR
Result: UDINT;
END_VAR
FB_Init_Count := FB_Init_Count + 1;
m_Info.szDriverName := 'IoDrvMCP3008';
m_Info.szVendorName := 'Open Source';
m_info.szDeviceName := 'MCP3008';
m_Info.wModuleType := 8000;
_IIoDrv := THIS^;
_IIoDrvParameter := THIS^;
m_IBaseItf := THIS^;
m_hInterface := IoMgrRegisterInstance2(dwClassId:=CLASSID_CCmpIoDrvTemplate, pItf:=m_IBaseItf, pResult:=ADR(Result));
FB_Init := TRUE;
METHOD FB_Reinit: BOOL
FB_Reinit_Count := FB_Reinit_Count + 1;
FB_Reinit := TRUE;
METHOD Initialize: UDINT
VAR_INPUT
wModuleType: UINT;
dwInstance: UDINT;
pConnector: pointer;
END_VAR
Initialize_Count := Initialize_Count + 1;
m_wModuleType := wModuleType;
m_dwInstance := dwInstance;
m_Info.wModuleType := wModuleType;
_MCP3008.Initialize(wModuleType, dwInstance, pConnector);
Initialize := CmpErrors.Errors.ERR_OK;
METHOD QueryInterface: pointer
VAR_INPUT
iid: DWORD;
pResult: pointer;
END_VAR
QueryInterface_Count := QueryInterface_Count + 1;
IF iid = ITFID_ICmpIoDrv THEN
QueryInterface := ADR(_IIoDrv);
AddRef();
IF (pResult <> 0) THEN
pResult^ := Errors.ERR_OK;
END_IF
RETURN;
ELSIF iid = ITFID_ICmpIoDrvParameter THEN
QueryInterface := ADR(_IIoDrvParameter);
AddRef();
IF (pResult <> 0) THEN
pResult^ := Errors.ERR_OK;
END_IF
RETURN;
ELSE
QueryInterface := SUPER^.QueryInterface(iid, pResult);
END_IF
METHOD IoDrvGetModuleDiagnosis: UDINT
VAR_INPUT
pConnector: pointer;
END_VAR
IF pConnector = 0 THEN
//we are called from the background task
_xBackGroundDiagStarted := TRUE;
END_IF
IoDrvGetModuleDiagnosis_Count := IoDrvGetModuleDiagnosis_Count + 1;
IoDrvGetModuleDiagnosis := Errors.ERR_NOTIMPLEMENTED;
METHOD IoDrvIdentify: UDINT
VAR_INPUT
pConnector: pointer;
END_VAR
IoDrvIdentify_Count := IoDrvIdentify_Count + 1;
IoDrvIdentify := Errors.ERR_NOTIMPLEMENTED;
METHOD IoDrvReadInputs: UDINT
VAR_INPUT
pConnectorMapList: pointer;
nCount: DINT;
END_VAR
VAR
i: DINT;
j: DINT;
END_VAR
IoDrvReadInputs_Count := IoDrvReadInputs_Count + 1;
IF pConnectorMapList = 0 OR nCount = 0 THEN
IoDrvReadInputs := Errors.ERR_PARAMETER;
RETURN;
END_IF
FOR i:=0 TO nCount - 1 DO
IF (pConnectorMapList[i].dwNumOfChannels = 0) THEN
CONTINUE;
END_IF
FOR j:= 0 TO UDINT_TO_UINT(pConnectorMapList[i].dwNumOfChannels) - 1 DO
IoMgrCopyInputLE(ADR(pConnectorMapList[i].pChannelMapList[j]), pConnectorMapList[i].pChannelMapList[j].pParameter^.dwDriverSpecific);
END_FOR
END_FOR
IoDrvReadInputs := Errors.ERR_OK;
METHOD IoDrvScanModules: UDINT
VAR_INPUT
pConnector: pointer;
ppConnectorList: pointer;
pnCount: pointer;
END_VAR
IoDrvScanModules_Count := IoDrvScanModules_Count + 1;
IoDrvScanModules := Errors.ERR_NOTIMPLEMENTED;
METHOD IoDrvStartBusCycle: UDINT
VAR_INPUT
pConnector: pointer;
END_VAR
IoDrvStartBusCycle_Count := IoDrvStartBusCycle_Count + 1;
//if background diagnosis is not active call IoDrvGetModuleDiagnosis; normally it will be called by the runtime if DRVPROP_BACKGROUND_GETDIAG is set
IF NOT _xBackGroundDiagStarted THEN
IoDrvGetModuleDiagnosis(m_pConnector); //DRVPROP_BACKGROUND_GETDIAG not set or runtime version < V3.5.1.0
END_IF
//optional: call IoDrvWatchdogTrigger or set driver property DRVPROP_WATCHDOG in UpdateConfiguration
IoDrvWatchdogTrigger(pConnector);
IF NOT _bDeactivated THEN
_MCP3008.AfterReadInputs();
_MCP3008.BeforeWriteOutputs();
END_IF
IoDrvStartBusCycle := Errors.ERR_OK;
METHOD IoDrvUpdateConfiguration: UDINT
VAR_INPUT
pConnectorList: pointer;
nCount: DINT;
END_VAR
VAR
pParameter: pointer;
pChild: pointer;
pstConnectorVendorName: pointer;
pstConnectorDeviceName: pointer;
Result: RTS_IEC_RESULT;
i: INT;
bySetting: BYTE;
END_VAR
IoDrvUpdateConfiguration_Count := IoDrvUpdateConfiguration_Count + 1;
IoDrvUpdateConfiguration := Errors.ERR_OK;
IF (pConnectorList = 0) THEN
RETURN;
END_IF
m_pConnector := IoMgrConfigGetConnector(pConnectorList, ADR(nCount), m_wModuleType, m_dwInstance);
IF m_pConnector = 0 THEN
IoDrvUpdateConfiguration := ERRORS.ERR_PARAMETER;
RETURN;
END_IF
//check if device is enabled in the device tree
IF (m_pConnector^.dwFlags AND ConnectorFlags.CF_ENABLE) = 0 THEN
_bDeactivated := TRUE;
IoDrvUpdateConfiguration := Errors.ERR_OK;
RETURN;
END_IF
IF m_pConnector^.hIoDrv = 0 THEN
m_pConnector^.hIoDrv := m_hInterface;
m_pConnector^.pFather^.hIoDrv := m_hInterface;
{IF defined (pou:IoMgrConfigSetDiagnosis)}
IoMgrConfigSetDiagnosis(m_pConnector,
ConnectorFlags.CF_DRIVER_AVAILABLE OR
ConnectorFlags.CF_CONNECTOR_FOUND OR
ConnectorFlags.CF_CONNECTOR_CONFIGURED OR
ConnectorFlags.CF_CONNECTOR_ACTIVE);
{END_IF}
{IF defined (pou:IoMgrConfigSetDiagnosis)}
IoMgrConfigSetDiagnosis(m_pConnector^.pFather,
ConnectorFlags.CF_DRIVER_AVAILABLE OR
ConnectorFlags.CF_CONNECTOR_FOUND OR
ConnectorFlags.CF_CONNECTOR_CONFIGURED OR
ConnectorFlags.CF_CONNECTOR_ACTIVE);
{END_IF}
{IF defined (pou:IoMgrSetDriverProperties)}
IoMgrSetDriverProperties(m_hInterface, DRVPROP_CONSISTENCY OR DRVPROP_BACKGROUND_GETDIAG);
//Note: background diagnosis property flag is optional (supported with 3.5.1.0 runtime)
{END_IF}
//Setup I/O area
FOR i:=0 TO 7 DO
pParameter := IoMgrConfigGetParameter(m_pConnector, 1000 + i);
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := ADR(_MCP3008.auiValue[i]);
END_IF
END_FOR
END_IF
METHOD IoDrvUpdateMapping: UDINT
VAR_INPUT
pTaskMapList: pointer;
nCount: DINT;
END_VAR
IoDrvUpdateMapping_Count := IoDrvUpdateMapping_Count + 1;
IF (pTaskMapList = 0) THEN
IoDrvUpdateMapping := Errors.ERR_PARAMETER;
RETURN;
END_IF
IoDrvUpdateMapping := Errors.ERR_OK;
METHOD IoDrvWatchdogTrigger: UDINT
VAR_INPUT
pConnector: pointer;
END_VAR
IoDrvWatchdogTrigger_Count := IoDrvWatchdogTrigger_Count + 1;
IoDrvWatchdogTrigger := Errors.ERR_OK;
METHOD IoDrvWriteOutputs: UDINT
VAR_INPUT
pConnectorMapList: pointer;
nCount: DINT;
END_VAR
VAR
i: DINT;
j: DINT;
k: UINT;
wSize: WORD;
pbyIecAddress: pointer;
bySrcValue: BYTE;
wSrcIndex: WORD;
bySrcMask: BYTE;
wDestIndex: WORD;
pdw: pointer;
pw: pointer;
END_VAR
IoDrvWriteOutputs_Count := IoDrvWriteOutputs_Count + 1;
IoDrvWriteOutputs := Errors.ERR_OK;
METHOD IoDrvReadParameter: UDINT
VAR_INPUT
pConnector: pointer;
pParameter: pointer;
pData: pointer;
dwBitSize: DWORD;
dwBitOffset: DWORD;
END_VAR
IF pConnector = 0 OR pParameter = 0 OR pData = 0 THEN
IoDrvReadParameter := Errors.ERR_PARAMETER;
RETURN;
END_IF
// All standard parameters of our device are handled by the IO-manager!
IoDrvReadParameter := Errors.ERR_FAILED;
METHOD IoDrvWriteParameter: UDINT
VAR_INPUT
pConnector: pointer;
pParameter: pointer;
pData: pointer;
dwBitSize: DWORD;
dwBitOffset: DWORD;
END_VAR
VAR
pParam: pointer;
pstDiagString: pointer;
END_VAR
IF pConnector = 0 OR pParameter = 0 OR pData = 0 THEN
IoDrvWriteParameter := Errors.ERR_PARAMETER;
RETURN;
END_IF
IoDrvWriteParameter := Errors.ERR_FAILED;
FUNCTION_BLOCK MCP3008 EXTENDS spi
VAR_OUTPUT
auiValue: ARRAY [..] OF ;
END_VAR
SUPER^();
CASE _iState OF
0:
IF SUPER^.init() THEN
_iState := 1;
END_IF
1:
_iState := 10;
END_CASE
METHOD AfterReadInputs: INT
VAR
aby: ARRAY [..] OF ;
usiChannel: USINT;
ui: UINT;
END_VAR
SUPER^.AfterReadInputs();
IF _iState = 10 THEN
FOR usiChannel := 0 TO 7 DO
aby[0] := 1;
aby[1] := 16#80 + SHL(usiChannel AND 7, 4);
aby[2] := 0;
IF NOT transfer(pabyTxBuffer:=ADR(aby) , pabyRxBuffer:=ADR(aby) , udiLen:=3 , uiDelayus:=0) THEN
_iState := 1000;
END_IF
ui := aby[2];
ui := ui + (BYTE_TO_UINT(aby[1]) AND 2#11) * 256;
auiValue[usiChannel] := ui;
END_FOR
END_IF
METHOD BeforeWriteOutputs: INT
VAR
i: USINT;
END_VAR
SUPER^.BeforeWriteOutputs();
METHOD Initialize: UDINT
VAR_INPUT
wModuleType: UINT;
dwInstance: UDINT;
pConnector: pointer;
END_VAR
VAR
pParam: pointer;
udiResult: UDINT;
END_VAR
SUPER^.Initialize(wModuleType, dwInstance, pConnector);