diff --git a/HowTo_UtilizeQt/LICENSE b/HowTo_UtilizeQt/LICENSE new file mode 100644 index 0000000..664d3ab --- /dev/null +++ b/HowTo_UtilizeQt/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2019 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/HowTo_UtilizeQt/Qt for WagoPFCXXXX.pdf b/HowTo_UtilizeQt/Qt for WagoPFCXXXX.pdf new file mode 100644 index 0000000..3340180 Binary files /dev/null and b/HowTo_UtilizeQt/Qt for WagoPFCXXXX.pdf differ diff --git a/HowTo_UtilizeQt/README.md b/HowTo_UtilizeQt/README.md new file mode 100644 index 0000000..7827fee --- /dev/null +++ b/HowTo_UtilizeQt/README.md @@ -0,0 +1,195 @@ + # HowTo: ADI - KBUS application using Qt + + ## You can choose which Qt-Version you want to build for: This HowTo used Qt Version 5.13 + + This HowTo describes how to build a Qt-Cross-Compile Environment so you can remotely run/debug + your application on a PFC device. + + Find within 1 simple demo program using the default Qt qmake generator for C/C++ builds + - kbusQtDemo : Has three different operation modes you can call by executing ./kbusQtDemo 1, 2 or 3 + 1 : kbusdemo + 2 : getkbusinfo + 3 : getkbusHeader + +# ATTENTION: +The ADI/DAL can only be used by one master, it can either be the CoDeSys-Runtime +or your own application. But not both. +Please make sure to stop the Runtime before running this demo. +- Temporally: +``` + >/etc/init.d/runtime stop +``` +- Permanent: +``` + #//Delete symbolic link + >rm /etc/rc.d/S98_runtime + #Recover symbolic link + >ln -s /etc/init.d/runtime /etc/rc.d/S98_runtime +``` + +# PREREQUISITES +This HowTo uses Qt-Creator to remotely deploy the application. +You need a working Cross-Compile Environment, see https://github.com/WAGO/pfc-firmware-sdk +Working means that you successfully followed the example to step 6.) and have the sysroot folders +within the platform folder(...) + +# About KBUS: + +The Kbus is working like a shifting register, means reading inputs and +writing outputs are capsulated within one Kbus-cycle. + +A Kbus-cycle triggered by a call of device specific function "libpackbus_Push()". + +Operating modes for driving the Kbus: +## 1) Operating mode “running”, a better name would be “manual” + +In mode “running” Kbus have to be driven by your application. +Kbus data only read or written on calling function "libpackbus_Push()". + +## Kbus operating mode "running": +- Highly deterministic(RealTimePrio) +- More program code needed. +- You have to think about Kbus-TimeOut of Output-IO-Terminals + +## What the hell means “Kbus-TimeOut of Output-IO-Terminals”? +Every WAGO Output-IO-Terminals monitors elapsed time since last Kbus-cycle. +If elapsed time exceed 50ms, IO-Terminal shut down the outputs. + +## And what is ADI/DAL's "WatchDog" functions good for? +Function „adi->WatchdogTrigger()“ only needed for PROFIBUS and CANopen +where fieldbus driven by a separate CHIP(DPC31) or software-stack. +“WatchdogTrigger()” is used to inform external fieldbus stack(CHIP) +about a living PLC program. +For KBUS, where entire fieldbus controlled by software, there is +no need to call “WatchdogTrigger()”. + +# Step by Step Ubuntu: +---------------------------------------------------------------------------- + +## 0) Follow the steps in the Official Guide “https://github.com/WAGO/pfc-firmware-sdk” until you reach step 6.) + +## 1.0) Get the latest(desired) Qt-Version + + Either by downloading the Source directly from the Website: + * [Qt-Everywhere](https://download.qt.io/archive/qt/5.13/5.13.0/single/) - Qt-Version 5.13.0 + + OR by downloading the Qt-Version with git: +``` + git clone -b 5.13.0 git://code.qt.io/qt/qt5.git +``` + Afterwards you need to call init_repository, optionally with the Modules you would like + otherwise all modules will be downloaded + -Also see * [Qt-Source](https://wiki.qt.io/Get_the_Source) + +## 1.2) Copy the folder "linux-arm-PFCXXXX-g++" into the downloaded Qt Folder: qtbase -> mkspecs -> devices + +## 1.1) Copy the file "qtbase/mkspecs/devices/linux-rasp-pi2-g++/" into the Folder we just created "linux-arm-PFCXXXX-g++" + + Copy the File from "qtbase/mkspecs/devices/linux-rasp-pi2-g++/qplatformdefs.h + into the "linux-arm-PFCXXXX-g++ Folder. + --> It is just a simple include file but cannot be added to this Tutorial, due + to licensing. + +## 1.3) Open a Terminal in the basefolder of the qt-source. You should see a file named configure in the folder. + + Now we need to export some Variables for the Configuration, you should adjust the Paths to fit your paths + If you plan to copy the Sysroot folders from your VM to your host System via scp or rsync + make sure to use -L to deference the Symbol Links + +``` + export TOOLCHAIN=*PATH_TO_YOUR_TOOLCHAIN* +``` + For example the LINARO Toolchain used in the WAGO Tutorial + → opt/wago/PFCXXXX/toolchain/arm-linux-gnueabihf/bin/arm-linux-gnueabihf- + +``` + export HOST_SYSROOT=*PATH_TO_HOST_SYSROOT* +``` + The host sysroot is the folder of your Toolchain Sysroot, if you don’t have one follow either: + - Download the precompiled sysroot from wago(“https://github.com/WAGO/gcc-linaro.toolchain-2017-precompiled”) + Build it yourself("https://github.com/WAGO/gcc-linaro.toolchain-2017"). + → opt/wago/PFCXXXX/toolchain/arm-linux-gnueabihf-sysroot + +``` + export TARGET_SYSROOT=*PATH_TO_TARGET_SYSROOT* +``` + The Target sysroot is also the Folder we created in the Wago Tutorial + You will find the Folder in ptxproj → platform-wago-pfcXXX → sysroot-target + +``` + export PREFIX=*PATH_YOU_WANT_THE_QT_VERSION_TO_INSTALL_TO* +``` + The Path the newly build Qt-Version will install to. + For example: /opt/Qt/5.13.0/wago_pfcxxx + +``` + export EXTPREFIX=*PATH_YOU_WANT_THE_SYSROOT_TO_INSTALL_TO* +``` + By default the sysroot will be installed into the Toolchain folder. If you want the Sysroot +to install into a different folder you should set this Value, otherwise leave it out in the Configure. + +## 1.4) Execute the command +``` +./configure -device linux-arm-PFCXXXX-g++ -device-option CROSS_COMPILE=$TOOLCHAIN -device-option SYSROOT_TARGET=$TARGET_SYSROOT -sysroot $HOST_SYSROOT -prefix $PREFIX -extprefix $EXTPREFIX -skip qtandroidextras -skip qtcharts -skip qtwinextras -skip qtlocation -skip qtwebengine -skip qtwebview -no-opengl -D WAGO_PFC +``` + Note: For further options see “https://doc.qt.io/archives/qtextended4.4/buildsystem/over-configure-options-1.html” + + → Follow the Prompts you will receive and check for a “success” message. + ▪ -device: The Device for which we will configure the build. Contains information about the Architecture and so on. + + ▪ skip … : Skips the Qt-Module so it will not be build, you can enter all the Qt-Modules you do not want to include into your build. + + ▪ No-opengl: The Wago-PFCXXX does not support opengl and it will not work either. So we need to tell Qt not to use it. + + ▪ -D Add an explicit define to the build, so we can later determine our system in make/qmake + + +## 1.5) Build and Install Qt + After the configure, run make -jn, n is the amount of threads your PC has + 1 + + Afterwards the Qt-Version will be build, this will take some time even on faster machines, expect it to take around 30-90 minutes. + + When the make is done, double check that no errors are listed in the last lines, if everything worked you are ready to install with: “make install” + → This will install the build into the Path provided by $PREFIX + +## 2.0) Setting up the Qt-Enviroment + + Check out the PFD-File "Qt for WagoPFCXXXX.pfd" for a detailed description + with a Picture Guide on HowTo do it. + + Summary: + + 1.) Install Qt-Creator + + 2.) Navigate to Tools -> Options -> Kits + + 2.1) Navigate to Debugger and add the gdb Debugger within your Toolchain + + 2.2) Navigate to Compiler and add the C/C++ Compiler within your Toolchain + + 2.3) Navigate to Qt Versions and add the Qt-Version we just build in Step 1 + + 2.4) Navigate to Kits and create a new Kit using our Qt-Version, Compiler + and Debugger. + + 3.) Navigate to Devices, Add a new Generic Linux Device, follow the Instruction + + 3.1) Navigate back to Kits and add the Generic Linux Device + + +## 3.0) Build the example + + Within the Qt-Creator load a project and navigate to the folder containing this Tutorial, open KBusQtDemo.pro. + + Follow the Project Settings within the Qt-Creator. + + If everything was setup correctly you should now be able to run the simple + demo Program remotely and debug/build from your Developer Machine + + +# Compatibility list: +| PFC | Qt-Version | Operating Systems | +|:-------------|:-------------|:------------:| +| **PFC200** | | | +| 8212 | 5.13.0 | Ubuntu 19.04, Windows 10(Build Toolchain yourself)| + diff --git a/HowTo_UtilizeQt/linux-arm-PFCXXXX-g++/qmake.conf b/HowTo_UtilizeQt/linux-arm-PFCXXXX-g++/qmake.conf new file mode 100644 index 0000000..5a007a9 --- /dev/null +++ b/HowTo_UtilizeQt/linux-arm-PFCXXXX-g++/qmake.conf @@ -0,0 +1,51 @@ +# +# qmake configuration for the BeagleBoard and BeagleBoard xM boards +# http://beagleboard.org/ + +MAKEFILE_GENERATOR = UNIX +CONFIG += incremental +QMAKE_INCREMENTAL_STYLE = sublib + +include(../../common/linux.conf) +include(../../common/gcc-base-unix.conf) +include(../../common/g++-unix.conf) + +load(device_config) + +# modifications to g++.conf +QMAKE_CC = $${CROSS_COMPILE}gcc +QMAKE_CXX = $${CROSS_COMPILE}g++ +QMAKE_LINK = $${QMAKE_CXX} +QMAKE_LINK_SHLIB = $${QMAKE_CXX} + +QMAKE_INCDIR = $$[QT_SYSROOT]/usr/include +QMAKE_LIBDIR = $$[QT_SYSROOT]/usr/lib + +QMAKE_INCDIR += $${SYSROOT_TARGET}/usr/include +QMAKE_LIBDIR += $${SYSROOT_TARGET}/usr/lib + +# modifications to linux.conf +QMAKE_AR = $${CROSS_COMPILE}ar cqs +QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy +QMAKE_NM = $${CROSS_COMPILE}nm -P +QMAKE_STRIP = $${CROSS_COMPILE}strip + +COMPILER_FLAGS = -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mthumb + +#modifications to gcc-base.conf +QMAKE_CFLAGS += $${COMPILER_FLAGS} +QMAKE_CXXFLAGS += $${COMPILER_FLAGS} +QMAKE_CXXFLAGS_RELEASE += -O3 + +QMAKE_LIBS += -lrt -lpthread -ldl -ldal + +DISTRO_OPTS += hard-float +DISTRO_OPTS += deb-multi-arch + +# No need for any special EGL device integration. +# Prioritize the default, compiled-in integration over any plugins. +EGLFS_DEVICE_INTEGRATION = none + +include(../common/linux_arm_device_post.conf) + +load(qt_config) diff --git a/HowTo_UtilizeQt/src/KBusQtDemo/KBusQtDemo.pro b/HowTo_UtilizeQt/src/KBusQtDemo/KBusQtDemo.pro new file mode 100644 index 0000000..b15f1d8 --- /dev/null +++ b/HowTo_UtilizeQt/src/KBusQtDemo/KBusQtDemo.pro @@ -0,0 +1,45 @@ +TARGET = KbusQtDemo +TEMPLATE = app + +SOURCES += main.cpp + +contains(DEFINES, WAGO_PFC){ # Check if we defined WAGO_PFC so we know its meant for this device, we defined it during the Qt-Build-Process + CONFIG += wago_pfc +} + +wago_pfc{ # Wago specific code, like the inlude Paths and Libraries + QT -= core gui # Is included by default, we dont want that! + + QMAKE_PLATFORM += wago_pfc + # Include Pfad fr andere Libs noch anpassen + exists($$SYSROOT_TARGET){ + message("Target_Sysroot found: $$SYSROOT_TARGET") + INCLUDEPATH += $${SYSROOT_TARGET}/usr/include/ + INCLUDEPATH += $${SYSROOT_TARGET}/usr/include/OsLinux/ + INCLUDEPATH += $${SYSROOT_TARGET}/usr/include/dal/ + INCLUDEPATH += $${SYSROOT_TARGET}/usr/include/diagnostic/ + INCLUDEPATH += $${SYSROOT_TARGET}/usr/include/dbus-1.0/ + + LIBS += -L$$[QT_SYSROOT] + LIBS += -L$${SYSROOT_TARGET}/usr/lib + } else { + error("Target-Sysroot cannot be set. Set Environment Variable "SYSROOT_TARGET"(Default is /opt/wago_pfc/sysroot)") + } + + # Build-Type = Debug or Release + CONFIG(release, debug|release) { + BUILD_TYPE = Release + } else { + BUILD_TYPE = Debug + } + message("Build-Typ: $$BUILD_TYPE") + + # System Libraries we are linking against so the ADI/DAL is working correctly + LIBS += -ldal -llibloader -lpthread -lffi -lrt -lgobject-2.0 -ldbus-glib-1 -lglib-2.0 -lpcre -lz + LIBS += -ltypelabel -loslinux -ldbuskbuscommon -ldbus-1 -lgio-2.0 -lwago_dbus -lgmodule-2.0 + + # The install path where we will copy the Application to + target.path= /root/ + message("Install Path on Wago_PFC: '$$target.path'") + INSTALLS += target +} diff --git a/HowTo_UtilizeQt/src/KBusQtDemo/main.cpp b/HowTo_UtilizeQt/src/KBusQtDemo/main.cpp new file mode 100644 index 0000000..8112297 --- /dev/null +++ b/HowTo_UtilizeQt/src/KBusQtDemo/main.cpp @@ -0,0 +1,916 @@ +//----------------------------------------------------------------------------- +// standard include files +//----------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +//----------------------------------------------------------------------------- +// include files for KBUS WAGO ADI +//----------------------------------------------------------------------------- +extern "C" { + #include + #include + #include +} + +//----------------------------------------------------------------------------- +// defines and test setup +//----------------------------------------------------------------------------- +#define DECOUTFILENAME "kbusinfo.h" +#define DEFOUTFILENAME "kbusinfo.c" +#define SUMMARYINFOFILENAME "kbusinfo.txt" + +#define OISSOK 0 +#define EADIINITFAILED -1 +#define EADISCANDEVFAILED -2 +#define EADIGETDEVLISTFAILED -3 +#define ENOKBUSFOUND -4 +#define EKBUSOPENFAILED -5 +#define EUNCONFIGFAILED -6 +#define ELDKCKBINFOCREATEFAILED -7 +#define ELDKCKBINFOGETSTATUSFAILED -8 +#define ELDKCKBINFOGTTERMINFOFAILED -9 +#define ELDKCKBINFOGTTERMLISTFAILED -10 +#define EOPENDECFILEFAILED -11 +#define EOPENDEFFILEFAILED -12 +#define EOPENSUMFILEFAILED -13 +// priorities +#define KBUS_MAINPRIO 40 // main loop +// runtime of the test +#define KBUS_TESTTIME 30 + +int KBusDemo() +{ + // vars for ADI-interface + tDeviceInfo deviceList[10]; // the list of devices given by the ADI + size_t nrDevicesFound; // number of devices found + size_t nrKbusFound; // position of the kbus in the list + tDeviceId kbusDeviceId; // device ID from the ADI + tApplicationDeviceInterface * adi; // pointer to the application interface + uint32_t taskId = 0; // task Id + tApplicationStateChangedEvent event; // var for the event interface of the ADI + + // process data + uint8_t pd_in[4096]; // kbus input process data + uint8_t pd_out[4096]; // kbus output process data + + // generic vars + int i = 0, loops = 0; + time_t last_t = 0, new_t; + long unsigned runtime = 0; + struct sched_param s_param; + + // startup info */ + printf("**************************************************\n"); + printf("*** KBUS Demo Application V3.00 ***\n"); + printf("**************************************************\n"); + + // clear process memory + memset(pd_in, 0, sizeof(pd_in)); + memset(pd_out, 0, sizeof(pd_out)); + + // connect to ADI-interface + adi = adi_GetApplicationInterface(); + + // init interface + adi->Init(); + + // scan devices + adi->ScanDevices(); + adi->GetDeviceList(sizeof(deviceList), deviceList, &nrDevicesFound); + + // find kbus device + nrKbusFound = -1; + for (i = 0; i < nrDevicesFound; ++i) + { + if (strcmp(deviceList[i].DeviceName, "libpackbus") == 0) + { + nrKbusFound = i; + printf("KBUS device found as device %i\n", i); + } + } + + // kbus not found > exit + if (nrKbusFound == -1) + { + printf("No KBUS device found \n"); + adi->Exit(); // disconnect ADI-Interface + return -1; // exit program + } + + // switch to RT Priority + s_param.sched_priority = KBUS_MAINPRIO; + sched_setscheduler(0, SCHED_FIFO, &s_param); + printf("switch to RT Priority 'KBUS_MAINPRIO'\n"); + + // open kbus device + kbusDeviceId = deviceList[nrKbusFound].DeviceId; + if (adi->OpenDevice(kbusDeviceId) != DAL_SUCCESS) + { + printf("Kbus device open failed\n"); + adi->Exit(); // disconnect ADI-Interface + return -2; // exit program + } + printf("KBUS device open OK\n"); + + // Set application state to "Running" to drive kbus by your selve. + event.State = ApplicationState_Running; + if (adi->ApplicationStateChanged(event) != DAL_SUCCESS) + { + // Set application state to "Running" failed + printf("Set application state to 'Running' failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return -3; // exit programm + } + printf("Set application state to 'Running' \n"); + + // run main loop for 30s + while (runtime < KBUS_TESTTIME) + { + usleep(10000); // wait 10 ms + + uint32_t retval = 0; + + // Use function "libpackbus_Push" to trigger one KBUS cycle. + if (adi->CallDeviceSpecificFunction("libpackbus_Push", &retval) != DAL_SUCCESS) + { + // CallDeviceSpecificFunction failed + printf("CallDeviceSpecificFunction failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return -4; // exit programm + } + + if (retval != DAL_SUCCESS) + { + // Function 'libpackbus_Push' failed + printf("Function 'libpackbus_Push' failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return -5; // exit programm + } + + loops++; + + // Trigger Watchdog + adi->WatchdogTrigger(); + + // 1s tick for test output + new_t = time(NULL); + if (new_t != last_t) + { + last_t = new_t; + runtime++; + + // read inputs + adi->ReadStart(kbusDeviceId, taskId); /* lock PD-In data */ + adi->ReadBytes(kbusDeviceId, taskId, 0, 1, (uint8_t *) &pd_in[0]); /* read 1 byte from address 0 */ + adi->ReadEnd(kbusDeviceId, taskId); /* unlock PD-In data */ + // calculate something + pd_out[0] += 1; + // write outputs + adi->WriteStart(kbusDeviceId, taskId); /* lock PD-out data */ + adi->WriteBytes(kbusDeviceId,taskId,0,1,(uint8_t *) &pd_out[0]); /* write */ + adi->WriteBytes(kbusDeviceId, taskId, 0, 16, (uint8_t *) &pd_out[0]); /* write */ + adi->WriteEnd(kbusDeviceId, taskId); /* unlock PD-out data */ + // print info + printf("%lu:%02lu:%02lu State = ",runtime/3600ul,(runtime/60ul)%60ul,runtime%60ul); + // show loops/s + printf("\n Loop/s = %i ",loops); + loops = 0; + // show process data + printf(" Input Data = %02X Output data = %02X ",(int) pd_in[0],(int) pd_out[0]); + printf("\n"); + } + + } // while .. + + usleep(1000); + + // close kbus device + adi->CloseDevice(kbusDeviceId); + + adi->Exit(); // disconnect ADI-Interface + + return 0; +} + +int GetKBusInfo() +{ + // vars for ADI-interface + tDeviceInfo deviceList[10]; // the list of devices given by the ADI + size_t nrDevicesFound; // number of devices found + size_t nrKbusFound; // position of the kbus in the list + tDeviceId kbusDeviceId; // device ID from the ADI + tApplicationDeviceInterface * adi; // pointer to the application interface + tApplicationStateChangedEvent event; // var for the event interface of the ADI + + // generic vars + int i = 0; + + // startup info */ + printf("**************************************************\n"); + printf("*** KBUS Conf Demo Application V1.00 ***\n"); + printf("**************************************************\n"); + + //*** Start KBUS ******************************************** + + // connect to ADI-interface + adi = adi_GetApplicationInterface(); + + // init interface + adi->Init(); + + // scan devices + adi->ScanDevices(); + adi->GetDeviceList(sizeof(deviceList), deviceList, &nrDevicesFound); + + // find kbus device + nrKbusFound = -1; + for (i = 0; i < nrDevicesFound; ++i) + { + if (strcmp(deviceList[i].DeviceName, "libpackbus") == 0) + { + nrKbusFound = i; + printf("KBUS device found as device %i\n", i); + } + else + { + printf("Found Non-KBUS as device%i: %s \n", i, deviceList[i].DeviceName); + } + } + + // kbus not found > exit + if (nrKbusFound == -1) + { + printf("No KBUS device found \n"); + adi->Exit(); // disconnect ADI-Interface + return -1; // exit program + } + + // open kbus device + kbusDeviceId = deviceList[nrKbusFound].DeviceId; + if (adi->OpenDevice(kbusDeviceId) != DAL_SUCCESS) + { + printf("Kbus device open failed\n"); + adi->Exit(); // disconnect ADI-Interface + return -2; // exit program + } + printf("KBUS device open OK\n"); + + // set application state to "Unconfigured" to let library drive kbus by them selve. + // In this mode library set up a thread who drive the kbus cyclic. + event.State = ApplicationState_Unconfigured; + if (adi->ApplicationStateChanged(event) != DAL_SUCCESS) + { + // Set application state to "Unconfigured" failed + printf("Set application state to 'Unconfigured' failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return -3; // exit programm + } + printf("Set application state to 'Unconfigured' \n"); + + //*** Retrieve KBUS-Config via DBUS *************************** + + if (KbusInfo_Failed == ldkc_KbusInfo_Create()) + { + printf(" ldkc_KbusInfo_Create() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return -11; + } + + // GetStatus + tldkc_KbusInfo_Status status; + if (KbusInfo_Failed == ldkc_KbusInfo_GetStatus(&status)) + { + printf(" ldkc_KbusInfo_GetStatus() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return -12; + } + printf("\n .KbusBitCount: %i ",status.KbusBitCount); + printf("\n .TerminalCount: %i ",status.TerminalCount); + printf("\n .ErrorCode: %i ",status.ErrorCode); + printf("\n .ErrorArg: %i ",status.ErrorArg); + printf("\n .ErrorPos: %i ",status.ErrorPos); + printf("\n .BitCountAnalogInput: %i ",status.BitCountAnalogInput); + printf("\n .BitCountAnalogOutput: %i ",status.BitCountAnalogOutput); + printf("\n .BitCountDigitalInput: %i ",status.BitCountDigitalInput); + printf("\n .BitCountDigitalOutput: %i ",status.BitCountDigitalOutput); + + // GetTerminalInfo + unsigned char ucPosition; + unsigned char ucIndex; + unsigned char ucCntOfTrmnlType; + unsigned char ucMaxPosition; + + size_t terminalCount; + u16 terminals[LDKC_KBUS_TERMINAL_COUNT_MAX]; + tldkc_KbusInfo_TerminalInfo terminalDescription[LDKC_KBUS_TERMINAL_COUNT_MAX]; + + if ( KbusInfo_Failed == ldkc_KbusInfo_GetTerminalInfo(OS_ARRAY_SIZE(terminalDescription), terminalDescription, &terminalCount) ) + { + printf(" ldkc_KbusInfo_GetTerminalInfo() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return -13; + } + + if ( KbusInfo_Failed == ldkc_KbusInfo_GetTerminalList(OS_ARRAY_SIZE(terminals), terminals, NULL) ) + { + printf(" ldkc_KbusInfo_GetTerminalList() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return -14; + } + ucPosition = 1; + ucMaxPosition = terminalCount; + + for (ucIndex = 0; ucPosition <= ucMaxPosition; ucPosition++, ucIndex++) + { + const u32 idx = ucPosition - 1; + + printf("\n Pos:%i;", ucPosition); + if( 0 == (terminals[idx] & 0x8000) ) + { + // Show second part of order number in "dec" format for complex IO-Terminals + printf("\t Type:%i;", terminals[idx]); + } + else + { + // Show bit coded information of stupid digital IO-Terminals in "hex" format + printf("\t Type:0x%x;", terminals[idx]); + } + printf("\t BitOffsetOut:%i;", terminalDescription[idx].OffsetOutput_bits); + printf("\t BitSizeOut:%i;", terminalDescription[idx].SizeOutput_bits); + printf("\t BitOffsetIn:%i;", terminalDescription[idx].OffsetInput_bits); + printf("\t BitSizeIn:%i;", terminalDescription[idx].SizeInput_bits); + printf("\t Channels:%i;", terminalDescription[idx].AdditionalInfo.ChannelCount); + printf("\t PiFormat:%i;", terminalDescription[idx].AdditionalInfo.PiFormat); + } + + usleep(1000); + + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + printf("\n getkbusinfo successful executed\n"); + return 0; // exit program +} + +int getKBusHeader() +{ + // vars for ADI-interface + tDeviceInfo deviceList[10]; // the list of devices given by the ADI + size_t nrDevicesFound; // number of devices found + size_t nrKbusFound; // position of the kbus in the list + tDeviceId kbusDeviceId; // device ID from the ADI + tApplicationDeviceInterface * adi; // pointer to the application interface + tApplicationStateChangedEvent event; // var for the event interface of the ADI + + // generic vars + int i = 0; + int32_t result; + + // startup info */ + printf("*****************************************************\n"); + printf("*** getkbusheader ***\n"); + printf("*** Version: %12s %8s ***\n", __DATE__, __TIME__); + printf("*****************************************************\n"); + + //*** Start KBUS ******************************************** + + // connect to ADI-interface + adi = adi_GetApplicationInterface(); + + + // init interface + result = adi->Init(); + if (DAL_FAILURE == result) + { + printf("ERROR: ADI->Init failed\n"); + printf("Did you stop the plclinux task?\n"); + return EADIINITFAILED; + }; + + // scan devices + result = adi->ScanDevices(); + if (DAL_FAILURE == result) + { + printf("ERROR: ADI->ScanDevices failed\n"); + return EADISCANDEVFAILED; + }; + + result = adi->GetDeviceList(sizeof(deviceList), deviceList, &nrDevicesFound); + if (DAL_FAILURE == result) + { + printf("ERROR: ADI->GetDeviceList failed\n"); + return EADIGETDEVLISTFAILED; + }; + + + // find kbus device + nrKbusFound = -1; + for (i = 0; i < nrDevicesFound; ++i) + { + if (strcmp(deviceList[i].DeviceName, "libpackbus") == 0) + { + nrKbusFound = i; + printf("KBUS device found as device %i\n", i); + } + else + { + printf("Found Non-KBUS device: %s", deviceList[i].DeviceName); + } + } + + // kbus not found > exit + if (nrKbusFound == -1) + { + printf("ERROR: No KBUS device found \n"); + adi->Exit(); // disconnect ADI-Interface + return ENOKBUSFOUND; // exit program + } + + // open kbus device + kbusDeviceId = deviceList[nrKbusFound].DeviceId; + if (adi->OpenDevice(kbusDeviceId) != DAL_SUCCESS) + { + printf("ERROR: Kbus device open failed\n"); + + adi->Exit(); // disconnect ADI-Interface + return EKBUSOPENFAILED; // exit program + } + printf("KBUS device open OK\n"); + + // set application state to "Unconfigured" to let library drive kbus by them selve. + // In this mode library set up a thread who drive the kbus cyclic. + event.State = ApplicationState_Unconfigured; + if (adi->ApplicationStateChanged(event) != DAL_SUCCESS) + { + // Set application state to "Unconfigured" failed + printf("ERROR: Set application state to 'Unconfigured' failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return EUNCONFIGFAILED; // exit programm + } + printf("Set application state to 'Unconfigured' \n"); + + //*** Retrieve KBUS-Config via DBUS *************************** + + if (KbusInfo_Failed == ldkc_KbusInfo_Create()) + { + printf("ERROR: ldkc_KbusInfo_Create() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + return ELDKCKBINFOCREATEFAILED; + } + + // GetStatus + tldkc_KbusInfo_Status status; + if (KbusInfo_Failed == ldkc_KbusInfo_GetStatus(&status)) + { + printf("ERROR: ldkc_KbusInfo_GetStatus() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return ELDKCKBINFOGETSTATUSFAILED; + } + printf("\n .KbusBitCount: %i ",status.KbusBitCount); + printf("\n .TerminalCount: %i ",status.TerminalCount); + printf("\n .ErrorCode: %i ",status.ErrorCode); + printf("\n .ErrorArg: %i ",status.ErrorArg); + printf("\n .ErrorPos: %i ",status.ErrorPos); + printf("\n .BitCountAnalogInput: %i ",status.BitCountAnalogInput); + printf("\n .BitCountAnalogOutput: %i ",status.BitCountAnalogOutput); + printf("\n .BitCountDigitalInput: %i ",status.BitCountDigitalInput); + printf("\n .BitCountDigitalOutput: %i \n",status.BitCountDigitalOutput); + + // GetTerminalInfo + size_t terminalCount; + u16 terminals[LDKC_KBUS_TERMINAL_COUNT_MAX]; + tldkc_KbusInfo_TerminalInfo terminalDescription[LDKC_KBUS_TERMINAL_COUNT_MAX]; + + if ( KbusInfo_Failed == ldkc_KbusInfo_GetTerminalInfo(OS_ARRAY_SIZE(terminalDescription), terminalDescription, &terminalCount) ) + { + printf("ERROR: ldkc_KbusInfo_GetTerminalInfo() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return ELDKCKBINFOGTTERMINFOFAILED; + } + + if ( KbusInfo_Failed == ldkc_KbusInfo_GetTerminalList(OS_ARRAY_SIZE(terminals), terminals, NULL) ) + { + printf("ERROR: ldkc_KbusInfo_GetTerminalList() failed\n"); + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return ELDKCKBINFOGTTERMLISTFAILED; + } + + unsigned char ucMaxPosition; + unsigned char ucPosition; + unsigned char ucChanCtr; + + ucMaxPosition = terminalCount; + + // screeninfo (same as WAGOs getkbusinfo, but fancier) + printf("\nPosition Type BitOffsetOut BitSizeOut BitOffsetIn BitSizeIn Channels PiFormat"); + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + + + printf("\n %4i,", ucPosition); + if( 0 == (terminals[idx] & 0x8000) ) + { + // Show second part of order number in "dec" format for complex IO-Terminals + printf(" %6i;", terminals[idx]); + } + else + { + // Show bit coded information of stupid digital IO-Terminals in "hex" format + printf(" 0x%x;", terminals[idx]); + } + printf(" %4i, %4i, %4i, %4i, %i, %i", + terminalDescription[idx].OffsetOutput_bits, + terminalDescription[idx].SizeOutput_bits, + terminalDescription[idx].OffsetInput_bits, + terminalDescription[idx].SizeInput_bits, + terminalDescription[idx].AdditionalInfo.ChannelCount, + terminalDescription[idx].AdditionalInfo.PiFormat); + } + + // Write to Files + FILE * fPtr; + time_t tmpTime; + struct tm * tmPtr; + int byteZahl; + + // Declaration File (aka Header File) + printf("\n\nWriting declaration file %s\n",DECOUTFILENAME); + fPtr = fopen(DECOUTFILENAME, "w"); + if (fPtr == NULL) + { + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + printf("ERROR: Cannot open outfile %s\n",DECOUTFILENAME); + return EOPENDECFILEFAILED; + } + + tmpTime = time(NULL); + tmPtr = localtime(&tmpTime); + + fprintf(fPtr,"/******************************************************************************/\n//\n"); + fprintf(fPtr,"// Created by getkbusinfo at %d-%02d-%02d_%02d:%02d:%02d\n//\n", + tmPtr->tm_year+1900,tmPtr->tm_mon+1,tmPtr->tm_mday, + tmPtr->tm_hour,tmPtr->tm_min,tmPtr->tm_sec); + fprintf(fPtr,"/******************************************************************************/\n\n"); + + fprintf(fPtr,"#ifndef KBUSINFO_H\n#define KBUSINFO_H\n\n"); + + fprintf(fPtr,"// In this array you will find all infos about the scanned kbus\n"); + fprintf(fPtr,"// Position, ModulType, BitOffsetOut, BitSizeOut, BitOffsetIn, BitSizeIn, Channels, PiFormat\n\n"); + fprintf(fPtr,"#define NROFKBUSMODULES %d\n",ucMaxPosition); + fprintf(fPtr,"#define NROFINFOROWS 8\n"); + fprintf(fPtr,"extern const unsigned short kbusSimpleInfo[NROFKBUSMODULES][NROFINFOROWS];\n\n"); + + // write the struct for the kbusInput + fprintf(fPtr,"// The typedef struct for the scanned kbusInput\n"); + fprintf(fPtr,"typedef struct __attribute__((packed))\n{\n"); + + // Byte before bit + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + if ((0 != terminalDescription[idx].SizeInput_bits) && (0 == (terminals[idx] & 0x8000))) + { + for (ucChanCtr = 1; ucChanCtr <= terminalDescription[idx].AdditionalInfo.ChannelCount; ucChanCtr++) + { + byteZahl = terminalDescription[idx].SizeInput_bits / terminalDescription[idx].AdditionalInfo.ChannelCount / 8; + switch (byteZahl) + { + case 1: + fprintf(fPtr,"\tunsigned char p%dt%dc%d;\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, + ucPosition, terminals[idx], ucChanCtr); + case 2: + fprintf(fPtr,"\tunsigned short p%dt%dc%d;\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, + ucPosition, terminals[idx], ucChanCtr); + break; + case 4: + fprintf(fPtr,"\tunsigned long p%dt%dc%d;\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, + ucPosition, terminals[idx], ucChanCtr); + break; + // Complex modules having 1 channel and 6 to 48 Bytes + default: + if ((byteZahl>= 6) && (byteZahl <= 48)) + { + fprintf(fPtr,"\tunsigned char p%dt%dc%d[%d];\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, byteZahl, + ucPosition, terminals[idx], ucChanCtr); + } + // all the rest (3, 5 Bytes and > 48 Bytes) is blocked + else + { + printf("Error creating tKbusInput element for KBUS-Position %d\n", ucPosition); + fclose(fPtr); + + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return -2; + } + break; + } + } + } + } + // Now the bit Part + + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + if ((0 != terminalDescription[idx].SizeInput_bits) && (0 != (terminals[idx] & 0x8000))) + { + for (ucChanCtr = 1; ucChanCtr <= terminalDescription[idx].SizeInput_bits; ucChanCtr++) + { + + fprintf(fPtr,"\tunsigned int p%dt4XXc%d:1;\t// Position %d, Typ 750-4XX, Channel %d\n", + ucPosition, ucChanCtr, + ucPosition, ucChanCtr); + } + } + } + + fprintf(fPtr,"} tKbusInput;\n\n"); + + + // Create the struct for the kbusOutput + fprintf(fPtr,"// The typedef struct for the scanned kbusOutput\n"); + fprintf(fPtr,"typedef struct __attribute__((packed))\n{\n"); + + // Byte before bit + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + if ((0 != terminalDescription[idx].SizeOutput_bits) && (0 == (terminals[idx] & 0x8000))) + { + for (ucChanCtr = 1; ucChanCtr <= terminalDescription[idx].AdditionalInfo.ChannelCount; ucChanCtr++) + { + byteZahl = terminalDescription[idx].SizeOutput_bits / terminalDescription[idx].AdditionalInfo.ChannelCount / 8; + switch (byteZahl) + { + case 1: + fprintf(fPtr,"\tunsigned char p%dt%dc%d;\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, + ucPosition, terminals[idx], ucChanCtr); + break; + case 2: + fprintf(fPtr,"\tunsigned short p%dt%dc%d;\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, + ucPosition, terminals[idx], ucChanCtr); + break; + case 4: + fprintf(fPtr,"\tunsigned long p%dt%dc%d;\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, + ucPosition, terminals[idx], ucChanCtr); + break; + default: + // Complex modules having 1 channel and 6 to 48 Bytes + if ((byteZahl>= 6) && (byteZahl <= 48)) + { + fprintf(fPtr,"\tunsigned char p%dt%dc%d[%d];\t// Position %d, Typ 750-%d, Channel %d\n", + ucPosition, terminals[idx], ucChanCtr, byteZahl, + ucPosition, terminals[idx], ucChanCtr); + } + // all the rest (3, 5 Bytes and > 48 Bytes) is blocked + else + { + printf("Error creating tKbusOutput element for KBUS-Position %d\n", ucPosition); + + fclose(fPtr); + + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + return -2; + } + break; + }; + } + } + } + + // Now the bit Part + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + if ((0 != terminalDescription[idx].SizeOutput_bits) && (0 != (terminals[idx] & 0x8000))) + { + for (ucChanCtr = 1; ucChanCtr <= terminalDescription[idx].SizeOutput_bits; ucChanCtr++) + { + + fprintf(fPtr,"\tunsigned int p%dt5XXc%d:1;\t// Position %d, Typ 750-5XX, Channel %d\n", + ucPosition, ucChanCtr, + ucPosition, ucChanCtr); + } + } + } + + fprintf(fPtr,"} tKbusOutput;\n\n"); + + fprintf(fPtr,"// The byte offset of the bit input field in tKbusInput\n"); + fprintf(fPtr,"#define BYTEOFFSETINPUTBITFIELD %d\n\n",status.BitCountAnalogInput/8); + fprintf(fPtr,"// The byte offset of the bit output field in tKbusOutput\n"); + fprintf(fPtr,"#define BYTEOFFSETOUTPUTBITFIELD %d\n\n",status.BitCountAnalogOutput/8); + + fprintf(fPtr,"// The structs and the pointer to byte- and bitfields\n"); + fprintf(fPtr,"extern tKbusInput kbusInputData;\n"); + fprintf(fPtr,"extern tKbusOutput kbusOutputData;\n\n"); + + fprintf(fPtr,"extern uint8_t * pKbusInputBitData;\n"); + fprintf(fPtr,"extern uint8_t * pKbusInputData;\n\n"); + + fprintf(fPtr,"extern uint8_t * pKbusOutputBitData;\n"); + fprintf(fPtr,"extern uint8_t * pKbusOutputData;\n\n"); + + fprintf(fPtr,"#endif // KBUSINFO_H\n"); + + fclose(fPtr); + + printf("\nWriting definition file %s\n",DEFOUTFILENAME); + + // Now definition stuff in a C-File + fPtr = fopen(DEFOUTFILENAME, "w"); + if (fPtr == NULL) + { + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + + printf("ERROR: Cannot open outfile %s\n",DEFOUTFILENAME); + return EOPENDEFFILEFAILED; // exit program + } + + tmpTime = time(NULL); + tmPtr = localtime(&tmpTime); + + fprintf(fPtr,"/******************************************************************************/\n//\n"); + fprintf(fPtr,"// Created by getkbusinfo at %d-%02d-%02d_%02d:%02d:%02d\n", + tmPtr->tm_year+1900,tmPtr->tm_mon+1,tmPtr->tm_mday, + tmPtr->tm_hour,tmPtr->tm_min,tmPtr->tm_sec); + fprintf(fPtr,"// see %s for further information\n//\n", DECOUTFILENAME); + fprintf(fPtr,"/******************************************************************************/\n\n"); + + fprintf(fPtr,"#include \"%s\"\n\n",DECOUTFILENAME); + fprintf(fPtr,"const unsigned short kbusSimpleInfo[NROFKBUSMODULES][NROFINFOROWS] = {\n"); + fprintf(fPtr,"//Position Type BitOffsetOut BitSizeOut BitOffsetIn BitSizeIn Channels PiFormat\n"); + + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + + + fprintf(fPtr," {%4i, ", ucPosition); + if( 0 == (terminals[idx] & 0x8000) ) + { + // Show second part of order number in "dec" format for complex IO-Terminals + fprintf(fPtr," %6i, ", terminals[idx]); + } + else + { + // Show bit coded information of stupid digital IO-Terminals in "hex" format + fprintf(fPtr," 0x%x, ", terminals[idx]); + } + fprintf(fPtr," %4i, %4i, %4i, %4i, %i, %i}", + terminalDescription[idx].OffsetOutput_bits, + terminalDescription[idx].SizeOutput_bits, + terminalDescription[idx].OffsetInput_bits, + terminalDescription[idx].SizeInput_bits, + terminalDescription[idx].AdditionalInfo.ChannelCount, + terminalDescription[idx].AdditionalInfo.PiFormat); + if (ucPosition != ucMaxPosition) + { + fprintf(fPtr,",\n"); + } + } + fprintf(fPtr,"\n};\n\n"); + + fprintf(fPtr,"tKbusInput kbusInputData;\n"); + fprintf(fPtr,"tKbusOutput kbusOutputData;\n\n"); + + fprintf(fPtr,"uint8_t * pKbusInputData;\n"); + fprintf(fPtr,"uint8_t * pKbusInputBitData;\n\n"); + + fprintf(fPtr,"uint8_t * pKbusOutputData;\n"); + fprintf(fPtr,"uint8_t * pKbusOutputBitData;\n\n"); + + fclose(fPtr); + + // Now the summary in a simple Ascii-File (target of this file is a simple machine readable form) + printf("\nWriting Summary file %s\n",SUMMARYINFOFILENAME); + fPtr = fopen(SUMMARYINFOFILENAME, "w"); + if (fPtr == NULL) + { + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + + printf("ERROR: Cannot open outfile %s\n",SUMMARYINFOFILENAME); + return EOPENSUMFILEFAILED; // exit program + } + + tmpTime = time(NULL); + tmPtr = localtime(&tmpTime); + + fprintf(fPtr,"%%******************************************************************************\n%%\n"); + fprintf(fPtr,"%% Created by getkbusheader at %d-%02d-%02d_%02d:%02d:%02d\n", + tmPtr->tm_year+1900,tmPtr->tm_mon+1,tmPtr->tm_mday, + tmPtr->tm_hour,tmPtr->tm_min,tmPtr->tm_sec); + fprintf(fPtr,"%% see %s for further information\n%%\n", DECOUTFILENAME); + fprintf(fPtr,"%%******************************************************************************\n\n"); + + fprintf(fPtr,"%%Position Type BitOffsetOut BitSizeOut BitOffsetIn BitSizeIn Channels PiFormat\n"); + + for (ucPosition = 1; ucPosition <= ucMaxPosition; ucPosition++) + { + const u32 idx = ucPosition - 1; + + fprintf(fPtr,"%4i %6i %4i %4i %4i %4i %i %i\n", + ucPosition, + terminals[idx], + terminalDescription[idx].OffsetOutput_bits, + terminalDescription[idx].SizeOutput_bits, + terminalDescription[idx].OffsetInput_bits, + terminalDescription[idx].SizeInput_bits, + terminalDescription[idx].AdditionalInfo.ChannelCount, + terminalDescription[idx].AdditionalInfo.PiFormat); + } + + fclose(fPtr); + + adi->CloseDevice(kbusDeviceId); // close kbus device + adi->Exit(); // disconnect ADI-Interface + ldkc_KbusInfo_Destroy(); + + printf("\ngetkbusinfo successful executed\n"); + + return OISSOK; // exit program +} + +int main(int argc, char* argv[]) +{ + int program; + + printf("You have to stop CoDeSys-Runtime *plclinux_rt* before running this demo \n"); + printf("With kill *plclinux_rt*\n"); + printf("OR /etc/init.d/runtime stop \n"); + + if(argc > 1) + { + program = *argv[1] - 48; + } + else + { + printf("The first Argument has to be a number with the Programm you want to start.\n"); + printf("Available programs:\n"); + printf("1: KBusDemo, Operating mode *running* \n"); + printf("2: GetKBusInfo, Using DBUS to retrieve Kbus details \n"); + printf("3: GetKBusHeader, Build suitable header files for connected IO-Terminals \n"); + + return -1; + } + + + switch (program) { + case 1: + return KBusDemo(); + + case 2: + return GetKBusInfo(); + + case 3: + return getKBusHeader(); + + default: + printf("Kein Demo-Programm gefunden mit ID: %d", program); + return 0; + } +}