diff --git a/webserver/core/hardware_layers/sl_rp4.cpp b/webserver/core/hardware_layers/sl_rp4.cpp
new file mode 100644
index 0000000..7650667
--- /dev/null
+++ b/webserver/core/hardware_layers/sl_rp4.cpp
@@ -0,0 +1,181 @@
+//-----------------------------------------------------------------------------
+// Copyright 2015 Thiago Alves
+//
+// This file is part of the OpenPLC Runtime.
+//
+// OpenPLC is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// OpenPLC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with OpenPLC. If not, see .
+//------
+//
+// This file is the hardware layer for the OpenPLC. If you change the platform
+// where it is running, you may only need to change this file. All the I/O
+// related stuff is here. Basically it provides functions to read and write
+// to the OpenPLC internal buffers in order to update I/O state.
+// Thiago Alves, Dec 2015
+//-----------------------------------------------------------------------------
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "ladder.h"
+#include "custom_layer.h"
+
+
+#define I2C_DEVICE_PATH "/dev/i2c-1"
+#define I2C_ADDRESS 0x1C
+#define SWITCH_REG_1 0x03
+#define SWITCH_REG_2 0x02
+#define SWITCH_REG_3 0x00
+
+int i2cHandle = -1;
+
+int16_t initI2C()
+{
+ i2cHandle = open(I2C_DEVICE_PATH, O_RDWR);
+ if (i2cHandle < 0)
+ {
+ perror("Error opening I2C device");
+ return -1;
+ }
+
+ if (ioctl(i2cHandle, I2C_SLAVE, I2C_ADDRESS) < 0)
+ {
+ perror("Error setting I2C address");
+ close(i2cHandle);
+ return -1;
+ }
+
+ return 0;
+}
+
+void closeI2C()
+{
+ close(i2cHandle);
+}
+
+int16_t getSwitchId()
+{
+ if (i2cHandle == -1)
+ {
+ int ret = initI2C();
+ if (ret < 0)
+ {
+ return -1;
+ }
+ }
+
+ char buf[1];
+
+ buf[0] = SWITCH_REG_1;
+ buf[1] = 0xFF;
+ if (write(i2cHandle, buf, 2) != 2)
+ {
+ perror("Error writing to register");
+ return -1;
+ }
+
+ buf[0] = SWITCH_REG_2;
+ buf[1] = 0x00;
+ if (write(i2cHandle, buf, 2) != 2)
+ {
+ perror("Error writing to register");
+ return -1;
+ }
+
+ buf[0] = SWITCH_REG_3;
+ if (write(i2cHandle, buf, 1) != 1)
+ {
+ perror("Error writing to register");
+ return -1;
+ }
+
+ if (read(i2cHandle, buf, 1) != 1)
+ {
+ perror("Error reading from register");
+ return -1;
+ }
+
+ int8_t retData = buf[0];
+ if (retData >= 0 && retData <= 9)
+ {
+ return retData;
+ }
+
+ return -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// This function is called by the main OpenPLC routine when it is initializing.
+// Hardware initialization procedures should be here.
+//-----------------------------------------------------------------------------
+void initializeHardware()
+{
+}
+
+//-----------------------------------------------------------------------------
+// This function is called by the main OpenPLC routine when it is finalizing.
+// Resource clearing procedures should be here.
+//-----------------------------------------------------------------------------
+void finalizeHardware()
+{
+}
+
+//-----------------------------------------------------------------------------
+// This function is called by the OpenPLC in a loop. Here the internal buffers
+// must be updated to reflect the actual Input state. The mutex bufferLock
+// must be used to protect access to the buffers on a threaded environment.
+//-----------------------------------------------------------------------------
+void updateBuffersIn()
+{
+ pthread_mutex_lock(&bufferLock); //lock mutex
+
+ /*********READING AND WRITING TO I/O**************
+
+ *bool_input[0][0] = read_digital_input(0);
+ write_digital_output(0, *bool_output[0][0]);
+
+ *int_input[0] = read_analog_input(0);
+ write_analog_output(0, *int_output[0]);
+
+ **************************************************/
+
+ pthread_mutex_unlock(&bufferLock); //unlock mutex
+}
+
+//-----------------------------------------------------------------------------
+// This function is called by the OpenPLC in a loop. Here the internal buffers
+// must be updated to reflect the actual Output state. The mutex bufferLock
+// must be used to protect access to the buffers on a threaded environment.
+//-----------------------------------------------------------------------------
+void updateBuffersOut()
+{
+ pthread_mutex_lock(&bufferLock); //lock mutex
+
+ /*********READING AND WRITING TO I/O**************
+
+ *bool_input[0][0] = read_digital_input(0);
+ write_digital_output(0, *bool_output[0][0]);
+
+ *int_input[0] = read_analog_input(0);
+ write_analog_output(0, *int_output[0]);
+
+ **************************************************/
+
+ pthread_mutex_unlock(&bufferLock); //unlock mutex
+}
diff --git a/webserver/core/lib/SL-RP4.h b/webserver/core/lib/SL-RP4.h
new file mode 100644
index 0000000..f5050d7
--- /dev/null
+++ b/webserver/core/lib/SL-RP4.h
@@ -0,0 +1,60 @@
+int16_t initI2C();
+void closeI2C();
+int16_t getSwitchId();
+
+// FUNCTION_BLOCK ROTARY_SWITCH
+// Data part
+typedef struct {
+ // FB Interface - IN, OUT, IN_OUT variables
+ __DECLARE_VAR(BOOL,EN)
+ __DECLARE_VAR(BOOL,ENO)
+ __DECLARE_VAR(BOOL,READ)
+ __DECLARE_VAR(BOOL,ERROR)
+ __DECLARE_VAR(INT,OUT)
+
+ // FB private variables - TEMP, private and located variables
+
+} ROTARY_SWITCH;
+
+static void ROTARY_SWITCH_init__(ROTARY_SWITCH *data__, BOOL retain);
+// Code part
+static void ROTARY_SWITCH_body__(ROTARY_SWITCH *data__);
+static void ROTARY_SWITCH_init__(ROTARY_SWITCH *data__, BOOL retain) {
+ __INIT_VAR(data__->EN,__BOOL_LITERAL(TRUE),retain)
+ __INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain)
+ __INIT_VAR(data__->READ,__BOOL_LITERAL(FALSE),retain)
+ __INIT_VAR(data__->ERROR,__BOOL_LITERAL(FALSE),retain)
+ __INIT_VAR(data__->OUT,0,retain)
+}
+
+// Code part
+static void ROTARY_SWITCH_body__(ROTARY_SWITCH *data__) {
+ // Control execution
+ if (!__GET_VAR(data__->EN)) {
+ __SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE));
+ return;
+ }
+ else {
+ __SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE));
+ }
+ // Initialise TEMP variables
+
+ if ((__GET_VAR(data__->READ,) == __BOOL_LITERAL(TRUE))) {
+ int16_t rotary_read = getSwitchId();
+ if (rotary_read < 0)
+ {
+ __SET_VAR(data__->,OUT,,0);
+ __SET_VAR(data__->,ERROR,,1);
+ }
+ else
+ {
+ __SET_VAR(data__->,OUT,,rotary_read);
+ __SET_VAR(data__->,ERROR,,0);
+ }
+ }
+
+ goto __end;
+
+__end:
+ return;
+} // ROTARY_SWITCH_body__()
\ No newline at end of file
diff --git a/webserver/core/lib/iec_std_FB.h b/webserver/core/lib/iec_std_FB.h
index d2f291e..04f4a70 100755
--- a/webserver/core/lib/iec_std_FB.h
+++ b/webserver/core/lib/iec_std_FB.h
@@ -1889,6 +1889,9 @@ __end:
#if defined(__linux__) && defined(__arm__) && defined(SEQUENT)
#include "sm_cards.h"
#endif
+#if defined(__linux__) && defined(__arm__) && defined(SL_RP4)
+ #include "SL-RP4.h"
+#endif
diff --git a/webserver/lib/SL-RP4.txt b/webserver/lib/SL-RP4.txt
new file mode 100644
index 0000000..9270067
--- /dev/null
+++ b/webserver/lib/SL-RP4.txt
@@ -0,0 +1,14 @@
+FUNCTION_BLOCK ROTARY_SWITCH
+VAR_INPUT
+READ : BOOL;
+END_VAR
+VAR_OUTPUT
+ERROR : BOOL;
+OUT : INT;
+END_VAR
+
+ IF READ = TRUE THEN
+ OUT := 0;
+ END_IF;
+
+END_FUNCTION_BLOCK
diff --git a/webserver/lib/standard_FB.txt b/webserver/lib/standard_FB.txt
index eb2e78c..6009bb1 100755
--- a/webserver/lib/standard_FB.txt
+++ b/webserver/lib/standard_FB.txt
@@ -45,5 +45,6 @@
{#include "sema.txt" }
{#include "communication_blocks.txt" }
{#include "sm_cards.txt" }
+{#include "SL-RP4.txt" }
{enable code generation}
diff --git a/webserver/scripts/change_hardware_layer.sh b/webserver/scripts/change_hardware_layer.sh
index d5176d3..a6cdc93 100755
--- a/webserver/scripts/change_hardware_layer.sh
+++ b/webserver/scripts/change_hardware_layer.sh
@@ -115,6 +115,13 @@ elif [ "$1" == "sequent" ]; then
echo rpi > ../scripts/openplc_platform
echo sequent > ../scripts/openplc_driver
+elif [ "$1" == "sl_rp4" ]; then
+ echo "Activating SL-RP4 driver"
+ cp ./hardware_layers/SL-RP4.cpp ./hardware_layer.cpp
+ echo "Setting Platform"
+ echo linux > ../scripts/openplc_platform
+ echo sl_rp4 > ../scripts/openplc_driver
+
else
echo "Error: Invalid hardware layer"
fi
diff --git a/webserver/scripts/compile_program.sh b/webserver/scripts/compile_program.sh
index 79494f9..42d2127 100755
--- a/webserver/scripts/compile_program.sh
+++ b/webserver/scripts/compile_program.sh
@@ -78,13 +78,21 @@ if [ "$OPENPLC_PLATFORM" = "win" ]; then
elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
echo "Compiling for Linux"
echo "Generating object files..."
- g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
+ if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
+ g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSL_RP4
+ else
+ g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
+ fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
exit 1
fi
- g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
+ if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
+ g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC -DSL_RP4
+ else
+ g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
+ fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
@@ -93,7 +101,11 @@ elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
- g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
+ if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
+ g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC -DSL_RP4
+ else
+ g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
+ fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"