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!"