lpcmanager

Enhanced code generation of MC9 busses, allowing nesting code given by LPCcomponsed. Added RS485 bus scanning logic and serial communication. Added (non working) control of RS485 transceiver through RTS
bus_template_code = {"MC8":"""
/* Code generated by LPCBus confnode */
/* LPCBus confnode includes */
#include "app_glue.h"
#ifdef _WINDOWS_H
#include "iec_types.h"
#else
#include "iec_std_lib.h"
#endif
%(declare_code)s
/* LPCBus confnode user variables definition */
%(var_decl)s
/* LPCBus confnode functions */
int __init_%(location_str)s(int argc,char **argv)
{
%(init_code)s
return 0;
}
void __cleanup_%(location_str)s(void)
{
}
void __retrieve_%(location_str)s(void)
{
%(retrieve_code)s
}
void __publish_%(location_str)s(void)
{
%(publish_code)s
}
""",
#############################
"MC9":"""
/* Code generated by LPCBus confnode */
#ifdef _WINDOWS_H
#include "iec_types.h"
#else
#include "iec_std_lib.h"
#endif
static inline int16_t getWord(char *buffer)
{
return *((int16_t*)buffer);
}
static inline void setWord(char *buffer, int16_t word)
{
*((int16_t*)buffer) = word;
}
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);
if(bit)
*buffer |= msk;
else
*buffer &= ~msk;
}
%(bus_decl)s
%(declare_code)s
/* LPCBus confnode user variables definition */
%(var_decl)s
/* LPCBus confnode functions */
int __init_%(location_str)s(int argc,char **argv)
{
%(bus_init_code)s
return 0;
}
void __cleanup_%(location_str)s(void)
{
%(bus_cleanup_code)s
}
void __retrieve_%(location_str)s(void)
{
%(bus_retrieve_code)s
}
void __publish_%(location_str)s(void)
{
%(bus_publish_code)s
}
"""}
bus_code = {
"MC9:Right": {
"decl" : """
#include <rtdm/rtdm.h>
/* LPCBus confnode includes */
#define RIGHT_READ_BUFSIZE 30 /**< Right bus read buffer size */
#define RIGHT_WRITE_BUFSIZE 30 /**< Right bus write buffer size */
#define MAX_RIGHT_MODULES 8
/**< Buffers for reading data from right bus modules */
typedef char rightReadBuf_t[MAX_RIGHT_MODULES][RIGHT_READ_BUFSIZE];
/**< Buffers for writing data to right bus modules */
typedef char rightWriteBuf_t[MAX_RIGHT_MODULES][RIGHT_WRITE_BUFSIZE];
/**< Tables containing information about connected modules
on right bus (initialized by Composer) */
typedef char rightI2CMod_t[MAX_RIGHT_MODULES][2];
#define RTIOC_TYPE_SMT RTDM_CLASS_EXPERIMENTAL
#define RTSMT_RTIOC_INIT _IOR(RTIOC_TYPE_SMT, 0x00, rightI2CMod_t)
//#define RTSMT_RTIOC_CLEAN _IOR(RTIOC_TYPE_SMT, 0x01, int)
#define RTSMT_RTIOC_READ _IOR(RTIOC_TYPE_SMT, 0x02, rightReadBuf_t)
#define RTSMT_RTIOC_WRITE _IOR(RTIOC_TYPE_SMT, 0x03, rightWriteBuf_t)
static rightReadBuf_t rightReadBuf;
static rightWriteBuf_t rightWriteBuf;
static rightI2CMod_t rightI2CMod;
static int rightbusfd = -1;
/* XXX TODO #include "smarteh.h" */
""",
"init":"""
#define DEVICEFILENAME "rightbus"
bzero(&rightReadBuf, sizeof(rightReadBuf_t));
bzero(&rightWriteBuf, sizeof(rightWriteBuf_t));
bzero(&rightI2CMod, sizeof(rightI2CMod_t));
%(init_code)s
int err;
rightbusfd = rt_dev_open( DEVICEFILENAME, 0);
if (rightbusfd < 0) {
printf("can't open %%s rtdm device, %%s\\n", DEVICEFILENAME,
strerror(-rightbusfd));
return rightbusfd;
}
err = rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_INIT, &rightI2CMod);
if (err) {
printf("error while RTSMT_RTIOC_INIT, %%s\\n",
strerror(-err));
rt_dev_close(rightbusfd);
return err;
}
""",
"retrieve":"""
rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_READ, &rightReadBuf);
%(retrieve_code)s
""",
"publish":"""
%(publish_code)s
rt_dev_ioctl(rightbusfd, RTSMT_RTIOC_WRITE, &rightWriteBuf);
""",
"cleanup":"""
rt_dev_close(rightbusfd);
""",
},
"MC9:On Board": {
"decl" : """
#define MAX_ONBOARD_DEVICES 2
/* Tables containing information about enabled on-board devices
(initialized by Composer) */
unsigned char onBoardDev[MAX_ONBOARD_DEVICES][2];
""",
"init":"""
bzero(&onBoardDev, sizeof(onBoardDev));
%(init_code)s
""",
"retrieve":"%(retrieve_code)s",
"publish":"%(publish_code)s",
"cleanup":"",
},
"MC9:Devices": {
"decl" : """
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/select.h>
#include <native/task.h>
#include <native/mutex.h>
#include <native/timer.h>
static struct termios oldterminfo;
void closeserial(int fd)
{
tcsetattr(fd, TCSANOW, &oldterminfo);
if (close(fd) < 0)
perror("closeserial()");
}
int setRTS(int fd)
{
int bit = TIOCM_RTS;
if (ioctl(fd, TIOCMBIS, &bit) == -1) {
perror("setRTS(): TIOCMGET");
return 0;
}
return 1;
}
int clearRTS(int fd)
{
int bit = TIOCM_RTS;
if (ioctl(fd, TIOCMBIC, &bit) == -1) {
perror("clearRTS(): TIOCMGET");
return 0;
}
return 1;
}
int openserial(char *devicename)
{
int fd;
struct termios attr;
speed_t baud = B115200; /* baud rate */
if ((fd = open(devicename, O_RDWR)) == -1) {
perror("openserial(): open()");
return 0;
}
if (tcgetattr(fd, &oldterminfo) == -1) {
perror("openserial(): tcgetattr()");
return 0;
}
attr = oldterminfo;
attr.c_oflag = 0;
// attr.c_cflag |= CRTSCTS | CLOCAL;
attr.c_cflag |= CLOCAL;
attr.c_cflag &= ~CRTSCTS;
attr.c_cflag &= ~PARENB; /* no parity */
attr.c_cflag &= ~CSTOPB; /* 1 stop bit */
attr.c_cflag &= ~CSIZE;
attr.c_cflag |= CS8 ; /* 8 bits */
cfsetospeed(&attr, baud); /* baud rate */
if (tcflush(fd, TCIOFLUSH) == -1) {
perror("openserial(): tcflush()");
return 0;
}
if (tcsetattr(fd, TCSANOW, &attr) == -1) {
perror("initserial(): tcsetattr()");
return 0;
}
/* Turn to write mode*/
setRTS(fd);
return fd;
}
typedef struct /* Type definition for timers for right modules */
{
unsigned char status; /* Current status of timer - running / expired */
RTIME actValue; /* Actual timer value */
RTIME toValue; /* Timeout value - initialized at startup */
} commTimer;
#define TIM_DISABLED 0
#define TIM_EN_RUNNING 1
#define TIM_EN_EXPIRED 2
#define EMPTY 0
#define LOCKED 1
#define FULL 2
#define MAX_UART_DEVICES 52
/* UART bus read and write buffer size */
#define UART_BUFSIZE 48
/* Tables containing information about connected devices on UART port
(initialized by Composer) */
unsigned char uartDev[MAX_UART_DEVICES][2];
/* Buffers for reading data from UART port devices */
typedef char uartDevReadBuf_t[MAX_UART_DEVICES][UART_BUFSIZE];
uartDevReadBuf_t uartDevReadBufA;
uartDevReadBuf_t uartDevReadBufB;
uartDevReadBuf_t *uartDevReadBuf_drv;
uartDevReadBuf_t *uartDevReadBuf_plc;
/* MC8 compatibility */
#define uartDevReadBuf (*uartDevReadBuf_drv)
/* Buffers for writing data to UART port devices */
typedef char uartDevWriteBuf_t[MAX_UART_DEVICES][UART_BUFSIZE];
uartDevWriteBuf_t uartDevWriteBufA;
uartDevWriteBuf_t uartDevWriteBufB;
uartDevWriteBuf_t *uartDevWriteBuf_drv;
uartDevWriteBuf_t *uartDevWriteBuf_plc;
/* MC8 compatibility */
#define uartDevWriteBuf (*uartDevWriteBuf_drv)
int uartDevWriteBuf_plc_state;
int uartDevReadBuf_plc_state;
/* Function interface definition for modules on UART (RS485) bus */
typedef void (*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 RT_TASK UART_task;
static RT_MUTEX UART_WriteMutex;
static RT_MUTEX UART_ReadMutex;
void UART_task_proc(void *arg)
{
int i;
while (rt_task_sleep_until(TM_INFINITE) == -EINTR){
printf("Hellllo world\\n");
if(!rt_mutex_acquire(&UART_WriteMutex, TM_INFINITE )){
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;
}
rt_mutex_release(&UART_WriteMutex);
}
/* Scan all positions for attached UART port modules */
for(i=0;i<MAX_UART_DEVICES;i++)
{
RTIME now = rt_timer_read();
/* Timers for right modules */
if(uartPortTim[i].status != TIM_DISABLED)
{
if(now - uartPortTim[i].actValue < uartPortTim[i].toValue)
{
uartPortTim[i].status = TIM_EN_RUNNING;
}
else
uartPortTim[i].status = TIM_EN_EXPIRED;
}
if(uartPortDevices[i] != NULL)
{
// Check timer status
if((uartPortTim[i].status == TIM_DISABLED)
|| (uartPortTim[i].status == TIM_EN_EXPIRED))
{
// Communicate with device
(*uartPortDevices[i])(
&uartDevReadBuf[i][0],
&uartDevWriteBuf[i][0],
uartDev[i][1]);
// If timer is enabled, reset it's value,
// otherwise keep it disabled
if(uartPortTim[i].status != TIM_DISABLED)
{
uartPortTim[i].actValue = now;
uartPortTim[i].status = TIM_EN_RUNNING;
}
else /* Keep timer disabled */
uartPortTim[i].status = TIM_DISABLED;
}
}
}
if(!rt_mutex_acquire(&UART_ReadMutex, TM_INFINITE )){
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;
}
rt_mutex_release(&UART_ReadMutex);
}
}
}
/**************************************************************************//**
* Calculate checksum of a buffer
* @param [in] buffer Pointer to buffer
* @return Checksum values on buffer locations 23 & 24
******************************************************************************/
void Checksum(unsigned char *buffer)
{
unsigned char i=0, j=0;
unsigned char checksum1=0, checksum2=0;
unsigned char checksum1Temp=0;
for(i=0;i<45;i++)
{
checksum1Temp=buffer[i];
for(j=0;j<8;j++) // Compute number of '1' of whole buff.
{
if((checksum1Temp & 0x01)>0)
checksum1++;
checksum1Temp = checksum1Temp >> 1;
}
checksum2 = checksum2 ^ buffer[i]; // Compute XOR of whole buffer
}
buffer[45] = checksum2; // Write number of '1' to buffer
buffer[46] = checksum1; // Write XOR to buffer
}
/**************************************************************************//**
* Check if checksum values of received buffer are valid
* @param [in] buffer Pointer to buffer
* @return TRUE if valid, otherwise FALSE
******************************************************************************/
unsigned char ChecksumValid(unsigned char *buffer)
{
unsigned char i=0, j=0;
unsigned char checksum1=0, checksum2=0;
unsigned char checksum1Temp=0;
for(i=0;i<45;i++)
{
checksum1Temp = buffer[i];
for(j=0;j<8;j++) // Compute number of '1' of whole buff.
{
if((checksum1Temp & 0x01)>0)
checksum1++;
checksum1Temp = checksum1Temp >> 1; // Compute XOR of whole buffer
}
checksum2 = checksum2^buffer[i];
}
if((checksum2==buffer[45]) && (checksum1==buffer[46])) // Check if computed checksums are the same as those in buffer (=> no error)
return TRUE;
else
return FALSE;
}
static int UART_fd;
/*************************************************************************//**
* 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 None
*****************************************************************************/
void UARTDevice(char* readBuf, char* writeBuf, char address)
{
fd_set set;
struct timeval timeout;
int rv;
// writeBuf[45] = address;
writeBuf[45] = 2;
char tmp[UART_BUFSIZE];
Checksum((unsigned char*)writeBuf+1);
writeBuf[0] = 'S';
//{
// int i;
// for (i=0; i<UART_BUFSIZE; i++){
// printf("|%%c:%%d", writeBuf[i], writeBuf[i]);
// }
// printf("\\n");
//}
//rt_task_sleep(rt_timer_ns2ticks(500000));
if(write(UART_fd, writeBuf, UART_BUFSIZE) != UART_BUFSIZE){
goto UARTDevfail;
}
FD_ZERO(&set); /* clear the set */
FD_SET(UART_fd, &set); /* add our file descriptor to the set */
timeout.tv_sec = 0;
timeout.tv_usec = 50000;
/* Turn to listen mode*/
clearRTS(UART_fd);
rv = select(UART_fd + 1, &set, NULL, NULL, &timeout);
if(rv == -1)
perror("select"); /* an error accured */
else if(rv == 0)
printf("timeout"); /* a timeout occured */
else if(read(UART_fd, tmp, UART_BUFSIZE) == UART_BUFSIZE){
memcpy(readBuf,tmp,UART_BUFSIZE);
return;
}
/* Turn to transmit mode*/
setRTS(UART_fd);
UARTDevfail:
tcflush(UART_fd, TCIOFLUSH);
}
/* Macro to transform milliseconds to xenomai ticks */
#define msTOxn(ms) rt_timer_ns2ticks(1000000L*ms)
void InitUartPortDevices(void)
{
unsigned char i=0;
for(i=0;i<MAX_UART_DEVICES;i++)
{
switch(uartDev[i][1])
{
case(130): /* P01, P02, P01V, P02V */
case(132):
case(134):
case(136):
case(138): /* CA1 */
case(140):
case(142):
case(144):
case(154): /* CR1 */
case(156):
case(158):
case(160):
case(162): /* IR1V */
case(164):
case(166):
case(168):
case(186): /* TH1V */
case(188):
case(190):
case(192):
uartPortDevices[i] = &UARTDevice;
uartPortTim[i].toValue = msTOxn(200); /* 200ms */
uartPortTim[i].status = TIM_EN_RUNNING;
break;
case(146): /* CH1 */
case(148):
case(150):
case(152):
uartPortDevices[i] = &UARTDevice;
uartPortTim[i].toValue = msTOxn(600); /* 600ms */
uartPortTim[i].status = TIM_EN_RUNNING;
break;
case(170): /* ID1, ID2, ID3 */
case(172):
case(174):
case(176):
uartPortDevices[i] = &UARTDevice;
uartPortTim[i].toValue = msTOxn(400); /* 400ms */
uartPortTim[i].status = TIM_EN_RUNNING;
break;
case(194): /* DP1V */
case(196):
case(198):
case(200):
case(202): /* DP2V */
case(204):
case(206):
case(208):
case(210): /* DT1V */
case(212):
case(214):
case(216):
case(218): /* DU1V */
case(220):
case(222):
case(224):
uartPortDevices[i] = &UARTDevice;
uartPortTim[i].toValue = msTOxn(400); /* 400ms */
uartPortTim[i].status = TIM_EN_RUNNING;
break;
default:
uartPortDevices[i] = NULL; /* "Empty" or unknown module */
uartPortTim[i].status = TIM_DISABLED;
break;
}
}
}
""",
"init":"""
int err;
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;
%(init_code)s
if((err = rt_mutex_create (&UART_WriteMutex, "UART_WriteMutex")))
return err;
if((err = rt_mutex_create (&UART_ReadMutex, "UART_ReadMutex")))
return err;
UART_fd = openserial(serialdev);
if (!UART_fd) {
fprintf(stderr, "Error while initializing %%s.\\n", serialdev);
return 1;
}
InitUartPortDevices();
if((err = rt_task_create(&UART_task, "UART_task", 0, 50, T_JOINABLE)))
return err;
if(rt_task_start(&UART_task, &UART_task_proc, NULL))
return err;
""",
"retrieve":"""
if(!rt_mutex_acquire(&UART_ReadMutex, TM_INFINITE )){
int prevstate;
if((prevstate=uartDevReadBuf_plc_state) == FULL){
uartDevReadBuf_plc_state = LOCKED;
}
rt_mutex_release(&UART_ReadMutex);
if(prevstate == FULL){
%(retrieve_code)s
/* unlock plc buffer */
uartDevReadBuf_plc_state = EMPTY;
}else{
/* No new data -> no update */
}
}
""",
"publish":"""
if(!rt_mutex_acquire(&UART_WriteMutex, TM_INFINITE )){
int prevstate;
prevstate=uartDevWriteBuf_plc_state;
uartDevWriteBuf_plc_state = LOCKED;
rt_mutex_release(&UART_WriteMutex);
%(publish_code)s
/* unlock plc buffer */
uartDevWriteBuf_plc_state = FULL;
/* wakeup task */
rt_task_unblock(&UART_task);
}
""",
"cleanup":"""
rt_task_delete(&UART_task);
rt_task_join(&UART_task);
closeserial(UART_fd);
rt_mutex_delete(&UART_WriteMutex);
rt_mutex_delete(&UART_ReadMutex);
""",
},
}
# to be overloaded at import
LPCarch = None
import os
from plcopen.structures import LOCATIONDATATYPES
from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP,\
LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
LOCATION_TYPES = {"I": LOCATION_VAR_INPUT,
"Q": LOCATION_VAR_OUTPUT,
"M": LOCATION_VAR_MEMORY}
LOCATION_DIRS = dict([(dir, size) for size, dir in LOCATION_TYPES.iteritems()])
LOCATION_SIZES = {}
for size, types in LOCATIONDATATYPES.iteritems():
for _type in types:
LOCATION_SIZES[_type] = size
def GetModuleChildren(module):
children = []
for child in module["children"]:
if child["type"] == LOCATION_GROUP:
children.extend(child["children"])
else:
children.append(child)
return children
def _GetVariables(module):
variables = []
for child in module["children"]:
if child["type"] in [LOCATION_GROUP, LOCATION_MODULE]:
variables.extend(_GetVariables(child))
else:
variables.append(child)
return variables
def GetLastModuleGroup(module):
group = module
for child in module["children"]:
if child["type"] == LOCATION_GROUP:
group = child
return group["children"]
def GetModuleBySomething(module, something, toks):
for child in GetModuleChildren(module):
if child.get(something) == toks[0]:
if len(toks) > 1:
return GetModuleBySomething(child, something, toks[1:])
return child
return None
def GetModuleVariable(module, location, direction):
for child in GetModuleChildren(module):
if child["location"] == location and child["type"] == LOCATION_TYPES[direction]:
return child
return None
def RemoveModuleChild(module, child):
if child in module["children"]:
module["children"].remove(child)
else:
for group in module["children"]:
if group["type"] == LOCATION_GROUP and child in group["children"]:
group["children"].remove(child)
class LPCBus(object):
def __init__(self):
self.VariableLocationTree = []
self.ResetUsedLocations()
self.Icon = None
def __getitem__(self, key):
if key == "children":
return self.VariableLocationTree
raise KeyError, "Only 'children' key is available"
def CTNEnabled(self):
return None
def SetIcon(self, icon):
self.Icon = icon
def _GetChildBySomething(self, something, toks):
return GetModuleBySomething({"children" : self.VariableLocationTree}, something, toks)
def GetBaseTypes(self):
return self.GetCTRoot().GetBaseTypes()
def GetSizeOfType(self, type):
return LOCATION_SIZES[self.GetCTRoot().GetBaseType(type)]
def _GetVariableLocationTree(self, current_location, infos):
if infos["type"] == LOCATION_MODULE:
location = current_location + (infos["IEC_Channel"],)
return {"name": infos["name"],
"type": infos["type"],
"location": ".".join(map(str, location + ("x",))),
"icon": infos["icon"],
"children": [self._GetVariableLocationTree(location, child) for child in infos["children"]]}
elif infos["type"] == LOCATION_GROUP:
return {"name": infos["name"],
"type": infos["type"],
"location": "",
"icon": infos["icon"],
"children": [self._GetVariableLocationTree(current_location, child) for child in infos["children"]]}
else:
size = self.GetSizeOfType(infos["IEC_type"])
location = "%" + LOCATION_DIRS[infos["type"]] + size + ".".join(map(str, current_location + infos["location"]))
return {"name": infos["name"],
"type": infos["type"],
"size": size,
"IEC_type": infos["IEC_type"],
"var_name": infos["name"],
"location": location,
"description": infos["description"],
"children": []}
def GetVariableLocationTree(self):
return {"name": self.BaseParams.getName(),
"type": LOCATION_CONFNODE,
"location": self.GetFullIEC_Channel(),
"icon": self.Icon,
"children": [self._GetVariableLocationTree(self.GetCurrentLocation(), child)
for child in self.VariableLocationTree]}
def CTNTestModified(self):
return False
def CTNMakeDir(self):
pass
def CTNRequestSave(self, from_project_path=None):
return None
def ResetUsedLocations(self):
self.UsedLocations = {}
def _AddUsedLocation(self, parent, location):
num = location.pop(0)
if not parent.has_key(num):
parent[num] = {"used": False, "children": {}}
if len(location) > 0:
self._AddUsedLocation(parent[num]["children"], location)
else:
parent[num]["used"] = True
def AddUsedLocation(self, location):
if len(location) > 0:
self._AddUsedLocation(self.UsedLocations, list(location))
def _CheckLocationConflicts(self, parent, location):
num = location.pop(0)
if not parent.has_key(num):
return False
if len(location) > 0:
if parent[num]["used"]:
return True
return self._CheckLocationConflicts(parent[num]["children"], location)
elif len(parent[num]["children"]) > 0:
return True
return False
def CheckLocationConflicts(self, location):
if len(location) > 0:
return self._CheckLocationConflicts(self.UsedLocations, list(location))
return False
def CTNGenerate_C(self, buildpath, locations):
"""
Generate C code
@param current_location: Tupple containing confnode IEC location : %I0.0.4.5 => (0,0,4,5)
@param locations: List of complete variables locations \
[{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
"NAME" : name of the variable (generally "__IW0_1_2" style)
"DIR" : direction "Q","I" or "M"
"SIZE" : size "X", "B", "W", "D", "L"
"LOC" : tuple of interger for IEC location (0,1,2,...)
}, ...]
@return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
"""
current_location = self.GetCurrentLocation()
# define a unique name for the generated C file
location_str = "_".join(map(str, current_location))
code_str = {"location_str": location_str,
"var_decl": "",
"declare_code": "",
"init_code": "",
"retrieve_code": "",
"publish_code": "",
}
for module in GetModuleChildren(self):
if module["init"] != "":
code_str["init_code"] += " %s\n" % module["init"]
# Adding variables
vars = []
self.ResetUsedLocations()
for location in locations:
loc = location["LOC"][len(current_location):]
group = next = self
i = 0
while next is not None and i < len(loc):
next = self._GetChildBySomething("IEC_Channel", loc[:i + 1])
if next is not None:
i += 1
group = next
var_loc = loc[i:]
for variable in GetModuleChildren(group):
if variable["location"] == var_loc and location["DIR"] == LOCATION_DIRS[variable["type"]]:
# if location["DIR"] != LOCATION_DIRS[variable["type"]]:
# raise Exception, "Direction conflict in variable definition"
# if location["IEC_TYPE"] != variable["IEC_type"]:
# raise Exception, "Type conflict in variable definition"
if location["DIR"] == "Q":
if self.CheckLocationConflicts(location["LOC"]):
raise Exception, "BYTE and BIT from the same BYTE can't be used together"
self.AddUsedLocation(location["LOC"])
vars.append({"location": location["NAME"],
"Type": variable["IEC_type"],
"Retrieve": variable["retrieve"],
"Publish": variable["publish"],
})
break
base_types = self.GetCTRoot().GetBaseTypes()
for var in vars:
prefix = ""
if var["Type"] in base_types:
prefix = "IEC_"
code_str["var_decl"] += "%s%s beremiz%s;\n"%(prefix, var["Type"], var["location"])
code_str["var_decl"] += "%s%s *%s = &beremiz%s;\n"%(prefix, var["Type"], var["location"], var["location"])
if var["Retrieve"] != "":
code_str["retrieve_code"] += " " + var["Retrieve"] % ("*" + var["location"]) + "\n"
if var["Publish"] != "":
code_str["publish_code"] += " " + var["Publish"] % ("*" + var["location"]) + "\n"
BusName = LPCarch + ":" + self.BaseParams.getName()
def bcode(section):
return bus_code.get(BusName,{"decl":"",
"init":"%(init_code)s",
"retrieve":"%(retrieve_code)s",
"publish":"%(publish_code)s",
"cleanup":"",
})[section] % code_str
code_str.update({
"bus_decl":bcode("decl"),
"bus_init_code": bcode("init"),
"bus_cleanup_code": bcode("cleanup"),
"bus_retrieve_code": bcode("retrieve"),
"bus_publish_code": bcode("publish"),
})
if LPCarch not in bus_template_code:
raise Exception, "Unknown arch %s. Please use %s"%(
LPCarch,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[LPCarch] % code_str)
module.close()
matiec_flags = '"-I%s" -Wno-unused-function'%os.path.abspath(self.GetCTRoot().GetIECLibPath())
return [(Gen_Module_path, matiec_flags)],"",True