retro-games: Artifact 5f48f89ee0677b001536b2a0
Retro Games
tickets
(Bin)
Last updated: 2020-08-28
retro-games: Artifact 5f48f89ee0677b001536b2a1
Retro Games
tickets
(Bin)
Last updated: 2020-08-28
code Discussion
I/O Drivers
code
(Discussion)
Forum for code comments
Last updated: 2018-01-24
tickets Discussion
I/O Drivers
tickets
(Discussion)
Forum for tickets comments
Last updated: 2018-01-24
doc Discussion
I/O Drivers
doc
(Discussion)
Forum for doc comments
Last updated: 2018-01-24
database Discussion
I/O Drivers
database
(Discussion)
Forum for database comments
Last updated: 2018-01-24
rpi-legacy: ./trunk/legacy/Libraries/SPI_PiFaceCaD.library.xml
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://www.plcopen.org/xml/tc6_0200">
<fileHeader companyName="" productName="CODESYS" productVersion="CODESYS V3.5 SP11" creationDateTime="2018-07-16T11:54:08.3422817" />
<contentHeader name="Raspberry SPI PiFace CaD" version="1.0.0.0" modificationDateTime="2015-11-24T04:28:44" organization="3S - Smart Software Solutions GmbH" author="3S - Smart Software Solutions GmbH">
<Comment>Library containing device support of PiFace Control&Display</Comment>
<coordinateInfo>
<fbd>
<scaling x="1" y="1" />
</fbd>
<ld>
<scaling x="1" y="1" />
</ld>
<sfc>
<scaling x="1" y="1" />
</sfc>
</coordinateInfo>
<addData>
<data name="http://www.3s-software.com/plcopenxml/projectinformation" handleUnknown="implementation">
<ProjectInformation>
<property name="Author" type="string">3S - Smart Software Solutions GmbH</property>
<property name="Company" type="string">3S - Smart Software Solutions GmbH</property>
<property name="DefaultNamespace" type="string">PiFaceCaD</property>
<property name="Description" type="string">Library containing device support of PiFace Control&Display</property>
<property name="Placeholder" type="string">PlaceholderTemplate</property>
<property name="Project" type="string">SPI_PiFaceCaD</property>
<property name="Released" type="boolean">false</property>
<property name="Title" type="string">Raspberry SPI PiFace CaD</property>
<property name="Version" type="version">1.0.0.0</property>
<property name="library-category-list" type="library-category-list" />
</ProjectInformation>
</data>
</addData>
</contentHeader>
<types>
<dataTypes />
<pous>
<pou name="PiFaceCaD" pouType="functionBlock">
<interface>
<outputVars>
<variable name="bySwitches">
<type>
<BYTE />
</type>
</variable>
</outputVars>
<localVars>
<variable name="_byHardwareAddress">
<type>
<BYTE />
</type>
</variable>
<variable name="_byCurDisplayControl">
<type>
<BYTE />
</type>
</variable>
<variable name="_byCurEntryMode">
<type>
<BYTE />
</type>
</variable>
<variable name="_byCurAddress">
<type>
<BYTE />
</type>
</variable>
</localVars>
<tempVars>
<variable name="i">
<type>
<INT />
</type>
</variable>
<variable name="k">
<type>
<INT />
</type>
</variable>
</tempVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/pouinheritance" handleUnknown="implementation">
<Inheritance>
<Extends>spi</Extends>
</Inheritance>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^();
CASE _iState OF
0:
IF SUPER^.init() THEN
_iState := 1;
END_IF
1:
write8(_byHardwareAddress, IOCON, 8); //enable hardware addressing
// Set GPIO Port A as inputs (switches)
write8(_byHardwareAddress, IODIRA, 255);
write8(_byHardwareAddress, GPPUA, 255);
// Set GPIO Port B as outputs (connected to HD44780)
write8(_byHardwareAddress, IODIRB, 0);
// enable interrupts
write8(_byHardwareAddress, GPINTENA, 255);
sleep_ns(DELAY_SETUP_0_NS);
write8(_byHardwareAddress, LCD_PORT, 3);
LCDPulseEnable();
sleep_ns(DELAY_SETUP_1_NS);
write8(_byHardwareAddress, LCD_PORT, 3);
LCDPulseEnable();
sleep_ns(DELAY_SETUP_2_NS);
write8(_byHardwareAddress, LCD_PORT, 3);
LCDPulseEnable();
write8(_byHardwareAddress, LCD_PORT, 2);
LCDPulseEnable();
LCDSendCommand(LCD_FUNCTIONSET OR LCD_4BITMODE OR LCD_2LINE OR LCD_5X8DOTS);
LCDSendCommand(LCD_DISPLAYCONTROL OR LCD_DISPLAYOFF OR LCD_CURSOROFF OR LCD_BLINKOFF);
Clear();
_byCurEntryMode := LCD_ENTRYLEFT OR LCD_ENTRYSHIFTDECREMENT;
LCDSendCommand(LCD_ENTRYMODESET OR _byCurEntryMode);
_byCurDisplayControl := LCD_DISPLAYON OR LCD_CURSORON OR LCD_BLINKON;
LCDSendCommand(LCD_DISPLAYCONTROL OR _byCurDisplayControl);
SetText('CODESYS ON', 'RASPBERRY PI');
_iState := 10;
END_CASE
</xhtml>
</ST>
</body>
<addData>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Initialize">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="wModuleType">
<type>
<UINT />
</type>
</variable>
<variable name="dwInstance">
<type>
<UDINT />
</type>
</variable>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<localVars>
<variable name="pParam">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="udiResult">
<type>
<UDINT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="Initialize" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.Initialize(wModuleType, dwInstance, pConnector);
(*pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF*)
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="BeforeWriteOutputs">
<interface>
<returnType>
<INT />
</returnType>
<localVars>
<variable name="i">
<type>
<USINT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="BeforeWriteOutputs" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.BeforeWriteOutputs();
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="AfterReadInputs">
<interface>
<returnType>
<INT />
</returnType>
<localVars>
<variable name="aby">
<type>
<array>
<dimension lower="0" upper="13" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="AfterReadInputs" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.AfterReadInputs();
IF _iState = 10 THEN
bySwitches := NOT read8(_byHardwareAddress, SWITCH_PORT);
END_IF
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="read8">
<interface>
<returnType>
<BYTE />
</returnType>
<inputVars>
<variable name="byHardwareAddress">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> hardware address </xhtml>
</documentation>
</variable>
<variable name="byPort">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port number to read </xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="abyTxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
<variable name="abyRxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="read8" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to read the data byte of one port using the following protocol:
Byte0: 16#41 + hardware address
Byte1: Port
Byte2: 16#FF
return value: data content</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="write8">
<interface>
<returnType>
<BOOL />
</returnType>
<inputVars>
<variable name="byHardwareAddress">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> hardware address </xhtml>
</documentation>
</variable>
<variable name="byPort">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port number to read </xhtml>
</documentation>
</variable>
<variable name="byValue">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> value to write </xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="abyTxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
<variable name="abyRxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="write8" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to write a data byte into a port using the following protocol:
Byte0: 16#41 + hardware address
Byte1: Port
Byte2: Value
return value: TRUE if successful</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="LCDPulseEnable">
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="LCDPulseEnable" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSetEnable(TRUE);
sleep_ns(DELAY_PULSE_NS);
LCDSetEnable(FALSE);
sleep_ns(DELAY_PULSE_NS);</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="LCDSendCommand">
<interface>
<inputVars>
<variable name="usiCommand">
<type>
<USINT />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="LCDSendCommand" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSetRs(FALSE);
LCDSendByte(usiCommand);
sleep_ns(DELAY_SETTLE_NS);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="LCDSendByte">
<interface>
<inputVars>
<variable name="usi">
<type>
<USINT />
</type>
</variable>
</inputVars>
<localVars>
<variable name="usiCurrentState">
<type>
<USINT />
</type>
</variable>
<variable name="usiNew">
<type>
<USINT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="LCDSendByte" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">// get current lcd port state and clear the data bits
usiCurrentState := read8(_byHardwareAddress, LCD_PORT) AND 16#F0;
// send first nibble (0bXXXX0000)
usiNew := usiCurrentState OR SHR(usi, 4);
write8(_byHardwareAddress, LCD_PORT, usiNew);
LCDPulseEnable();
// send second nibble (0b0000XXXX)
usiNew := usiCurrentState OR (usi AND 2#1111);
write8(_byHardwareAddress, LCD_PORT, usiNew);
LCDPulseEnable();
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="writeBit">
<interface>
<returnType>
<BOOL />
</returnType>
<inputVars>
<variable name="byHardwareAddress">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> hardware address </xhtml>
</documentation>
</variable>
<variable name="byPort">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port number to read </xhtml>
</documentation>
</variable>
<variable name="byBit">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> bit number to read/write </xhtml>
</documentation>
</variable>
<variable name="xValue">
<type>
<BOOL />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> value to write </xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="byValue">
<type>
<BYTE />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="writeBit" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to modify one bit of a certain register:
It first reads the register, modifies the bit and then writes the register (no matter if the bit already had the desired value)
return value: TRUE if successful</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">byValue := read8(byHardwareAddress, byPort);
IF xValue THEN
byValue := byValue OR SHL(USINT#1, byBit);
ELSE
byValue := byValue AND NOT SHL(USINT#1, byBit);
END_IF
writeBit := write8(byHardwareAddress, byPort, byValue);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="LCDSetRs">
<interface>
<inputVars>
<variable name="x">
<type>
<BOOL />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="LCDSetRs" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">writeBit(_byHardwareAddress, LCD_PORT, PIN_RS, x);</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="sleep_ns">
<interface>
<inputVars>
<variable name="udiNs">
<type>
<UDINT />
</type>
</variable>
</inputVars>
<localVars>
<variable name="udi1">
<type>
<ULINT />
</type>
</variable>
<variable name="udi2">
<type>
<ULINT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="sleep_ns" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SysTimeGetNs(udi1);
REPEAT
SysTimeGetNs(udi2);
UNTIL udi2-udi1 >= udiNs
END_REPEAT</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="LCDSetEnable">
<interface>
<inputVars>
<variable name="x">
<type>
<BOOL />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="LCDSetEnable" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">writeBit(_byHardwareAddress, LCD_PORT, PIN_ENABLE, x);</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Write">
<interface>
<inputVars>
<variable name="sText">
<type>
<string />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml">string to write</xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="i">
<type>
<INT />
</type>
</variable>
<variable name="pby">
<type>
<pointer>
<baseType>
<BYTE />
</baseType>
</pointer>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="Write" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method writes text at the current position
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_SETDDRAMADDR OR _byCurAddress);
pby := ADR(sText);
FOR i:=0 TO len(sText)-1 DO
IF pby[i] = 10 THEN
SetCursor(0,1);
ELSE
LCDSendData(pby[i]);
_byCurAddress := _byCurAddress + 1;
END_IF
END_FOR
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Clear">
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="Clear" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to clear the display
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_CLEARDISPLAY);
_byCurAddress := 0;
sleep_ns(DELAY_CLEAR_NS);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Home">
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="Home" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to home the cursor to the upper left corner
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_RETURNHOME);
_byCurAddress := 0;
sleep_ns(DELAY_CLEAR_NS);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="SetCursor">
<interface>
<inputVars>
<variable name="usiColumn">
<type>
<USINT />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml">column to place the cursor (0..15)</xhtml>
</documentation>
</variable>
<variable name="usiRow">
<type>
<USINT />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml">row to place the cursor (0,1)</xhtml>
</documentation>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="SetCursor" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method sets the cursor to a specified position
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">usiColumn := MAX(0, MIN(usiColumn, (LCD_RAM_WIDTH / 2) - 1));
usiRow := MAX(0, MIN(usiRow, LCD_MAX_LINES - 1));
_byCurAddress := (usiColumn + ROW_OFFSETS[usiRow]) MOD LCD_RAM_WIDTH;
LCDSendCommand(LCD_SETDDRAMADDR OR _byCurAddress);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="LCDSendData">
<interface>
<inputVars>
<variable name="data">
<type>
<USINT />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="LCDSendData" />
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSetRs(TRUE);
LCDSendByte(data);
sleep_ns(DELAY_SETTLE_NS);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="MoveLeft">
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="MoveLeft" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method shifts the content of the display about one char to the left
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_CURSORSHIFT OR LCD_DISPLAYMOVE OR LCD_MOVELEFT);</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="MoveRight">
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="MoveRight" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method shifts the content of the display about one char to the right
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_CURSORSHIFT OR LCD_DISPLAYMOVE OR LCD_MOVERIGHT);</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="SetText">
<interface>
<inputVars>
<variable name="sLine1">
<type>
<string />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> first line</xhtml>
</documentation>
</variable>
<variable name="sLine2">
<type>
<string />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> second line</xhtml>
</documentation>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="SetText" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method sets the content of the display
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SetCursor(0, 0);
Write(sLine1);
SetCursor(0, 1);
Write(sLine2);
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="WriteCustomBitmap">
<interface>
<inputVars>
<variable name="byLocation">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> storage positions of the bitmap (0..7)</xhtml>
</documentation>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="WriteCustomBitmap" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method writes text at the current position
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_SETDDRAMADDR OR _byCurAddress);
LCDSendData(byLocation);
_byCurAddress := _byCurAddress + 1;</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="DefineCustomBitmap">
<interface>
<inputVars>
<variable name="byLocation">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> storage positions of the bitmap (0..7)</xhtml>
</documentation>
</variable>
<variable name="abyBitmap">
<type>
<array>
<dimension lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> bitmap definition: each byte (0 (top)..7 (bottom)) represents on line; each bit (0 (right)..4 (left)) of a byte represents one pixel in the line</xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="i">
<type>
<INT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="object_name" Value="DefineCustomBitmap" />
</Attributes>
</data>
</addData>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to clear the display
return value: none</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">LCDSendCommand(LCD_SETCGRAMADDR OR SHL(byLocation, 3));
FOR i := 0 TO 7 DO
LCDSendData(abyBitmap[i]);
END_FOR</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="Backlight">
<interface>
<returnType>
<BOOL />
</returnType>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> Sets the backlight on or off</xhtml>
</documentation>
</interface>
<SetAccessor>
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="hide" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">writeBit(_byHardwareAddress, LCD_PORT, PIN_BACKLIGHT, Backlight);
</xhtml>
</ST>
</body>
<addData />
</SetAccessor>
<addData />
</Property>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="Display">
<interface>
<returnType>
<BOOL />
</returnType>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> Switches the display on or off</xhtml>
</documentation>
</interface>
<SetAccessor>
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="hide" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF Display THEN
_byCurDisplayControl := _byCurDisplayControl OR LCD_DISPLAYON;
ELSE
_byCurDisplayControl := _byCurDisplayControl AND NOT LCD_DISPLAYON;
END_IF
LCDSendCommand(LCD_DISPLAYCONTROL OR _byCurDisplayControl);
</xhtml>
</ST>
</body>
<addData />
</SetAccessor>
<addData />
</Property>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="Cursor">
<interface>
<returnType>
<BOOL />
</returnType>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> Displays or hides the cursor</xhtml>
</documentation>
</interface>
<SetAccessor>
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="hide" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF Cursor THEN
_byCurDisplayControl := _byCurDisplayControl OR LCD_CURSORON;
ELSE
_byCurDisplayControl := _byCurDisplayControl AND NOT LCD_CURSORON;
END_IF
LCDSendCommand(LCD_DISPLAYCONTROL OR _byCurDisplayControl);
</xhtml>
</ST>
</body>
<addData />
</SetAccessor>
<addData />
</Property>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="Blink">
<interface>
<returnType>
<BOOL />
</returnType>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> Displays or hides the blinking rectangle</xhtml>
</documentation>
</interface>
<SetAccessor>
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="hide" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF Blink THEN
_byCurDisplayControl := _byCurDisplayControl OR LCD_BLINKON;
ELSE
_byCurDisplayControl := _byCurDisplayControl AND NOT LCD_BLINKON;
END_IF
LCDSendCommand(LCD_DISPLAYCONTROL OR _byCurDisplayControl);
</xhtml>
</ST>
</body>
<addData />
</SetAccessor>
<addData />
</Property>
</data>
</addData>
</pou>
</pous>
</types>
<instances>
<configurations />
</instances>
<addData>
<data name="http://www.3s-software.com/plcopenxml/globalvars" handleUnknown="implementation">
<globalVars name="GCL_PIFaceCaD" constant="true">
<variable name="IODIRA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> I/O direction A</xhtml>
</documentation>
</variable>
<variable name="IODIRB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#1" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> I/O direction B</xhtml>
</documentation>
</variable>
<variable name="IPOLA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#2" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> I/O polarity A</xhtml>
</documentation>
</variable>
<variable name="IPOLB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#3" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> I/O polarity B</xhtml>
</documentation>
</variable>
<variable name="GPINTENA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#4" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt enable A</xhtml>
</documentation>
</variable>
<variable name="GPINTENB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#5" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt enable B</xhtml>
</documentation>
</variable>
<variable name="DEFVALA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#6" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> register default value A (interupts)</xhtml>
</documentation>
</variable>
<variable name="DEFVALB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#7" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> register default value B (interupts)</xhtml>
</documentation>
</variable>
<variable name="INTCONA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#8" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt control A</xhtml>
</documentation>
</variable>
<variable name="INTCONB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#9" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt control B</xhtml>
</documentation>
</variable>
<variable name="IOCON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#A" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> I/O config (also : USINT := 16#0B)</xhtml>
</documentation>
</variable>
<variable name="GPPUA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#C" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port A pullups</xhtml>
</documentation>
</variable>
<variable name="GPPUB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#D" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port B pullups</xhtml>
</documentation>
</variable>
<variable name="INTFA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#E" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt flag A (where the interupt came from)</xhtml>
</documentation>
</variable>
<variable name="INTFB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#F" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt flag B</xhtml>
</documentation>
</variable>
<variable name="INTCAPA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#10" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt capture A (value at interupt is saved here)</xhtml>
</documentation>
</variable>
<variable name="INTCAPB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#11" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt capture B</xhtml>
</documentation>
</variable>
<variable name="GPIOA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#12" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port A</xhtml>
</documentation>
</variable>
<variable name="GPIOB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#13" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port B</xhtml>
</documentation>
</variable>
<variable name="OLATA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#14" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> output latch A</xhtml>
</documentation>
</variable>
<variable name="OLATB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#15" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> output latch B</xhtml>
</documentation>
</variable>
<variable name="BANK_OFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> addressing mode</xhtml>
</documentation>
</variable>
<variable name="BANK_ON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#80" />
</initialValue>
</variable>
<variable name="INT_MIRROR_ON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#40" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt mirror (INTa|INTb)</xhtml>
</documentation>
</variable>
<variable name="INT_MIRROR_OFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="SEQOP_OFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#20" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> incrementing address pointer</xhtml>
</documentation>
</variable>
<variable name="SEQOP_ON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="DISSLW_ON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#10" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> slew rate</xhtml>
</documentation>
</variable>
<variable name="DISSLW_OFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="HAEN_ON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#8" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> hardware addressing</xhtml>
</documentation>
</variable>
<variable name="HAEN_OFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="ODR_ON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#4" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> open drain for interupts</xhtml>
</documentation>
</variable>
<variable name="ODR_OFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="INTPOL_HIGH">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#2" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> interupt polarity</xhtml>
</documentation>
</variable>
<variable name="INTPOL_LOW">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="DELAY_PULSE_NS">
<type>
<UDINT />
</type>
<initialValue>
<simpleValue value="1000" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> 1us</xhtml>
</documentation>
</variable>
<variable name="DELAY_SETTLE_NS">
<type>
<UDINT />
</type>
<initialValue>
<simpleValue value="40000" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> 40us</xhtml>
</documentation>
</variable>
<variable name="DELAY_CLEAR_NS">
<type>
<UDINT />
</type>
<initialValue>
<simpleValue value="2600000" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> 2.6ms</xhtml>
</documentation>
</variable>
<variable name="DELAY_SETUP_0_NS">
<type>
<UDINT />
</type>
<initialValue>
<simpleValue value="15000000" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> 15ms</xhtml>
</documentation>
</variable>
<variable name="DELAY_SETUP_1_NS">
<type>
<UDINT />
</type>
<initialValue>
<simpleValue value="5000000" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> 5ms</xhtml>
</documentation>
</variable>
<variable name="DELAY_SETUP_2_NS">
<type>
<UDINT />
</type>
<initialValue>
<simpleValue value="1000000" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> 1ms</xhtml>
</documentation>
</variable>
<variable name="PIN_D4">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="0" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> mcp23s17 GPIOB to HD44780 pin map</xhtml>
</documentation>
</variable>
<variable name="PIN_D5">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="1" />
</initialValue>
</variable>
<variable name="PIN_D6">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="2" />
</initialValue>
</variable>
<variable name="PIN_D7">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="3" />
</initialValue>
</variable>
<variable name="PIN_ENABLE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="4" />
</initialValue>
</variable>
<variable name="PIN_RW">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="5" />
</initialValue>
</variable>
<variable name="PIN_RS">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="6" />
</initialValue>
</variable>
<variable name="PIN_BACKLIGHT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="7" />
</initialValue>
</variable>
<variable name="LCD_CLEARDISPLAY">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#1" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> commands</xhtml>
</documentation>
</variable>
<variable name="LCD_RETURNHOME">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#2" />
</initialValue>
</variable>
<variable name="LCD_ENTRYMODESET">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#4" />
</initialValue>
</variable>
<variable name="LCD_DISPLAYCONTROL">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#8" />
</initialValue>
</variable>
<variable name="LCD_CURSORSHIFT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#10" />
</initialValue>
</variable>
<variable name="LCD_FUNCTIONSET">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#20" />
</initialValue>
</variable>
<variable name="LCD_SETCGRAMADDR">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#40" />
</initialValue>
</variable>
<variable name="LCD_SETDDRAMADDR">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#80" />
</initialValue>
</variable>
<variable name="LCD_NEWLINE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#C0" />
</initialValue>
</variable>
<variable name="LCD_ENTRYRIGHT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> flags for display entry mode</xhtml>
</documentation>
</variable>
<variable name="LCD_ENTRYLEFT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#2" />
</initialValue>
</variable>
<variable name="LCD_ENTRYSHIFTINCREMENT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#1" />
</initialValue>
</variable>
<variable name="LCD_ENTRYSHIFTDECREMENT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_DISPLAYON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#4" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> flags for display on/off control</xhtml>
</documentation>
</variable>
<variable name="LCD_DISPLAYOFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_CURSORON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#2" />
</initialValue>
</variable>
<variable name="LCD_CURSOROFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_BLINKON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#1" />
</initialValue>
</variable>
<variable name="LCD_BLINKOFF">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_DISPLAYMOVE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#8" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> flags for display/cursor shift</xhtml>
</documentation>
</variable>
<variable name="LCD_CURSORMOVE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_MOVERIGHT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#4" />
</initialValue>
</variable>
<variable name="LCD_MOVELEFT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_8BITMODE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#10" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> flags for function set</xhtml>
</documentation>
</variable>
<variable name="LCD_4BITMODE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_2LINE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#8" />
</initialValue>
</variable>
<variable name="LCD_1LINE">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_5X10DOTS">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#4" />
</initialValue>
</variable>
<variable name="LCD_5X8DOTS">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="LCD_MAX_LINES">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="2" />
</initialValue>
</variable>
<variable name="LCD_WIDTH">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16" />
</initialValue>
</variable>
<variable name="LCD_RAM_WIDTH">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="80" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> RAM is 80 wide, split over two lines</xhtml>
</documentation>
</variable>
<variable name="ROW_OFFSETS">
<type>
<array>
<dimension lower="0" upper="1" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
<initialValue>
<arrayValue>
<value>
<simpleValue value="0" />
</value>
<value>
<simpleValue value="16#40" />
</value>
</arrayValue>
</initialValue>
</variable>
<variable name="SWITCH_PORT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="GPIOA" />
</initialValue>
</variable>
<variable name="LCD_PORT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="GPIOB" />
</initialValue>
</variable>
</globalVars>
</data>
<data name="http://www.3s-software.com/plcopenxml/libraries" handleUnknown="implementation">
<Libraries>
<Library Name="#CAA Types" Namespace="CAA" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="CAA Types Extern, * (CAA Technical Workgroup)" />
<Library Name="#Standard" Namespace="Standard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Standard, * (System)" />
<Library Name="SysTypes Interfaces, * (System)" Namespace="SysTypes" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<Library Name="#IoStandard" Namespace="IoStandard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="IoStandard, * (System)" />
<Library Name="#Raspberry Pi Peripherals" Namespace="Raspi" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Raspberry Pi Peripherals, * (3S - Smart Software Solutions GmbH)" />
<Library Name="#SysTime" Namespace="SysTime" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="SysTime, * (System)" />
<addData />
</Libraries>
</data>
</addData>
</project>
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/IoDrvGPIO.library.md
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>enumenum---
This function block is the base class for SPI devices controlled via the SPI device /dev/spidev0.0.
It is meant to be extended by other function blocks that overload the body and the following methods/properties and replace it with their specific implementation,
always including a call of the base implementation with super^.<MethodName>() :
- body (general handling, start-up)
- AfterReadInputs (reading input data)
- BeforeWriteOutputs (writing output data)
- Initialize [optional] (used to read parameters from the configuration)
- Operational [optional] (used to signal the status of the device)
The body of this FB is called by the methods AfterReadInputs and BeforeWriteOutputs, where _xAfterReadInputs indicates the caller.
Use _iState to control your statemachine. A value of 10 by default indicates that the drive is operational.
Do not forget to call the base implementation with super^(), where the diagnosis indicators are set according to the Operational property.
~~~ST
FUNCTION_BLOCK GPIO
VAR_INPUT
aeType: ARRAY [..] OF ;
axOutputs: ARRAY [..] OF ;
udiPWMFrequency: UDINT;
uiPWMDutyCycle: UINT;
END_VAR
VAR_OUTPUT
dwInputs: DWORD;
axInputs: ARRAY [..] OF ;
END_VAR
VAR
_pConnector: pointer;
_udiInstance: UDINT;
_uiModuleType: UINT;
_aeOldType: ARRAY [..] OF ;
_axOldOutputs: ARRAY [..] OF ;
_udiOldPWMFrequency: UDINT;
_uiOldPWMDutyCycle: UINT;
_hShmGPIOBASE: SysTypes.RTS_IEC_HANDLE;
_iState: INT;
_iOldState: INT;
_eProcessorType: ProcessorType;
_xAfterReadInputs: BOOL;
END_VAR
VAR
BCM2708_PERI_BASE: DWORD;
BCM2709_PERI_BASE: DWORD;
GPIO_PWMCTL: DWORD;
GPIO_PWMSTA: DWORD;
GPIO_PWMDMAC: DWORD;
GPIO_PWMRNG1: DWORD;
GPIO_PWMDAT1: DWORD;
GPIO_PWMFIF1: DWORD;
GPIO_PWMRNG2: DWORD;
GPIO_PWMDAT2: DWORD;
GPIO_CM_PWMCTL: DWORD;
GPIO_CM_PWMDIV: DWORD;
PAGE_SIZE: DWORD;
BLOCK_SIZE: DWORD;
END_VAR
VAR
PERI_BASE: DWORD;
GPIO_PADS: DWORD;
GPIO_BASE: DWORD;
GPIO_TIMER: DWORD;
GPIO_PWMBASE: DWORD;
GPIO_CLKBASE: DWORD;
END_VAR
~~~
~~~ST
IF _iState <> _iOldState THEN
IF Operational THEN
IoMgrConfigResetDiagnosis(_pConnector, ConnectorFlags.CF_CONNECTOR_ERROR);
IoMgrConfigSetDiagnosis(_pConnector, ConnectorFlags.CF_DRIVER_AVAILABLE OR ConnectorFlags.CF_CONNECTOR_FOUND OR ConnectorFlags.CF_CONNECTOR_CONFIGURED OR ConnectorFlags.CF_CONNECTOR_ACTIVE);
ELSE
IoMgrConfigResetDiagnosis(_pConnector, ConnectorFlags.CF_CONNECTOR_ACTIVE);
IoMgrConfigSetDiagnosis(_pConnector, ConnectorFlags.CF_DRIVER_AVAILABLE OR ConnectorFlags.CF_CONNECTOR_FOUND OR ConnectorFlags.CF_CONNECTOR_CONFIGURED OR ConnectorFlags.CF_CONNECTOR_ERROR);
END_IF
_iOldState := _iState;
END_IF
IF _iState = 0 THEN
init();
(*ELSIF _iState >0 AND _iState < 10 THEN
ConfigurePWM();*)
END_IF
//SysShm.SysSharedMemoryRead(_hShmGPIOPWM, 16#4, ADR(udiTestSTatus), 4, ADR(result));
~~~
---
~~~ST
METHOD AfterReadInputs: INT
~~~
~~~ST
_xAfterReadInputs := TRUE;
THIS^();
_xAfterReadInputs := FALSE;
IF _iState = 10 THEN
GetInputs();
END_IF
~~~
---
~~~ST
METHOD BeforeWriteOutputs: INT
~~~
~~~ST
IF _iState = 10 THEN
SetType();
SetOutputs();
END_IF
THIS^();
~~~
---
~~~ST
METHOD Initialize: UDINT
VAR_INPUT
wModuleType: UINT;
dwInstance: UDINT;
pConnector: pointer;
END_VAR
VAR
pParam: pointer;
udiResult: UDINT;
END_VAR
~~~
~~~ST
_uiModuleType := wModuleType;
_udiInstance := dwInstance;
_pConnector := pConnector;
_eProcessorType := DetermineProcessorType();
DetermineConstants();
init();
~~~
---
~~~ST
METHOD ConfigurePWM: BOOL
VAR
udi: UDINT;
Result: UDINT;
iCounter: INT;
END_VAR
~~~
~~~ST
CASE _iState OF
1:
udi := 0;
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMCTL, ADR(udi), 4, ADR(result));// Turn off PWM.
IF Result = Errors.ERR_OK THEN
_iState := _iState + 1;
ELSE
_iState := 1000;
END_IF
2:
SysShm.SysSharedMemoryRead(_hShmGPIOCLK, GPIO_CM_PWMCTL, ADR(udi), 4, ADR(result));
IF Result <> Errors.ERR_OK THEN
_iState := 1000;
RETURN;
END_IF
udi.4 := FALSE;
udi := udi OR 16#5A00_0000; // Turn off enable flag.
SysShm.SysSharedMemoryWrite(_hShmGPIOCLK, GPIO_CM_PWMCTL, ADR(udi), 4, ADR(result));
IF Result = Errors.ERR_OK THEN
_iState := _iState + 1;
ELSE
_iState := 1000;
END_IF
3:
SysShm.SysSharedMemoryRead(_hShmGPIOCLK, GPIO_CM_PWMCTL, ADR(udi), 4, ADR(result));
IF Result = Errors.ERR_OK THEN
IF NOT udi.7 THEN
_iState := _iState + 1;
END_IF
ELSE
_iState := 1000;
END_IF
4:
udi := 16#5A000000 OR SHL(DWORD#5, 12); // Configure divider.
SysShm.SysSharedMemoryWrite(_hShmGPIOCLK, GPIO_CM_PWMDIV, ADR(udi), 4, ADR(result));
IF Result = Errors.ERR_OK THEN
_iState := _iState + 1;
ELSE
_iState := 1000;
END_IF
5:
udi := 16#5A00_0206; // Source=PLLD (500 MHz), 1-stage MASH.
SysShm.SysSharedMemoryWrite(_hShmGPIOCLK, GPIO_CM_PWMCTL, ADR(udi), 4, ADR(result));
IF Result = Errors.ERR_OK THEN
_iState := _iState + 1;
ELSE
_iState := 1000;
END_IF
6:
udi := 16#5A00_0216; // Enable clock.
SysShm.SysSharedMemoryWrite(_hShmGPIOCLK, GPIO_CM_PWMCTL, ADR(udi), 4, ADR(result));
IF Result = Errors.ERR_OK THEN
_iState := _iState + 1;
ELSE
_iState := 1000;
END_IF
7:
// Wait for busy flag to turn on.
SysShm.SysSharedMemoryRead(_hShmGPIOCLK, GPIO_CM_PWMCTL, ADR(udi), 4, ADR(result));
IF Result = Errors.ERR_OK THEN
IF udi.7 THEN
_iState := _iState + 1;
END_IF
ELSE
_iState := 1000;
END_IF
8:
udi := 100;
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMRNG1, ADR(udi), 4, ADR(result));
IF Result <> Errors.ERR_OK THEN
_iState := 1000;
RETURN;
END_IF
udi := 20;
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMDAT1, ADR(udi), 4, ADR(result));
IF Result <> Errors.ERR_OK THEN
_iState := 1000;
RETURN;
END_IF
udi := 16#81;
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMCTL, ADR(udi), 4, ADR(result)); // Channel 1 M/S mode, no FIFO, PWM mode, enabled.
IF Result <> Errors.ERR_OK THEN
_iState := 1000;
RETURN;
END_IF
_iState := _iState + 1;
9:
aeType[18] := ALT5;
SetType();
_iState := 10;
END_CASE
~~~
---
~~~ST
METHOD DetermineConstants:
~~~
~~~ST
IF _eProcessorType = ProcessorType.BCM2708 THEN
// Raspberry Pi Model B+
PERI_BASE := BCM2708_PERI_BASE;
ELSE
// Raspberry Pi 2 Model B
// Raspberry Pi 3 Model B and all others
PERI_BASE := BCM2709_PERI_BASE;
END_IF
GPIO_PADS := (PERI_BASE + 16#00100000);
GPIO_BASE := (PERI_BASE + 16#00200000);
GPIO_TIMER := (PERI_BASE + 16#0000B000);
GPIO_PWMBASE := (PERI_BASE + 16#0020C000);
GPIO_CLKBASE := (PERI_BASE + 16#00101000);
~~~
---
~~~ST
METHOD DetermineProcessorType: ProcessorType
VAR
Result: RTS_IEC_RESULT;
Handle: RTS_IEC_HANDLE;
fr: FileReader;
str: string;
i: INT;
iLen: INT;
strType: string;
x: BOOL;
END_VAR
~~~
~~~ST
Handle := SysFileOpen(szFile:='/proc/cpuinfo' , am:=ACCESS_MODE.AM_READ , pResult:= ADR(Result));
IF Result = CmpErrors.Errors.ERR_OK THEN
fr(hFile:=Handle );
WHILE fr.GetLine(ADR(str), SIZEOF(str)) DO
iLen := Len(Str);
IF iLen > 10 THEN
IF LEFT(str, 10) = 'model name' THEN
i := find(str, ':');
strType := RIGHT(str, iLen-i-1);
strType := LEFT(strType, 5);
EXIT;
END_IF
END_IF
END_WHILE
END_IF
SysFileClose(Handle);
IF strType='ARMv6' THEN
// Raspberry Pi 1 and Model B+
DetermineProcessorType := ProcessorType.BCM2708;
ELSE
// Raspberry Pi 2 Model B
// Raspberry Pi 3 Model B and all others
DetermineProcessorType := ProcessorType.BCM2709;
END_IF
~~~
---
~~~ST
METHOD Fb_exit: BOOL
VAR_INPUT
bInCopyCode: BOOL;
END_VAR
~~~
~~~ST
IF _hShmGPIOBASE <> RTS_INVALID_HANDLE THEN
SysShm.SysSharedMemoryClose(_hShmGPIOBASE);
_hShmGPIOBASE := RTS_INVALID_HANDLE;
END_IF
(*
IF _hShmGPIOPWM <> RTS_INVALID_HANDLE THEN
SysShm.SysSharedMemoryClose(_hShmGPIOPWM);
_hShmGPIOPWM := RTS_INVALID_HANDLE;
END_IF
IF _hShmGPIOCLK <> RTS_INVALID_HANDLE THEN
SysShm.SysSharedMemoryClose(_hShmGPIOCLK);
_hShmGPIOCLK := RTS_INVALID_HANDLE;
END_IF*)
~~~
---
~~~ST
METHOD GetInputs:
VAR
Result: UDINT;
i: INT;
END_VAR
~~~
~~~ST
SysShm.SysSharedMemoryRead(_hShmGPIOBase, 16#34, ADR(dwInputs), 4, ADR(result));
FOR i:=0 TO 31 DO
axInputs[i] := (dwInputs AND SHL(UDINT#1, i)) > 0;
END_FOR
~~~
---
~~~ST
METHOD GetType:
VAR
Result: UDINT;
ul: UDINT;
i: INT;
j: UDINT;
END_VAR
~~~
~~~ST
j := 0;
FOR i:=0 TO 31 DO
IF (i MOD 10) = 0 THEN
SysSharedMemoryRead(_hShmGPIOBase, j*4, ADR(ul), 4, ADR(result));
j := j + 1;
END_IF
aeType[i] := UDINT_TO_USINT(SHR(ul, INT_TO_UDINT(i MOD 10) * 3) AND 2#111);
END_FOR
_aeOldType := aeType;
~~~
---
~~~ST
METHOD SetOutputs:
VAR
Result: UDINT;
ulOn: UDINT;
ulOff: UDINT;
i: INT;
END_VAR
~~~
~~~ST
FOR i:=0 TO 31 DO
IF _axOldOutputs[i] <> axOutputs[i] AND aeType[i] = GPIOType.O THEN
IF axOutputs[i] THEN
ulOn := ulOn OR SHL(UDINT#1, i);
ELSE
ulOff := ulOff OR SHL(UDINT#1, i);
END_IF
END_IF
END_FOR
IF ulOn > 0 THEN
SysShm.SysSharedMemoryWrite(_hShmGPIOBase, 16#1C, ADR(ulOn), 4, ADR(result));
END_IF
IF ulOff > 0 THEN
SysShm.SysSharedMemoryWrite(_hShmGPIOBase, 16#28, ADR(ulOff), 4, ADR(result));
END_IF
_axOldOutputs := axOutputs;
//PWM
(*
IF udiPWMFrequency <> _udiOldPWMFrequency THEN
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMRNG1, ADR(udiPWMFrequency), 4, ADR(result));
_udiOldPWMFrequency := udiPWMFrequency;
END_IF
IF uiPWMDutyCycle <> _uiOldPWMDutyCycle THEN
ulOn := uiPWMDutyCycle;
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMDAT1, ADR(ulOn), 4, ADR(result));
_uiOldPWMDutyCycle := uiPWMDutyCycle;
ulOn := 16#81;
SysShm.SysSharedMemoryWrite(_hShmGPIOPWM, GPIO_PWMCTL, ADR(ulOn), 4, ADR(result)); // Channel 1 M/S mode, no FIFO, PWM mode, enabled.
END_IF*)
~~~
---
~~~ST
METHOD SetType:
VAR
Result: UDINT;
ul: UDINT;
ulOrig: UDINT;
i: INT;
j: UDINT;
udiOffset: UDINT;
END_VAR
~~~
~~~ST
j := 0;
FOR i:=0 TO 31 DO
IF (i MOD 10) = 0 THEN
SysSharedMemoryRead(_hShmGPIOBase, j*4, ADR(ul), 4, ADR(result));
ulOrig := ul;
END_IF
IF _aeOldType[i] <> aeType[i] THEN
IF aeType[i] = GPIOType.I OR aeType[i] = GPIOType.O THEN
udiOffset := INT_TO_UDINT(i MOD 10) * 3;
CASE aeType[i] OF
GPIOType.I:
ul := ul AND NOT SHL(7, udiOffset);
GPIOType.O:
ul := ul AND NOT SHL(7, udiOffset);
ul := ul OR SHL(1, udiOffset);
_axOldOutputs[i] := axInputs[i];
END_CASE
END_IF
END_IF
IF ((i MOD 10) = 9 OR i=31) THEN
IF ul <> ulOrig THEN
SysSharedMemoryWrite(_hShmGPIOBase, j*4, ADR(ul), 4, ADR(result));
END_IF
j := j + 1;
END_IF
END_FOR
_aeOldType := aeType;
~~~
---
~~~ST
METHOD init: BOOL
VAR
Result1: UDINT;
Result2: UDINT;
Result3: UDINT;
ul: UDINT;
i: INT;
strEmpty: string;
END_VAR
~~~
~~~ST
IF _hShmGPIOBASE = RTS_INVALID_HANDLE THEN
ul := BLOCK_SIZE;
IF _hShmGPIOBASE = RTS_INVALID_HANDLE THEN
_hShmGPIOBASE := SysSharedMemoryCreate(pszName:=strEmpty , ulPhysicalAddress:=GPIO_BASE , pulSize:= ADR(ul), pResult:=ADR(Result1) );
END_IF
(* IF _hShmGPIOPWM = RTS_INVALID_HANDLE THEN
_hShmGPIOPWM := SysSharedMemoryCreate(pszName:=strEmpty , ulPhysicalAddress:=GPIO_PWMBASE , pulSize:= ADR(ul), pResult:=ADR(Result2) );
END_IF
IF _hShmGPIOCLK = RTS_INVALID_HANDLE THEN
_hShmGPIOCLK := SysSharedMemoryCreate(pszName:=strEmpty , ulPhysicalAddress:=GPIO_CLKBASE , pulSize:= ADR(ul), pResult:=ADR(Result3) );
END_IF
*)
IF Result1 = 0 AND Result2 = 0 AND Result3 = 0 THEN
init := TRUE;
GetType();
GetInputs();
FOR i:=0 TO 31 DO
IF aeType[i] = GPIOType.O THEN
axOutputs[i] := axInputs[i];
END_IF
END_FOR
_axOldOutputs := axOutputs;
SetOutputs();
_iState := 10;
ELSE
_iState := 1000;
END_IF
END_IF
~~~
---
~~~ST
FUNCTION_BLOCK IoDrvGPIO EXTENDS IoDrvBase
VAR
CLASSID_CCmpIoDrvTemplate: DWORD;
END_VAR
VAR
_IIoDrv: ICmpIoDrv;
_IIoDrvParameter: ICmpIoDrvParameter;
_GPIO: GPIO;
_dwInUse: DWORD;
_xBackGroundDiagStarted: BOOL;
_bDeactivated: BOOL;
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 := 'IoDrvGPIO';
m_Info.szVendorName := '3S - Smart Software Solutions';
m_Info.szDeviceName := 'Raspberry GPIOs';
m_Info.wModuleType := 8000;
_IIoDrv := THIS^;
_IIoDrvParameter := THIS^;
m_IBaseItf := THIS^;
m_hInterface := IoMgrRegisterInstance2(CLASSID_CCmpIoDrvTemplate, m_IBaseItf, 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;
_GPIO.Initialize(wModuleType, dwInstance, pConnector);
Initialize := 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
//Todo: update connectorflags if something changed
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;
wSize: WORD;
pbyIecAddress: pointer;
bySrcValue: BYTE;
bySrcMask: BYTE;
wSrcIndex: WORD;
wDestIndex: WORD;
pdw: pointer;
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
pbyIecAddress := pConnectorMapList[i].pChannelMapList[j].pbyIecAddress;
wDestIndex := pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset / 8;
IF (pConnectorMapList[i].pChannelMapList[j].wSize = 1) THEN
IF _GPIO.axInputs[pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset] THEN
(*IF (PiFace.byIn AND SHL(BYTE#1, pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset MOD 8)) <> 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 = 32 THEN
pdw := pbyIecAddress + wDestIndex;
pdw^ := _GPIO.dwInputs;
END_IF
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
_GPIO.AfterReadInputs();
_GPIO.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
// 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 <> 0) THEN
bySetting := IoMgrConfigGetParameterValueByte(pParameter, ADR(Result));
IF bySetting >= 0 AND bySetting <= 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 <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2000); (* outputs *)
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2100); (* outputs *)
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := 10; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2101); (* outputs *)
IF (pParameter <> 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 <> 0) DO
IF (pChild^.dwFlags AND ConnectorFlags.CF_ENABLE) <> 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
~~~
---
~~~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;
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;
CASE pConnectorMapList[i].pChannelMapList[j].pParameter^.dwDriverSpecific OF
0: // digitals
IF pConnectorMapList[i].pChannelMapList[j].wSize = 1 THEN
bySrcValue := pbyIecAddress[wSrcIndex];
k := pConnectorMapList[i].pChannelMapList[j].wParameterBitOffset;
IF (_dwInUse AND SHL(DWORD#1, k)) > 0 THEN
_GPIO.axOutputs[k] := BYTE_TO_BOOL(pbyIecAddress[wSrcIndex] AND SHL(BYTE#1, pConnectorMapList[i].pChannelMapList[j].wIecAddressBitOffset MOD 8));
END_IF
ELSIF pConnectorMapList[i].pChannelMapList[j].wSize = 32 THEN
pdw := pbyIecAddress;
FOR k:=0 TO 32 DO
IF (_dwInUse AND SHL(DWORD#1, k)) > 0 THEN
_GPIO.axOutputs[k] := DWORD_TO_BOOL(pdw^ AND SHL(1, k));
END_IF
END_FOR
END_IF
10:
pdw := pbyIecAddress;
_GPIO.udiPWMFrequency := DWORD#100_000_000 / pdw^;
14:
pw := pbyIecAddress;
_GPIO.uiPWMDutyCycle := UDINT_TO_UINT(UINT_TO_UDINT(pw^) * _GPIO.udiPWMFrequency / UDINT#65536);
END_CASE
END_FOR
END_FOR
IoDrvWriteOutputs := Errors.ERR_OK;
~~~
---
~~~ST
METHOD IoDrvGetConnector: pointer
VAR_INPUT
pResult: pointer;
END_VAR
~~~
~~~ST
IF m_pConnector = 0 THEN
IF pResult <> 0 THEN
pResult^ := Errors.ERR_FAILED;
END_IF
IoDrvGetConnector := 0;
RETURN;
END_IF
IF pResult <> 0 THEN
pResult^ := Errors.ERR_OK;
END_IF
IoDrvGetConnector := m_pConnector;
~~~
---
~~~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;
~~~
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/SM3_Drive_Servo.library.xml
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://www.plcopen.org/xml/tc6_0200">
<fileHeader companyName="" productName="CODESYS" productVersion="CODESYS V3.5 SP11" creationDateTime="2018-07-16T11:54:07.1620221" />
<contentHeader name="SM3_Drive_Servo" version="3.5.11.0" modificationDateTime="2017-07-03T23:33:24" organization="3S - Smart Software Solutions GmbH">
<Comment>SoftMotion driver for model making servos</Comment>
<coordinateInfo>
<fbd>
<scaling x="1" y="1" />
</fbd>
<ld>
<scaling x="1" y="1" />
</ld>
<sfc>
<scaling x="1" y="1" />
</sfc>
</coordinateInfo>
<addData>
<data name="http://www.3s-software.com/plcopenxml/projectinformation" handleUnknown="implementation">
<ProjectInformation>
<property name="Company" type="string">3S - Smart Software Solutions GmbH</property>
<property name="Description" type="string">SoftMotion driver for model making servos</property>
<property name="Placeholder" type="string">SM3 Drive Servo</property>
<property name="Project" type="string">SM3_Drive_Servo</property>
<property name="Released" type="boolean">true</property>
<property name="ShowSmartCodingInfo" type="boolean">true</property>
<property name="SystemApplicationLibrary" type="boolean">false</property>
<property name="Title" type="string">SM3_Drive_Servo</property>
<property name="Version" type="version">3.5.11.0</property>
<property name="library-category-list" type="library-category-list">Intern|SoftMotion</property>
</ProjectInformation>
</data>
<data name="http://www.3s-software.com/plcopenxml/autogeneratedobjects" handleUnknown="implementation">
<AutogeneratedObjects>
<libraryInfoFunctions>false</libraryInfoFunctions>
<projectInfoFunctions>true</projectInfoFunctions>
<propertyAccessorFunctions>true</propertyAccessorFunctions>
</AutogeneratedObjects>
</data>
</addData>
</contentHeader>
<types>
<dataTypes />
<pous>
<pou name="AXIS_REF_SERVO" pouType="functionBlock">
<interface>
<localVars>
<variable name="pAdafruitPWM">
<type>
<pointer>
<baseType>
<derived name="PWM.AdafruitPWM" />
</baseType>
</pointer>
</type>
</variable>
<variable name="usiAxisIndex">
<type>
<USINT />
</type>
</variable>
<variable name="lrMinPos">
<type>
<LREAL />
</type>
</variable>
<variable name="lrMaxPos">
<type>
<LREAL />
</type>
</variable>
<variable name="lrMinPwm">
<type>
<LREAL />
</type>
<initialValue>
<simpleValue value="1" />
</initialValue>
</variable>
<variable name="lrMaxPwm">
<type>
<LREAL />
</type>
<initialValue>
<simpleValue value="2" />
</initialValue>
</variable>
<variable name="lrInitPos">
<type>
<LREAL />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/pouinheritance" handleUnknown="implementation">
<Inheritance>
<Extends>AXIS_REF_VIRTUAL_SM3</Extends>
</Inheritance>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">;</xhtml>
</ST>
</body>
<addData>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="CommunicationStateMachine">
<interface>
<returnType>
<BOOL />
</returnType>
<localVars>
<variable name="x">
<type>
<LREAL />
</type>
</variable>
<variable name="pParam">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF pAdafruitPWM = 0 THEN
IF m_pConnector<>0 THEN
IF m_pConnector^.pFather <> 0 THEN
IF m_pConnector^.pFather^.pFather <> 0 THEN
pParam := ConfigGetParameter(m_pConnector^.pFather^.pFather, 1);
IF pParam <> 0 THEN
pAdafruitPWM := pParam^.dwDriverSpecific;
IF pAdafruitPWM <> 0 THEN
usiAxisIndex := pAdafruitPWM^.RegisterAxis();
END_IF
END_IF
END_IF
END_IF
END_IF
END_IF
IF pAdafruitPwm <> 0 THEN
bCommunication := pAdafruitPwm^.Operational;
ELSE
bCommunication := 0;
SMC_LogFBError(pDrive:=THIS, wID:=300, pbyErrorInstance:=THIS);
wCommunicationState := 1000;
END_IF
IF NOT bVirtual THEN
CASE wCommunicationState OF
0:
IF usiAxisIndex <> 255 THEN
{IF hasattribute (pou: AdafruitPwm, 'setPWMRange')}
pAdafruitPWM^.setPWMRange(usiAxisIndex, lrMinPwm, lrMaxPwm);
{END_IF}
wCommunicationState := 10;
END_IF
10:
fActPosition := lrInitPos;
IF bCommunication THEN
wCommunicationState := 100;
END_IF
END_CASE
// simulate actual values
IF bRegulatorOn THEN
IF pAdafruitPWM > 0 THEN
IF lrMinPos < lrMaxPos THEN
x := LIMIT(lrMinPos, fSetPosition, lrMaxPos);
ELSE
x := LIMIT(lrMaxPos, fSetPosition, lrMinPos);
END_IF
pAdafruitPWM^.alrPWM[usiAxisIndex] := (x + fOffsetPosition - lrMinPos) / (lrMaxPos - lrMinPos);
END_IF
fActPosition := fSetPosition;
IF iMovementType = 0 THEN (*modulo*)
x := SM0.fmod(fActPosition + fOffsetPosition (* + fLogicalOffsetPosition logisch ist nicht gleichzeitig virtuell, oder?*) - fLastActPosition - fLastPositionOffset, fPositionPeriod);
IF x*2 > fPositionPeriod THEN
x := x - fPositionPeriod;
END_IF
fActVelocity := x / fTaskCycle;
ELSE
fActVelocity := (fActPosition + fOffsetPosition (* + fLogicalOffsetPosition logisch ist nicht gleichzeitig virtuell, oder?*) - fLastActPosition - fLastPositionOffset) / fTaskCycle;
END_IF
fActAcceleration := (fActVelocity - fLastActVelocity) / fTaskCycle;
fActJerk := fSetJerk;
fActTorque := fSetTorque;
END_IF
//check limits
IF nAxisState<>errorstop AND nAxisState<>power_off THEN
IF fMaxVelocity > 0 AND fMaxVelocity < ABS(fActVelocity) THEN
SMC_LogFBError(THIS, SMC_VD_MAX_VELOCITY_EXCEEDED, 0);
iOwner := -1;
nAxisState := errorstop;
END_IF
IF fActAcceleration*fActVelocity > 0 THEN
//acceleration
IF fMaxAcceleration > 0 AND fMaxAcceleration < ABS(fActAcceleration) AND NOT bError THEN
SMC_LogFBError(THIS, SMC_VD_MAX_ACCELERATION_EXCEEDED, 0);
iOwner := -1;
nAxisState := errorstop;
END_IF
ELSE
//deceleration
IF fMaxDeceleration > 0 AND fMaxDeceleration < ABS(fActAcceleration) AND NOT bError THEN
SMC_LogFBError(THIS, SMC_VD_MAX_DECELERATION_EXCEEDED, 0);
iOwner := -1;
nAxisState := errorstop;
END_IF
END_IF
END_IF
IF nAxisState=errorstop OR nAxisState=power_off OR bySwitchingState=0 THEN
fActVelocity := 0;
fActAcceleration := 0;
END_IF
//store old values
fLastActPosition := fActPosition;
fLastPositionOffset := fOffsetPosition(* + fLogicalOffsetPosition logisch ist nicht gleichzeitig virtuell, oder?*);
fLastActVelocity := fActVelocity;
pAdafruitPWM^.axEnable[usiAxisIndex] := bRegulatorOn;
bRegulatorRealState := bRegulatorOn AND bCommunication; (* immitate power/halt states *)
bDriveStartRealState := bDriveStart;
IF bErrorAckn THEN
bError:=FALSE;
bErrorAckn := FALSE;
END_IF
END_IF
CommunicationStateMachine := SUPER^.CommunicationStateMachine();</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="GetMappedDriveParameter">
<interface>
<returnType>
<BOOL />
</returnType>
<inputVars>
<variable name="bRead">
<type>
<BOOL />
</type>
</variable>
<variable name="diParameterNumber">
<type>
<DINT />
</type>
</variable>
</inputVars>
<outputVars>
<variable name="diDriveParameterNumber">
<type>
<DINT />
</type>
</variable>
<variable name="usiDataLength">
<type>
<USINT />
</type>
</variable>
</outputVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF diParameterNumber = 1030 OR diParameterNumber = 1031 OR diParameterNumber = 1032 THEN
diDriveParameterNumber := 0;
GetMappedDriveParameter:=TRUE;
ELSE
GetMappedDriveParameter := SUPER^.GetMappedDriveParameter(
bRead:=bRead,
diParameterNumber:=diParameterNumber,
diDriveParameterNumber => diDriveParameterNumber,
usiDataLength => usiDataLength);
END_IF
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="GetStandardConfigParams">
<interface>
<returnType>
<BOOL />
</returnType>
<localVars>
<variable name="pParam">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">GetStandardConfigParams := SUPER^.GetStandardConfigParams();
IF m_pConnector <> 0 THEN
pParam := ConfigGetParameter(m_pConnector, 65536);
IF pParam <> 0 THEN
lrMinPos := ConfigGetParameterValueLREAL(pParam, 0);
END_IF
pParam := ConfigGetParameter(m_pConnector, 65537);
IF pParam <> 0 THEN
lrMaxPos := ConfigGetParameterValueLREAL(pParam, 0);
END_IF
pParam := ConfigGetParameter(m_pConnector, 65538);
IF pParam <> 0 THEN
lrInitPos := ConfigGetParameterValueLREAL(pParam, 0);
END_IF
pParam := ConfigGetParameter(m_pConnector, 65539);
IF pParam <> 0 THEN
lrMinPwm := ConfigGetParameterValueLREAL(pParam, 0);
END_IF
pParam := ConfigGetParameter(m_pConnector, 65540);
IF pParam <> 0 THEN
lrMaxPwm := ConfigGetParameterValueLREAL(pParam, 0);
END_IF
END_IF
byRealControllerMode := SMC_position;
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="DriverName">
<interface>
<returnType>
<string length="16" />
</returnType>
</interface>
<GetAccessor>
<interface />
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">DriverName := 'ModelingServo';
</xhtml>
</ST>
</body>
<addData />
</GetAccessor>
<addData />
</Property>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="DriverVersion">
<interface>
<returnType>
<DWORD />
</returnType>
</interface>
<GetAccessor>
<interface>
<localVars>
<variable name="v">
<type>
<derived name="Version" />
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">v := GetVersion();
DriverVersion := SHL(UINT_TO_DWORD(v.uiMajor), 24) + SHL(UINT_TO_DWORD(v.uiMinor), 16) + SHL(UINT_TO_DWORD(v.uiServicePack), 8) + 2 * v.uiPatch - BOOL_TO_DWORD(NOT GetBooleanProperty("Released"));
</xhtml>
</ST>
</body>
<addData />
</GetAccessor>
<addData />
</Property>
</data>
</addData>
</pou>
<pou name="SMC_PosControlInput" pouType="functionBlock">
<interface>
<inputVars>
<variable name="bLimitPos">
<type>
<BOOL />
</type>
</variable>
<variable name="bLimitNeg">
<type>
<BOOL />
</type>
</variable>
<variable name="wActPosition">
<type>
<WORD />
</type>
</variable>
<variable name="dwActPosition">
<type>
<DWORD />
</type>
</variable>
<variable name="bExternalError">
<type>
<BOOL />
</type>
</variable>
<variable name="bRegulatorRealState">
<type>
<BOOL />
</type>
</variable>
<variable name="bDriveStartRealState">
<type>
<BOOL />
</type>
</variable>
<variable name="dwEncoderCounterModulo">
<type>
<DWORD />
</type>
<initialValue>
<simpleValue value="0" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> encoder modulo value </xhtml>
</documentation>
</variable>
</inputVars>
<outputVars>
<variable name="bUseWord">
<type>
<BOOL />
</type>
</variable>
</outputVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF wActPosition <> 0 THEN
bUseWord := TRUE;
END_IF</xhtml>
</ST>
</body>
<addData />
</pou>
<pou name="SMC_PosControlOutput" pouType="functionBlock">
<interface>
<inputVars>
<variable name="bRegulatorOnIn">
<type>
<BOOL />
</type>
</variable>
<variable name="bDriveStartIn">
<type>
<BOOL />
</type>
</variable>
<variable name="fSetVelocity">
<type>
<LREAL />
</type>
</variable>
<variable name="fMaxVelocityNeg">
<type>
<LREAL />
</type>
</variable>
<variable name="fMaxVelocityPos">
<type>
<LREAL />
</type>
</variable>
<variable name="diMaxVelocityNeg">
<type>
<DINT />
</type>
</variable>
<variable name="diZeroVelocity">
<type>
<DINT />
</type>
</variable>
<variable name="diMaxVelocityPos">
<type>
<DINT />
</type>
</variable>
<variable name="bInvertDirection">
<type>
<BOOL />
</type>
</variable>
</inputVars>
<outputVars>
<variable name="bRegulatorOn">
<type>
<BOOL />
</type>
</variable>
<variable name="bDriveStart">
<type>
<BOOL />
</type>
</variable>
<variable name="diSetVelocity">
<type>
<DINT />
</type>
</variable>
<variable name="iSetVelocity">
<type>
<INT />
</type>
</variable>
</outputVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">bRegulatorOn := bRegulatorOnIn;
bDriveStart := bDriveStartIn;
IF bDriveStartIn THEN
IF bInvertDirection THEN
fSetVelocity := fSetVelocity*-1;
END_IF
IF fSetVelocity < 0 THEN
fSetVelocity := MAX(fSetVelocity, fMaxVelocityNeg);
diSetVelocity := diZeroVelocity + LREAL_TO_DINT(fSetVelocity/fMaxVelocityNeg* DINT_TO_LREAL(diMaxVelocityNeg-diZeroVelocity));
ELSE
fSetVelocity := MIN(fSetVelocity, fMaxVelocityPos);
diSetVelocity := diZeroVelocity + LREAL_TO_DINT(fSetVelocity/fMaxVelocityPos* DINT_TO_LREAL(diMaxVelocityPos-diZeroVelocity));
END_IF
ELSE
diSetVelocity := diZeroVelocity;
END_IF
iSetVelocity := DINT_TO_INT(diSetVelocity);</xhtml>
</ST>
</body>
<addData />
</pou>
</pous>
</types>
<instances>
<configurations />
</instances>
<addData>
<data name="http://www.3s-software.com/plcopenxml/libraries" handleUnknown="implementation">
<Libraries>
<Library Name="#IoStandard" Namespace="IoStandard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="IoStandard, * (System)" />
<Library Name="#SM3_Basic" Namespace="SM3_Basic" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="SM3_Basic, * (3S - Smart Software Solutions GmbH)" />
<Library Name="#Standard" Namespace="Standard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Standard, * (System)" />
<Library Name="#Raspberry I2C AdafruitPWM" Namespace="PWM" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Raspberry I2C AdafruitPWM, * (3S - Smart Software Solutions GmbH)" />
<Library Name="#SM3_Shared" Namespace="SM0" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="SM3_Shared, * (3S - Smart Software Solutions GmbH)" />
<addData />
</Libraries>
</data>
</addData>
</project>
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/IoDrvPiFace.library.md
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>---
~~~ST
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
~~~
~~~ST
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
~~~
---
~~~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);
pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF
~~~
---
~~~ST
METHOD BeforeWriteOutputs: INT
VAR
i: USINT;
END_VAR
~~~
~~~ST
SUPER^.BeforeWriteOutputs();
IF _iState = 10 THEN
write8(_byHardwareAddress, GCL_PIFace.OUTPUT_PORT, byOut);
END_IF
~~~
---
~~~ST
METHOD AfterReadInputs: INT
VAR
aby: ARRAY [..] OF ;
END_VAR
~~~
~~~ST
SUPER^.AfterReadInputs();
IF _iState = 10 THEN
byIn := NOT read8(_byHardwareAddress, GCL_PIFace.INPUT_PORT);
END_IF
~~~
---
~~~ST
METHOD read8: BYTE
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
END_VAR
VAR
abyTxBuffer: ARRAY [..] OF ;
abyRxBuffer: ARRAY [..] OF ;
END_VAR
~~~
~~~ST
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
~~~
---
~~~ST
METHOD write8: BOOL
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
byValue: BYTE;
END_VAR
VAR
abyTxBuffer: ARRAY [..] OF ;
abyRxBuffer: ARRAY [..] OF ;
END_VAR
~~~
~~~ST
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
~~~
---
~~~ST
FUNCTION_BLOCK IoDrvPiFace EXTENDS IoDrvBase
VAR
CLASSID_CCmpIoDrvTemplate: DWORD;
END_VAR
VAR
_IIoDrv: ICmpIoDrv;
_IIoDrvParameter: ICmpIoDrvParameter;
_xBackGroundDiagStarted: BOOL;
_bDeactivated: BOOL;
PiFace: PiFaceDigital;
END_VAR
~~~
~~~ST
~~~
---
~~~ST
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
~~~
~~~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
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)) <> 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;
~~~
---
~~~ST
METHOD IoDrvIdentify: UDINT
VAR_INPUT
pConnector: pointer;
END_VAR
~~~
~~~ST
IoDrvIdentify_Count := IoDrvIdentify_Count + 1;
IoDrvIdentify := Errors.ERR_NOTIMPLEMENTED;
~~~
---
~~~ST
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
~~~
~~~ST
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 <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2000); (* outputs *)
IF (pParameter <> 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 <> 0) DO
IF (pChild^.dwFlags AND ConnectorFlags.CF_ENABLE) <> 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
~~~
---
~~~ST
METHOD IoDrvWatchdogTrigger: UDINT
VAR_INPUT
pConnector: pointer;
END_VAR
~~~
~~~ST
IoDrvWatchdogTrigger_Count := IoDrvWatchdogTrigger_Count + 1;
IoDrvWatchdogTrigger := 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 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 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
~~~
~~~ST
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)) <> 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;
~~~
---
~~~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
PiFace.AfterReadInputs();
PiFace.BeforeWriteOutputs();
END_IF
IoDrvStartBusCycle := Errors.ERR_OK;
~~~
---
~~~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
//Todo: update connectorflags if something changed
IoDrvGetModuleDiagnosis_Count := IoDrvGetModuleDiagnosis_Count + 1;
IoDrvGetModuleDiagnosis := Errors.ERR_NOTIMPLEMENTED;
~~~
---
~~~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
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 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 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;
PiFace.Initialize(wModuleType, dwInstance, pConnector);
Initialize := Errors.ERR_OK;
~~~
---
~~~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 := '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;
~~~
---
~~~ST
METHOD IoDrvGetConnector: pointer
VAR_INPUT
pResult: pointer;
END_VAR
~~~
~~~ST
IF m_pConnector = 0 THEN
IF pResult <> 0 THEN
pResult^ := Errors.ERR_FAILED;
END_IF
IoDrvGetConnector := 0;
RETURN;
END_IF
IF pResult <> 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
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/SPI_PiFace.library.xml
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://www.plcopen.org/xml/tc6_0200">
<fileHeader companyName="" productName="CODESYS" productVersion="CODESYS V3.5 SP11" creationDateTime="2018-07-16T11:54:08.0749653" />
<contentHeader name="Raspberry SPI PiFace" version="1.2.0.0" modificationDateTime="2015-11-24T04:28:44" organization="3S - Smart Software Solutions GmbH" author="3S - Smart Software Solutions GmbH">
<Comment>Library containing device support of PiFace Digital</Comment>
<coordinateInfo>
<fbd>
<scaling x="1" y="1" />
</fbd>
<ld>
<scaling x="1" y="1" />
</ld>
<sfc>
<scaling x="1" y="1" />
</sfc>
</coordinateInfo>
<addData>
<data name="http://www.3s-software.com/plcopenxml/projectinformation" handleUnknown="implementation">
<ProjectInformation>
<property name="Author" type="string">3S - Smart Software Solutions GmbH</property>
<property name="Company" type="string">3S - Smart Software Solutions GmbH</property>
<property name="DefaultNamespace" type="string">PiFace</property>
<property name="Description" type="string">Library containing device support of PiFace Digital</property>
<property name="Placeholder" type="string">PlaceholderTemplate</property>
<property name="Project" type="string">SPI_PiFace</property>
<property name="Released" type="boolean">false</property>
<property name="Title" type="string">Raspberry SPI PiFace</property>
<property name="Version" type="version">1.2.0.0</property>
<property name="library-category-list" type="library-category-list" />
</ProjectInformation>
</data>
</addData>
</contentHeader>
<types>
<dataTypes />
<pous>
<pou name="PiFaceDigital" pouType="functionBlock">
<interface>
<inputVars>
<variable name="byOut">
<type>
<BYTE />
</type>
</variable>
</inputVars>
<outputVars>
<variable name="byIn">
<type>
<BYTE />
</type>
</variable>
</outputVars>
<localVars>
<variable name="_byHardwareAddress">
<type>
<BYTE />
</type>
</variable>
</localVars>
<tempVars>
<variable name="i">
<type>
<INT />
</type>
</variable>
<variable name="k">
<type>
<INT />
</type>
</variable>
</tempVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/pouinheritance" handleUnknown="implementation">
<Inheritance>
<Extends>spi</Extends>
</Inheritance>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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
</xhtml>
</ST>
</body>
<addData>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Initialize">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="wModuleType">
<type>
<UINT />
</type>
</variable>
<variable name="dwInstance">
<type>
<UDINT />
</type>
</variable>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<localVars>
<variable name="pParam">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="udiResult">
<type>
<UDINT />
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.Initialize(wModuleType, dwInstance, pConnector);
pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="BeforeWriteOutputs">
<interface>
<returnType>
<INT />
</returnType>
<localVars>
<variable name="i">
<type>
<USINT />
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.BeforeWriteOutputs();
IF _iState = 10 THEN
write8(_byHardwareAddress, GCL_PIFace.OUTPUT_PORT, byOut);
END_IF</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="AfterReadInputs">
<interface>
<returnType>
<INT />
</returnType>
<localVars>
<variable name="aby">
<type>
<array>
<dimension lower="0" upper="13" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.AfterReadInputs();
IF _iState = 10 THEN
byIn := NOT read8(_byHardwareAddress, GCL_PIFace.INPUT_PORT);
END_IF
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="read8">
<interface>
<returnType>
<BYTE />
</returnType>
<inputVars>
<variable name="byHardwareAddress">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> hardware address </xhtml>
</documentation>
</variable>
<variable name="byPort">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port number to read </xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="abyTxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
<variable name="abyRxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
</localVars>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to read the data byte of one port using the following protocol:
Byte0: 16#41 + hardware address
Byte1: Port
Byte2: 16#FF
return value: data content</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="write8">
<interface>
<returnType>
<BOOL />
</returnType>
<inputVars>
<variable name="byHardwareAddress">
<type>
<subrangeSigned>
<range lower="0" upper="7" />
<baseType>
<BYTE />
</baseType>
</subrangeSigned>
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> hardware address </xhtml>
</documentation>
</variable>
<variable name="byPort">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> port number to read </xhtml>
</documentation>
</variable>
<variable name="byValue">
<type>
<BYTE />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> value to write </xhtml>
</documentation>
</variable>
</inputVars>
<localVars>
<variable name="abyTxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
<variable name="abyRxBuffer">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
</localVars>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method is used to write a data byte into a port using the following protocol:
Byte0: 16#41 + hardware address
Byte1: Port
Byte2: Value
return value: TRUE if successful</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
</addData>
</pou>
</pous>
</types>
<instances>
<configurations />
</instances>
<addData>
<data name="http://www.3s-software.com/plcopenxml/globalvars" handleUnknown="implementation">
<globalVars name="GCL_PIFace" constant="true">
<variable name="OUTPUT_PORT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#12" />
</initialValue>
</variable>
<variable name="INPUT_PORT">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#13" />
</initialValue>
</variable>
<variable name="IOCON">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#A" />
</initialValue>
</variable>
<variable name="GPIOA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#12" />
</initialValue>
</variable>
<variable name="GPIOB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#13" />
</initialValue>
</variable>
<variable name="GPPUB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#D" />
</initialValue>
</variable>
<variable name="IODIRA">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#0" />
</initialValue>
</variable>
<variable name="IODIRB">
<type>
<USINT />
</type>
<initialValue>
<simpleValue value="16#1" />
</initialValue>
</variable>
</globalVars>
</data>
<data name="http://www.3s-software.com/plcopenxml/libraries" handleUnknown="implementation">
<Libraries>
<Library Name="#CAA Types" Namespace="CAA" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="CAA Types Extern, * (CAA Technical Workgroup)" />
<Library Name="#Standard" Namespace="Standard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Standard, * (System)" />
<Library Name="SysTypes Interfaces, * (System)" Namespace="SysTypes" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<Library Name="#IoStandard" Namespace="IoStandard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="IoStandard, * (System)" />
<Library Name="#Raspberry Pi Peripherals" Namespace="Raspi" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Raspberry Pi Peripherals, * (3S - Smart Software Solutions GmbH)" />
<addData />
</Libraries>
</data>
</addData>
</project>
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/SPI_MCP3008.library.md
Bash
bash
(Bash)
<?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 := '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;
~~~
---
~~~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
//Todo: update connectorflags if something changed
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;
wSize: WORD;
pbyIecAddress: pointer;
bySrcValue: BYTE;
bySrcMask: BYTE;
wSrcIndex: WORD;
wDestIndex: WORD;
pdw: pointer;
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
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;
~~~
---
~~~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
// 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 <> 0) THEN
bySetting := IoMgrConfigGetParameterValueByte(pParameter, ADR(Result));
IF bySetting >= 0 AND bySetting <= 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 <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2000); (* outputs *)
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2100); (* outputs *)
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := 10; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2101); (* outputs *)
IF (pParameter <> 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 <> 0) DO
IF (pChild^.dwFlags AND ConnectorFlags.CF_ENABLE) <> 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
~~~
---
~~~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 IoDrvGetConnector: pointer
VAR_INPUT
pResult: pointer;
END_VAR
~~~
~~~ST
IF m_pConnector = 0 THEN
IF pResult <> 0 THEN
pResult^ := Errors.ERR_FAILED;
END_IF
IoDrvGetConnector := 0;
RETURN;
END_IF
IF pResult <> 0 THEN
pResult^ := Errors.ERR_OK;
END_IF
IoDrvGetConnector := m_pConnector;
~~~
---
~~~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);
(*
pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF*)
~~~
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/OneWire_DS18B20.library.xml
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://www.plcopen.org/xml/tc6_0200">
<fileHeader companyName="" productName="CODESYS" productVersion="CODESYS V3.5 SP11" creationDateTime="2018-07-16T11:54:05.9004452" />
<contentHeader name="Raspberry 1-wire DS18B20" version="1.3.0.0" modificationDateTime="2015-11-24T04:28:44" organization="3S - Smart Software Solutions GmbH" author="3S - Smart Software Solutions GmbH">
<Comment>Library containing device support for DS18B20 under Raspberry Pi</Comment>
<coordinateInfo>
<fbd>
<scaling x="1" y="1" />
</fbd>
<ld>
<scaling x="1" y="1" />
</ld>
<sfc>
<scaling x="1" y="1" />
</sfc>
</coordinateInfo>
<addData>
<data name="http://www.3s-software.com/plcopenxml/projectinformation" handleUnknown="implementation">
<ProjectInformation>
<property name="Author" type="string">3S - Smart Software Solutions GmbH</property>
<property name="Company" type="string">3S - Smart Software Solutions GmbH</property>
<property name="DefaultNamespace" type="string">DS18B20</property>
<property name="Description" type="string">Library containing device support for DS18B20 under Raspberry Pi</property>
<property name="Placeholder" type="string">PlaceholderTemplate</property>
<property name="Project" type="string">OneWire_DS18B20</property>
<property name="Released" type="boolean">false</property>
<property name="Title" type="string">Raspberry 1-wire DS18B20</property>
<property name="Version" type="version">1.3.0.0</property>
<property name="library-category-list" type="library-category-list" />
</ProjectInformation>
</data>
</addData>
</contentHeader>
<types>
<dataTypes />
<pous>
<pou name="OneWire_DS18B20" pouType="functionBlock">
<interface>
<outputVars>
<variable name="rTemp">
<type>
<REAL />
</type>
</variable>
<variable name="stdTimeStamp">
<type>
<derived name="RTS_SYSTIMEDATE" />
</type>
</variable>
<variable name="xSignalOk">
<type>
<BOOL />
</type>
</variable>
</outputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/pouinheritance" handleUnknown="implementation">
<Inheritance>
<Extends>OneWire</Extends>
</Inheritance>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">super^();</xhtml>
</ST>
</body>
<addData>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="AfterReadInputs">
<interface>
<returnType>
<INT />
</returnType>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This method can be overloaded by extending FBs.
It is used to read in the inputs of the device in the beginning of the cycle.
Always including a call of the base implementation with super^.AfterReadInputs()
In the base implementation, the body of the FB is called.</xhtml>
</documentation>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">Evaluate();
SUPER^.AfterReadInputs();
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Evaluate">
<interface>
<localVars>
<variable name="fr">
<type>
<derived name="FileReader" />
</type>
</variable>
<variable name="hFile">
<type>
<derived name="RTS_IEC_HANDLE" />
</type>
</variable>
<variable name="result">
<type>
<derived name="RTS_IEC_RESULT" />
</type>
</variable>
<variable name="udiRead">
<type>
<UDINT />
</type>
</variable>
<variable name="sPath">
<type>
<string />
</type>
</variable>
<variable name="sData">
<type>
<string />
</type>
</variable>
<variable name="i">
<type>
<INT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF _pMaster <> 0 THEN
sPath := DataPath;
hFile := SysFileOpen(sPath, ACCESS_MODE.AM_READ, ADR(result));
IF hFile <> RTS_INVALID_HANDLE THEN
fr(hFile := hFile);
IF fr.GetLine(ADR(sData), SIZEOF(sData)) AND LEN(sData) > 3 THEN
IF RIGHT(sData, 3) = 'YES' THEN
xSignalOk := TRUE;
ELSE
xSignalOk := FALSE;
END_IF
ELSE
xSignalOk := FALSE;
END_IF
IF xSignalOk THEN
IF fr.GetLine(ADR(sData), SIZEOF(sData)) THEN
i := FIND(sData, 't=');
IF i > 0 THEN
sData := RIGHT(sData, LEN(sData) - i - 1);
IF sData = '85000' THEN
xSignalOk := FALSE;
ELSE
rTemp := STRING_TO_REAL(sData) * 1E-3;
SysTimeRtcConvertUtcToDate(SysTimeRtcGet(result), stdTimeStamp);
END_IF
ELSE
xSignalOk := FALSE;
END_IF
END_IF
END_IF
ELSE
xSignalOk := FALSE;
END_IF
SysFileClose(hFile);
END_IF
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/property" handleUnknown="implementation">
<Property name="Operational">
<interface>
<returnType>
<BOOL />
</returnType>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> This property has to return TRUE, when the device is configured and running</xhtml>
</documentation>
</interface>
<GetAccessor>
<interface>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="hide" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">Operational := xSignalOk;</xhtml>
</ST>
</body>
<addData />
</GetAccessor>
<addData />
</Property>
</data>
</addData>
</pou>
</pous>
</types>
<instances>
<configurations />
</instances>
<addData>
<data name="http://www.3s-software.com/plcopenxml/libraries" handleUnknown="implementation">
<Libraries>
<Library Name="#Standard" Namespace="Standard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Standard, * (System)" />
<Library Name="#IoStandard" Namespace="IoStandard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="IoStandard, * (System)" />
<Library Name="#Raspberry Pi Peripherals" Namespace="Raspi" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Raspberry Pi Peripherals, * (3S - Smart Software Solutions GmbH)" />
<Library Name="#SysFile" Namespace="SysFile" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="SysFile, * (System)" />
<Library Name="#SysTimeRtc" Namespace="SysTimeRtc" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="SysTimeRtc, * (System)" />
<Library Name="SysTypes Interfaces, * (System)" Namespace="SysTypes" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<addData />
</Libraries>
</data>
</addData>
</project>
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/SPI_PiFace.library.md
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>---
~~~ST
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
~~~
~~~ST
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
~~~
---
~~~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);
pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF
~~~
---
~~~ST
METHOD BeforeWriteOutputs: INT
VAR
i: USINT;
END_VAR
~~~
~~~ST
SUPER^.BeforeWriteOutputs();
IF _iState = 10 THEN
write8(_byHardwareAddress, GCL_PIFace.OUTPUT_PORT, byOut);
END_IF
~~~
---
~~~ST
METHOD AfterReadInputs: INT
VAR
aby: ARRAY [..] OF ;
END_VAR
~~~
~~~ST
SUPER^.AfterReadInputs();
IF _iState = 10 THEN
byIn := NOT read8(_byHardwareAddress, GCL_PIFace.INPUT_PORT);
END_IF
~~~
---
~~~ST
METHOD read8: BYTE
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
END_VAR
VAR
abyTxBuffer: ARRAY [..] OF ;
abyRxBuffer: ARRAY [..] OF ;
END_VAR
~~~
~~~ST
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
~~~
---
~~~ST
METHOD write8: BOOL
VAR_INPUT
byHardwareAddress: subrangeSigned;
byPort: BYTE;
byValue: BYTE;
END_VAR
VAR
abyTxBuffer: ARRAY [..] OF ;
abyRxBuffer: ARRAY [..] OF ;
END_VAR
~~~
~~~ST
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
~~~
VAR_GLOBAL
OUTPUT_PORT: USINT;
INPUT_PORT: USINT;
IOCON: USINT;
GPIOA: USINT;
GPIOB: USINT;
GPPUB: USINT;
IODIRA: USINT;
IODIRB: USINT;
END_VAR
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/I2C_SRF02.library.md
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>---
~~~ST
FUNCTION_BLOCK SRF02_Supersonic EXTENDS i2c
VAR_INPUT
lrMinDistance: LREAL;
lrMaxDistance: LREAL;
END_VAR
VAR_OUTPUT
lrDistance: LREAL;
xValid: BOOL;
xNewMeasurement: BOOL;
END_VAR
VAR
timer: TON;
END_VAR
~~~
~~~ST
xNewMeasurement := FALSE;
SUPER^();
CASE _iState OF
0:
IF usiAddress = 0 THEN
usiAddress := 16#70;
END_IF
IF SUPER^.init() THEN
_iState := 5;
END_IF
5:
Timer.pt := T#70MS;
_iState := 10;
xValid := FALSE;
END_CASE
~~~
---
~~~ST
METHOD AfterReadInputs: INT
VAR
Buffer: ARRAY [..] OF ;
len: DINT;
END_VAR
~~~
~~~ST
SUPER^.AfterReadInputs();
IF _iState = 10 THEN
timer(IN:=TRUE);
IF timer.Q THEN
len := Read(ADR(Buffer), 4);
IF len = 4 THEN
lrDistance := BYTE_TO_LREAL(Buffer[2])*0.01 + BYTE_TO_LREAL(Buffer[3]) * 2.56;
xValid := (lrDistance >= lrMinDistance AND lrDistance <= lrMaxDistance);
xNewMeasurement := TRUE;
ELSE
xValid := FALSE;
END_IF
Write8(0, 16#51); //new measurement
timer(IN:=FALSE);
END_IF
END_IF
~~~
---
~~~ST
METHOD BeforeWriteOutputs: INT
~~~
~~~ST
SUPER^.BeforeWriteOutputs();
~~~
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/SPI_MCP3008.library.xml
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://www.plcopen.org/xml/tc6_0200">
<fileHeader companyName="" productName="CODESYS" productVersion="CODESYS V3.5 SP11" creationDateTime="2018-07-16T11:54:07.7840602" />
<contentHeader name="Raspberry SPI MCP3008" version="3.5.11.0" modificationDateTime="2017-07-03T23:33:34" organization="3S - Smart Software Solutions GmbH" author="3S - Smart Software Solutions GmbH">
<Comment>Library containing device support of MCP3008</Comment>
<coordinateInfo>
<fbd>
<scaling x="1" y="1" />
</fbd>
<ld>
<scaling x="1" y="1" />
</ld>
<sfc>
<scaling x="1" y="1" />
</sfc>
</coordinateInfo>
<addData>
<data name="http://www.3s-software.com/plcopenxml/projectinformation" handleUnknown="implementation">
<ProjectInformation>
<property name="Author" type="string">3S - Smart Software Solutions GmbH</property>
<property name="Company" type="string">3S - Smart Software Solutions GmbH</property>
<property name="DefaultNamespace" type="string">MCP3008</property>
<property name="Description" type="string">Library containing device support of MCP3008</property>
<property name="Placeholder" type="string">SPI MCP3008</property>
<property name="Project" type="string">SPI_MCP3008</property>
<property name="Released" type="boolean">true</property>
<property name="Title" type="string">Raspberry SPI MCP3008</property>
<property name="Version" type="version">3.5.11.0</property>
<property name="library-category-list" type="library-category-list">Target</property>
</ProjectInformation>
</data>
</addData>
</contentHeader>
<types>
<dataTypes />
<pous>
<pou name="IoDrvMCP3008" pouType="functionBlock">
<interface>
<localVars>
<variable name="_IIoDrv">
<type>
<derived name="ICmpIoDrv" />
</type>
</variable>
<variable name="_IIoDrvParameter">
<type>
<derived name="ICmpIoDrvParameter" />
</type>
</variable>
<variable name="_MCP3008">
<type>
<derived name="MCP3008" />
</type>
</variable>
<variable name="_dwInUse">
<type>
<DWORD />
</type>
</variable>
<variable name="_xBackGroundDiagStarted">
<type>
<BOOL />
</type>
</variable>
<variable name="_bDeactivated">
<type>
<BOOL />
</type>
</variable>
</localVars>
<localVars constant="true">
<variable name="CLASSID_CCmpIoDrvTemplate">
<type>
<DWORD />
</type>
<initialValue>
<simpleValue value="16#FF03" />
</initialValue>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> TODO</xhtml>
</documentation>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/pouinheritance" handleUnknown="implementation">
<Inheritance>
<Extends>IoDrvBase</Extends>
<Implements>ICmpIoDrvParameter</Implements>
</Inheritance>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml" />
</ST>
</body>
<addData>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="FB_Exit">
<interface>
<returnType>
<BOOL />
</returnType>
<inputVars>
<variable name="bInCopyCode">
<type>
<BOOL />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">FB_Exit_Count := FB_Exit_Count + 1;
FB_Exit := TRUE;</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="FB_Init">
<interface>
<returnType>
<BOOL />
</returnType>
<inputVars>
<variable name="bInitRetains">
<type>
<BOOL />
</type>
</variable>
<variable name="bInCopyCode">
<type>
<BOOL />
</type>
</variable>
</inputVars>
<localVars>
<variable name="Result">
<type>
<UDINT />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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;</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="FB_Reinit">
<interface>
<returnType>
<BOOL />
</returnType>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">FB_Reinit_Count := FB_Reinit_Count + 1;
FB_Reinit := TRUE;</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Initialize">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="wModuleType">
<type>
<UINT />
</type>
</variable>
<variable name="dwInstance">
<type>
<UDINT />
</type>
</variable>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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;</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="QueryInterface">
<interface>
<returnType>
<pointer>
<baseType>
<pointer>
<baseType>
<BYTE />
</baseType>
</pointer>
</baseType>
</pointer>
</returnType>
<inputVars>
<variable name="iid">
<type>
<DWORD />
</type>
<documentation>
<xhtml xmlns="http://www.w3.org/1999/xhtml"> InterfaceID </xhtml>
</documentation>
</variable>
<variable name="pResult">
<type>
<pointer>
<baseType>
<UDINT />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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
</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvGetModuleDiagnosis">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvIdentify">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IoDrvIdentify_Count := IoDrvIdentify_Count + 1;
IoDrvIdentify := Errors.ERR_NOTIMPLEMENTED;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvReadInputs">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnectorMapList">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnectorMap" />
</baseType>
</pointer>
</type>
</variable>
<variable name="nCount">
<type>
<DINT />
</type>
</variable>
</inputVars>
<localVars>
<variable name="i">
<type>
<DINT />
</type>
</variable>
<variable name="j">
<type>
<DINT />
</type>
</variable>
<variable name="wSize">
<type>
<WORD />
</type>
</variable>
<variable name="pbyIecAddress">
<type>
<pointer>
<baseType>
<BYTE />
</baseType>
</pointer>
</type>
</variable>
<variable name="bySrcValue">
<type>
<BYTE />
</type>
</variable>
<variable name="bySrcMask">
<type>
<BYTE />
</type>
</variable>
<variable name="wSrcIndex">
<type>
<WORD />
</type>
</variable>
<variable name="wDestIndex">
<type>
<WORD />
</type>
</variable>
<variable name="pdw">
<type>
<pointer>
<baseType>
<DWORD />
</baseType>
</pointer>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvScanModules">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
<variable name="ppConnectorList">
<type>
<pointer>
<baseType>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</baseType>
</pointer>
</type>
</variable>
<variable name="pnCount">
<type>
<pointer>
<baseType>
<DINT />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IoDrvScanModules_Count := IoDrvScanModules_Count + 1;
IoDrvScanModules := Errors.ERR_NOTIMPLEMENTED;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvStartBusCycle">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvUpdateConfiguration">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnectorList">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
<variable name="nCount">
<type>
<DINT />
</type>
</variable>
</inputVars>
<localVars>
<variable name="pParameter">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pChild">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pstConnectorVendorName">
<type>
<pointer>
<baseType>
<string />
</baseType>
</pointer>
</type>
</variable>
<variable name="pstConnectorDeviceName">
<type>
<pointer>
<baseType>
<string />
</baseType>
</pointer>
</type>
</variable>
<variable name="Result">
<type>
<derived name="RTS_IEC_RESULT" />
</type>
</variable>
<variable name="i">
<type>
<INT />
</type>
</variable>
<variable name="bySetting">
<type>
<BYTE />
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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 <> 0) THEN
bySetting := IoMgrConfigGetParameterValueByte(pParameter, ADR(Result));
IF bySetting >= 0 AND bySetting <= 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 <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2000); (* outputs *)
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := 0; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2100); (* outputs *)
IF (pParameter <> 0) THEN
pParameter^.dwDriverSpecific := 10; (* Device offset 0 *)
END_IF
pParameter := IoMgrConfigGetParameter(m_pConnector, 2101); (* outputs *)
IF (pParameter <> 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 <> 0) DO
IF (pChild^.dwFlags AND ConnectorFlags.CF_ENABLE) <> 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</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvUpdateMapping">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pTaskMapList">
<type>
<pointer>
<baseType>
<derived name="IoConfigTaskMap" />
</baseType>
</pointer>
</type>
</variable>
<variable name="nCount">
<type>
<DINT />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IoDrvUpdateMapping_Count := IoDrvUpdateMapping_Count + 1;
IF (pTaskMapList = 0) THEN
IoDrvUpdateMapping := Errors.ERR_PARAMETER;
RETURN;
END_IF
IoDrvUpdateMapping := Errors.ERR_OK;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvWatchdogTrigger">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IoDrvWatchdogTrigger_Count := IoDrvWatchdogTrigger_Count + 1;
IoDrvWatchdogTrigger := Errors.ERR_OK;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvWriteOutputs">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnectorMapList">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnectorMap" />
</baseType>
</pointer>
</type>
</variable>
<variable name="nCount">
<type>
<DINT />
</type>
</variable>
</inputVars>
<localVars>
<variable name="i">
<type>
<DINT />
</type>
</variable>
<variable name="j">
<type>
<DINT />
</type>
</variable>
<variable name="k">
<type>
<UINT />
</type>
</variable>
<variable name="wSize">
<type>
<WORD />
</type>
</variable>
<variable name="pbyIecAddress">
<type>
<pointer>
<baseType>
<BYTE />
</baseType>
</pointer>
</type>
</variable>
<variable name="bySrcValue">
<type>
<BYTE />
</type>
</variable>
<variable name="wSrcIndex">
<type>
<WORD />
</type>
</variable>
<variable name="bySrcMask">
<type>
<BYTE />
</type>
</variable>
<variable name="wDestIndex">
<type>
<WORD />
</type>
</variable>
<variable name="pdw">
<type>
<pointer>
<baseType>
<DWORD />
</baseType>
</pointer>
</type>
</variable>
<variable name="pw">
<type>
<pointer>
<baseType>
<WORD />
</baseType>
</pointer>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IoDrvWriteOutputs_Count := IoDrvWriteOutputs_Count + 1;
IoDrvWriteOutputs := Errors.ERR_OK;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvGetConnector">
<interface>
<returnType>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</returnType>
<inputVars>
<variable name="pResult">
<type>
<pointer>
<baseType>
<derived name="RTS_IEC_RESULT" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF m_pConnector = 0 THEN
IF pResult <> 0 THEN
pResult^ := Errors.ERR_FAILED;
END_IF
IoDrvGetConnector := 0;
RETURN;
END_IF
IF pResult <> 0 THEN
pResult^ := Errors.ERR_OK;
END_IF
IoDrvGetConnector := m_pConnector;
</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvReadParameter">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pParameter">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pData">
<type>
<pointer>
<baseType>
<BYTE />
</baseType>
</pointer>
</type>
</variable>
<variable name="dwBitSize">
<type>
<DWORD />
</type>
</variable>
<variable name="dwBitOffset">
<type>
<DWORD />
</type>
</variable>
</inputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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;
</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="IoDrvWriteParameter">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pParameter">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pData">
<type>
<pointer>
<baseType>
<BYTE />
</baseType>
</pointer>
</type>
</variable>
<variable name="dwBitSize">
<type>
<DWORD />
</type>
</variable>
<variable name="dwBitOffset">
<type>
<DWORD />
</type>
</variable>
</inputVars>
<localVars>
<variable name="pParam">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="pstDiagString">
<type>
<pointer>
<baseType>
<string />
</baseType>
</pointer>
</type>
</variable>
</localVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/attributes" handleUnknown="implementation">
<Attributes>
<Attribute Name="conditionalshow" Value="" />
</Attributes>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">IF pConnector = 0 OR pParameter = 0 OR pData = 0 THEN
IoDrvWriteParameter := Errors.ERR_PARAMETER;
RETURN;
END_IF
IoDrvWriteParameter := Errors.ERR_FAILED;</xhtml>
</ST>
</body>
<BuildProperties>
<EnableSystemCall>true</EnableSystemCall>
</BuildProperties>
<addData />
</Method>
</data>
</addData>
</pou>
<pou name="MCP3008" pouType="functionBlock">
<interface>
<outputVars>
<variable name="auiValue">
<type>
<array>
<dimension lower="0" upper="7" />
<baseType>
<UINT />
</baseType>
</array>
</type>
</variable>
</outputVars>
<addData>
<data name="http://www.3s-software.com/plcopenxml/pouinheritance" handleUnknown="implementation">
<Inheritance>
<Extends>spi</Extends>
</Inheritance>
</data>
</addData>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^();
CASE _iState OF
0:
IF SUPER^.init() THEN
_iState := 1;
END_IF
1:
_iState := 10;
END_CASE
</xhtml>
</ST>
</body>
<addData>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="AfterReadInputs">
<interface>
<returnType>
<INT />
</returnType>
<localVars>
<variable name="aby">
<type>
<array>
<dimension lower="0" upper="2" />
<baseType>
<BYTE />
</baseType>
</array>
</type>
</variable>
<variable name="usiChannel">
<type>
<USINT />
</type>
</variable>
<variable name="ui">
<type>
<UINT />
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">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
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="BeforeWriteOutputs">
<interface>
<returnType>
<INT />
</returnType>
<localVars>
<variable name="i">
<type>
<USINT />
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.BeforeWriteOutputs();
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
<data name="http://www.3s-software.com/plcopenxml/method" handleUnknown="implementation">
<Method name="Initialize">
<interface>
<returnType>
<UDINT />
</returnType>
<inputVars>
<variable name="wModuleType">
<type>
<UINT />
</type>
</variable>
<variable name="dwInstance">
<type>
<UDINT />
</type>
</variable>
<variable name="pConnector">
<type>
<pointer>
<baseType>
<derived name="IoConfigConnector" />
</baseType>
</pointer>
</type>
</variable>
</inputVars>
<localVars>
<variable name="pParam">
<type>
<pointer>
<baseType>
<derived name="IoConfigParameter" />
</baseType>
</pointer>
</type>
</variable>
<variable name="udiResult">
<type>
<UDINT />
</type>
</variable>
</localVars>
</interface>
<body>
<ST>
<xhtml xmlns="http://www.w3.org/1999/xhtml">SUPER^.Initialize(wModuleType, dwInstance, pConnector);
(*
pParam := ConfigGetParameter(_pConnector, 1);
IF pParam <> 0 THEN
_byHardwareAddress := IoStandard.ConfigGetParameterValueByte(pParam, ADR(udiResult));
END_IF*)
</xhtml>
</ST>
</body>
<addData />
</Method>
</data>
</addData>
</pou>
</pous>
</types>
<instances>
<configurations />
</instances>
<addData>
<data name="http://www.3s-software.com/plcopenxml/libraries" handleUnknown="implementation">
<Libraries>
<Library Name="#CAA Types" Namespace="CAA" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="CAA Types Extern, * (CAA Technical Workgroup)" />
<Library Name="#Standard" Namespace="Standard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Standard, * (System)" />
<Library Name="#IoStandard" Namespace="IoStandard" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="IoStandard, * (System)" />
<Library Name="#IoDrvBase" Namespace="IoDrvBase" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="IoDrvBase, * (System)" />
<Library Name="IoDriver Parameter Interfaces, * (System)" Namespace="IIoDrvParameter" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<Library Name="IoDriver Interfaces, * (System)" Namespace="IIoDrv" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<Library Name="CmpErrors2 Interfaces, * (System)" Namespace="CmpErrors" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<Library Name="#Raspberry Pi Peripherals" Namespace="RasPi" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" DefaultResolution="Raspberry Pi Peripherals, * (3S - Smart Software Solutions GmbH)" />
<Library Name="SysTypes2 Interfaces, * (System)" Namespace="SysTypes" HideWhenReferencedAsDependency="false" PublishSymbolsInContainer="false" SystemLibrary="false" LinkAllContent="false" />
<addData />
</Libraries>
</data>
</addData>
</project>
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/Libraries/SenseHat.library.md
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8"?>enumenumenum---
This Function Block is instanciated along with the Sense Hat device of the raspberry PI.
It's inputs and outputs allow to easily access the sensors, inputs and LED outputs of the
Sense Hat Device.
~~~ST
FUNCTION_BLOCK SenseHat EXTENDS i2c
VAR_INPUT
adwPixel: ARRAY [..] OF ;
xUpdatePixel: BOOL;
xUpdateJoystick: BOOL;
xUpdateLSM9DS1: BOOL;
xUpdateHTS221: BOOL;
xUpdateLPS25H: BOOL;
END_VAR
VAR_OUTPUT
xJoystickUp: BOOL;
xJoystickDown: BOOL;
xJoystickLeft: BOOL;
xJoystickRight: BOOL;
xJoystickEnter: BOOL;
rTemperatureHTS221: REAL;
rHumidity: REAL;
rTemperatureLPS25H: REAL;
lrPressure: LREAL;
rGyroX: REAL;
rGyroY: REAL;
rGyroZ: REAL;
rAccelX: REAL;
rAccelY: REAL;
rAccelZ: REAL;
rCompX: REAL;
rCompY: REAL;
rCompZ: REAL;
END_VAR
VAR
_sFilePixel: string;
_sFileJoy: string;
_sName: string;
_hJoystickFile: RTS_IEC_HANDLE;
_Joystick: JoystickInput;
_awWordPixel: ARRAY [..] OF ;
_Timer100: TON;
_rTemperature_S: REAL;
_rTemperature_C: REAL;
_rHumidity_S: REAL;
_rHumidity_C: REAL;
_usiMagAddress: USINT;
_rGyroScale: REAL;
_rAccelScale: REAL;
_rMagScale: REAL;
END_VAR
VAR_TEMP
_i: INT;
_hFile: RTS_IEC_HANDLE;
_diResult: DINT;
_xResult: BOOL;
_abyData: ARRAY [..] OF ;
_uiT0_C_8: UINT;
_uiT1_C_8: UINT;
_byH0_H_2: BYTE;
_byH1_H_2: BYTE;
_iT0_OUT: INT;
_iT1_OUT: INT;
_iH0_T0_OUT: INT;
_iH1_T0_OUT: INT;
_rT0: REAL;
_rT1: REAL;
_rH0: REAL;
_rH1: REAL;
END_VAR
~~~
~~~ST
SUPER^();
CASE _iState OF
0:
//Pixel map
_sName := '';
{analysis -26}
FOR _i := 0 TO 10 DO
_sFilePixel := CONCAT('/sys/class/graphics/fb', INT_TO_STRING(_i));
_sFilePixel := CONCAT(_sFilePixel, '/name');
{analysis -130}
_hFile := CmpCharDevice.CDOpen(_sFilePixel, CmpCharDevice.ACCESS_MODE.O_RDONLY, ADR(_diResult));
{analysis +130}
IF NOT(_hFile = RTS_INVALID_HANDLE) THEN
{analysis -19}
_diResult := CmpCharDevice.CDRead(_hFile, ADR(_sName), 12, ADR(_diResult));
{analysis +19}
_diResult := CmpCharDevice.CDClose(_hFile, ADR(_diResult));
IF _sName = 'RPi-Sense FB' THEN
_sFilePixel := CONCAT('/dev/fb', INT_TO_STRING(_i));
EXIT;
END_IF
END_IF
END_FOR
{analysis +26}
_iState := 10;
10:
//Joystick Input
_sName := '';
{analysis -26}
FOR _i := 0 TO 10 DO
_sFileJoy := CONCAT('/sys/class/input/event', INT_TO_STRING(_i));
_sFileJoy := CONCAT(_sFileJoy, '/device/name');
{analysis -130}
_hFile := CmpCharDevice.CDOpen(_sFileJoy, CmpCharDevice.ACCESS_MODE.O_RDONLY, ADR(_diResult));
{analysis +130}
IF NOT(_hFile = RTS_INVALID_HANDLE) THEN
{analysis -19}
_diResult := CmpCharDevice.CDRead(_hFile, ADR(_sName), 31, ADR(_diResult));
{analysis +19}
_diResult := CmpCharDevice.CDClose(_hFile, ADR(_diResult));
IF _sName = 'Raspberry Pi Sense HAT Joystick' THEN
_sFileJoy := CONCAT('/dev/input/event', INT_TO_STRING(_i));
EXIT;
END_IF
END_IF
END_FOR
{analysis +26}
_iState := 20;
20:
//Humidity and Temperature HTS221
usiAddress := 16#5F;
//Power up and set sample rate
_xResult := write8(16#20, 2#10000110);
//Pressure and Temperature LPS25H
usiAddress := 16#5C;
//Reset
_xResult := write8(16#20, 2#10100100);
//Gyro- and Accelereometer LSM9DS1
usiAddress := 16#6A;
//Reset
_xResult := write8(16#22, 2#11000000);
_iState := 25;
25:
//Short waiting for the actions done in state 40 to
//be done by the sense hat
_Timer100(IN:=TRUE);
IF _Timer100.Q THEN
_Timer100(IN:=FALSE);
_iState := 30;
END_IF
30:
//Humidity- and Temperature HTS221
usiAddress := 16#5F;
//Configure Averaging
_xResult := write8(16#10, 2#000101011);
// Get calibration data
// Temperature Calibration
{analysis -52}
IF ReadRegister(16#35, ADR(_abyData[1]), 1) = 1 THEN // + 16#80 ?
IF ReadRegister(16#32, ADR(_abyData), 1) = 1 THEN
_uiT0_C_8 := SHL(BYTE_TO_UINT(_abyData[1] AND 16#3), 8) OR BYTE_TO_UINT(_abyData[0]);
_rT0 := UINT_TO_REAL(_uiT0_C_8) / 8;
END_IF
END_IF
IF ReadRegister(16#33, ADR(_abyData), 1) = 1 THEN
_uiT1_C_8 := SHL(BYTE_TO_UINT(_abyData[1] AND 16#C), 6) OR BYTE_TO_UINT(_abyData[0]);
_rT1 := UINT_TO_REAL(_uiT1_C_8) / 8;
END_IF
IF ReadRegister(16#3C, ADR(_abyData[0]), 1) = 1 AND ReadRegister(16#3D, ADR(_abyData[1]), 1) = 1 THEN
_iT0_OUT := UINT_TO_INT(SHL(BYTE_TO_UINT(_abyData[1]), 8) OR BYTE_TO_UINT(_abyData[0]));
END_IF
IF ReadRegister(16#3E, ADR(_abyData[0]), 1) = 1 AND ReadRegister(16#3F, ADR(_abyData[1]), 1) = 1 THEN
_iT1_OUT := UINT_TO_INT(SHL(BYTE_TO_UINT(_abyData[1]), 8) OR BYTE_TO_UINT(_abyData[0]));
END_IF
// Humidity Calibration
IF ReadRegister(16#30, ADR(_byH0_H_2), 1) = 1 THEN
_rH0 := BYTE_TO_REAL(_byH0_H_2) / 2;
END_IF
IF ReadRegister(16#31, ADR(_byH1_H_2), 1) = 1 THEN
_rH1 := BYTE_TO_REAL(_byH1_H_2) / 2;
END_IF
IF ReadRegister(16#36, ADR(_abyData[0]), 1) = 1 AND ReadRegister(16#37, ADR(_abyData[1]), 1) = 1 THEN
_iH0_T0_OUT := UINT_TO_INT(SHL(BYTE_TO_UINT(_abyData[1]), 8) OR BYTE_TO_UINT(_abyData[0]));
END_IF
IF ReadRegister(16#3A, ADR(_abyData[0]), 1) = 1 AND ReadRegister(16#3B, ADR(_abyData[1]), 1) = 1 THEN
_iH1_T0_OUT := UINT_TO_INT(SHL(BYTE_TO_UINT(_abyData[1]), 8) OR BYTE_TO_UINT(_abyData[0]));
END_IF
{analysis +52}
{analysis -66}
{analysis -40}
IF _iT1_OUT-_iT0_OUT <> 0 THEN
_rTemperature_S := (_rT1-_rT0)/INT_TO_REAL(_iT1_OUT-_iT0_OUT);
END_IF
_rTemperature_C := _rT0-(_rTemperature_S*INT_TO_REAL(_iT0_OUT));
IF _iH1_T0_OUT-_iH0_T0_OUT <> 0 THEN
_rHumidity_S := (_rH1-_rH0)/INT_TO_REAL(_iH1_T0_OUT-_iH0_T0_OUT);
END_IF
_rHumidity_C := (_rH0)-(_rHumidity_S*INT_TO_REAL(_iH0_T0_OUT));
{analysis +40}
{analysis +66}
_iState := 40;
40:
//Pressure and Temperature LPS25H
usiAddress := 16#5C;
//Configure Averaging
_xResult := write8(16#10, 2#00001010);
//Configure FIFO
_xResult := write8(16#2E, 2#00000000);
//Set FIFO mode
_xResult := write8(16#21, 2#01000000);
_iState := 45;
45:
//Short waiting for the actions done in state 40 to
//be done by the sense hat
_Timer100(IN:=TRUE);
IF _Timer100.Q THEN
_Timer100(IN:=FALSE);
_iState := 50;
END_IF
50:
//Magnetsensor LSM9DS1
//Find out Mag-Address
usiAddress := 16#1C;
IF ReadRegister(16#0F, ADR(_abyData[0]), 1) = 1 AND _abyData[0] = 16#3D THEN
_usiMagAddress := usiAddress;
ELSE
usiAddress := 16#1D;
IF ReadRegister(16#0F, ADR(_abyData[0]), 1) = 1 AND _abyData[0] = 16#3D THEN
_usiMagAddress := usiAddress;
ELSE
usiAddress := 16#1E;
IF ReadRegister(16#0F, ADR(_abyData[0]), 1) = 1 AND _abyData[0] = 16#3D THEN
_usiMagAddress := usiAddress;
ELSE
usiAddress := 16#1F;
IF ReadRegister(16#0F, ADR(_abyData[0]), 1) = 1 AND _abyData[0] = 16#3D THEN
_usiMagAddress := usiAddress;
END_IF
END_IF
END_IF
END_IF
//Gyro LSM9DS1
usiAddress := 16#6A;
//Gyro set bandwidth and rate and scale
//500dps --> Scale 0.07
_xResult := write8(16#10, 2#01001011);
_rGyroScale := 0.0175;
//Gyro activate HP filter
_xResult := write8(16#12, 2#01000100);
//Accel LSM9DS1
usiAddress := 16#6A;
//Accel set bandwidth and rate and scale
_xResult := write8(16#20, 2#01110000);
_rAccelScale := 0.000122;
//Accel set no filters
_xResult := write8(16#21, 2#00000000);
//Mag LSM9DS1
usiAddress := _usiMagAddress;
//Mag set sample rate
_xResult := write8(16#20, 2#00010000);
//Mag set scale
_xResult := write8(16#21, 2#01000000);
_rMagScale := 0.029;
//Mag set continuous conversion mode
_xResult := write8(16#22, 2#00000000);
_iState := 100;
ELSE
_iState := 100;
END_CASE
~~~
---
~~~ST
METHOD Fb_Exit: BOOL
VAR_INPUT
bInCopyCode: BOOL;
END_VAR
VAR
diResult: DINT;
diFunRes: DINT;
END_VAR
~~~
~~~ST
IF NOT(_hJoystickFile = RTS_INVALID_HANDLE) THEN
diFunRes := CmpCharDevice.CDClose(_hJoystickFile, ADR(diResult));
_hJoystickFile := RTS_INVALID_HANDLE;
END_IF
~~~
---
~~~ST
METHOD AfterReadInputs: INT
VAR
diResult: DINT;
diFunRes: DINT;
byStatus: BYTE;
abyData: ARRAY [..] OF ;
iData: INT;
diData: DINT;
pbyE: pointer;
xSet: BOOL;
END_VAR
~~~
~~~ST
AfterReadInputs := SUPER^.AfterReadInputs();
IF _iState = 100 THEN
//Joystick Readout
IF xUpdateJoystick THEN
IF _hJoystickFile = RTS_INVALID_HANDLE THEN
{analysis -58}
{analysis -130}
_hJoystickFile := CmpCharDevice.CDOpen(_sFileJoy, CmpCharDevice.ACCESS_MODE.O_RDONLY + DINT#4000 (* CmpCharDevice.ACCESS_MODE.O_NONBLOCK*), ADR(diResult));
{analysis +130}
{analysis +58}
END_IF
(* Ioctl was used, when "Blocking-Read-Out" was done:
--> EVIOCGKEY(len) for testing if joystick data is available; we need to call Ioctl with an ADR operator
so disable the corresponding compiler warning
{warning disable C0033}
CmpCharDevice.CDIoctl(hFile, UDINT_TO_DINT(RASPI._IOC(2, pbyE^, 16#18, SIZEOF(ariData))), ADR(ariData), ADR(udiResult));
{warning restore C0033}
IF udiResult = 0 AND ariData[1] + ariData[6] > 0 THEN ... *)
IF NOT(_hJoystickFile = RTS_INVALID_HANDLE) THEN
diResult := 0;
WHILE diResult = 0 DO
{analysis -19}
diFunRes := CmpCharDevice.CDRead(_hJoystickFile, ADR(_Joystick), SIZEOF(_Joystick), ADR(diResult));
{analysis +19}
IF diResult <> 0 THEN //no data to read
EXIT;
END_IF
IF _Joystick.eEvent = JoystickEvent.EV_KEY THEN
xSet := FALSE;
IF _Joystick.eState = JoystickState.STATE_PRESS THEN
xSet := TRUE;
ELSIF _Joystick.eState = JoystickState.STATE_RELEASE THEN
xSet := FALSE;
ELSE
CONTINUE;
END_IF
///Set booleans
{analysis -75}
{analysis -76}
CASE _Joystick.eKey OF
JoystickKey.KEY_UP:
xJoystickUp := xSet;
JoystickKey.KEY_DOWN:
xJoystickDown := xSet;
JoystickKey.KEY_LEFT:
xJoystickLeft := xSet;
JoystickKey.KEY_RIGHT:
xJoystickRight:= xSet;
JoystickKey.KEY_ENTER:
xJoystickEnter := xSet;
END_CASE
{analysis +76}
{analysis +75}
END_IF
END_WHILE
END_IF
ELSE
IF NOT(_hJoystickFile = RTS_INVALID_HANDLE) THEN
diFunRes := CmpCharDevice.CDClose(_hJoystickFile, ADR(diResult));
_hJoystickFile := RTS_INVALID_HANDLE;
END_IF
END_IF
//Gyro, Accelerometer and Magnetometer LSM9DS1
IF xUpdateLSM9DS1 THEN
//Gyro and Accelerometer
{analysis -52}
usiAddress := 16#6A;
IF ReadRegister(16#17, ADR(byStatus), 1) = 1 THEN
IF (byStatus AND 2) > 0 THEN
//Gyro data available
IF ReadRegister(16#18, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#19, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rGyroX := INT_TO_REAL(iData) * _rGyroScale;
END_IF
IF ReadRegister(16#1A, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#1B, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rGyroY := INT_TO_REAL(iData) * _rGyroScale;
END_IF
IF ReadRegister(16#1C, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#1D, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rGyroZ := INT_TO_REAL(iData) * _rGyroScale;
END_IF
END_IF
IF (byStatus AND 1) > 0 THEN
//Accel data available
IF ReadRegister(16#28, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#29, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rAccelX := INT_TO_REAL(iData) * _rAccelScale;
END_IF
IF ReadRegister(16#2A, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#2B, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rAccelY := INT_TO_REAL(iData) * _rAccelScale;
END_IF
IF ReadRegister(16#2C, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#2D, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rAccelZ := INT_TO_REAL(iData) * _rAccelScale;
END_IF
END_IF
END_IF
//Magnetometer
usiAddress := _usiMagAddress;
IF ReadRegister(16#27, ADR(byStatus), 1) = 1 THEN
IF (byStatus AND 1) > 0 THEN
IF ReadRegister(16#28, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#29, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rCompX := INT_TO_REAL(iData) * _rMagScale;
END_IF
END_IF
IF (byStatus AND 2) > 0 THEN
IF ReadRegister(16#2A, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#2B, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rCompY := INT_TO_REAL(iData) * _rMagScale;
END_IF
END_IF
IF (byStatus AND 4) > 0 THEN
IF ReadRegister(16#2C, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#2D, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rCompZ := INT_TO_REAL(iData) * _rMagScale;
END_IF
END_IF
END_IF
{analysis +52}
END_IF
//Pressure and Temperature LPS25h
IF xUpdateLPS25H THEN
{analysis -52}
usiAddress := 16#5C;
IF ReadRegister(16#27, ADR(byStatus), 1) = 1 THEN
IF (byStatus AND 2) > 0 THEN
IF ReadRegister(16#28, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#29, ADR(abyData[1]), 1) = 1 AND ReadRegister(16#2A, ADR(abyData[2]), 1) = 1 THEN
diData := UDINT_TO_DINT(SHL(BYTE_TO_UDINT(abyData[2]), 16) OR SHL(BYTE_TO_UDINT(abyData[1]), 8) OR BYTE_TO_UDINT(abyData[0]));
lrPressure := DINT_TO_LREAL(diData) / 4096;
END_IF
END_IF
IF (byStatus AND 1) > 0 THEN
IF ReadRegister(16#2B, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#2C, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rTemperatureLPS25H := INT_TO_REAL(iData) / 480 + 42.5;
END_IF
END_IF
END_IF
{analysis +52}
END_IF
//Humidity and Temperature HTS221
IF xUpdateHTS221 THEN
usiAddress := 16#5F;
{analysis -52}
IF ReadRegister(16#27, ADR(byStatus), 1) = 1 THEN
IF (byStatus AND 2) > 0 THEN
IF ReadRegister(16#28, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#29, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rHumidity := INT_TO_REAL(iData) * _rHumidity_S + _rHumidity_C;
END_IF
END_IF
IF (byStatus AND 1) > 0 THEN
IF ReadRegister(16#2A, ADR(abyData[0]), 1) = 1 AND ReadRegister(16#2B, ADR(abyData[1]), 1) = 1 THEN
iData := UINT_TO_INT(SHL(BYTE_TO_UINT(abyData[1]), 8) OR BYTE_TO_UINT(abyData[0]));
rTemperatureHTS221 := INT_TO_REAL(iData) * _rTemperature_S + _rTemperature_C;
END_IF
END_IF
END_IF
{analysis +52}
END_IF
END_IF
~~~
---
~~~ST
METHOD BeforeWriteOutputs: INT
VAR
i: INT;
hFile: RTS_IEC_HANDLE;
diResult: DINT;
diFunRes: DINT;
END_VAR
~~~
~~~ST
BeforeWriteOutputs := SUPER^.BeforeWriteOutputs();
IF _iState = 100 THEN
//Pixel
IF xUpdatePixel THEN
//Convert 32Bit ARGB value to 16Bit RGB565
{analysis -52}
FOR i := 0 TO 63 DO
_awWordPixel[i] := UDINT_TO_WORD(SHL(SHR(adwPixel[i] AND 16#00FF0000, 16 + 3) AND 16#1F, 11) + //R
SHL(SHR(adwPixel[i] AND 16#0000FF00, 8 + 2) AND 16#3F, 5) + //G
(SHR(adwPixel[i] AND 16#000000FF, 3) AND 16#1F)); //B
END_FOR
{analysis +52}
{analysis -130}
hFile := CmpCharDevice.CDOpen(_sFilePixel, CmpCharDevice.ACCESS_MODE.O_WRONLY, ADR(diResult));
{analysis +130}
IF NOT(hFile = RTS_INVALID_HANDLE) THEN
{analysis -19}
diFunRes := CmpCharDevice.CDWrite(hFile, ADR(_awWordPixel), 128, ADR(diResult));
{analysis +19}
diFunRes := CmpCharDevice.CDClose(hFile, ADR(diResult));
END_IF
END_IF
END_IF
~~~
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/license.txt
Bash
bash
(Bash)
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
This project makes use of the following 3rd party nuget packages:
This list was generated with this command:
PM > Get-Package | Select-Object Id,LicenseUrl
Id LicenseUrl
-- ----------
DynamicLanguageRuntime https://github.com/IronLanguages/dlr/blob/master/LICENSE
IronPython https://github.com/IronLanguages/ironpython2/blob/master/LICENSE
Currently all used packages are using Apache 2.0 license.
Last updated: 2018-07-16
rpi-legacy: ./trunk/legacy/package.manifest
Bash
bash
(Bash)
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Package>
<Strings>
<String Id="GeneralName">
<Neutral>Raspberry Pi Legacy</Neutral>
</String>
<String Id="GeneralCopyright">
<Neutral>Copyright (c) 2016-2018 by 3S-Smart Software Solutions GmbH. All rights reserved.</Neutral>
</String>
<String Id="GeneralDescription">
<Neutral>This package contains the plugin, Libraries, Devices and so on for CODESYS Control for Raspberry PI.</Neutral>
<Localized Culture="de">Dieses Installationspaket umfasst das PlugIn, Bibliotheken, Gerätebeschreibungen usw. CODESYS Control for Raspberry PI.</Localized>
</String>
<String Id="license">
<Neutral>license.txt</Neutral>
</String>
</Strings>
<General>
<Id>72f7cc9b-cd6c-408c-8203-90f84602a514</Id>
<Version>1.0.0.1</Version>
<Name>$GeneralName</Name>
<Vendor>3S-Smart Software Solutions GmbH</Vendor>
<Copyright>$GeneralCopyright</Copyright>
<Description>$GeneralDescription</Description>
<LicenseAgreement>$license</LicenseAgreement>
<RequiredInstallerVersion>3.5.6.0</RequiredInstallerVersion>
</General>
<Components>
<Component>
<General>
<Id>0</Id>
<Name>Raspberry Pi Legacy</Name>
<Description>Raspberry Pi Legacy</Description>
<Selectable>False</Selectable>
<SelectedByDefault>True</SelectedByDefault>
</General>
<Items>
<DeviceDescription>
<Path>Devices/AdafruitPWM SoftMotion.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/AdafruitPWM.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/AK8975.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/CODESYS Control for Raspberry Pi SL.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/GPIOs.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/MCP3008.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/MPU6050.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/MPU9150.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/PiCamera.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/PiFace.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/PiFaceIOdrv.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/SM3_Drive_Servo.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/SRF02.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/DS18B20.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/GPIOsBplus.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/I2CMaster.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/SPIMaster.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/OneWireMaster.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/PiFaceControlDisplay.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/MCP23S17.devdesc.xml</Path>
</DeviceDescription>
<DeviceDescription>
<Path>Devices/SenseHat.devdesc.xml</Path>
</DeviceDescription>
<Library>
<Path>Libraries/I2C_Gyroscopes.library</Path>
</Library>
<Library>
<Path>Libraries/I2C_SRF02.library</Path>
</Library>
<Library>
<Path>Libraries/IoDrvPiFace.library</Path>
</Library>
<Library>
<Path>Libraries/SM3_Drive_Servo.library</Path>
</Library>
<Library>
<Path>Libraries/SPI_MCP3008.library</Path>
</Library>
<Library>
<Path>Libraries/SPI_PiFace.library</Path>
</Library>
<Library>
<Path>Libraries/I2C_AdafruitPWM.library</Path>
</Library>
<Library>
<Path>Libraries/IoDrvGPIO.library</Path>
</Library>
<Library>
<Path>Libraries/OneWire_DS18B20.library</Path>
</Library>
<Library>
<Path>Libraries/SPI_PiFaceCaD.library</Path>
</Library>
<Library>
<Path>Libraries/SPI_MCP23S17.library</Path>
</Library>
<Library>
<Path>Libraries/SenseHat.library</Path>
</Library>
</Items>
</Component>
</Components>
</Package>
Last updated: 2018-07-16
code Discussion
Wharfie
code
(Discussion)
Forum for code comments
Last updated: 2018-02-14
wiki Discussion
Wharfie
wiki
(Discussion)
Forum for wiki comments
Last updated: 2018-02-14
tickets Discussion
Wharfie
tickets
(Discussion)
Forum for tickets comments
Last updated: 2018-02-24
Wharfie SVN repository
Wharfie
code
(SVN Repository)
Last updated: 2020-08-04
Home
Wharfie
wiki
(WikiPage)
Download debian package codesuccessful Build Embedded Linux Automate Building of Image Role out up-to-date images Get Cross-Toolchains Legal concerns Install Debian Other distributions Documentation Commands Tutorials Quickstart CODESYS Raspberry Pi Build Embedded Linux Wharfie is a modern build system for embedded devices. The concept is very similar to "docker". Both, "docker" and "wharfie", are using a simple format to describe custom linux system configurations and rebuild those easily. Wharfie uses basically the same syntax, while it is not fully compatible. While "docker" is focusing on scalable web services, "wharfie" is focusing on embedded linux systems. With "wharfie" you can easily build a root filesystem, based on the Debian distribution from scratch. To configure the system for your needs, you just write all necessary configuration steps into a configuration file. You don't do this configuration at the live system. Those configuration files are called Dockerfile in the docker eco-system. It's pendent in the world of wharfie is called Wharfile. Automate Building of Image When you install linux on an embedded target, it is very common, that you are first faced with a preconfigured system, which you have to configure manually. Doing this multiple times can become really anoying. Wharfie helps you in this process, as it can repeat all the configuration steps for you. ... # Set the locale RUN locale-gen en_US.UTF-8 RUN git clone https://github.com/pyload/pyload.git /opt/pyload \ && cd /opt/pyload \ && git checkout stable \ && echo "/opt/pyload/pyload-config" > /opt/pyload/module/config/configdir ADD pyload-config/ /opt/pyload/pyload-config ADD ../common/files/pyload.service /etc/systemd/system/pyload.service ... Role out up-to-date images Because the building process can be highly automated, you can easily just rebuild the images on a regular basis, and keep the images which you role out to new targets always up-to-date. # rebuild $ wharfie --clean $ wharfie Get Cross-Toolchains Wharfie supports armhf, armel, i386 and amd64 from debian. At least for ARM it is always difficult to get cross-toolchains, which can be easily archived and reused on different hosts. But also for x86 it makes fully sense to archive a cross toolchain for the systems, which you are roling out somewhere. Otherwise it can become difficult to rebuild programs for your systems in a few years. FROM debian_armhf_stretch TOOLCHAIN toolchain_debian_armhf_stretch.tar Legal concerns When using the linux OS for embeddded systems, a lot of legal issues have to be respected. Wharfie contains two additional commands to face these issues: LICENSE <filename></filename> SOURCE <filename></filename> These commands are creating tarballs, containing all the source packages, or all the licenses of your system, which were installed through debian packages. This feature makes it very easy to prepare yourself for distributing such an image. You will need to be able to provide such packages when you plan to distribute the image as part of a product, as well as when you share it with others in form of a download on the internet. When you publish anything, which contains code that was released under a third party license, you are usually forced to provide at least a list of all those licenses, containing the license text. Install Debian Click on the download link at the top of the package. Install the package on the terminal, using dpkg: sudo dpkg -i wharfie.deb Other distributions Use SVN to checkout the repository: svn checkout https://forge.codesys.com/svn/tol,wharfie,code/trunk wharfie-code Enter the directory and install the files under /usr/local/ cd wharfie ./install.sh
Last updated: 2020-02-07
Quickstart Tutorial
Wharfie
wiki
(WikiPage)
Step 1: Debian Base System Step 2: Bootable debian with systemd Step 3: Username and password Step 4: Wireless network Step 5: Make a bootable image Final: The resulting file [[include IndexMain (already included)] This tutorial guides you on a basic setup of a debian based root filesystem. Without knowing anything about "wharfie", we can define what we want: Bootable debian with systemd Our desired username and password Wireless network SSH access To make everything a bit more specific, we configure the system for the Raspberry Pi Zero W. Step 1: Debian Base System With the simple Statement "FROM", we can decide which debian version and which architecture we want to use. The exact syntax is: FROM debian_<architecture>_<version> When doing anything with the Raspberry Pi, you have to know which CPU version you have, as you will need to select the correct architecture. Don't think, that this is not necessary, as Raspbian can serve all variants with a single image. They can do this, as they selected a compromise between the two major architecture variants, which debian is using. But no worries, the rule is easy: Single Core: armel Multi Core: armhf As the Raspberry Pi Zero hosts a single core CPU, we are using "armel". FROM debian_armel_stretch TO rpi.tar Step 2: Bootable debian with systemd We are installing the following pakets: systemd-sysv: This paket installs systemd, as well as the compatibility wrapper generator for system V. It is actually still a good idea, as some pakets (like dhcpcd5) still uses system V init scripts. dhcpcd5: This will enable the configuration of the IP address, using DHCP. wpa_supplicant: This will enable us to connect to a WPA secured access point. openssh: This will enable SSH access to the device. We will install everything with the following two flags: -y to answer all questions during installation with "yes" *-no-install-recommends to install only fix dependencies and keep the system small RUN apt-get update && apt-get install -y -no-install-recommends systemd-sysv dhcpcd5 wpa_supplicant openssh Now we just need the following actions, to add a proper /etc/fstab file. ADD files/fstab /etc/fstab Step 3: Username and password It should be rather selfexplainatory. This concept is widely used in docker images to add specific users and change their passwords. RUN useradd -ms /bin/bash wharfie; echo "wharfie:wharfie" | chpasswd; echo "root:root" | chpasswd; Step 4: Wireless network To load the network driver and to start wpa_supplicant for connecting to our access point, we use the following actions. ADD files/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-wlan0.conf ADD files/wireless.conf /etc/modules-load.d/wireless.conf RUN sed -i 's,^Requires,#Requires,' /lib/systemd/system/wpa_supplicant@.service; \ systemctl enable wpa_supplicant@wlan0.service; We are starting wpa_supplicant for our interface wlan0. Dhcpcd is by default configured to assign IP addresses to every available network interface. So /etc/network/interfaces is not used at all. Step 5: Make a bootable image The result of the build would currently be a simple tar archive. To bring this root filesystem onto a bootable SD card image, containing a bootloader, a kernel, kernel modules and all necessary firmware files, we can use a script from the folder "examples/bootstrategy/raspberrypi.sh". This is downloading the most current raspian image and is exchanging the rootfilesystem. RUN HOST \ ../../bootstrategy/raspberrypi.sh rpi.img Note, that RUN HOST is executed from a subfolder of your current working directory, which contains the full root filesystem. Therefore a relative path needs to contain an additional "../". Final: The resulting file All the steps above, need to be written into a file named "Wharfile". You should create a new folder for your image, where you can place this file. The additional files which are needed can be placed where you like, but it's recommended to use a subfolder (e.g. "files/" or "root/") to collect all files which are added using the ADD command. Here is the listing of the file. You file find a slighly changed version of it in the "examples" folder of wharfie. FROM debian_armel_stretch TO rpi.tar RUN apt-get update && apt-get install -y -no-install-recommends systemd-sysv dhcpcd5 wpa_supplicant openssh ADD files/fstab /etc/fstab RUN useradd -ms /bin/bash wharfie; echo "wharfie:wharfie" | chpasswd; echo "root:root" | chpasswd; ADD files/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant-wlan0.conf ADD files/wireless.conf /etc/modules-load.d/wireless.conf RUN sed -i 's,^Requires,#Requires,' /lib/systemd/system/wpa_supplicant@.service; \ systemctl enable wpa_supplicant@wlan0.service; RUN HOST \ ../../bootstrategy/raspberrypi.sh rpi.img To build the image, just change into the newly created folder, containing the "Wharfile" and type the command "wharfie". You will be asked to enter your password, as some of the actions during build need root access. After the image is created, it can be used on the target. In case of the Raspberry Pi from this example, the file "rpi.img" can be written on an SD card using the tool "dd". Have fun!
Last updated: 2019-11-30