00001
00002
00003 from collections import OrderedDict
00004 import configparser, sys
00005 import argparse
00006
00007 bitlengths = {
00008 0x0002: 8,
00009 0x0003: 16,
00010 0x0004: 32,
00011 0x0005: 8,
00012 0x0006: 16,
00013 0x0007: 32,
00014 0x0008: 32,
00015 0x0010: 64,
00016 0x0015: 64,
00017 0x001B: 64,
00018 }
00019
00020 def to_hex(value, digits):
00021 return ("%0"+str(digits)+ "x") % value
00022
00023 def get_mapping(ini, name, writable):
00024 if not ini[name].getboolean("PDOMapping"):
00025 print (name, "is not mappable")
00026 exit(1)
00027 try:
00028 can_write = 'w' in ini[name]["AccessType"]
00029 except:
00030 can_write = False
00031
00032 try:
00033 can_read = 'r' in ini[name]["AccessType"]
00034 except:
00035 can_read = False
00036 if (writable and not can_write) or (not writable and not can_read):
00037 print (name, "is not accesable")
00038 exit(1)
00039
00040 parts = name.split("sub")
00041 obj = int(parts[0],16)
00042 sub = int(parts[1],16) if len(parts) == 2 else 0
00043 return (obj, sub, bitlengths[int(ini[name]["DataType"],0)])
00044
00045 def set_pdo(ini, writable, nr, objs, transmission):
00046 if len(objs) > len(set(objs)):
00047 print ("objetcs are not unique")
00048 exit(1)
00049 comobj = to_hex(nr + (0x1400 if writable else 0x1800), 4).upper()
00050 mapobj = to_hex(nr + (0x1600 if writable else 0x1A00), 4).upper()
00051
00052 if not comobj in ini or not mapobj in ini:
00053 print (writable , nr , " is invalid")
00054 exit(1)
00055 mapping = []
00056 bits = 0
00057 for o in objs:
00058 m = get_mapping(ini, o, writable)
00059 bits += m[2]
00060 if bits > 64:
00061 print ("mapping exceeds 64 bits")
00062 exit(1)
00063 mapping.append("0x" + to_hex(m[0],4) + to_hex(m[1],2) +to_hex(m[2],2))
00064
00065 ini[comobj+"sub1"]["ParameterValue"]="$NODEID+0x%x" % ((0x200 if writable else 0x180)+nr*0x100)
00066 ini[comobj+"sub2"]["ParameterValue"]="0x%x" % transmission
00067
00068 ini[mapobj+"sub0"]["ParameterValue"]=str(len(mapping))
00069 for i in range(len(mapping)):
00070 ini[mapobj+"sub%x" % (i+1)]["ParameterValue"]=mapping[i]
00071 for i in range(len(mapping),8):
00072 try:
00073 del ini[mapobj+"sub%x" % (i+1)]["ParameterValue"]
00074 except:
00075 pass
00076
00077 def patch(fname,out, writable, nr, objs, transmission):
00078 ini = configparser.RawConfigParser(dict_type=OrderedDict,allow_no_value=True)
00079 ini.optionxform = lambda option: option
00080 ini.readfp(open(fname))
00081
00082 set_pdo(ini, writable, nr, objs, transmission)
00083 ini.write(open(out,'w'), False)
00084
00085 def patch_all(fname,out, pdos):
00086 ini = configparser.RawConfigParser(dict_type=OrderedDict,allow_no_value=True)
00087 ini.optionxform = lambda option: option
00088 ini.readfp(open(fname))
00089
00090 for (k,v) in pdos.items():
00091 parts = k.split("PDO");
00092 objs = [ o[0] for o in v[1:] ]
00093 set_pdo(ini, parts[0] == "R", int(parts[1])-1, objs, v[0])
00094 ini.write(open(out,'w'), False)
00095
00096
00097 if __name__ == "__main__":
00098 parser = argparse.ArgumentParser()
00099 parser.add_argument("file")
00100 parser.add_argument("pdo", choices=["tpdo","rpdo"])
00101 parser.add_argument("nr", type=int)
00102 parser.add_argument("objs",nargs='+',metavar='OBJ')
00103 parser.add_argument("--transmission", type=lambda x:int(x,0),default=1)
00104 parser.add_argument("--out")
00105
00106 args = parser.parse_args(args)
00107
00108
00109 out = args.out
00110 if not out:
00111 out = args.file
00112 patch(args.file, out, args.nr, args.pdo == "rpdo", args.objs, args.transmission)