[r1]: / trunk / mcp3008 / Libraries / SPI_MCP3008.library.md  Maximize  Restore  History

Download this file

483 lines (418 with data), 9.6 kB

<?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 &lt;&gt; 0) THEN
        pResult^ := Errors.ERR_OK;
    END_IF
    RETURN; 
ELSIF iid = ITFID_ICmpIoDrvParameter THEN
    QueryInterface := ADR(_IIoDrvParameter);
    AddRef();
    IF (pResult &lt;&gt; 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 &lt; 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 &lt;&gt; 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);