--- a/HostFirmwareUpdater.py Wed Jul 29 10:52:37 2020 +0200
+++ b/HostFirmwareUpdater.py Mon Apr 12 10:01:38 2021 +0200
@@ -34,6 +34,8 @@
+from LPCArch import GetLPCArch UPDATE_SCRIPT_TIMEOUT = 600
class HostFirmwareUpdater(object):
@@ -65,7 +67,9 @@
self._CreateFirmwareImageFileSizeMD5File()
self._CreateFirmwareImageFileMD5File()
# start the update script
- status, textError = self.controller._connector.RunUpdateScript(self.updateType)
+ product_name = GetLPCArch() + updateFlashTypeArg = "mmc" if product_name == "MC10" else "ubi" + status, textError = self.controller._connector.RunUpdateScript(self.updateType, updateFlashTypeArg) raise Exception(textError)
# The update script is now running: Feeding the update script with firmware image data
--- a/LPCArch.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCArch.py Mon Apr 12 10:01:38 2021 +0200
@@ -1,15 +1,31 @@
-PLC_GOT_modules = ['GOT', 'GOT_111', 'GOT_131', 'LHC2_GOT_111']
-PLC_MC9_modules = ['MC9', 'MW1']
-SOM28_modules = PLC_MC9_modules + PLC_GOT_modules
+WX_GOT_modules = ['GOT', 'GOT_111', 'GOT_131', 'LHC2_GOT_111'] +SVG_GOT_modules = ['GOT_012'] +MC9_modules = ['MC9', 'MW1'] +SOM28_modules = MC9_modules + WX_GOT_modules +SOM6_modules = SVG_GOT_modules
+def SetLPCProduct(given):
+ if product in SOM28_modules: + if product in SOM6_modules:
+ if product in SOM28_modules: + elif product in SOM6_modules: + elif product is "MC8" : --- a/LPCBeremiz.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCBeremiz.py Mon Apr 12 10:01:38 2021 +0200
@@ -3,7 +3,6 @@
from __future__ import absolute_import
-from VariableExporter import VariableWriter
# XXX TODO : strip dead code. document.
@@ -16,15 +15,6 @@
class LPCBeremiz(Beremiz):
def _init_coll_FileMenu_Items(self, parent):
- config = wx.ConfigBase.Get()
- export = str(config.Read("Exporter"))
- config.Write("Exporter", '0')
AppendMenu(parent, help='', id=wx.ID_SAVE,
kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S'))
AppendMenu(parent, help='', id=wx.ID_CLOSE,
@@ -37,10 +27,6 @@
AppendMenu(parent, help='', id=wx.ID_PRINT,
kind=wx.ITEM_NORMAL, text=_(u'Print'))
- AppendMenu(parent, help='', id=ID_EXPORT,
- kind=wx.ITEM_NORMAL, text=_(u'Export'))
- parent.AppendSeparator()
AppendMenu(parent, help='', id=wx.ID_EXIT,
kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q'))
@@ -49,8 +35,6 @@
self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP)
self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW)
self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT)
- self.Bind(wx.EVT_MENU, lambda event: VariableWriter(self, event, self.CTR.ProjectPath), id=ID_EXPORT)
self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT)
self.AddToMenuToolBar([(wx.ID_SAVE, "save", _(u'Save'), None),
--- a/LPCBus.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCBus.py Mon Apr 12 10:01:38 2021 +0200
@@ -3,22 +3,27 @@
modpath = os.path.split(__file__)[0]
-from LPCArch import GetLPCArch, SOM28_modules
+from LPCArch import GetLPCArch, GetLPCProduct, SOM28_modules +product = GetLPCProduct() -if arch in SOM28_modules:
- bus_template_name = "MC9"
- bus_template_name = arch
LPCBusSourcePath = os.path.join(modpath,"LPCBus")
return open(os.path.join(LPCBusSourcePath,fname)).read()
-Busses = [ "Right", "On Board", "Devices" ]
+# busses available per architecture +Busses = {"MC8" :[ ("Right", "uC_Right"), + ("On Board", "uC_OnBoard"), + ("Devices", "uC_Devices")], + "MC9" :[ ("Right", "SOM28_Right"), + ("On Board", "SOM_OnBoard"), + ("Devices", "SOM_Devices")], + "MC10" :[("On Board", "SOM_OnBoard"), + ("Devices", "SOM_Devices")]} -# This matches names of .h files in LPCBus with Arch from LPCArch
+# This matches names of .h files in LPCBus with product from LPCArch @@ -26,9 +31,13 @@
"LHC2_GOT_111":"LHC2_GOT100"
-bus_template_code = { plc:GetLocalCode(plc+".c") for plc in ["MC8", "MC9"] }
+bus_template_code = { plc: GetLocalCode( + "MC10": "SOM"}[plc]+".c") for plc in Busses.keys()} # This is in case some bus has some special LDFLAGS
@@ -224,16 +233,16 @@
- bus_code = { "MC9:%s"%bus :
+ bus_code = { "%s:%s"%(arch, bus_name) : - header + GetLocalCode("%s_%s_%s.c"%("MC9",''.join(bus.split()),section))
+ header + GetLocalCode("%s_%s.c"%(bus_template,section)) - ("decl",GetLocalCode("%s.h" % headernames[arch])),
+ ("decl",GetLocalCode("%s.h" % headernames[product])),
+ for bus_name, bus_template in Busses[arch]} for module in GetModuleChildren(self):
@@ -280,7 +289,7 @@
code_str["publish_code"] += " " + var["Publish"] % ("*" + var["location"]) + "\n"
- BusName = bus_template_name + ":" + self.BaseParams.getName()
+ BusName = arch + ":" + self.BaseParams.getName() @@ -298,12 +307,12 @@
"bus_publish_code": bcode("publish"),
- if bus_template_name not in bus_template_code:
- raise Exception, "Unknown arch %s. Please use %s"%(
- bus_template_name,repr(bus_template_code.keys()))
+ if arch not in bus_template_code: + raise Exception, "Unknown product %s. Please use %s"%( + arch,repr(bus_template_code.keys())) Gen_Module_path = os.path.join(buildpath, "Bus_%s.c"%location_str)
module = open(Gen_Module_path,'w')
- module.write(bus_template_code[bus_template_name] % code_str)
+ module.write(bus_template_code[arch] % code_str) cflags = '"-I%s" "-I%s" -Wno-unused-function'%(
--- a/LPCBus/GOT.h Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCBus/GOT.h Mon Apr 12 10:01:38 2021 +0200
@@ -1,3 +1,9 @@
-#ifndef RUN_LED_GPIO_1_31
-#define RUN_LED_GPIO_1_31
+// GPIO_1_31 = 32 + 31 = 63 +#define LPCBUS_DEVICES_PORT "/dev/ttyAPP1" --- a/LPCBus/GOT100.h Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCBus/GOT100.h Mon Apr 12 10:01:38 2021 +0200
@@ -1,15 +1,16 @@
-#ifndef RUN_LED_GPIO_1_31
-#define RUN_LED_GPIO_1_31
-#ifndef CAN0_EN_GPIO_0_21
-#define CAN0_EN_GPIO_0_21
+// GPIO_1_31 = 32 + 31 = 63 -#ifndef CAN1_EN_GPIO_0_17
-#define CAN1_EN_GPIO_0_17
+#define LPCBUS_DEVICES_PORT "/dev/ttyAPP1" --- a/LPCBus/LHC2_GOT100.h Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCBus/LHC2_GOT100.h Mon Apr 12 10:01:38 2021 +0200
@@ -1,7 +1,19 @@
+// GPIO_1_31 = 32 + 31 = 63
+#define LPCBUS_DEVICES_PORT "/dev/ttyAPP3" --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/MC10.h Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,9 @@
+#define LPCBUS_DEVICES_PORT "/dev/ttymxc2" --- a/LPCBus/MC8.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/* Code generated by LPCBus confnode */
-/* LPCBus confnode includes */
- #include "iec_std_lib.h"
-/* LPCBus confnode user variables definition */
-/* LPCBus confnode functions */
-int __init_%(location_str)s(int argc,char **argv)
-void __cleanup_%(location_str)s(void)
-void __retrieve_%(location_str)s(void)
-void __publish_%(location_str)s(void)
--- a/LPCBus/MC9.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/* Code generated by LPCBus confnode */
- #include "iec_std_lib.h"
-static inline int16_t getWord(char *buffer)
- return ((int16_t)*buffer<<8) + (int16_t)*(buffer+1);
-static inline int16_t getWordSwapped(char *buffer)
- return (((int16_t)*(buffer+1))<<8) + (int16_t)*buffer;
-static inline void setWord(char *buffer, int16_t word)
- *buffer = (char)(word>>8);
- *(buffer+1) = (char)(word);
-static inline void setWordSwapped(char *buffer, int16_t word)
- *(buffer+1) = (char)(word>>8);
-static inline int8_t getBit(char *buffer, unsigned char bitOffset)
- return (*buffer & (0x01 << bitOffset)) && 1;
-static inline void setBit(char *buffer, unsigned char bitOffset, int8_t bit)
- unsigned char msk = (0x01 << bitOffset);
-static void setWord16(short *buffer, uint16_t word)
-static int16_t getWord16(short *buffer)
- return((uint16_t)*buffer);
-static inline unsigned char getByte(char *buffer)
- return((unsigned char)*buffer);
-static inline void setByte(char *buffer, unsigned char byte)
- unsigned char status; /* Current status of timer - running / expired */
- uint64_t actValue; /* Actual timer value */
- uint64_t toValue; /* Timeout value - initialized at startup */
- uint64_t oldTime; /* Time at previous timer increment; NOTE: if RTIME (unsigned long long) changes type, oldTime has to be adapted */
-#define TIM_EN_RUNNING 1
-#define TIM_EN_EXPIRED 2
-/* LPCBus confnode user variables definition */
-/* LPCBus confnode functions */
-int __init_%(location_str)s(int argc,char **argv)
-void __cleanup_%(location_str)s(void)
-void __retrieve_%(location_str)s(void)
-void __publish_%(location_str)s(void)
--- a/LPCBus/MC9.h Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCBus/MC9.h Mon Apr 12 10:01:38 2021 +0200
@@ -1,11 +1,15 @@
-#ifndef RUN_LED_GPIO_1_13
-#define RUN_LED_GPIO_1_13
+// GPIO_1_13 = 32 + 13 = 45 -#ifndef CAN0_EN_GPIO_0_21
-#define CAN0_EN_GPIO_0_21
-#ifndef CAN1_EN_GPIO_0_17
-#define CAN1_EN_GPIO_0_17
+#define LPCBUS_DEVICES_PORT "/dev/ttyAPP1" --- a/LPCBus/MC9_Devices_cleanup.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-pthread_mutex_lock(&UART_WakeCondLock);
-pthread_cond_signal(&UART_WakeCond);
-pthread_mutex_unlock(&UART_WakeCondLock);
-pthread_join(UART_task, NULL);
--- a/LPCBus/MC9_Devices_decl.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,588 +0,0 @@
-#include <alchemy/task.h>
-#include <alchemy/mutex.h>
-#include <alchemy/timer.h>
-static struct termios oldterminfo;
-void closeserial(int fd)
- tcsetattr(fd, TCSANOW, &oldterminfo);
- perror("closeserial()");
-/*--------------------------- Serial Port handling ---------------------------*/
-int openserial(char *devicename, unsigned long baudrate)
- speed_t baud = B115200; /* baud rate */
- if ((fd = open(devicename, O_RDWR)) == -1) {
- perror("openserial(): open()");
- if (tcgetattr(fd, &oldterminfo) == -1) {
- perror("openserial(): tcgetattr()");
- attr.c_cflag |= CLOCAL;
- attr.c_cflag |= CS8 ; /* 8 bits */
- /* no parity, 1 stop bit */
- cfsetspeed(&attr, baud); /* baud rate */
- if (tcflush(fd, TCIOFLUSH) == -1) {
- perror("openserial(): tcflush()");
- if (tcsetattr(fd, TCSANOW, &attr) == -1) {
- perror("initserial(): tcsetattr()");
-#define MAX_UART_DEVICES 32
-#define UART_BUFSIZE_SHORT 26 /* UART bus read & write buffer size - short buffer for LPC-2 */
-#define UART_BUFSIZE_LONG 48 /* UART bus read & write buffer size - long buffer for LHC-2 */
-#define UART_RETRY_NUM 0
-char uartBufSize = UART_BUFSIZE_SHORT; /* Smarteh uart bus: buffer size */
-unsigned long uartBaudrate = 19200; /* Smarteh uart bus: baudrate */
-struct timeval uartTimeout = {0,40000}; /* Smarteh uart bus: timeout */
-/* Tables containing information about connected devices on UART port
- (initialized by Composer) */
-unsigned char uartDev[MAX_UART_DEVICES][2];
-unsigned char uartDevNum = MAX_UART_DEVICES;
-/* Buffers for reading data from UART port devices */
-typedef char uartDevReadBuf_t[MAX_UART_DEVICES][UART_BUFSIZE_LONG];
-uartDevReadBuf_t uartDevReadBufA;
-uartDevReadBuf_t uartDevReadBufB;
-uartDevReadBuf_t *uartDevReadBuf_drv;
-uartDevReadBuf_t *uartDevReadBuf_plc;
-uartDevReadBuf_t uartDevReadBuf;
-/* Buffers for writing data to UART port devices */
-typedef char uartDevWriteBuf_t[MAX_UART_DEVICES][UART_BUFSIZE_LONG];
-uartDevWriteBuf_t uartDevWriteBufA;
-uartDevWriteBuf_t uartDevWriteBufB;
-uartDevWriteBuf_t *uartDevWriteBuf_drv;
-uartDevWriteBuf_t *uartDevWriteBuf_plc;
-#define uartDevWriteBuf (*uartDevWriteBuf_drv)
-int uartDevWriteBuf_plc_state;
-int uartDevReadBuf_plc_state;
-/* Buffers for communication statuses with UART port devices */
-/* 2D arrays due to compatibility with Composer (LpcSmartehIDE) */
-char uartCommErrCntBuf [MAX_UART_DEVICES][1];
-char uartCommStatusBuf[MAX_UART_DEVICES][1];
-/* Function interface definition for modules on UART (RS485) bus */
-typedef unsigned char (*uartPortFunct)(char*, char*, char);
-/* Table describing module positions on UART (RS485) bus (parsed from Composer data) */
-uartPortFunct uartPortDevices[MAX_UART_DEVICES] = {NULL};
-/* Table of timers (one for each position) */
-static commTimer uartPortTim[MAX_UART_DEVICES];
-static pthread_t UART_task;
-static pthread_mutex_t UART_WriteMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t UART_ReadMutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t UART_WakeCondLock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t UART_WakeCond = PTHREAD_COND_INITIALIZER;
-static int UART_WakeCondValue = 0;
-static int UART_task_active;
-void* UART_task_proc(void *arg)
- static unsigned char i=0;
- static uint64_t lastCommTime=0;
- struct sched_param param = { .sched_priority = 10 };
- pthread_setname_np(pthread_self(), "UART_task");
- pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m);
- pthread_mutex_lock(&UART_WakeCondLock);
- active = UART_task_active;
- while(!UART_WakeCondValue && active){
- pthread_cond_wait(&UART_WakeCond, &UART_WakeCondLock);
- active = UART_task_active;
- UART_WakeCondValue = 0;
- pthread_mutex_unlock(&UART_WakeCondLock);
- // Communicate only with initialised UART devices
- if(uartPortDevices[i] != NULL)
- // Timers for UART port modules
- if(uartPortTim[i].status != TIM_DISABLED)
- struct timespec time_ref;
- if(clock_gettime(CLOCK_MONOTONIC, &time_ref)){
- perror("clock_gettime(time_ref)");
- actTime = time_ref.tv_nsec + time_ref.tv_sec * 1000000000LL;
- uartPortTim[i].actValue = actTime - uartPortTim[i].oldTime;
- if((uartPortTim[i].actValue < uartPortTim[i].toValue)
- || (actTime - lastCommTime < 50000000))
- uartPortTim[i].status = TIM_EN_RUNNING;
- uartPortTim[i].status = TIM_EN_EXPIRED;
- uartPortTim[i].oldTime = actTime;
- lastCommTime = actTime;
- if((uartPortTim[i].status == TIM_DISABLED)
- || (uartPortTim[i].status == TIM_EN_EXPIRED))
- if(!pthread_mutex_lock(&UART_WriteMutex)){
- if(uartDevWriteBuf_plc_state == FULL){
- uartDevWriteBuf_t *uartDevWriteBuf_tmp;
- uartDevWriteBuf_tmp = uartDevWriteBuf_plc;
- uartDevWriteBuf_plc = uartDevWriteBuf_drv;
- uartDevWriteBuf_drv = uartDevWriteBuf_tmp;
- uartDevWriteBuf_plc_state = EMPTY;
- pthread_mutex_unlock(&UART_WriteMutex);
- // Communicate with device
- commStat = (*uartPortDevices[i])(
- &uartDevWriteBuf[i][0],
- memcpy(uartDevReadBuf_drv, &uartDevReadBuf, sizeof(uartDevReadBuf_t));
- if(!pthread_mutex_lock(&UART_ReadMutex)){
- if(uartDevReadBuf_plc_state == EMPTY){
- uartDevReadBuf_t *uartDevReadBuf_tmp;
- uartDevReadBuf_tmp = uartDevReadBuf_plc;
- uartDevReadBuf_plc = uartDevReadBuf_drv;
- uartDevReadBuf_drv = uartDevReadBuf_tmp;
- uartDevReadBuf_plc_state = FULL;
- pthread_mutex_unlock(&UART_ReadMutex);
- // Check communication status:
- uartCommStatusBuf[i][0] = TRUE;
- uartCommErrCntBuf[i][0] = 0;
- if(uartCommErrCntBuf[i][0] < UART_RETRY_NUM)
- uartCommErrCntBuf[i][0]++;
- uartCommStatusBuf[i][0] = FALSE;
- // If timer is enabled, reset it's value,
- // otherwise keep it disabled
- if(uartPortTim[i].status != TIM_DISABLED)
- uartPortTim[i].actValue = 0;
- uartPortTim[i].status = TIM_EN_RUNNING;
- else /* Keep timer disabled */
- uartPortTim[i].status = TIM_DISABLED;
- // Procede with next UART device only after
- // communication with the current one is done
- else /* Go back to the first UART device */
-#define TAIL_LEN 3 /* Length of data tail in bytes */
-/**************************************************************************//**
-* Calculate checksum of a buffer
-* @param [in] buffer Pointer to buffer
-* @param [in] bufLen Buffer length
-* @return Checksum values on buffer locations bufLen-TAIL_LEN &
-******************************************************************************/
-void Checksum(unsigned char *buffer, unsigned char bufLen)
- unsigned char i=0, j=0;
- unsigned char checksum1=0, checksum2=0;
- unsigned char checksum1Temp=0;
- for(i=0;i<bufLen-TAIL_LEN;i++)
- checksum1Temp=buffer[i];
- for(j=0;j<8;j++) /* Compute number of '1' of whole buff. */
- if((checksum1Temp & 0x01)>0)
- checksum1Temp = checksum1Temp >> 1;
- checksum2 = checksum2 ^ buffer[i]; /* Compute XOR of whole buffer */
- buffer[bufLen-TAIL_LEN] = checksum2; /* Write number of '1' to buffer */
- buffer[bufLen-TAIL_LEN+1] = checksum1; /* Write XOR to buffer */
-/**************************************************************************//**
-* Check if checksum values of received buffer are valid
-* @param [in] buffer Pointer to buffer
-* @param [in] bufLen Buffer length
-* @return TRUE if valid, otherwise FALSE
-******************************************************************************/
-unsigned char ChecksumValid(unsigned char *buffer, unsigned char bufLen)
- unsigned char i=0, j=0;
- unsigned char checksum1=0, checksum2=0;
- unsigned char checksum1Temp=0;
- for(i=0;i<bufLen-TAIL_LEN;i++)
- checksum1Temp = buffer[i];
- for(j=0;j<8;j++) /* Compute number of '1' of whole buff. */
- if((checksum1Temp & 0x01)>0)
- checksum1Temp = checksum1Temp >> 1; /* Compute XOR of whole buffer */
- checksum2 = checksum2 ^ buffer[i];
- /* Check if computed checksums are the same as those in buffer (=> no error) */
- if((checksum2==buffer[bufLen-TAIL_LEN]) && (checksum1==buffer[bufLen-TAIL_LEN+1]))
-/*************************************************************************//**
-* Support for UART modules
-* @param [in] readBuf Pointer to read buffer (for previously polled UART device!)
-* @param [out] writeBuf Pointer to write buffer (for current device)
-* @param [in] address UART device address
-* @return TRUE if communication was successful, otherwise FALSE
-*****************************************************************************/
-unsigned char UARTDevice(char* readBuf, char* writeBuf, char address)
- struct timeval timeout;
- /* Prepare transmit buffer */
- memcpy(tmp+1,writeBuf,uartBufSize-TAIL_LEN-1);
- tmp[uartBufSize-TAIL_LEN] = address;
- Checksum((unsigned char*)tmp+1, uartBufSize);
- tcflush(UART_fd, TCIOFLUSH);
- if(write(UART_fd, tmp, uartBufSize) != uartBufSize){
- FD_ZERO(&set); /* clear the set */
- FD_SET(UART_fd, &set); /* add our file descriptor to the set */
- timeout.tv_sec = uartTimeout.tv_sec;
- timeout.tv_usec = uartTimeout.tv_usec;
- while(count < uartBufSize){
- rv = select(UART_fd + 1, &set, NULL, NULL, &timeout);
- printf("RS485 select error\n");
- int rr = read(UART_fd, tmp + count, uartBufSize - count);
- printf("RS485 read error %%d\n",rr);
- /* Copy received buffer */
- if((count == uartBufSize) && (tmp[uartBufSize-TAIL_LEN] == address)){
- if(ChecksumValid((unsigned char*)tmp+1, uartBufSize)){
- memcpy(readBuf,tmp+1,uartBufSize-TAIL_LEN-1);
- tcflush(UART_fd, TCIOFLUSH);
-/* Macro to transform milliseconds to ns */
-#define msTOns(ms) (1000000L*ms)
-void InitUartPortDevices_longBuffer(void)
- uartTimeout.tv_sec = 0;
- uartTimeout.tv_usec = 20000; /* 20 ms timeout */
- for(i=0;i<MAX_UART_DEVICES;i++)
- uartPortDevices[i] = &UARTDevice;
- uartPortTim[i].toValue = msTOns(50); /* 50ms */
- uartPortTim[i].status = TIM_EN_RUNNING;
- case(240): /* 240-254 are reserved for EEPROM settings */
- uartPortDevices[i] = NULL; /* "Empty" or unknown module */
- uartPortTim[i].status = TIM_DISABLED;
- uartDevNum--; /* Substract unused devices from MAX_UART_DEVICES */
-void InitUartPortDevices_shortBuffer(void)
- uartTimeout.tv_sec = 0;
- uartTimeout.tv_usec = 40000; /* 40 ms timeout */
- for(i=0;i<MAX_UART_DEVICES;i++)
- case(130): /* P01, P02, P01V, P02V */
- case(178): /* AQ1, SM1, SM5, SM6, SM7 */
- uartPortDevices[i] = &UARTDevice;
- uartPortTim[i].toValue = msTOns(250); /* 250ms */
- uartPortTim[i].status = TIM_EN_RUNNING;
- uartPortDevices[i] = &UARTDevice;
- uartPortTim[i].toValue = msTOns(650); /* 650ms */
- uartPortTim[i].status = TIM_EN_RUNNING;
- case(170): /* ID1, ID2, ID3 */
- uartPortDevices[i] = &UARTDevice;
- uartPortTim[i].toValue = msTOns(450); /* 450ms */
- uartPortTim[i].status = TIM_EN_RUNNING;
- uartPortDevices[i] = NULL; /* "Empty" or unknown module */
- uartPortTim[i].status = TIM_DISABLED;
--- a/LPCBus/MC9_Devices_init.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-char *serialdev = "/dev/ttyAPP3";
-char *serialdev = "/dev/ttyAPP1";
-uartDevWriteBuf_plc_state = EMPTY;
-uartDevReadBuf_plc_state = EMPTY;
-bzero(&uartDev, sizeof(uartDev));
-bzero(&uartDevReadBufA, sizeof(uartDevReadBuf_t));
-bzero(&uartDevReadBufB, sizeof(uartDevReadBuf_t));
-uartDevReadBuf_drv = &uartDevReadBufA;
-uartDevReadBuf_plc = &uartDevReadBufB;
-bzero(&uartDevWriteBufA, sizeof(uartDevWriteBuf_t));
-bzero(&uartDevWriteBufB, sizeof(uartDevWriteBuf_t));
-uartDevWriteBuf_drv = &uartDevWriteBufA;
-uartDevWriteBuf_plc = &uartDevWriteBufB;
-bzero(&uartCommStatusBuf, sizeof(uartCommStatusBuf));
-bzero(&uartCommErrCntBuf, sizeof(uartCommErrCntBuf));
-UART_fd = openserial(serialdev, uartBaudrate); /* uartBaudrate is initialized from Composer */
- fprintf(stderr, "Error while initializing %%s.\n", serialdev);
-if(uartBufSize == UART_BUFSIZE_LONG) /* uartBufSize is initialized from Composer */
- InitUartPortDevices_longBuffer();
- InitUartPortDevices_shortBuffer();
-if(err = pthread_create(&UART_task, NULL, &UART_task_proc, NULL));
--- a/LPCBus/MC9_Devices_publish.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-if(!pthread_mutex_lock(&UART_WriteMutex)){
- prevstate=uartDevWriteBuf_plc_state;
- uartDevWriteBuf_plc_state = LOCKED;
- pthread_mutex_unlock(&UART_WriteMutex);
- /* unlock plc buffer */
- uartDevWriteBuf_plc_state = FULL;
- pthread_mutex_lock(&UART_WakeCondLock);
- UART_WakeCondValue = 1;
- pthread_cond_signal(&UART_WakeCond);
- pthread_mutex_unlock(&UART_WakeCondLock);
--- a/LPCBus/MC9_Devices_retrieve.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-if(!pthread_mutex_lock(&UART_ReadMutex)){
- if((prevstate=uartDevReadBuf_plc_state) == FULL){
- uartDevReadBuf_plc_state = LOCKED;
- pthread_mutex_unlock(&UART_ReadMutex);
- /* unlock plc buffer */
- uartDevReadBuf_plc_state = EMPTY;
- /* No new data -> no update */
--- a/LPCBus/MC9_OnBoard_cleanup.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-#endif /* ONBOARD_I2C */
-#ifdef CAN0_EN_GPIO_0_21
-gpio_set_pin_value(CAN0_EN_dev, 1);
-gpio_close(CAN0_EN_dev);
-#endif /* CAN0_EN_GPIO_0_21 */
-#ifdef CAN1_EN_GPIO_0_17
-gpio_set_pin_value(CAN1_EN_dev, 1);
-gpio_close(CAN1_EN_dev);
-#endif /* CAN1_EN_GPIO_0_17 */
-gpio_set_pin_value(RUN_LED_dev, 1);
-gpio_close(RUN_LED_dev);
--- a/LPCBus/MC9_OnBoard_decl.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*------------------------- GPIO -------------------------------------*/
-/* from armadeus/target/packages/as_devices/c/as_gpio* */
-# define ERROR(fmt, ...) printf(fmt, ##__VA_ARGS__)
-//# define ERROR(fmt, ...) /*fmt, ##__VA_ARGS__*/
- int pin_file; /* pin file for 2.6.29 interface*/
-struct gpio_device *RUN_LED_dev;
-#ifdef CAN0_EN_GPIO_0_21
-struct gpio_device *CAN0_EN_dev;
-#endif /* CAN0_EN_GPIO_0_21 */
-#ifdef CAN1_EN_GPIO_0_17
-struct gpio_device *CAN1_EN_dev;
-#endif /* CAN1_EN_GPIO_0_17 */
-static int write_file_bool(int fd, int value)
- ret = write(fd, value?"1":"0", 1);
- ERROR("write error\n");
- if (lseek(fd, 0, SEEK_SET) < 0) {
- ERROR("lseek error\n");
-static int gpio_set_pin_value(struct gpio_device *aDev, int aValue)
- int pin_file = aDev->pin_file;
- retval = write_file_bool(pin_file, aValue);
- ERROR("Can't write value\n");
-static struct gpio_device *gpio_open(int aGpioNum)
- struct gpio_device *dev;
- export_file = open("/sys/class/gpio/export", O_WRONLY);
- ERROR("Can't open /sys/class/gpio/export\nBe sure that gpiolib is under your kernel\n");
- snprintf(buf, BUFF_SIZE, "%%d", aGpioNum);
- retval = write(export_file, buf, strlen(buf));
- ERROR("/sys/class/gpio/export can't be written\n");
- snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/direction", aGpioNum);
- gpio_dir_fd = open(buf, O_WRONLY);
- ERROR("Can't open gpio%%d direction\n", aGpioNum);
- ret = write(gpio_dir_fd, "out", 3);
- ERROR("Error writing direction\n");
- snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/value", aGpioNum);
- pin_file = open(buf, O_RDWR);
- ERROR("Can't export gpio number %%d\n", aGpioNum);
- dev = malloc(sizeof(struct gpio_device));
- ERROR("Can't allocate gpio_device structure\n");
- dev->port_num = aGpioNum;
- dev->pin_file = pin_file;
- gpio_set_pin_value(dev, 1);
-static int gpio_close(struct gpio_device *aDev)
- ERROR("device is NULL\n");
- unexport_file = open("/sys/class/gpio/unexport", O_WRONLY);
- if (unexport_file < 0) {
- ERROR("Can't open /sys/class/gpio/unexport\nBe sure that gpiolib is under your kernel\n");
- snprintf(buf, BUFF_SIZE, "%%d", aDev->port_num);
- retval = write(unexport_file, buf, strlen(buf));
- ERROR("/sys/class/gpio/unexport can't be written\n");
-/* TODO : DELETE !... but keep this until composer stops sending code snippets for mbrtu */
- MB_PAR_ODD = 0, /**< ODD parity. */
- MB_PAR_EVEN = 1, /**< Even parity. */
- MB_PAR_NONE = 2 /**< No parity. */
-unsigned long mbBaudRate = 115200; /**< Modbus baud-rate setting: 9600, 19200, 38400, 57600, 115200 */
-eMBSerialParity mbParity = MB_PAR_NONE; /**< Modbus parity setting: odd, even, none */
-#include "rt_imx_smt_onboard.h"
-static readBuf_t onBoardReadBuf;
-static writeBuf_t onBoardWriteBuf;
-static busInit_t onBoardBusInit;
-static int onboardbusfd = -1;
-#endif /* ONBOARD_I2C */
--- a/LPCBus/MC9_OnBoard_init.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#define ONBOARDDEVFILENAME "/dev/rtdm/onboard"
-bzero(&onBoardReadBuf , sizeof(readBuf_t));
-bzero(&onBoardWriteBuf, sizeof(writeBuf_t));
-bzero(&onBoardBusInit , sizeof(busInit_t));
-onBoardBusInit.common_ticktime__ = common_ticktime__;
-#define onBoardDev (onBoardBusInit.rightI2CMod)
-#endif /* ONBOARD_I2C */
-#ifdef CAN0_EN_GPIO_0_21
-CAN0_EN_dev = gpio_open(21);
-gpio_set_pin_value(CAN0_EN_dev, 0);
-#endif /* CAN0_EN_GPIO_0_21 */
-#ifdef CAN1_EN_GPIO_0_17
-CAN1_EN_dev = gpio_open(17);
-gpio_set_pin_value(CAN1_EN_dev, 0);
-#endif /* CAN1_EN_GPIO_0_17 */
-for(i=0; i<MAX_RIGHT_MODULES; i++) {
- switch(onBoardDev[i][1]) {
- onboardbusfd = open(ONBOARDDEVFILENAME, 0);
- printf("can't open %%s rtdm device, %%s\n", ONBOARDDEVFILENAME,
- strerror(-onboardbusfd));
- err = ioctl(onboardbusfd, RTSMT_RTIOC_INIT, &onBoardBusInit);
- printf("error while RTSMT_RTIOC_INIT, %%s\n", strerror(-err));
-#endif /* ONBOARD_I2C */
-#if defined RUN_LED_GPIO_1_13
-RUN_LED_dev = gpio_open(45);
-#elif defined RUN_LED_GPIO_1_31
-RUN_LED_dev = gpio_open(63);
-#endif /* RUN LED GPIO_1_13/GPIO_1_31 */
-gpio_set_pin_value(RUN_LED_dev, 0);
--- a/LPCBus/MC9_OnBoard_publish.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
- ioctl(onboardbusfd, RTSMT_RTIOC_WRITE, &onBoardWriteBuf);
-#endif /* ONBOARD_I2C */
--- a/LPCBus/MC9_OnBoard_retrieve.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
- ioctl(onboardbusfd, RTSMT_RTIOC_READ, &onBoardReadBuf);
-#endif /* ONBOARD_I2C */
--- a/LPCBus/MC9_Right_cleanup.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
--- a/LPCBus/MC9_Right_decl.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#include "rt_imx_smt_right.h"
-static readBuf_t rightReadBuf;
-static writeBuf_t rightWriteBuf;
-static busInit_t rightBusInit;
-static int rightbusfd = -1;
-/* XXX TODO #include "smarteh.h" */
--- a/LPCBus/MC9_Right_init.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#define DEVICEFILENAME "/dev/rtdm/rightbus"
-bzero(&rightReadBuf, sizeof(readBuf_t));
-bzero(&rightWriteBuf, sizeof(writeBuf_t));
-bzero(&rightBusInit, sizeof(busInit_t));
-rightBusInit.common_ticktime__ = common_ticktime__;
-#define rightI2CMod (rightBusInit.rightI2CMod)
-rightbusfd = open( DEVICEFILENAME, 0);
- printf("can't open %%s rtdm device, %%s\\n", DEVICEFILENAME,
- strerror(-rightbusfd));
-err = ioctl(rightbusfd, RTSMT_RTIOC_INIT, &rightBusInit);
- printf("error while RTSMT_RTIOC_INIT, %%s\\n",
--- a/LPCBus/MC9_Right_publish.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-ioctl(rightbusfd, RTSMT_RTIOC_WRITE, &rightWriteBuf);
--- a/LPCBus/MC9_Right_retrieve.c Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-ioctl(rightbusfd, RTSMT_RTIOC_READ, &rightReadBuf);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,105 @@
+/* Code generated by LPCBus confnode */ + #include "iec_std_lib.h" +static inline int16_t getWord(char *buffer) + return ((int16_t)*buffer<<8) + (int16_t)*(buffer+1); +static inline int16_t getWordSwapped(char *buffer) + return (((int16_t)*(buffer+1))<<8) + (int16_t)*buffer; +static inline void setWord(char *buffer, int16_t word) + *buffer = (char)(word>>8); + *(buffer+1) = (char)(word); +static inline void setWordSwapped(char *buffer, int16_t word) + *(buffer+1) = (char)(word>>8); +static inline int8_t getBit(char *buffer, unsigned char bitOffset) + return (*buffer & (0x01 << bitOffset)) && 1; +static inline void setBit(char *buffer, unsigned char bitOffset, int8_t bit) + unsigned char msk = (0x01 << bitOffset); +static void setWord16(short *buffer, uint16_t word) +static int16_t getWord16(short *buffer) + return((uint16_t)*buffer); +static inline unsigned char getByte(char *buffer) + return((unsigned char)*buffer); +static inline void setByte(char *buffer, unsigned char byte) + unsigned char status; /* Current status of timer - running / expired */ + uint64_t actValue; /* Actual timer value */ + uint64_t toValue; /* Timeout value - initialized at startup */ + uint64_t oldTime; /* Time at previous timer increment; NOTE: if RTIME (unsigned long long) changes type, oldTime has to be adapted */ +#define TIM_EN_RUNNING 1 +#define TIM_EN_EXPIRED 2 +/* LPCBus confnode user variables definition */ +/* LPCBus confnode functions */ +int __init_%(location_str)s(int argc,char **argv) +void __cleanup_%(location_str)s(void) +void __retrieve_%(location_str)s(void) +void __publish_%(location_str)s(void) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM28_Right_cleanup.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,1 @@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM28_Right_decl.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,12 @@
+#include "rt_imx_smt_right.h" +static readBuf_t rightReadBuf; +static writeBuf_t rightWriteBuf; +static busInit_t rightBusInit; +static int rightbusfd = -1; +/* XXX TODO #include "smarteh.h" */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM28_Right_init.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,26 @@
+#define DEVICEFILENAME "/dev/rtdm/rightbus" +bzero(&rightReadBuf, sizeof(readBuf_t)); +bzero(&rightWriteBuf, sizeof(writeBuf_t)); +bzero(&rightBusInit, sizeof(busInit_t)); +rightBusInit.common_ticktime__ = common_ticktime__; +#define rightI2CMod (rightBusInit.rightI2CMod) +rightbusfd = open( DEVICEFILENAME, 0); + printf("can't open %%s rtdm device, %%s\\n", DEVICEFILENAME, + strerror(-rightbusfd)); +err = ioctl(rightbusfd, RTSMT_RTIOC_INIT, &rightBusInit); + printf("error while RTSMT_RTIOC_INIT, %%s\\n", --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM28_Right_publish.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,2 @@
+ioctl(rightbusfd, RTSMT_RTIOC_WRITE, &rightWriteBuf); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM28_Right_retrieve.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,2 @@
+ioctl(rightbusfd, RTSMT_RTIOC_READ, &rightReadBuf); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_Devices_cleanup.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,8 @@
+pthread_mutex_lock(&UART_WakeCondLock); +pthread_cond_signal(&UART_WakeCond); +pthread_mutex_unlock(&UART_WakeCondLock); +pthread_join(UART_task, NULL); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_Devices_decl.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,588 @@
+#include <alchemy/task.h> +#include <alchemy/mutex.h> +#include <alchemy/timer.h> +static struct termios oldterminfo; +void closeserial(int fd) + tcsetattr(fd, TCSANOW, &oldterminfo); + perror("closeserial()"); +/*--------------------------- Serial Port handling ---------------------------*/ +int openserial(char *devicename, unsigned long baudrate) + speed_t baud = B115200; /* baud rate */ + if ((fd = open(devicename, O_RDWR)) == -1) { + perror("openserial(): open()"); + if (tcgetattr(fd, &oldterminfo) == -1) { + perror("openserial(): tcgetattr()"); + attr.c_cflag |= CLOCAL; + attr.c_cflag |= CS8 ; /* 8 bits */ + /* no parity, 1 stop bit */ + cfsetspeed(&attr, baud); /* baud rate */ + if (tcflush(fd, TCIOFLUSH) == -1) { + perror("openserial(): tcflush()"); + if (tcsetattr(fd, TCSANOW, &attr) == -1) { + perror("initserial(): tcsetattr()"); +#define MAX_UART_DEVICES 32 +#define UART_BUFSIZE_SHORT 26 /* UART bus read & write buffer size - short buffer for LPC-2 */ +#define UART_BUFSIZE_LONG 48 /* UART bus read & write buffer size - long buffer for LHC-2 */ +#define UART_RETRY_NUM 0 +char uartBufSize = UART_BUFSIZE_SHORT; /* Smarteh uart bus: buffer size */ +unsigned long uartBaudrate = 19200; /* Smarteh uart bus: baudrate */ +struct timeval uartTimeout = {0,40000}; /* Smarteh uart bus: timeout */ +/* Tables containing information about connected devices on UART port + (initialized by Composer) */ +unsigned char uartDev[MAX_UART_DEVICES][2]; +unsigned char uartDevNum = MAX_UART_DEVICES; +/* Buffers for reading data from UART port devices */ +typedef char uartDevReadBuf_t[MAX_UART_DEVICES][UART_BUFSIZE_LONG]; +uartDevReadBuf_t uartDevReadBufA; +uartDevReadBuf_t uartDevReadBufB; +uartDevReadBuf_t *uartDevReadBuf_drv; +uartDevReadBuf_t *uartDevReadBuf_plc; +uartDevReadBuf_t uartDevReadBuf; +/* Buffers for writing data to UART port devices */ +typedef char uartDevWriteBuf_t[MAX_UART_DEVICES][UART_BUFSIZE_LONG]; +uartDevWriteBuf_t uartDevWriteBufA; +uartDevWriteBuf_t uartDevWriteBufB; +uartDevWriteBuf_t *uartDevWriteBuf_drv; +uartDevWriteBuf_t *uartDevWriteBuf_plc; +#define uartDevWriteBuf (*uartDevWriteBuf_drv) +int uartDevWriteBuf_plc_state; +int uartDevReadBuf_plc_state; +/* Buffers for communication statuses with UART port devices */ +/* 2D arrays due to compatibility with Composer (LpcSmartehIDE) */ +char uartCommErrCntBuf [MAX_UART_DEVICES][1]; +char uartCommStatusBuf[MAX_UART_DEVICES][1]; +/* Function interface definition for modules on UART (RS485) bus */ +typedef unsigned char (*uartPortFunct)(char*, char*, char); +/* Table describing module positions on UART (RS485) bus (parsed from Composer data) */ +uartPortFunct uartPortDevices[MAX_UART_DEVICES] = {NULL}; +/* Table of timers (one for each position) */ +static commTimer uartPortTim[MAX_UART_DEVICES]; +static pthread_t UART_task; +static pthread_mutex_t UART_WriteMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t UART_ReadMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t UART_WakeCondLock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t UART_WakeCond = PTHREAD_COND_INITIALIZER; +static int UART_WakeCondValue = 0; +static int UART_task_active; +void* UART_task_proc(void *arg) + static unsigned char i=0; + static uint64_t lastCommTime=0; + struct sched_param param = { .sched_priority = 10 }; + pthread_setname_np(pthread_self(), "UART_task"); + pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); + pthread_mutex_lock(&UART_WakeCondLock); + active = UART_task_active; + while(!UART_WakeCondValue && active){ + pthread_cond_wait(&UART_WakeCond, &UART_WakeCondLock); + active = UART_task_active; + UART_WakeCondValue = 0; + pthread_mutex_unlock(&UART_WakeCondLock); + // Communicate only with initialised UART devices + if(uartPortDevices[i] != NULL) + // Timers for UART port modules + if(uartPortTim[i].status != TIM_DISABLED) + struct timespec time_ref; + if(clock_gettime(CLOCK_MONOTONIC, &time_ref)){ + perror("clock_gettime(time_ref)"); + actTime = time_ref.tv_nsec + time_ref.tv_sec * 1000000000LL; + uartPortTim[i].actValue = actTime - uartPortTim[i].oldTime; + if((uartPortTim[i].actValue < uartPortTim[i].toValue) + || (actTime - lastCommTime < 50000000)) + uartPortTim[i].status = TIM_EN_RUNNING; + uartPortTim[i].status = TIM_EN_EXPIRED; + uartPortTim[i].oldTime = actTime; + lastCommTime = actTime; + if((uartPortTim[i].status == TIM_DISABLED) + || (uartPortTim[i].status == TIM_EN_EXPIRED)) + if(!pthread_mutex_lock(&UART_WriteMutex)){ + if(uartDevWriteBuf_plc_state == FULL){ + uartDevWriteBuf_t *uartDevWriteBuf_tmp; + uartDevWriteBuf_tmp = uartDevWriteBuf_plc; + uartDevWriteBuf_plc = uartDevWriteBuf_drv; + uartDevWriteBuf_drv = uartDevWriteBuf_tmp; + uartDevWriteBuf_plc_state = EMPTY; + pthread_mutex_unlock(&UART_WriteMutex); + // Communicate with device + commStat = (*uartPortDevices[i])( + &uartDevWriteBuf[i][0], + memcpy(uartDevReadBuf_drv, &uartDevReadBuf, sizeof(uartDevReadBuf_t)); + if(!pthread_mutex_lock(&UART_ReadMutex)){ + if(uartDevReadBuf_plc_state == EMPTY){ + uartDevReadBuf_t *uartDevReadBuf_tmp; + uartDevReadBuf_tmp = uartDevReadBuf_plc; + uartDevReadBuf_plc = uartDevReadBuf_drv; + uartDevReadBuf_drv = uartDevReadBuf_tmp; + uartDevReadBuf_plc_state = FULL; + pthread_mutex_unlock(&UART_ReadMutex); + // Check communication status: + uartCommStatusBuf[i][0] = TRUE; + uartCommErrCntBuf[i][0] = 0; + if(uartCommErrCntBuf[i][0] < UART_RETRY_NUM) + uartCommErrCntBuf[i][0]++; + uartCommStatusBuf[i][0] = FALSE; + // If timer is enabled, reset it's value, + // otherwise keep it disabled + if(uartPortTim[i].status != TIM_DISABLED) + uartPortTim[i].actValue = 0; + uartPortTim[i].status = TIM_EN_RUNNING; + else /* Keep timer disabled */ + uartPortTim[i].status = TIM_DISABLED; + // Procede with next UART device only after + // communication with the current one is done + else /* Go back to the first UART device */ +#define TAIL_LEN 3 /* Length of data tail in bytes */ +/**************************************************************************//** +* Calculate checksum of a buffer +* @param [in] buffer Pointer to buffer +* @param [in] bufLen Buffer length +* @return Checksum values on buffer locations bufLen-TAIL_LEN & +******************************************************************************/ +void Checksum(unsigned char *buffer, unsigned char bufLen) + unsigned char i=0, j=0; + unsigned char checksum1=0, checksum2=0; + unsigned char checksum1Temp=0; + for(i=0;i<bufLen-TAIL_LEN;i++) + checksum1Temp=buffer[i]; + for(j=0;j<8;j++) /* Compute number of '1' of whole buff. */ + if((checksum1Temp & 0x01)>0) + checksum1Temp = checksum1Temp >> 1; + checksum2 = checksum2 ^ buffer[i]; /* Compute XOR of whole buffer */ + buffer[bufLen-TAIL_LEN] = checksum2; /* Write number of '1' to buffer */ + buffer[bufLen-TAIL_LEN+1] = checksum1; /* Write XOR to buffer */ +/**************************************************************************//** +* Check if checksum values of received buffer are valid +* @param [in] buffer Pointer to buffer +* @param [in] bufLen Buffer length +* @return TRUE if valid, otherwise FALSE +******************************************************************************/ +unsigned char ChecksumValid(unsigned char *buffer, unsigned char bufLen) + unsigned char i=0, j=0; + unsigned char checksum1=0, checksum2=0; + unsigned char checksum1Temp=0; + for(i=0;i<bufLen-TAIL_LEN;i++) + checksum1Temp = buffer[i]; + for(j=0;j<8;j++) /* Compute number of '1' of whole buff. */ + if((checksum1Temp & 0x01)>0) + checksum1Temp = checksum1Temp >> 1; /* Compute XOR of whole buffer */ + checksum2 = checksum2 ^ buffer[i]; + /* Check if computed checksums are the same as those in buffer (=> no error) */ + if((checksum2==buffer[bufLen-TAIL_LEN]) && (checksum1==buffer[bufLen-TAIL_LEN+1])) +/*************************************************************************//** +* Support for UART modules +* @param [in] readBuf Pointer to read buffer (for previously polled UART device!) +* @param [out] writeBuf Pointer to write buffer (for current device) +* @param [in] address UART device address +* @return TRUE if communication was successful, otherwise FALSE +*****************************************************************************/ +unsigned char UARTDevice(char* readBuf, char* writeBuf, char address) + struct timeval timeout; + /* Prepare transmit buffer */ + memcpy(tmp+1,writeBuf,uartBufSize-TAIL_LEN-1); + tmp[uartBufSize-TAIL_LEN] = address; + Checksum((unsigned char*)tmp+1, uartBufSize); + tcflush(UART_fd, TCIOFLUSH); + if(write(UART_fd, tmp, uartBufSize) != uartBufSize){ + FD_ZERO(&set); /* clear the set */ + FD_SET(UART_fd, &set); /* add our file descriptor to the set */ + timeout.tv_sec = uartTimeout.tv_sec; + timeout.tv_usec = uartTimeout.tv_usec; + while(count < uartBufSize){ + rv = select(UART_fd + 1, &set, NULL, NULL, &timeout); + printf("RS485 select error\n"); + int rr = read(UART_fd, tmp + count, uartBufSize - count); + printf("RS485 read error %%d\n",rr); + /* Copy received buffer */ + if((count == uartBufSize) && (tmp[uartBufSize-TAIL_LEN] == address)){ + if(ChecksumValid((unsigned char*)tmp+1, uartBufSize)){ + memcpy(readBuf,tmp+1,uartBufSize-TAIL_LEN-1); + tcflush(UART_fd, TCIOFLUSH); +/* Macro to transform milliseconds to ns */ +#define msTOns(ms) (1000000L*ms) +void InitUartPortDevices_longBuffer(void) + uartTimeout.tv_sec = 0; + uartTimeout.tv_usec = 20000; /* 20 ms timeout */ + for(i=0;i<MAX_UART_DEVICES;i++) + uartPortDevices[i] = &UARTDevice; + uartPortTim[i].toValue = msTOns(50); /* 50ms */ + uartPortTim[i].status = TIM_EN_RUNNING; + case(240): /* 240-254 are reserved for EEPROM settings */ + uartPortDevices[i] = NULL; /* "Empty" or unknown module */ + uartPortTim[i].status = TIM_DISABLED; + uartDevNum--; /* Substract unused devices from MAX_UART_DEVICES */ +void InitUartPortDevices_shortBuffer(void) + uartTimeout.tv_sec = 0; + uartTimeout.tv_usec = 40000; /* 40 ms timeout */ + for(i=0;i<MAX_UART_DEVICES;i++) + case(130): /* P01, P02, P01V, P02V */ + case(178): /* AQ1, SM1, SM5, SM6, SM7 */ + uartPortDevices[i] = &UARTDevice; + uartPortTim[i].toValue = msTOns(250); /* 250ms */ + uartPortTim[i].status = TIM_EN_RUNNING; + uartPortDevices[i] = &UARTDevice; + uartPortTim[i].toValue = msTOns(650); /* 650ms */ + uartPortTim[i].status = TIM_EN_RUNNING; + case(170): /* ID1, ID2, ID3 */ + uartPortDevices[i] = &UARTDevice; + uartPortTim[i].toValue = msTOns(450); /* 450ms */ + uartPortTim[i].status = TIM_EN_RUNNING; + uartPortDevices[i] = NULL; /* "Empty" or unknown module */ + uartPortTim[i].status = TIM_DISABLED; --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_Devices_init.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,38 @@
+char *serialdev = LPCBUS_DEVICES_PORT; +uartDevWriteBuf_plc_state = EMPTY; +uartDevReadBuf_plc_state = EMPTY; +bzero(&uartDev, sizeof(uartDev)); +bzero(&uartDevReadBufA, sizeof(uartDevReadBuf_t)); +bzero(&uartDevReadBufB, sizeof(uartDevReadBuf_t)); +uartDevReadBuf_drv = &uartDevReadBufA; +uartDevReadBuf_plc = &uartDevReadBufB; +bzero(&uartDevWriteBufA, sizeof(uartDevWriteBuf_t)); +bzero(&uartDevWriteBufB, sizeof(uartDevWriteBuf_t)); +uartDevWriteBuf_drv = &uartDevWriteBufA; +uartDevWriteBuf_plc = &uartDevWriteBufB; +bzero(&uartCommStatusBuf, sizeof(uartCommStatusBuf)); +bzero(&uartCommErrCntBuf, sizeof(uartCommErrCntBuf)); +UART_fd = openserial(serialdev, uartBaudrate); /* uartBaudrate is initialized from Composer */ + fprintf(stderr, "Error while initializing %%s.\n", serialdev); +if(uartBufSize == UART_BUFSIZE_LONG) /* uartBufSize is initialized from Composer */ + InitUartPortDevices_longBuffer(); + InitUartPortDevices_shortBuffer(); +if(err = pthread_create(&UART_task, NULL, &UART_task_proc, NULL)); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_Devices_publish.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,19 @@
+if(!pthread_mutex_lock(&UART_WriteMutex)){ + prevstate=uartDevWriteBuf_plc_state; + uartDevWriteBuf_plc_state = LOCKED; + pthread_mutex_unlock(&UART_WriteMutex); + /* unlock plc buffer */ + uartDevWriteBuf_plc_state = FULL; + pthread_mutex_lock(&UART_WakeCondLock); + UART_WakeCondValue = 1; + pthread_cond_signal(&UART_WakeCond); + pthread_mutex_unlock(&UART_WakeCondLock); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_Devices_retrieve.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,19 @@
+if(!pthread_mutex_lock(&UART_ReadMutex)){ + if((prevstate=uartDevReadBuf_plc_state) == FULL){ + uartDevReadBuf_plc_state = LOCKED; + pthread_mutex_unlock(&UART_ReadMutex); + /* unlock plc buffer */ + uartDevReadBuf_plc_state = EMPTY; + /* No new data -> no update */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_OnBoard_cleanup.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,17 @@
+#endif /* ONBOARD_I2C */ +#ifdef CAN0_EN_GPIO_0_21 +gpio_set_pin_value(CAN0_EN_dev, 1); +gpio_close(CAN0_EN_dev); +#endif /* CAN0_EN_GPIO_0_21 */ +#ifdef CAN1_EN_GPIO_0_17 +gpio_set_pin_value(CAN1_EN_dev, 1); +gpio_close(CAN1_EN_dev); +#endif /* CAN1_EN_GPIO_0_17 */ +gpio_set_pin_value(RUN_LED_dev, 1); +gpio_close(RUN_LED_dev); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_OnBoard_decl.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,170 @@
+/*------------------------- GPIO -------------------------------------*/ +/* from armadeus/target/packages/as_devices/c/as_gpio* */ +# define ERROR(fmt, ...) printf(fmt, ##__VA_ARGS__) +//# define ERROR(fmt, ...) /*fmt, ##__VA_ARGS__*/ + int pin_file; /* pin file for 2.6.29 interface*/ +struct gpio_device *RUN_LED_dev; +#ifdef CAN0_EN_GPIO_0_21 +struct gpio_device *CAN0_EN_dev; +#endif /* CAN0_EN_GPIO_0_21 */ +#ifdef CAN1_EN_GPIO_0_17 +struct gpio_device *CAN1_EN_dev; +#endif /* CAN1_EN_GPIO_0_17 */ +static int write_file_bool(int fd, int value) + ret = write(fd, value?"1":"0", 1); + ERROR("write error\n"); + if (lseek(fd, 0, SEEK_SET) < 0) { + ERROR("lseek error\n"); +static int gpio_set_pin_value(struct gpio_device *aDev, int aValue) + int pin_file = aDev->pin_file; + retval = write_file_bool(pin_file, aValue); + ERROR("Can't write value\n"); +static struct gpio_device *gpio_open(int aGpioNum) + struct gpio_device *dev; + export_file = open("/sys/class/gpio/export", O_WRONLY); + ERROR("Can't open /sys/class/gpio/export\nBe sure that gpiolib is under your kernel\n"); + snprintf(buf, BUFF_SIZE, "%%d", aGpioNum); + retval = write(export_file, buf, strlen(buf)); + ERROR("/sys/class/gpio/export can't be written\n"); + snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/direction", aGpioNum); + gpio_dir_fd = open(buf, O_WRONLY); + ERROR("Can't open gpio%%d direction\n", aGpioNum); + ret = write(gpio_dir_fd, "out", 3); + ERROR("Error writing direction\n"); + snprintf(buf, BUFF_SIZE, "/sys/class/gpio/gpio%%d/value", aGpioNum); + pin_file = open(buf, O_RDWR); + ERROR("Can't export gpio number %%d\n", aGpioNum); + dev = malloc(sizeof(struct gpio_device)); + ERROR("Can't allocate gpio_device structure\n"); + dev->port_num = aGpioNum; + dev->pin_file = pin_file; + gpio_set_pin_value(dev, 1); +static int gpio_close(struct gpio_device *aDev) + ERROR("device is NULL\n"); + unexport_file = open("/sys/class/gpio/unexport", O_WRONLY); + if (unexport_file < 0) { + ERROR("Can't open /sys/class/gpio/unexport\nBe sure that gpiolib is under your kernel\n"); + snprintf(buf, BUFF_SIZE, "%%d", aDev->port_num); + retval = write(unexport_file, buf, strlen(buf)); + ERROR("/sys/class/gpio/unexport can't be written\n"); +/* TODO : DELETE !... but keep this until composer stops sending code snippets for mbrtu */ + MB_PAR_ODD = 0, /**< ODD parity. */ + MB_PAR_EVEN = 1, /**< Even parity. */ + MB_PAR_NONE = 2 /**< No parity. */ +unsigned long mbBaudRate = 115200; /**< Modbus baud-rate setting: 9600, 19200, 38400, 57600, 115200 */ +eMBSerialParity mbParity = MB_PAR_NONE; /**< Modbus parity setting: odd, even, none */ +#include "rt_imx_smt_onboard.h" +static readBuf_t onBoardReadBuf; +static writeBuf_t onBoardWriteBuf; +static busInit_t onBoardBusInit; +static int onboardbusfd = -1; +#endif /* ONBOARD_I2C */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_OnBoard_init.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,53 @@
+#define ONBOARDDEVFILENAME "/dev/rtdm/onboard" +bzero(&onBoardReadBuf , sizeof(readBuf_t)); +bzero(&onBoardWriteBuf, sizeof(writeBuf_t)); +bzero(&onBoardBusInit , sizeof(busInit_t)); +onBoardBusInit.common_ticktime__ = common_ticktime__; +#define onBoardDev (onBoardBusInit.rightI2CMod) +#endif /* ONBOARD_I2C */ +CAN0_EN_dev = gpio_open(CAN0_EN_GPIO); +gpio_set_pin_value(CAN0_EN_dev, 0); +CAN1_EN_dev = gpio_open(CAN1_EN_GPIO); +gpio_set_pin_value(CAN1_EN_dev, 0); +for(i=0; i<MAX_RIGHT_MODULES; i++) { + switch(onBoardDev[i][1]) { + onboardbusfd = open(ONBOARDDEVFILENAME, 0); + printf("can't open %%s rtdm device, %%s\n", ONBOARDDEVFILENAME, + strerror(-onboardbusfd)); + err = ioctl(onboardbusfd, RTSMT_RTIOC_INIT, &onBoardBusInit); + printf("error while RTSMT_RTIOC_INIT, %%s\n", strerror(-err)); +#endif /* ONBOARD_I2C */ +#if defined RUN_LED_GPIO +RUN_LED_dev = gpio_open(RUN_LED_GPIO); +gpio_set_pin_value(RUN_LED_dev, 0); --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_OnBoard_publish.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,6 @@
+ ioctl(onboardbusfd, RTSMT_RTIOC_WRITE, &onBoardWriteBuf); +#endif /* ONBOARD_I2C */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/SOM_OnBoard_retrieve.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,6 @@
+ ioctl(onboardbusfd, RTSMT_RTIOC_READ, &onBoardReadBuf); +#endif /* ONBOARD_I2C */ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCBus/uC.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,35 @@
+/* Code generated by LPCBus confnode */ +/* LPCBus confnode includes */ + #include "iec_std_lib.h" +/* LPCBus confnode user variables definition */ +/* LPCBus confnode functions */ +int __init_%(location_str)s(int argc,char **argv) +void __cleanup_%(location_str)s(void) +void __retrieve_%(location_str)s(void) +void __publish_%(location_str)s(void) --- a/LPCExtension.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCExtension.py Mon Apr 12 10:01:38 2021 +0200
@@ -8,33 +8,39 @@
from POULibrary import SimplePOULibraryFactory
-from LPCArch import arch, PLC_MC9_modules, PLC_GOT_modules
+from LPCArch import GetLPCProduct, GetLPCSOM, MC9_modules, WX_GOT_modules, SVG_GOT_modules # _lpcmanager_path, arch, etc are defined here because
# globals() of LPCManager.py are passed to extentions
+wanted_features_names = ["c_ext", "py_ext", "wxglade_hmi"] features.libraries=[('Native', 'NativeLib.NativeLibrary', True)]
return os.path.join(_lpcmanager_path, 'Pous', "pous"+name+".xml")
-if arch in PLC_MC9_modules:
+product = GetLPCProduct() +if product in MC9_modules + WX_GOT_modules + SVG_GOT_modules: features.libraries += [('Python', 'py_ext.PythonLibrary', True),
('RTC', SimplePOULibraryFactory(_poulibpath("RTC")), True)]
-elif arch in PLC_GOT_modules:
- features.libraries += [('Python', 'py_ext.PythonLibrary', True),
- ('RTC', SimplePOULibraryFactory(_poulibpath("RTC")), True),
- ('GOT', SimplePOULibraryFactory(_poulibpath("GOT")), True)]
+ if product in WX_GOT_modules: + features.libraries += [('GOT', SimplePOULibraryFactory(_poulibpath("GOT")), True)] + if product in SVG_GOT_modules: + features.libraries += [('SVGHMI', 'LPCSVGHMI.SVGHMILibrary', True)] features.libraries += [('LPC', SimplePOULibraryFactory(_poulibpath("LPC")), True)]
+if product in WX_GOT_modules: + wanted_features_names.extend(["wxglade_hmi"]) # --------- Configuration Tree Nodes (CTN) catalog extension ------------
_oldcatalog = features.catalog
catalog_index = dict(zip(zip(*_oldcatalog)[0],_oldcatalog))
-wanted_beremiz_features = [catalog_index[feature]
- for feature in ["c_ext", "py_ext", "wxglade_hmi"]]
+wanted_beremiz_features = [catalog_index[feature] + for feature in wanted_features_names] features.catalog = wanted_beremiz_features + [
('lpchmi', _('Smarteh HMI'), _('Create customized HMI'), 'lpchmi.LPCHMI'),
('bacnet', _('Bacnet support'), _('Map located variables over Bacnet'), 'LPCBACnet.RootClass'),
@@ -42,6 +48,8 @@
('LPCBus', _('LPC bus'), _('Support for Smarteh modules'), 'LPCBus.LPCBus'),
('CanOpen', _('CANOpen'), _('Support for CANopen'), 'LPCCanFestival.LPCCanOpen')]
+if product in SVG_GOT_modules: + features.catalog += [ catalog_index['svghmi'][:3]+('LPCSVGHMI.SVGHMI',) ] # --------- Connectors Extension ------------
@@ -67,21 +75,22 @@
from LPCtarget import LPC_target
+ targets.targets = {product : { + "xsd": os.path.join(_lpcmanager_path, som+"target", "XSD"), + "class": targets.targets["Xenomai"]["class"], + "code": {"plc_"+som+"_main.c": targets.targets["Xenomai"]["code"]["plc_Xenomai_main.c"], + "plc_"+som+"_main_retain.c": os.path.join(_lpcmanager_path, + "plc_"+som+"_main_retain.c")}}} # targets.targets["LPC"] = {"xsd": os.path.join(_lpcmanager_path, "LPCtarget", "XSD"),
# "class": lambda: LPC_target,
# "code": {os.path.join(_lpcmanager_path, "LPCtarget", "plc_LPC_main.c")}}
# targets.toolchains["makefile"] = os.path.join(_lpcmanager_path, "LPCtarget", "XSD_toolchain_makefile")
-# for arch in SOM28_modules:
-targets.targets = {arch : {
- "xsd": os.path.join(_lpcmanager_path, "SOM28target", "XSD"),
- "class": targets.targets["Xenomai"]["class"],
- "code": {"plc_SOM28_main.c": targets.targets["Xenomai"]["code"]["plc_Xenomai_main.c"],
- "plc_SOM28_main_retain.c": os.path.join(_lpcmanager_path,
- "plc_SOM28_main_retain.c")}}}
# --------- Custom columns function Extension ------------
@@ -92,3 +101,25 @@
from WxGladeEditor import WxGladeEditor
WxGladeHMI.EditorType = WxGladeEditor
PythonEditor.COLUMNS_TYPE = {'Options': WampOptionsCellEditor}
+# --------- special OnChange behavior ------------ +# ----- on load options and OnChange colums fix -------- +from py_ext.PythonFileCTNMixin import PythonFileCTNMixin +from OnChangeFromOptions import GetVarOnChangeContent, FixOptions +PythonFileCTNMixin.GetVarOnChangeContent = GetVarOnChangeContent +old_PythonFileCTNMixin__init__ = PythonFileCTNMixin.__init__ +def PythonFileCTNMixin__init__with_FixOptions(self): + old_PythonFileCTNMixin__init__(self) +PythonFileCTNMixin.__init__ = PythonFileCTNMixin__init__with_FixOptions --- a/LPCManager.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCManager.py Mon Apr 12 10:01:38 2021 +0200
@@ -22,7 +22,7 @@
# Path of directory containing current python file
_lpcmanager_path = os.path.split(__file__)[0]
-from LPCArch import SetLPCArch
+from LPCArch import SetLPCProduct from Beremiz import BeremizIDELauncher
class LPCManagerLauncher(BeremizIDELauncher):
@@ -68,7 +68,7 @@
+ SetLPCProduct(self.arch) # overload with exacltly same code, but this is intended.
# we want extensions to use globals of this module, not Beremiz.py
--- a/LPCModbus.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCModbus.py Mon Apr 12 10:01:38 2021 +0200
@@ -3,8 +3,11 @@
from __future__ import absolute_import
from modbus.modbus import _ModbusRTUclientPlug, _ModbusRTUslavePlug, RootClass
+from LPCArch import GetLPCArch wrong_uart_name = "ttyS0"
-good_uart_name = "ttyAPP3"
+good_uart_name = {"MC9":"ttyAPP3", + "MC10":"ttymxc4"}[GetLPCArch()] _ModbusRTUclientPlug.XSD = _ModbusRTUclientPlug.XSD.replace(wrong_uart_name,good_uart_name)
_ModbusRTUslavePlug.XSD = _ModbusRTUslavePlug.XSD.replace(wrong_uart_name,good_uart_name)
--- a/LPCProjectController.py Wed Jul 29 10:52:37 2020 +0200
+++ b/LPCProjectController.py Mon Apr 12 10:01:38 2021 +0200
@@ -11,7 +11,7 @@
from HostFirmwareUpdater import HostFirmwareUpdater
from plcopen.types_enums import ComputeConfigurationResourceName
-from LPCArch import GetLPCArch
+from LPCArch import GetLPCProduct @@ -28,6 +28,14 @@
LPCMethodsFromStatus["Stopped"]["_UpdateFw"] = True
LPCMethodsFromStatus["Empty"]["_UpdateFw"] = True
+ProjectController.ConfNodeMethods += [ + "name": _("Manage alarms"), + "tooltip": _("Describe and translate alarms"), + "method": "_ManageAlarms" class LPCProjectController(ProjectController):
StatusMethods = ProjectController.StatusMethods + LPCStatusMethods
DefaultMethods = LPCDefaultMethods
@@ -87,7 +95,7 @@
- product_name = GetLPCArch().lower().replace("_","")
+ product_name = GetLPCProduct().lower().replace("_","") if not self._connector.CheckProductID(product_name):
message = (_("Product ID doesn't match selected target type.\n"))
dialog = wx.MessageDialog(
@@ -162,6 +170,20 @@
+ def _ManageAlarms(self): + dlg = wx.SingleChoiceDialog( + 'Alarms translations', 'Choose a language to edit:', + if dlg.ShowModal() == wx.ID_OK: + print('You selected: %s\n' % dlg.GetStringSelection()) Method called by user to flash the firmware of the PLC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LPCSVGHMI.py Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,20 @@
+from svghmi.svghmi import SVGHMI, SVGHMILibrary +browser_commandline = 'qt_webenginewidgets_minimal --js-flags="--max_old_space_size=16 --gc_interval=100 --optimize_for_size" --single-process --no-sandbox http://127.0.0.1:{port}/{name}' +# set default values so that COG browser is managed by SVGHMI +SVGHMI.XSD = """<?xml version="1.0" encoding="utf-8" ?> + <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <xsd:element name="SVGHMI"> + <xsd:attribute name="OnStart" type="xsd:string" use="optional" default='"""+browser_commandline+"""'/> + <xsd:attribute name="OnStop" type="xsd:string" use="optional" default="killall qt_webenginewidgets_minimal"/> + <xsd:attribute name="OnWatchdog" type="xsd:string" use="optional" default="sh -c 'killall qt_webenginewidgets_minimal; sleep 1; """+\ + browser_commandline.replace('"', '"')+"""'"/> + <xsd:attribute name="WatchdogInitial" type="xsd:integer" use="optional" default="30"/> + <xsd:attribute name="WatchdogInterval" type="xsd:integer" use="optional" default="5"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OnChangeFromOptions.py Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,43 @@
+from __future__ import absolute_import +from OptionsParsing import ParseOptions, GenOptions +def GetVarOnChangeContent(var): + Function to overide the way PythonFileCTNMixin access OnChange column when + opts = ParseOptions(var.getopts()) + for onchangecall in var.getonchange().split(','): + onchangecall = onchangecall.strip() + new_onchange.append(onchangecall) + if opts.variable_type_selection == 1 : # "Static" + new_onchange += ["StoredValue"] + elif opts.variable_type_selection == 3 : # "Alarm" + new_onchange += ["Alarm"] + return ','.join(new_onchange) + return var.getonchange() + Function to be called at the end of PythonFileCTNMixin.__init__() + for var in self.CodeFile.variables.variable: + onchange.strip() for onchange in var.getonchange().split(',')] + opts = ParseOptions(var.getopts()) + for unwanted in ["Alarm", "StoredValue"]: + if unwanted in onchanges: + opts.is_onchange = True + onchanges.remove(unwanted) + var.setonchange(','.join(onchanges)) + var.setopts(GenOptions(opts)) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OptionsParsing.py Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,82 @@
+from __future__ import absolute_import +VARIABLETYPE = ["None", "Static", "Session", "Alarm"] +opt_parser = re.compile(r'(\w+)\s*(?:=\s*"([^"]+)"\s*|=([^\s]+)\s*)?') +class OptionsType(dict): + variable_type_selection = 0, + options = VARIABLETYPE[opts.variable_type_selection] + if opts.min is not None or opts.max is not None: + options += ' min=' + str(opts.min if opts.min is not None else 0) + options += ' max=' + str(opts.max if opts.min is not None else 0) + options += ' precision=' + str(opts.precision) + for name in ['subgroup', 'unit', 'other', 'tags']: + if content is not None: + quoting = '"' if ' ' in content else '' + options += ' ' + name + '=' + quoting + content + quoting + options = re.findall(opt_parser,opts) + for key,dblquote_value,smpl_value in options: + value = dblquote_value+smpl_value + elif key in VARIABLETYPE[1:]: + res.variable_type_selection = VARIABLETYPE.index(key) + if key in ["precision", "min","max"]: + raise Exception("Unknown key in options") --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SOM6Target/XSD.template Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,9 @@
+<xsd:element name="%(target_name)s"> + <xsd:attribute name="Compiler" type="xsd:string" use="optional" default="$CC"/> + <xsd:attribute name="CFLAGS" type="xsd:string" use="optional" default="$CFLAGS"/> + <xsd:attribute name="Linker" type="xsd:string" use="optional" default="$CC"/> + <xsd:attribute name="LDFLAGS" type="xsd:string" use="optional" default="$LDFLAGS"/> + <xsd:attribute name="XenoConfig" type="xsd:string" use="optional"/> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SOM6Target/plc_SOM6_main_retain.c Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,328 @@
+#include <alchemy/event.h> +#include <alchemy/mutex.h> +#include <rtdm/spi_apf28_rtdm_ioctl.h> +#include <xenomai/init.h> +/* SPI configurable parameters */ +/* --------------------------- */ +#define TEST_SPI_CLK_PHASE RTDM_SPI_CLKPHASE_LOW +#define TEST_SPI_CLK_POLARITY RTDM_SPI_CLKPOLARITY_LOW +#define TEST_SPI_SPEED 20000000 +#define TEST_SPI_BITS_PER_WORD RTDM_SPI_8BPW +#define TEST_SPI_CHIPSELECT1 RTDM_SPI_SS0 +#define TEST_SPI_CHIPSELECT2 RTDM_SPI_SS0 +/* Use the DMA from transfer > 4 bytes */ +#define TEST_SPI_DMA_BYTES_MIN 4 +#define NVRAM_SIZE 0x8000 +#define RETAIN_BUFFER_SIZE (NVRAM_SIZE - IDLEN) +static RT_TASK RETAIN_task; +static RT_MUTEX RETAIN_Mutex; +static RT_EVENT RETAIN_Event; +/* Data protected by mutex */ + unsigned char cmd[CMDSIZE]; + unsigned char id[IDLEN]; + unsigned char vars[RETAIN_BUFFER_SIZE]; +static unsigned short actual_size; +static int retain_busy = 0; +/* 0 : PLC can update. No SPI transmission undergoing + 1 : PLC cannot update. SPI transmission undergoing */ +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +static uint8_t rcmd[] = { +int SPI_Read(void *buf, unsigned int len){ + if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) { + printf("Failed to lock CS\n"); + status = write(fd_spi, rcmd, ARRAY_SIZE(rcmd)); + fprintf(stderr, "Failed to send read command. ERR : %d\n", status); + if (ioctl(fd_spi, RTDM_SPI_LOCK_CS_SET, &uint) < 0) { + printf("Failed to unlock CS\n"); + size = read(fd_spi, buf, len); + fprintf(stderr, "Failed to read %d bytes on the SPI bus. size : %d\n", +int SPI_Write(void *buf, unsigned int len){ + status = write(fd_spi, buf, len); + fprintf(stderr, "Failed to write memory. ERR : %d\n", status); +static void SPI_init(void) + /* Open the SPI RTDM device */ + if ((fd_spi = open("/dev/rtdm/spi_apf28_rtdm", 0)) < 0) { + printf("rt_spi_open error\n"); + /* Bus configuration */ + uint = TEST_SPI_CLK_PHASE; + if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_SET, &uint) < 0) { + printf("Failed to configure the clock phase\n"); + if (ioctl(fd_spi, RTDM_SPI_CLKPHASE_GET, &uint) < 0) { + printf("Failed to get the clock phase\n"); + uint = TEST_SPI_CLK_POLARITY; + if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_SET, &uint) < 0) { + printf("Failed to configure the clock polarity\n"); + if (ioctl(fd_spi, RTDM_SPI_CLKPOLARITY_GET, &uint) < 0) { + printf("Failed to get the clock polarity\n"); + ulong = TEST_SPI_SPEED; + if (ioctl(fd_spi, RTDM_SPI_FREQ_SET, &ulong) < 0) { + printf("Failed to configure the frequency\n"); + if (ioctl(fd_spi, RTDM_SPI_FREQ_GET, &ulong) < 0) { + printf("Failed to get the frequency\n"); + uint = TEST_SPI_BITS_PER_WORD; + if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_SET, &uint) < 0) { + printf("Failed to configure the BPW\n"); + if (ioctl(fd_spi, RTDM_SPI_BITSPERWORD_GET, &uint) < 0) { + printf("Failed to get the BPW\n"); + uint = TEST_SPI_CHIPSELECT1; + if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_SET, &uint) < 0) { + printf("Failed to configure the chip select\n"); + if (ioctl(fd_spi, RTDM_SPI_CHIPSELECT_GET, &uint) < 0) { + printf("Failed to get the chip select\n"); + /* DMA usage definition */ + uint = TEST_SPI_DMA_BYTES_MIN; + if (ioctl(fd_spi, RTDM_SPI_DMA_SET, &uint) < 0) { + printf("Failed to configure the DMA threshold\n"); + if (ioctl(fd_spi, RTDM_SPI_DMA_GET, &uint) < 0) { + printf("Failed to get the DMA threshold\n"); + /* Prepare for future write commands */ + /* Set Sequencial access mode */ + // status = write(fd_spi, mbuf, ARRAY_SIZE(mbuf)); + printf("RETAIN : Failed to change mode. ERR : %d\n", status); + // TODO: remove this !!! + /* Read the whole NVRAM at start */ + SPI_Read(&priv.buf, NVRAM_SIZE); +void RETAIN_task_proc(void *arg) + while (!rt_event_wait(&RETAIN_Event, 1, &msk, EV_ANY, TM_INFINITE)) { + if(rt_mutex_acquire(&RETAIN_Mutex, TM_INFINITE)) return; + SPI_Write(&priv, CMDSIZE + actual_size + IDLEN); + if(rt_event_clear(&RETAIN_Event, 1, NULL)) return; + if(rt_mutex_release(&RETAIN_Mutex)) return; +void InitRetain(void) /* TODO return error and care */ + if(rt_event_create (&RETAIN_Event, "RETAIN_Event", 0, 0)) + if(rt_mutex_create (&RETAIN_Mutex, "RETAIN_Mutex")) + if(rt_task_create(&RETAIN_task, "RETAIN_task", 0, 50, T_JOINABLE)) + SPI_init(); /*TODO if error */ + if(rt_task_start(&RETAIN_task, &RETAIN_task_proc, NULL)) + while(!NVRAM_Done && count--){ + printf("NVRAM init timeout\n"); +void CleanupRetain(void) + rt_task_delete(&RETAIN_task); + rt_task_join(&RETAIN_task); + rt_mutex_delete(&RETAIN_Mutex); + rt_event_delete(&RETAIN_Event); +void ValidateRetainBuffer(void) + memcpy(priv.buf.id, PLC_ID, IDLEN); + rt_mutex_release(&RETAIN_Mutex); + rt_event_signal(&RETAIN_Event, 1); +void InValidateRetainBuffer(void) + int ret = rt_mutex_acquire(&RETAIN_Mutex, TM_NONBLOCK); + if(ret == -EWOULDBLOCK){ + /* mutex was unavailable */ + /* invalidate that buffer */ + bzero(&priv.buf.id[0], IDLEN); + //printf("invalidate retain\n"); +int CheckRetainBuffer(void) + /* compare RETAIN ID buffer with MD5 */ + /* return true if identical */ + res = memcmp(&priv.buf.id[0], PLC_ID, IDLEN) == 0; +void Retain(unsigned int offset, unsigned int count, void *p) + if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE){ + /* write in RETAIN buffer at offset*/ + actual_size = offset + count; + memcpy(&priv.buf.vars[offset], p, count); +void Remind(unsigned int offset, unsigned int count, void *p) + if(!retain_busy && offset + count < RETAIN_BUFFER_SIZE) + /* read at offset in RETAIN buffer */ + memcpy(p, &priv.buf.vars[offset], count); --- a/VariableExporter.py Wed Jul 29 10:52:37 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-def VariableWriter(parent, event, path):
- FileDialog = wx.FileDialog(parent, "Save CSV file", "", "", "CSV files (*.csv)|*.csv",
- wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
- if FileDialog.ShowModal() == wx.ID_OK:
- if FileDialog.GetPath()[-4:] == ".csv":
- export = FileDialog.GetPath()
- export = FileDialog.GetPath() + ".csv"
- parent.Controler.logger.write(_("Exporting to " +export+" ...\n"))
- with open(path + "\plc.xml") as infile:
- start_program = line.find("name")
- if start_program != -1:
- end_program = line[start_program:].find(" ")
- program_name = line[start_program + 6:start_program + end_program - 1]
- start_type = line.find("pouType")
- end_type = line[start_type:].find("\"")
- program_type = line[start_type + 9:start_type + end_type + 8]
- if ":= UINT_TO_WORD(" in line:
- idx = line.find(":= UINT_TO_WORD(")
- end = line[idx:].find(")")
- name = line[idx + len(":= UINT_TO_WORD("):idx + end]
- address = target.split("_")[-1]
- modbus_list.append(name)
- modbus_dict[name] = [target, address, program_name, program_type]
- elif ":= WORD_TO_UINT(" in line and not "UINT_TO_WORD" in line:
- idx = line.find(":= WORD_TO_UINT(")
- end = line[idx:].find(")")
- name = line[idx + len(":= WORD_TO_UINT("):idx + end]
- address = name.split("_")[-1]
- setting_list.append([target, "", "", "", "", name, address])
- elif ":= WORD_TO_BOOL(" in line:
- idx = line.find(":= WORD_TO_BOOL(")
- end = line[idx + len(":= WORD_TO_BOOL("):].find(" ")
- name = line[idx + len(":= WORD_TO_BOOL("):idx + len(":= WORD_TO_BOOL(") + end]
- target = line[:idx].strip()
- address = name.split("_")[-1]
- bit_start = line.find(" N := ")
- bit_end = line[bit_start:].find(")")
- bit = line[bit_start + len(" N := "):bit_start + bit_end]
- command_list.append([target, "", "", "", "", name, address+"."+bit])
- elif ":= BOOL_TO_WORD(" in line:
- idx = line.find(":= BOOL_TO_WORD(") + len(":= BOOL_TO_WORD(")
- if "UINT_TO_BOOL(" in line[idx:]:
- idx += len("UINT_TO_BOOL")
- end = line[idx:].find(")")
- end = line[idx:].find(")")
- name = line[idx:idx+end]
- target_start = len("(*")
- target_end = line.find(" := ")
- target = line[target_start:target_end].strip()
- address = target.split("_")[-1]
- bit_start = line.find(" N := ")
- bit_end = line[bit_start:].find(")")
- bit = line[bit_start + len(" N := "):bit_start + bit_end]
- bit_dict[name] = [target, address+"."+bit, program_name, program_type]
- bit_dict[name] = [target, address, program_name, program_type]
- dir_list = [os.path.join(path, o) for o in os.listdir(path) if os.path.isdir(os.path.join(path, o))]
- if dir[-6:] == "py_ext":
- py_directories.append(dir)
- ["NAME", "DESCRIPTION", "TYPE", "GROUP", "SUBGROUP", "TYPE OF VARIABLE", "MODBUS NAME", "MODBUS ADDRESS", "PROGRAM NAME",
- for dir in py_directories:
- with open(dir + "\pyfile.xml") as infile:
- idx_name = line.find("name")
- end_name = line[idx_name:].find(" ")
- name = line[idx_name + 6:idx_name + end_name - 1]
- curr_variable.append(name)
- idx_desc = line.find("desc")
- end_desc = line[idx_desc+7:].find("\"")
- desc = line[idx_desc + 6:idx_desc + 7 + end_desc]
- if len(curr_variable) > 0:
- curr_variable.append(desc)
- idx_type = line.find("type")
- end_type = line[idx_type:].find(" ")
- type = line[idx_type + 6:idx_type + end_type - 1]
- group = dir.split("\\")[-1].split("@")[0]
- if len(curr_variable) > 0:
- curr_variable.append(type)
- curr_variable.append(group)
- idx_opts = line.find("opts")
- end_opts = line[idx_opts + 6:].find("\"")
- opts = line[idx_opts + 6: idx_opts + end_opts + 6]
- options = opts.split(" ")
- if o in ["Session", "Alarm", "Static"]:
- idx_subgroup = o.find("subgroup")
- subgroup = o[idx_subgroup + 9:]
- if len(curr_variable) > 0:
- curr_variable.append(subgroup)
- curr_variable.append(o_type)
- if len(curr_variable) > 0:
- if name in modbus_list:
- curr_variable += modbus_dict[name]
- curr_variable += bit_dict[name]
- curr_variable += ["", "", "", ""]
- if curr_variable != []:
- variables.append(curr_variable)
- with open(export, "wb") as f:
- writer.writerows(variables)
- writer.writerows(setting_list)
- writer.writerows(command_list)
- parent.Controler.logger.write(_("Export completed successfully.\n"))
- dialog = wx.MessageDialog(parent, "File is oppened in another program. Please close it before exporting.", style= wx.OK | wx.ICON_EXCLAMATION)
- parent.Controler.logger.write_error(_("Export failed.\n"))
\ No newline at end of file
--- a/WampOptionsEditor.py Wed Jul 29 10:52:37 2020 +0200
+++ b/WampOptionsEditor.py Mon Apr 12 10:01:38 2021 +0200
@@ -1,10 +1,18 @@
from __future__ import absolute_import
+from collections import namedtuple +from OptionsParsing import ParseOptions, VARIABLETYPE, GenOptions, OptionsType [ID_OPTIONSWIZARDDIALOG,ID_ONCHANGE,ID_OPTIONSTYPECHOICE,ID_SUBGROUPTEXT,ID_UNITTEXT,ID_VALUECHECKBOX,ID_MINSPIN,ID_MAXSPIN,ID_PRECISIONSPIN, ID_INITIALSPIN,ID_SCADACHECKBOX,ID_OTHERTEXT,ID_DESCRIPTION,ID_STATIC] = [wx.NewId() for _init_ctrls in range(14)]
-VARIABLETYPE = ["None", "Static", "Session", "Alarm"]
+excluded_chars = [ord(i) for i in '\n"'] +sanitizer = "".join([chr(i if i not in excluded_chars else ord(' ')) for i in xrange(256)]) class WampOptionsEditor(wx.Dialog):
@@ -34,7 +42,6 @@
self.minValue=wx.StaticText(self, wx.ID_ANY, _("Min value:"))
self.maxValue=wx.StaticText(self, wx.ID_ANY, _("Max value:"))
self.PrecisionValue = wx.StaticText(self, wx.ID_ANY, _("Precision:"))
- self.InitialValue = wx.StaticText(self, wx.ID_ANY, _("Initial:"))
self.PropertySizer.AddWindow(self.minValue, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
self.PropertySizer.AddWindow(self.MinSpin, flag=wx.GROW)
@@ -48,12 +55,8 @@
self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Other:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
self.PropertySizer.AddWindow(self.OtherText, flag=wx.GROW)
- self.PropertySizer.AddWindow(self.InitialValue, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
- self.PropertySizer.AddWindow(self.InitialText, flag=wx.GROW)
- self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Description:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15)
- self.PropertySizer.AddWindow(self.DescriptionText, flag=wx.GROW)
+ self.PropertySizer.AddWindow(wx.StaticText(self, wx.ID_ANY, _("Tags:")), flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=15) + self.PropertySizer.AddWindow(self.Tags, flag=wx.GROW) self.PropertySizer.AddGrowableCol(1, 1)
self.MainSizer.AddSizer(self.PropertySizer, flag=wx.GROW | wx.UP | wx.RIGHT, border=15)
self.ButtonSizer.AddWindow(self.ClearButton)
@@ -79,13 +82,12 @@
self.MinSpin = wx.SpinCtrl(parent=self, id=ID_MINSPIN, style=wx.SP_VERTICAL)
self.MaxSpin = wx.SpinCtrl(parent=self, id=ID_MAXSPIN, style=wx.SP_VERTICAL)
self.PrecisionSpin = wx.SpinCtrl(parent=self, id=ID_PRECISIONSPIN, style=wx.SP_VERTICAL)
- self.InitialText = wx.TextCtrl(parent=self, id=ID_INITIALSPIN)
self.MinSpin.SetRange(-1000000, 1000000)
self.MaxSpin.SetRange(-1000000, 1000000)
self.ScadaCheckbox = wx.CheckBox(parent=self, id=ID_SCADACHECKBOX)
self.StaticCheckbox = wx.CheckBox(parent=self, id=ID_STATIC)
self.OtherText = wx.TextCtrl(parent=self, id=ID_OTHERTEXT)
- self.DescriptionText = wx.TextCtrl(parent=self, id=ID_DESCRIPTION, size=(-1, 100), style=wx.TE_MULTILINE | wx.SUNKEN_BORDER)
+ self.Tags = wx.TextCtrl(parent=self, id=ID_DESCRIPTION, size=(-1, 100), style=wx.TE_MULTILINE|wx.SUNKEN_BORDER) self.ClearButton = wx.Button(self, wx.ID_CLEAR, _("Clear"))
self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL)
self.ValueCheckbox.Bind(wx.EVT_CHECKBOX, self.EnableValue)
@@ -98,8 +100,6 @@
self.MinSpin.Enable(False)
self.MaxSpin.Enable(False)
self.PrecisionSpin.Enable(False)
- self.InitialText.Enable(False)
- self.DescriptionText.Enable(False)
self.StaticCheckbox.Enable(False)
self.Bind(wx.EVT_CHOICE, self.Enabler, self.OptionsTypeChoice)
@@ -108,16 +108,13 @@
- def __init__(self, parent, opt, desc):
+ def __init__(self, parent, opt):
self._init_ctrls(parent, opt)
- self.SetOptions(opt, desc)
@@ -132,8 +129,6 @@
self.OnChangeCheckbox.Enable(True)
self.ValueCheckbox.Enable(True)
self.PrecisionSpin.Enable(True)
- self.InitialText.Enable(True)
- self.DescriptionText.Enable(True)
self.ScadaCheckbox.Enable(True)
self.OtherText.Enable(True)
@@ -143,8 +138,6 @@
self.OnChangeCheckbox.Enable(False)
self.ValueCheckbox.Enable(True)
self.PrecisionSpin.Enable(True)
- self.InitialText.Enable(True)
- self.DescriptionText.Enable(True)
if self.OptionsTypeChoice.GetSelection() == 3 and self.ScadaCheckbox.GetValue():
self.StaticCheckbox.Enable(True)
@@ -171,9 +164,8 @@
self.MaxSpin.Enable(False)
self.StaticCheckbox.Enable(False)
self.PrecisionSpin.SetValue(0)
- self.InitialText.SetValue("")
self.OnChangeCheckbox.SetValue(False)
- self.DescriptionText.SetValue("")
self.OnChangeCheckbox.Enable(False)
self.OtherText.Enable(False)
self.SubgroupText.Enable(False)
@@ -183,8 +175,7 @@
self.MinSpin.Enable(False)
self.MaxSpin.Enable(False)
self.PrecisionSpin.Enable(False)
- self.InitialText.Enable(False)
- self.DescriptionText.Enable(False)
+ self.Tags.Enable(False) self.StaticCheckbox.Enable(False)
def OnTypeChoice(self, event):
@@ -193,93 +184,65 @@
def EnableValue(self, event):
self.MinSpin.Enable(self.ValueCheckbox.GetValue())
self.MaxSpin.Enable(self.ValueCheckbox.GetValue())
- def SetOptions(self, opt, desc):
- optionsTemp = opt1.split(" ")
- options.append(el.split("="))
- self.OptionsTypeChoice.SetSelection(0)
- elif el[0] == "Static":
- self.OptionsTypeChoice.SetSelection(1)
- elif el[0] == "Session":
- self.OptionsTypeChoice.SetSelection(2)
- self.OptionsTypeChoice.SetSelection(3)
- self.ScadaCheckbox.SetValue(True)
- self.StaticCheckbox.Enable(True)
- self.StaticCheckbox.SetValue(True)
- if el[0] == "subgroup":
- self.SubgroupText.SetValue(el[1])
- self.UnitText.SetValue(el[1])
- self.ValueCheckbox.SetValue(True)
- self.MinSpin.SetValue(int(el[1]))
- self.MinSpin.Enable(True)
- self.ValueCheckbox.SetValue(True)
- self.MaxSpin.SetValue(int(el[1]))
- self.MaxSpin.Enable(True)
- self.OtherText.SetValue(el[1])
- elif el[0] == "precision":
- self.PrecisionSpin.SetValue(int(el[1]))
- self.OnChangeCheckbox.Enable(True)
- self.OnChangeCheckbox.SetValue(True)
- if self.OptionsTypeChoice.GetSelection() == 3 and self.ScadaCheckbox.GetValue():
- self.StaticCheckbox.Enable(True)
- self.InitialText.SetValue(opt3)
- self.DescriptionText.SetValue(desc)
+ def SetOptions(self, opts): + res = ParseOptions(opts) + self.OptionsTypeChoice.SetSelection(res.variable_type_selection) + self.OnChangeCheckbox.SetValue(res.is_onchange) + self.ScadaCheckbox.SetValue(res.is_scada) + self.StaticCheckbox.SetValue(res.is_static) + self.StaticCheckbox.Enable( + res.is_static or (res.variable_type_selection == 3 and res.is_scada)) + if res.subgroup is not None: + self.SubgroupText.SetValue(res.subgroup) + if res.unit is not None: + self.UnitText.SetValue(res.unit) + if res.min is not None or res.max is not None: + self.ValueCheckbox.SetValue(True) + self.MinSpin.Enable(True) + self.MaxSpin.Enable(True) + self.MinSpin.SetValue(res.min if res.min else 0) + self.MaxSpin.SetValue(res.max if res.max else 0) + if res.other is not None: + self.OtherText.SetValue(res.other) + if res.precision is not None: + self.PrecisionSpin.SetValue(res.precision) + if res.tags is not None: + self.Tags.SetValue(res.tags) - self.TypeSelected = self.OptionsTypeChoice.GetSelection()
- if self.TypeSelected<0:
- options = VARIABLETYPE[self.TypeSelected]
- if self.ScadaCheckbox.GetValue():
- if self.StaticCheckbox.GetValue():
- if self.SubgroupText.GetLineText(0) != "":
- options += " subgroup=" + self.SubgroupText.GetLineText(0)
- if self.UnitText.GetLineText(0) != "":
- options += " unit=" + self.UnitText.GetLineText(0)
+ opts.variable_type_selection = max(self.OptionsTypeChoice.GetSelection(), 0) + opts.is_onchange = self.OnChangeCheckbox.GetValue() + opts.is_scada = self.ScadaCheckbox.GetValue() + opts.is_static = self.StaticCheckbox.GetValue() if self.MinSpin.IsEnabled():
- options += " min=" + str(self.MinSpin.GetValue())
- options += " max=" + str(self.MaxSpin.GetValue())
- if self.PrecisionSpin.GetValue() != 0:
- options += " precision=" + str(self.PrecisionSpin.GetValue())
- if self.OtherText.GetLineText(0) != "":
- options += " other=" + self.OtherText.GetLineText(0)
- if self.OnChangeCheckbox.GetValue():
- if VARIABLETYPE[self.TypeSelected] == "Alarm":
- elif VARIABLETYPE[self.TypeSelected] == "Static":
- self.value = "StoredValue"
- self.Description = self.DescriptionText.GetValue()
- self.Initial = self.InitialText.GetValue()
- return options, self.OnChange,self.value, self.Description, self.Initial
+ opts.min = self.MinSpin.GetValue() + opts.max = self.MaxSpin.GetValue() + opts.precision = self.PrecisionSpin.GetValue() + for name, ctrl in [('subgroup', self.SubgroupText), + ('unit', self.UnitText), + ('other', self.OtherText), + content = ctrl.GetValue().encode('ascii','ignore').translate(sanitizer,eraser) + return GenOptions(opts) class WampOptionsCellControl(wx.PyControl):
@@ -300,7 +263,7 @@
# create location text control
self.Options = wx.TextCtrl(self, size=wx.Size(0, -1),
style=wx.TE_PROCESS_ENTER)
- self.Options.Bind(wx.EVT_KEY_DOWN, self.OnDurationChar)
+ self.Options.Bind(wx.EVT_KEY_DOWN, self.OnChar) main_sizer.AddWindow(self.Options, flag=wx.GROW)
@@ -316,16 +279,6 @@
- def OnDurationChar(self, event):
- keycode = event.GetKeyCode()
- if keycode in [wx.WXK_RETURN, wx.WXK_TAB]:
- self.Parent.Parent.ProcessEvent(event)
- elif keycode == wx.WXK_ESCAPE:
- self.Duration.SetValue(self.Default)
- self.Parent.Parent.CloseEditControl()
def SetValue(self, value):
self.Options.SetValue(value)
@@ -338,19 +291,15 @@
def OnEditButtonClick(self, event):
# pop up the Duration Editor dialog
- options = [self.GetValue(), self.table.GetValueByName(self.row, "OnChange"), self.table.GetValueByName(self.row, "Initial")]
- desc = self.table.GetValueByName(self.row, "Description")
- dialog = WampOptionsEditor(self.parent, options, desc)
+ options = self.GetValue() + # backward compatibility + dialog = WampOptionsEditor(self.parent, options) answer = dialog.ShowModal()
- opt, OnChange, value, description, initial = dialog.GetOptions()
+ opt = dialog.GetOptions()
- self.table.SetValueByName(self.row, "OnChange", value)
- self.table.SetValueByName(self.row, "OnChange", "")
- self.table.SetValueByName(self.row, "Description", description)
- self.table.SetValueByName(self.row, "Initial", str(initial))
@@ -372,7 +321,7 @@
class WampOptionsCellEditor(wx.grid.PyGridCellEditor):
- Grid cell editor that uses DurationCellControl to display an edit button.
+ Grid cell editor that uses WampOptionsCellControl to display an edit button. def __init__(self, table, row, col):
@@ -396,21 +345,19 @@
self.CellControl.SetValue(self.table.GetValueByName(self.row, self.colname))
self.CellControl.SetFocus()
- def EndEditInternal(self, row, col, grid, old_duration):
- duration = self.CellControl.GetValue()
- changed = duration != old_duration
- self.table.SetValueByName(row, self.colname, duration)
- self.CellControl.Disable()
- if wx.VERSION >= (3, 0, 0):
- def EndEdit(self, row, col, grid, oldval):
- return self.EndEditInternal(row, col, grid, oldval)
- def EndEdit(self, row, col, grid):
- oldval = self.table.GetValueByName(row, self.colname)
- return self.EndEditInternal(row, col, grid, oldval)
+ def EndEdit(self, row, col, grid, oldval): + value = self.CellControl.GetValue() + changed = value != oldval + def ApplyEdit(self, row, col, grid): + value = self.CellControl.GetValue() + self.table.SetValueByName(row, self.colname, value) + self.CellControl.Disable() self.CellControl.SetDimensions(rect.x + 1, rect.y,
Binary file images/ALARM.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/images/genicons.sh Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,17 @@
+for fname in `ls *.svg`; do + for i in `cat $fname |grep -o -e '%%[^%]*%%'|sed 's/%//g'` + if [ $i.png -nt $fname ]; then + echo "$INKSCAPE" $fname -z -e $i.png -i $i + "$INKSCAPE" $fname -z -e $i.png -i $i --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/images/icons.svg Mon Apr 12 10:01:38 2021 +0200
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + sodipodi:version="0.32" + inkscape:version="0.92.3 (2405546, 2018-03-11)" + sodipodi:docname="icons.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <dc:format>image/svg+xml</dc:format> + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + inkscape:window-height="836" + inkscape:window-width="1800" + inkscape:pageshadow="2" + inkscape:pageopacity="0" + inkscape:zoom="5.6568543" + inkscape:cx="380.11858" + inkscape:cy="676.83086" + inkscape:current-layer="g46158" + inkscape:guide-bbox="true" + inkscape:window-maximized="1" + inkscape:measure-start="904.956,703.964" + inkscape:measure-end="930.144,704.058"> + snapvisiblegridlinesonly="true" /> + style="font-style:normal;font-weight:normal;font-size:40.12579727px;line-height:0%;font-family:'Bitstream Vera Sans';fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + style="text-align:center;text-anchor:middle" + x="371.85562">LPCManager icons</tspan></text> + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none" + style="font-size:12.76000023px;line-height:1.25">%% ALARM %%</tspan></text> + transform="matrix(1.5,0,0,1.5,-202.5,-195.93108)" + style="stroke-width:0.66666669"> + style="display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:0;fill-rule:evenodd;stroke:none;stroke-width:0.66666669;marker:none;enable-background:accumulate" /> + inkscape:transform-center-y="-1.9795276" + inkscape:transform-center-x="-0.011147353" + d="m 420.17779,390.02543 -7.17729,0.0865 -7.17828,-0.0479 3.51374,-6.25895 3.63061,-6.19263 3.66355,6.17246 z" + inkscape:randomized="0" + inkscape:flatsided="false" + sodipodi:arg2="1.568032" + sodipodi:arg1="0.52090978" + sodipodi:r2="4.2112961" + sodipodi:r1="8.2882175" + sodipodi:cy="385.90063" + sodipodi:cx="412.98886" + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffcc00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.44444481;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + sodipodi:type="star" /> + transform="scale(1.191303,0.839417)" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.66666669" + xml:space="preserve"><tspan + style="font-size:12.4041214px;line-height:1.25;font-family:sans-serif;stroke-width:0.66666669" + sodipodi:role="line">!</tspan></text>