[r2]: / trunk / legacy / Libraries / SPI_MCP3008.library.md  Maximize  Restore  History

Download this file

566 lines (495 with data), 12.2 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 := '3S - Smart Software Solutions';
m_info.szDeviceName := 'MCP3008_IO';
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

//Todo: update connectorflags if something changed

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;
    wSize: WORD;
    pbyIecAddress: pointer;
    bySrcValue: BYTE;
    bySrcMask: BYTE;
    wSrcIndex: WORD;
    wDestIndex: WORD;
    pdw: pointer;
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     
        pbyIecAddress := pConnectorMapList[i].pChannelMapList[j].pbyIecAddress;
        wDestIndex := pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset / 8;
        IF (pConnectorMapList[i].pChannelMapList[j].wSize = SIZEOF(UINT)*8) THEN
            pdw := pbyIecAddress + wDestIndex;
            pdw^ := _MCP3008.auiValue[j];
        END_IF
    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
    // Reset application
    // TODO: Free ressources
    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}                                        

    _dwInUse := 0;
    FOR i:=0 TO 31 DO
        pParameter := IoMgrConfigGetParameter(m_pConnector, INT_TO_DWORD(i));       
        IF (pParameter &lt;&gt; 0) THEN
            bySetting := IoMgrConfigGetParameterValueByte(pParameter, ADR(Result));
            IF bySetting &gt;= 0 AND bySetting &lt;= 7 THEN
                //_GPIO.aeType[i] := bySetting;
                _dwInUse := _dwInUse OR SHL(DWORD#1, i);
            END_IF
        END_IF
    END_FOR 

    //Setup I/O area
    pParameter := IoMgrConfigGetParameter(m_pConnector, 1000);      (* inputs *)
    IF (pParameter &lt;&gt; 0) THEN
        pParameter^.dwDriverSpecific := 0;                  (* Device offset 0 *)
    END_IF
    pParameter := IoMgrConfigGetParameter(m_pConnector, 2000);      (* outputs *)
    IF (pParameter &lt;&gt; 0) THEN
        pParameter^.dwDriverSpecific := 0;                  (* Device offset 0 *)
    END_IF
    pParameter := IoMgrConfigGetParameter(m_pConnector, 2100);      (* outputs *)
    IF (pParameter &lt;&gt; 0) THEN
        pParameter^.dwDriverSpecific := 10;                 (* Device offset 0 *)
    END_IF
    pParameter := IoMgrConfigGetParameter(m_pConnector, 2101);      (* outputs *)
    IF (pParameter &lt;&gt; 0) THEN
        pParameter^.dwDriverSpecific := 14;                 (* Device offset 0 *)
    END_IF

    (* no child devices used 
    //Go through all childs of the device
    pChild := IoMgrConfigGetFirstChild(m_pConnector, ADR(nCount), m_pConnector);
    WHILE (pChild &lt;&gt; 0) DO
        IF (pChild^.dwFlags AND ConnectorFlags.CF_ENABLE) &lt;&gt; 0 THEN
            pChild^.hIoDrv := m_hInterface; 
            {IF defined (pou:IoMgrConfigSetDiagnosis)}
            IoMgrConfigSetDiagnosis(pChild,
                                    ConnectorFlags.CF_DRIVER_AVAILABLE OR
                                    ConnectorFlags.CF_CONNECTOR_FOUND OR
                                    ConnectorFlags.CF_CONNECTOR_CONFIGURED OR
                                    ConnectorFlags.CF_CONNECTOR_ACTIVE);
            {END_IF}
        END_IF
        pChild := IoMgrConfigGetNextChild(pChild, ADR(nCount), m_pConnector);
    END_WHILE*)
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 IoDrvGetConnector: pointer
VAR_INPUT
    pResult: pointer;
END_VAR
IF m_pConnector = 0 THEN
    IF pResult &lt;&gt; 0 THEN
        pResult^ := Errors.ERR_FAILED;
    END_IF
    IoDrvGetConnector := 0; 
    RETURN;
END_IF
IF pResult &lt;&gt; 0 THEN
    pResult^ := Errors.ERR_OK;
END_IF
IoDrvGetConnector := m_pConnector;

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);

(*
pParam := ConfigGetParameter(_pConnector, 1);
IF pParam &lt;&gt; 0 THEN
    _byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF*)