--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/gen_cfile.py Wed May 10 16:59:40 2006 +0200
@@ -0,0 +1,492 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+copyright_notice="""/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+"""
+
+from node import *
+from types import *
+
+import re, os
+
+word_model = re.compile('([a-zA-Z_0-9]*)')
+type_model = re.compile('([\_A-Z]*)([0-9]*)')
+range_model = re.compile('([\_A-Z]*)([0-9]*)\[([\-0-9]*)-([\-0-9]*)\]')
+
+categories = [("SDO_SVR", 0x1200, 0x127F), ("SDO_CLT", 0x1280, 0x12FF),
+ ("PDO_RCV", 0x1400, 0x15FF), ("PDO_RCV_MAP", 0x1600, 0x17FF),
+ ("PDO_TRS", 0x1800, 0x19FF), ("PDO_TRS_MAP", 0x1A00, 0x1BFF)]
+index_categories = ["firstIndex", "lastIndex"]
+
+generated_tag = """\n/* File generated by gen_cfile.py. Should not be modified. */\n"""
+
+# Format a string for making a C++ variable
+def FormatName(name):
+ wordlist = [word for word in word_model.findall(name) if word != '']
+ result = ''
+ sep = ''
+ for word in wordlist:
+ result += "%s%s"%(sep,word)
+ sep = '_'
+ return result
+
+# Extract the informations from a given type name
+def GetValidTypeInfos(typename):
+ result = type_model.match(typename)
+ if result:
+ values = result.groups()
+ if values[0] in ("UNSIGNED", "INTEGER") and eval(values[1]) in [i * 8 for i in xrange(1, 9)]:
+ return "UNS%s"%values[1], "", "uint%s"%values[1]
+ elif values[0] == "REAL" and eval(values[1]) in (32, 64):
+ return "%s%s"%(values[0], values[1]), "", "real%s"%values[1]
+ elif values[0] == "VISIBLE_STRING":
+ if values[1] == "":
+ return "UNS8", "[10]", "visible_string"
+ else:
+ return "UNS8", "[%s]"%values[1], "visible_string"
+ return None
+
+def WriteFile(filepath, content):
+ cfile = open(filepath,"w")
+ cfile.write(content)
+ cfile.close()
+
+def GenerateFileContent(Manager, headerfilepath):
+ global type
+ texts = {}
+ texts["maxPDOtransmit"] = 0
+ texts["NodeName"], texts["NodeID"], texts["NodeType"] = Manager.GetCurrentNodeInfos()
+ internal_types = {}
+ texts["iam_a_slave"] = 0
+ if (texts["NodeType"] == "slave"):
+ texts["iam_a_slave"] = 1
+
+ # Compiling lists of indexes
+ rangelist = [idx for name,idx in Manager.GetCurrentValidIndexes(0, 0x260)]
+ listIndex = [idx for name,idx in Manager.GetCurrentValidIndexes(0x1000, 0xFFFF)]
+ communicationlist = [idx for name,idx in Manager.GetCurrentValidIndexes(0x1000, 0x11FF)]
+ sdolist = [idx for name,idx in Manager.GetCurrentValidIndexes(0x1200, 0x12FF)]
+ pdolist = [idx for name,idx in Manager.GetCurrentValidIndexes(0x1400, 0x1BFF)]
+ variablelist = [idx for name,idx in Manager.GetCurrentValidIndexes(0x2000, 0xBFFF)]
+
+#-------------------------------------------------------------------------------
+# Declaration of the value range types
+#-------------------------------------------------------------------------------
+
+ valueRangeContent = ""
+ strDefine = ""
+ strSwitch = ""
+ num = 0
+ for index in rangelist:
+ rangename = Manager.GetEntryName(index)
+ result = range_model.match(rangename)
+ if result:
+ num += 1
+ internal_types[rangename] = "valueRange_%d"%num
+ typeindex = Manager.GetCurrentEntry(index, 1)
+ typename = Manager.GetTypeName(typeindex)
+ typeinfos = GetValidTypeInfos(typename)
+ if typeinfos == None:
+ raise ValueError, """!!! %s isn't a valid type for CanFestival."""%typename
+ typename = typeinfos[0]
+ minvalue = str(Manager.GetCurrentEntry(index, 2))
+ maxvalue = str(Manager.GetCurrentEntry(index, 3))
+ strDefine += "\n#define valueRange_%d 0x%02X /* Type %s, %s < value < %s */"%(num,index,typename,minvalue,maxvalue)
+ strSwitch += """ case valueRange_%d:
+ if (*(%s*)Value < (%s)%s) return OD_VALUE_TOO_LOW;
+ if (*(%s*)Value > (%s)%s) return OD_VALUE_TOO_HIGH;
+ break;\n"""%(num,typename,typename,minvalue,typename,typename,maxvalue)
+
+ valueRangeContent += strDefine
+ valueRangeContent += "\nUNS32 %(NodeName)s_valueRangeTest (UNS8 typeValue, void * value)\n{"%texts
+ valueRangeContent += "\n switch (typeValue) {\n"
+ valueRangeContent += strSwitch
+ valueRangeContent += " }\n return 0;\n}\n"
+
+#-------------------------------------------------------------------------------
+# Creation of the mapped variables and object dictionary
+#-------------------------------------------------------------------------------
+
+ mappedVariableContent = ""
+ strDeclareHeader = ""
+ strDeclareCallback = ""
+ indexContents = {}
+ indexCallbacks = {}
+ for index in listIndex:
+ texts["index"] = index
+ strIndex = ""
+ entry_infos = Manager.GetEntryInfos(index)
+ texts["EntryName"] = entry_infos["name"]
+ values = Manager.GetCurrentEntry(index)
+ callbacks = Manager.HasCurrentEntryCallbacks(index)
+ if index in variablelist:
+ strIndex += "\n/* index 0x%(index)04X : Mapped variable %(EntryName)s */\n"%texts
+ else:
+ strIndex += "\n/* index 0x%(index)04X : %(EntryName)s. */\n"%texts
+ if type(values) == ListType:
+ texts["value"] = values[0]
+ strIndex += " UNS8 %(NodeName)s_highestSubIndex_obj%(index)04X = %(value)d; // number of subindex - 1\n"%texts
+
+ # Entry type is VAR
+ if type(values) != ListType:
+ subentry_infos = Manager.GetSubentryInfos(index, 0)
+ typename = Manager.GetTypeName(subentry_infos["type"])
+ typeinfos = GetValidTypeInfos(typename)
+ if typeinfos == None:
+ raise ValueError, """!!! %s isn't a valid type for CanFestival."""%typename
+ if typename not in internal_types:
+ internal_types[typename] = typeinfos[2]
+ texts["subIndexType"] = typeinfos[0]
+ texts["suffixe"] = typeinfos[1]
+ if typeinfos[2] == "visible_string":
+ texts["value"] = "\"%s\""%values
+ else:
+ texts["value"] = "0x%X"%values
+ if index in variablelist:
+ texts["name"] = FormatName(subentry_infos["name"])
+ strDeclareHeader += "extern %(subIndexType)s %(name)s%(suffixe)s;\t\t// Mapped at index 0x%(index)04X, subindex 0x00\n"%texts
+ if callbacks:
+ strDeclareHeader += "extern ODCallback_t %(name)s_callbacks[];\t\t// Callbacks of index0x%(index)04X\n"%texts
+ mappedVariableContent += "%(subIndexType)s %(name)s%(suffixe)s = %(value)s;\t\t// Mapped at index 0x%(index)04X, subindex 0x00\n"%texts
+ else:
+ strIndex += " %(subIndexType)s %(NodeName)s_obj%(index)04X%(suffixe)s = %(value)s;\n"%texts
+ values = [values]
+ else:
+
+ # Entry type is RECORD
+ if entry_infos["struct"] & OD_IdenticalSubindexes:
+ subentry_infos = Manager.GetSubentryInfos(index, 1)
+ typename = Manager.GetTypeName(subentry_infos["type"])
+ typeinfos = GetValidTypeInfos(typename)
+ if typeinfos == None:
+ raise ValueError, """!!! %s isn't a valid type for CanFestival."""%typename
+ if typename not in internal_types:
+ internal_types[typename] = typeinfos[2]
+ texts["subIndexType"] = typeinfos[0]
+ texts["suffixe"] = typeinfos[1]
+ texts["length"] = values[0]
+ if index in variablelist:
+ texts["name"] = FormatName(entry_infos["name"])
+ strDeclareHeader += "%(subIndexType)s %(name)s[%(length)d]%(suffixe)s;\t\t// Mapped at index 0x%(index)04X, subindex 0x01 - 0x%(length)02X\n"%texts
+ if callbacks:
+ strDeclareHeader += "extern ODCallback_t %(name)s_callbacks[];\t\t// Callbacks of index0x%(index)04X\n"%texts
+ mappedVariableContent = "%(subIndexType)s %(name)s[] =\t\t// Mapped at index 0x%(index)04X, subindex 0x01 - 0x%(length)02X\n {\n"%texts
+ for subIndex, value in enumerate(values):
+ sep = ","
+ if subIndex > 0:
+ if subIndex == len(values)-1:
+ sep = ""
+ if typeinfos[2] == "visible_string":
+ value = "\"%s\""%value
+ else:
+ value = "0x%X"%value
+ mappedVariableContent += " %s%s\n"%(value, sep)
+ mappedVariableContent += " }\n"
+ else:
+ strIndex += " %(subIndexType)s %(NodeName)s_obj%(index)04X[] = \n {\n"%texts
+ for subIndex, value in enumerate(values):
+ sep = ","
+ if subIndex > 0:
+ if subIndex == len(values)-1:
+ sep = ""
+ if typeinfos[2] == "visible_string":
+ value = "\"%s\""%value
+ else:
+ value = str(value)
+ strIndex += " %s%s\n"%(value, sep)
+ strIndex += " };\n"
+ else:
+
+ # Entry type is ARRAY
+ for subIndex, value in enumerate(values):
+ texts["subIndex"] = subIndex
+ if subIndex > 0:
+ subentry_infos = Manager.GetSubentryInfos(index, subIndex)
+ typename = Manager.GetTypeName(subentry_infos["type"])
+ typeinfos = GetValidTypeInfos(typename)
+ if typeinfos == None:
+ raise ValueError, """!!! %s isn't a valid type for CanFestival."""%typename
+ if typename not in internal_types:
+ internal_types[typename] = typeinfos[2]
+ texts["subIndexType"] = typeinfos[0]
+ texts["suffixe"] = typeinfos[1]
+ if typeinfos[2] == "visible_string":
+ texts["value"] = "\"%s\""%value
+ else:
+ texts["value"] = "0x%X"%value
+ texts["name"] = FormatName(subentry_infos["name"])
+ if index in variablelist:
+ strDeclareHeader += "extern %(subIndexType)s %(name)s%(suffixe)s;\t\t// Mapped at index 0x%(index)04X, subindex 0x%(subIndex)02X\n"%texts
+ mappedVariableContent += "%(subIndexType)s %(name)s%(suffixe)s = %(value)s;\t\t// Mapped at index 0x%(index)04X, subindex 0x%(subIndex)02X\n"%texts
+ else:
+ strIndex += " %(subIndexType)s %(NodeName)s_obj%(index)04X_%(name)s%(suffixe)s = %(value)s;\n"%texts
+ if callbacks:
+ texts["name"] = FormatName(entry_infos["name"])
+ strDeclareHeader += "extern ODCallback_t %(name)s_callbacks[];\t\t// Callbacks of index0x%(index)04X\n"%texts
+
+ # Generating Dictionary C++ entry
+ if callbacks:
+ if index in variablelist:
+ name = FormatName(entry_infos["name"])
+ else:
+ name = "%(NodeName)s_Index%(index)04X"%texts
+ strIndex += " ODCallback_t %s_callbacks[] = \n {\n"%name
+ for subIndex in xrange(len(values)):
+ strIndex += " NULL,\n"
+ strIndex += " };\n"
+ indexCallbacks[index] = "*callbacks = %s_callbacks; "%name
+ else:
+ indexCallbacks[index] = ""
+ strIndex += " subindex %(NodeName)s_Index%(index)04X[] = \n {\n"%texts
+ for subIndex in xrange(len(values)):
+ subentry_infos = Manager.GetSubentryInfos(index, subIndex)
+ if subIndex < len(values) - 1:
+ sep = ","
+ else:
+ sep = ""
+ typename = Manager.GetTypeName(subentry_infos["type"])
+ typeinfos = GetValidTypeInfos(typename)
+ if typename.startswith("VISIBLE_STRING"):
+ subIndexType = "visible_string"
+ elif typename in internal_types:
+ subIndexType = internal_types[typename]
+ else:
+ subIndexType = typename
+ if subIndex == 0:
+ if entry_infos["struct"] & OD_MultipleSubindexes:
+ name = "%(NodeName)s_highestSubIndex_obj%(index)04X"%texts
+ elif index in variablelist:
+ name = FormatName(subentry_infos["name"])
+ else:
+ name = FormatName("%s_obj%04X"%(texts["NodeName"], texts["index"]))
+ elif entry_infos["struct"] & OD_IdenticalSubindexes:
+ if index in variablelist:
+ name = "%s[%d]"%(FormatName(entry_infos["name"]), subIndex - 1)
+ else:
+ name = "%s_obj%04X[%d]"%(texts["NodeName"], texts["index"], subIndex - 1)
+ else:
+ if index in variablelist:
+ name = FormatName(subentry_infos["name"])
+ else:
+ name = "%s_obj%04X_%s"%(texts["NodeName"], texts["index"], FormatName(subentry_infos["name"]))
+ if subIndexType == "visible_string":
+ sizeof = name
+ else:
+ sizeof = typeinfos[0]
+ params = Manager.GetCurrentParamsEntry(index, subIndex)
+ if params["save"]:
+ save = "|TO_BE_SAVE"
+ else:
+ save = ""
+ strIndex += " { %s%s, %s, sizeof (%s), (void*)&%s }%s\n"%(subentry_infos["access"].upper(),save,subIndexType,sizeof,name,sep)
+ strIndex += " };\n"
+ indexContents[index] = strIndex
+
+#-------------------------------------------------------------------------------
+# Declaration of Particular Parameters
+#-------------------------------------------------------------------------------
+
+ if 0x1006 not in communicationlist:
+ entry_infos = Manager.GetEntryInfos(0x1006)
+ texts["EntryName"] = entry_infos["name"]
+ indexContents[0x1006] = """\n/* index 0x1006 : %(EntryName)s */
+ UNS32 %(NodeName)s_obj1006 = 0;
+"""%texts
+
+ if 0x1016 in communicationlist:
+ texts["nombre"] = Manager.GetCurrentEntry(0x1016, 0)
+ else:
+ texts["nombre"] = 0
+ entry_infos = Manager.GetEntryInfos(0x1016)
+ texts["EntryName"] = entry_infos["name"]
+ indexContents[0x1016] = """\n/* index 0x1016 : %(EntryName)s */
+ UNS8 %(NodeName)s_highestSubIndex_obj1016 = 0;
+ UNS32 %(NodeName)s_obj1016[0];
+ subindex %(NodeName)s_Index1016[0];
+"""%texts
+ if texts["nombre"] > 0:
+ strTimers = "TIMER_HANDLE %(NodeName)s_heartBeatTimers[%(nombre)d] = {TIMER_NONE,};\n"%texts
+ else:
+ strTimers = "TIMER_HANDLE %(NodeName)s_heartBeatTimers[0];\n"%texts
+
+ if 0x1017 not in communicationlist:
+ entry_infos = Manager.GetEntryInfos(0x1017)
+ texts["EntryName"] = entry_infos["name"]
+ indexContents[0x1017] = """\n/* index 0x1017 : %(EntryName)s */
+ UNS16 %(NodeName)s_obj1017 = 0;
+"""%texts
+
+#-------------------------------------------------------------------------------
+# Declaration of navigation in the Object Dictionary
+#-------------------------------------------------------------------------------
+
+ strDeclareIndex = ""
+ strDeclareSwitch = ""
+ strQuickIndex = ""
+ quick_index = {}
+ for index_cat in index_categories:
+ quick_index[index_cat] = {}
+ for cat, idx_min, idx_max in categories:
+ quick_index[index_cat][cat] = 0
+ maxPDOtransmit = 0
+ for i, index in enumerate(listIndex):
+ texts["index"] = index
+ strDeclareIndex += " { (subindex*)%(NodeName)s_Index%(index)04X,sizeof(%(NodeName)s_Index%(index)04X)/sizeof(%(NodeName)s_Index%(index)04X[0]), 0x%(index)04X},\n"%texts
+ strDeclareSwitch += " case 0x%04X: i = %d;%sbreak;\n"%(index, i, indexCallbacks[index])
+ for cat, idx_min, idx_max in categories:
+ if idx_min <= index <= idx_max:
+ quick_index["lastIndex"][cat] = i
+ if quick_index["firstIndex"][cat] == 0:
+ quick_index["firstIndex"][cat] = i
+ if cat == "PDO_TRS":
+ maxPDOtransmit += 1
+ texts["maxPDOtransmit"] = max(1, maxPDOtransmit)
+ for index_cat in index_categories:
+ strQuickIndex += "\nquick_index %s_%s = {\n"%(texts["NodeName"], index_cat)
+ sep = ","
+ for i, (cat, idx_min, idx_max) in enumerate(categories):
+ if i == len(categories) - 1:
+ sep = ""
+ strQuickIndex += " %s : %d%s\n"%(cat, quick_index[index_cat][cat], sep)
+ strQuickIndex += "};\n"
+
+#-------------------------------------------------------------------------------
+# Write File Content
+#-------------------------------------------------------------------------------
+
+ fileContent = copyright_notice + generated_tag + """
+#include "%s"
+"""%(headerfilepath)
+
+ fileContent += """
+/**************************************************************************/
+/* Declaration of the mapped variables */
+/**************************************************************************/
+""" + mappedVariableContent
+
+ fileContent += """
+/**************************************************************************/
+/* Declaration of the value range types */
+/**************************************************************************/
+""" + valueRangeContent
+
+ fileContent += """
+/**************************************************************************/
+/* The node id */
+/**************************************************************************/
+/* node_id default value.*/
+UNS8 %(NodeName)s_bDeviceNodeId = 0x%(NodeID)02X;
+
+//*****************************************************************************/
+/* Array of message processing information */
+
+const UNS8 %(NodeName)s_iam_a_slave = %(iam_a_slave)d;
+
+"""%texts
+ fileContent += strTimers
+
+ fileContent += """
+//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+//
+// OBJECT DICTIONARY
+//
+//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+"""%texts
+ contentlist = indexContents.keys()
+ contentlist.sort()
+ for index in contentlist:
+ fileContent += indexContents[index]
+
+ fileContent += """
+const indextable %(NodeName)s_objdict[] =
+{
+"""%texts
+ fileContent += strDeclareIndex
+ fileContent += """};
+
+const indextable * %(NodeName)s_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks)
+{
+ int i;
+ *callbacks = NULL;
+ switch(wIndex){
+"""%texts
+ fileContent += strDeclareSwitch
+ fileContent += """ default:
+ *errorCode = OD_NO_SUCH_OBJECT;
+ return NULL;
+ }
+ *errorCode = OD_SUCCESSFUL;
+ return &%(NodeName)s_objdict[i];
+}
+
+// To count at which received SYNC a PDO must be sent.
+// Even if no pdoTransmit are defined, at least one entry is computed
+// for compilations issues.
+UNS8 %(NodeName)s_count_sync[%(maxPDOtransmit)d] = {0,};
+"""%texts
+ fileContent += strQuickIndex
+ fileContent += """
+UNS16 %(NodeName)s_ObjdictSize = sizeof(%(NodeName)s_objdict)/sizeof(%(NodeName)s_objdict[0]);
+
+CO_Data %(NodeName)s_Data = CANOPEN_NODE_DATA_INITIALIZER(%(NodeName)s);
+
+"""%texts
+
+#-------------------------------------------------------------------------------
+# Write Header File Content
+#-------------------------------------------------------------------------------
+
+ HeaderFileContent = copyright_notice + generated_tag + """
+#include "data.h"
+
+// prototypes of function to be filled by app
+void %(NodeName)s_SDOtimeoutError(UNS8 line);
+void %(NodeName)s_heartbeatError(UNS8);
+
+UNS8 %(NodeName)s_canSend(Message *);
+
+void %(NodeName)s_initialisation();
+void %(NodeName)s_preOperational();
+void %(NodeName)s_operational();
+void %(NodeName)s_stopped();
+
+void %(NodeName)s_post_sync();
+void %(NodeName)s_post_TPDO();
+
+// Master node data struct
+extern CO_Data %(NodeName)s_Data;
+
+"""%texts
+ HeaderFileContent += strDeclareHeader
+
+ return fileContent,HeaderFileContent
+
+#-------------------------------------------------------------------------------
+# Main Function
+#-------------------------------------------------------------------------------
+
+def GenerateFile(filepath, manager):
+ headerfilepath = os.path.splitext(filepath)[0]+".h"
+ content, header = GenerateFileContent(manager, os.path.split(headerfilepath)[1])
+ WriteFile(filepath, content)
+ WriteFile(headerfilepath, header)
+ return True