[r1]: / trunk / legacy / Libraries / IoDrvPiFace.library.md  Maximize  Restore  History

Download this file

650 lines (572 with data), 15.0 kB

<?xml version="1.0" encoding="utf-8"?>---

FUNCTION_BLOCK PiFaceDigital EXTENDS spi
VAR_INPUT
    byOut: BYTE;
END_VAR
VAR_OUTPUT
    byIn: BYTE;
END_VAR
VAR
    _byHardwareAddress: BYTE;
END_VAR
VAR_TEMP
    i: INT;
    k: INT;
END_VAR
SUPER^();

CASE _iState OF
0:
    IF SUPER^.init() THEN
        _iState := 1;
    END_IF  
1:
    write8(_byHardwareAddress, IOCON, 8); //enable hardware addressing
    write8(_byHardwareAddress, GPIOA, 0); //turn on port A
    write8(_byHardwareAddress, IODIRA, 0); //set port A as an output
    write8(_byHardwareAddress, IODIRB, 16#FF); // set port B as an input
    write8(_byHardwareAddress, GPPUB, 16#FF);   // turn on port B pullups
    _iState := 10;
END_CASE

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

METHOD BeforeWriteOutputs: INT
VAR
    i: USINT;
END_VAR
SUPER^.BeforeWriteOutputs();

IF _iState = 10 THEN
    write8(_byHardwareAddress, GCL_PIFace.OUTPUT_PORT, byOut);
END_IF

METHOD AfterReadInputs: INT
VAR
    aby: ARRAY [..] OF ;
END_VAR
SUPER^.AfterReadInputs();

IF _iState = 10 THEN
    byIn := NOT read8(_byHardwareAddress, GCL_PIFace.INPUT_PORT);
END_IF

METHOD read8: BYTE
VAR_INPUT
    byHardwareAddress: subrangeSigned;
    byPort: BYTE;
END_VAR
VAR
    abyTxBuffer: ARRAY [..] OF ;
    abyRxBuffer: ARRAY [..] OF ;
END_VAR
abyTxBuffer[0] := 16#40 + SHL(byHardwareAddress, 1) + 1; //SPI_READ_CMD;
abyTxBuffer[1] := byPort;
abyTxBuffer[2] := 16#FF;

IF transfer(pabyTxBuffer:=ADR(abyTxBuffer) , pabyRxBuffer:=ADR(abyRxBuffer) , udiLen:=3 , uiDelayus:=5 ) THEN
    read8 := abyRxBuffer[2];
ELSE
    _iState := 1000;
END_IF

METHOD write8: BOOL
VAR_INPUT
    byHardwareAddress: subrangeSigned;
    byPort: BYTE;
    byValue: BYTE;
END_VAR
VAR
    abyTxBuffer: ARRAY [..] OF ;
    abyRxBuffer: ARRAY [..] OF ;
END_VAR
abyTxBuffer[0] := 16#40 + SHL(byHardwareAddress, 1); //SPI_WRITE_CMD;
abyTxBuffer[1] := byPort;
abyTxBuffer[2] := byValue;

write8 := transfer(pabyTxBuffer:=ADR(abyTxBuffer) , pabyRxBuffer:=ADR(abyRxBuffer) , udiLen:=3 , uiDelayus:=5 );

IF NOT write8 THEN
    _iState := 1000;
END_IF

FUNCTION_BLOCK IoDrvPiFace EXTENDS IoDrvBase
VAR
    CLASSID_CCmpIoDrvTemplate: DWORD;
END_VAR
VAR
    _IIoDrv: ICmpIoDrv;
    _IIoDrvParameter: ICmpIoDrvParameter;
    _xBackGroundDiagStarted: BOOL;
    _bDeactivated: BOOL;
    PiFace: PiFaceDigital;
END_VAR


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;
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 = 1) THEN
            IF (PiFace.byIn AND SHL(BYTE#1, pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset MOD 8)) &lt;&gt; 0 THEN
            {IF defined (pou:SysCpuSetBit2)}
                SysCpuSetBit2(ADR(pbyIecAddress[wDestIndex]), pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset MOD 8);          
            {ELSE}    
                SysCpuSetBit(ADR(pbyIecAddress[wDestIndex]), pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset MOD 8);           
            {END_IF}    
            ELSE
            {IF defined (pou:SysCpuResetBit2)}
                SysCpuResetBit2(ADR(pbyIecAddress[wDestIndex]), pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset MOD 8);            
            {ELSE}    
                SysCpuResetBit(ADR(pbyIecAddress[wDestIndex]), pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset MOD 8);         
            {END_IF}    
            END_IF                      
        ELSIF pConnectorMapList[i].pChannelMapList[j].wSize = 8 THEN
            pbyIecAddress[wDestIndex] := PiFace.byIn;
        END_IF
    END_FOR
END_FOR

IoDrvReadInputs := Errors.ERR_OK;

METHOD IoDrvIdentify: UDINT
VAR_INPUT
    pConnector: pointer;
END_VAR
IoDrvIdentify_Count := IoDrvIdentify_Count + 1;
IoDrvIdentify := Errors.ERR_NOTIMPLEMENTED;

METHOD IoDrvUpdateConfiguration: UDINT
VAR_INPUT
    pConnectorList: pointer;
    nCount: DINT;
END_VAR
VAR
    pParameter: pointer;
    pChild: pointer;
    pstConnectorVendorName: pointer;
    pstConnectorDeviceName: pointer;
    dwTest: pointer;
    Result: RTS_IEC_RESULT;
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}                                        

    //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

    //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 IoDrvWatchdogTrigger: UDINT
VAR_INPUT
    pConnector: pointer;
END_VAR
IoDrvWatchdogTrigger_Count := IoDrvWatchdogTrigger_Count + 1;
IoDrvWatchdogTrigger := 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 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 IoDrvWriteOutputs: UDINT
VAR_INPUT
    pConnectorMapList: pointer;
    nCount: DINT;
END_VAR
VAR
    i: DINT;
    j: DINT;
    wSize: WORD;
    pbyIecAddress: pointer;
    bySrcValue: BYTE;
    wSrcIndex: WORD;
    bySrcMask: BYTE;
    wDestIndex: WORD;
END_VAR
IoDrvWriteOutputs_Count := IoDrvWriteOutputs_Count + 1;

IF pConnectorMapList = 0 OR nCount = 0 THEN
    IoDrvWriteOutputs := 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
        wSrcIndex := pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset / 8; 
        pbyIecAddress := pConnectorMapList[i].pChannelMapList[j].pbyIecAddress;         

        IF pConnectorMapList[i].pChannelMapList[j].wSize = 1 THEN
            bySrcValue := pbyIecAddress[wSrcIndex];

            IF (pbyIecAddress[wSrcIndex] AND SHL(BYTE#1, pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset MOD 8)) &lt;&gt; 0 THEN
            {IF defined (pou:SysCpuSetBit2)}
                SysCpuSetBit2(ADR(PiFace.byOut), pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset MOD 8);            
            {ELSE}    
                SysCpuSetBit(ADR(PiFace.byOut), pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset MOD 8);         
            {END_IF}    
            ELSE
            {IF defined (pou:SysCpuResetBit2)}
                SysCpuResetBit2(ADR(PiFace.byOut), pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset MOD 8);              
            {ELSE}    
                SysCpuResetBit(ADR(PiFace.byOut), pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset MOD 8);               
            {END_IF}    
            END_IF          
        ELSIF pConnectorMapList[i].pChannelMapList[j].wSize = 8 THEN
            PiFace.byOut := pbyIecAddress[wSrcIndex];
        END_IF
    END_FOR
END_FOR

IoDrvWriteOutputs := Errors.ERR_OK;

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
    PiFace.AfterReadInputs();
    PiFace.BeforeWriteOutputs();
END_IF

IoDrvStartBusCycle := Errors.ERR_OK;

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

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

PiFace.Initialize(wModuleType, dwInstance, pConnector);

Initialize := Errors.ERR_OK;

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 := 'IoDrvPiFace';
m_Info.szVendorName := '3S - Smart Software Solutions';
m_Info.szDeviceName := 'Raspberry PiFace Digital';
m_Info.wModuleType := 501;

_IIoDrv := THIS^;
_IIoDrvParameter := THIS^;

m_IBaseItf := THIS^;
m_hInterface := IoMgrRegisterInstance2(CLASSID_CCmpIoDrvTemplate, m_IBaseItf, ADR(Result));
FB_Init := TRUE;

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;

VAR_GLOBAL
OUTPUT_PORT: USINT;
INPUT_PORT: USINT;
IOCON: USINT;
GPIOA: USINT;
GPIOB: USINT;
GPPUB: USINT;
IODIRA: USINT;
IODIRB: USINT;
END_VAR