--- a +++ b/trunk/mcp3008/Libraries/SPI_MCP3008.library.md @@ -0,0 +1,482 @@ +<?xml version="1.0" encoding="utf-8"?>--- + +~~~ST +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 + +~~~ +~~~ST + +~~~ +--- +~~~ST +METHOD FB_Exit: BOOL +VAR_INPUT + bInCopyCode: BOOL; +END_VAR + +~~~ +~~~ST +FB_Exit_Count := FB_Exit_Count + 1; +FB_Exit := TRUE; +~~~ +--- +~~~ST +METHOD FB_Init: BOOL +VAR_INPUT + bInitRetains: BOOL; + bInCopyCode: BOOL; +END_VAR +VAR + Result: UDINT; +END_VAR + +~~~ +~~~ST +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; +~~~ +--- +~~~ST +METHOD FB_Reinit: BOOL + +~~~ +~~~ST +FB_Reinit_Count := FB_Reinit_Count + 1; +FB_Reinit := TRUE; +~~~ +--- +~~~ST +METHOD Initialize: UDINT +VAR_INPUT + wModuleType: UINT; + dwInstance: UDINT; + pConnector: pointer; +END_VAR + +~~~ +~~~ST +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; +~~~ +--- +~~~ST +METHOD QueryInterface: pointer +VAR_INPUT + iid: DWORD; + pResult: pointer; +END_VAR + +~~~ +~~~ST +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 + +~~~ +--- +~~~ST +METHOD IoDrvGetModuleDiagnosis: UDINT +VAR_INPUT + pConnector: pointer; +END_VAR + +~~~ +~~~ST +IF pConnector = 0 THEN + //we are called from the background task + _xBackGroundDiagStarted := TRUE; +END_IF + +IoDrvGetModuleDiagnosis_Count := IoDrvGetModuleDiagnosis_Count + 1; +IoDrvGetModuleDiagnosis := Errors.ERR_NOTIMPLEMENTED; +~~~ +--- +~~~ST +METHOD IoDrvIdentify: UDINT +VAR_INPUT + pConnector: pointer; +END_VAR + +~~~ +~~~ST +IoDrvIdentify_Count := IoDrvIdentify_Count + 1; +IoDrvIdentify := Errors.ERR_NOTIMPLEMENTED; +~~~ +--- +~~~ST +METHOD IoDrvReadInputs: UDINT +VAR_INPUT + pConnectorMapList: pointer; + nCount: DINT; +END_VAR +VAR + i: DINT; + j: DINT; +END_VAR + +~~~ +~~~ST +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; +~~~ +--- +~~~ST +METHOD IoDrvScanModules: UDINT +VAR_INPUT + pConnector: pointer; + ppConnectorList: pointer; + pnCount: pointer; +END_VAR + +~~~ +~~~ST +IoDrvScanModules_Count := IoDrvScanModules_Count + 1; +IoDrvScanModules := Errors.ERR_NOTIMPLEMENTED; +~~~ +--- +~~~ST +METHOD IoDrvStartBusCycle: UDINT +VAR_INPUT + pConnector: pointer; +END_VAR + +~~~ +~~~ST +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; +~~~ +--- +~~~ST +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 + +~~~ +~~~ST +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 +~~~ +--- +~~~ST +METHOD IoDrvUpdateMapping: UDINT +VAR_INPUT + pTaskMapList: pointer; + nCount: DINT; +END_VAR + +~~~ +~~~ST +IoDrvUpdateMapping_Count := IoDrvUpdateMapping_Count + 1; + +IF (pTaskMapList = 0) THEN + IoDrvUpdateMapping := Errors.ERR_PARAMETER; + RETURN; +END_IF + +IoDrvUpdateMapping := Errors.ERR_OK; +~~~ +--- +~~~ST +METHOD IoDrvWatchdogTrigger: UDINT +VAR_INPUT + pConnector: pointer; +END_VAR + +~~~ +~~~ST +IoDrvWatchdogTrigger_Count := IoDrvWatchdogTrigger_Count + 1; +IoDrvWatchdogTrigger := Errors.ERR_OK; +~~~ +--- +~~~ST +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 + +~~~ +~~~ST +IoDrvWriteOutputs_Count := IoDrvWriteOutputs_Count + 1; +IoDrvWriteOutputs := Errors.ERR_OK; +~~~ +--- +~~~ST +METHOD IoDrvReadParameter: UDINT +VAR_INPUT + pConnector: pointer; + pParameter: pointer; + pData: pointer; + dwBitSize: DWORD; + dwBitOffset: DWORD; +END_VAR + +~~~ +~~~ST +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; + +~~~ +--- +~~~ST +METHOD IoDrvWriteParameter: UDINT +VAR_INPUT + pConnector: pointer; + pParameter: pointer; + pData: pointer; + dwBitSize: DWORD; + dwBitOffset: DWORD; +END_VAR +VAR + pParam: pointer; + pstDiagString: pointer; +END_VAR + +~~~ +~~~ST +IF pConnector = 0 OR pParameter = 0 OR pData = 0 THEN + IoDrvWriteParameter := Errors.ERR_PARAMETER; + RETURN; +END_IF + +IoDrvWriteParameter := Errors.ERR_FAILED; +~~~ +--- + +~~~ST +FUNCTION_BLOCK MCP3008 EXTENDS spi +VAR_OUTPUT + auiValue: ARRAY [..] OF ; +END_VAR + +~~~ +~~~ST +SUPER^(); + +CASE _iState OF +0: + IF SUPER^.init() THEN + _iState := 1; + END_IF +1: + _iState := 10; +END_CASE + +~~~ +--- +~~~ST +METHOD AfterReadInputs: INT +VAR + aby: ARRAY [..] OF ; + usiChannel: USINT; + ui: UINT; +END_VAR + +~~~ +~~~ST +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 + +~~~ +--- +~~~ST +METHOD BeforeWriteOutputs: INT +VAR + i: USINT; +END_VAR + +~~~ +~~~ST +SUPER^.BeforeWriteOutputs(); + +~~~ +--- +~~~ST +METHOD Initialize: UDINT +VAR_INPUT + wModuleType: UINT; + dwInstance: UDINT; + pConnector: pointer; +END_VAR +VAR + pParam: pointer; + udiResult: UDINT; +END_VAR + +~~~ +~~~ST +SUPER^.Initialize(wModuleType, dwInstance, pConnector); + + + +~~~