diff --git a/utils/convertsub.py b/utils/convertsub.py new file mode 100755 index 0000000..dc59cc2 --- /dev/null +++ b/utils/convertsub.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +""" +This is a little program which generates soft motor initialisation lines and iocsh morsels +from a motor substitutions file. + +Mark Koennecke, December 2019 +""" +import sys +import pdb +import os + +if len(sys.argv) < 2: + print('Usage:\n\tconvertsub XXXX.substitutions') + sys.exit(1) + +subLen = 0 +motors = [] +port = None + +with open(sys.argv[1],'r') as fin: + line = fin.readline() + while line: + line = line.replace(' ','') + line = line.strip('{}') + l = line.split(',') + if line.find('DHLM') > 0: # that is the index discovery line + lowlimidx = l.index('DLLM') + highlimidx = l.index('DHLM') + mresidx = l.index('MRES') + addridx = l.index('ADDR') + prefix = l[0] + subLen = len(l) + portIdx = l.index('PORT') + elif subLen > 0: + l = line.split(',') + if subLen == len(l): + motors.append((l[addridx],l[mresidx],l[lowlimidx],l[highlimidx])) + port = l[portIdx] + else: + pass + line = fin.readline() + +print('%d motors found' % len(motors)) + +fname = os.path.splitext(sys.argv[1])[0] + '.cmd' + +out = open(fname,'w') +out.write('motorSimCreateController(\"%s\",%d)\n' % (port, len(motors)+2)) +for mot in motors: + mres = float(mot[1]) + highlim = int(float(mot[3])/mres) + lowlim = int(float(mot[2])/mres) + out.write('motorSimConfigAxis(\"%s\",%s,%d,%d,0,0)\n' %(port,mot[0],highlim,lowlim)) +out.write('dbLoadTemplate(\"$(TOP)/%s\")\n' % (sys.argv[1])) +out.close() +print(fname + ' written') diff --git a/utils/deltatau.py b/utils/deltatau.py new file mode 100755 index 0000000..fda4bad --- /dev/null +++ b/utils/deltatau.py @@ -0,0 +1,51 @@ +""" + This is some code for communicating with a Delta-Tau PMAC motor + controller as used at SINQ from python. Python 3 is assumed and + tested. We use the ethernet protocol of the Pmac. This code benefits + from the SICS driver for Pmac which in turn benefits from the driver + written by Pete Leicester at Diamond. + + + Usage: python36 deltatau.py pmachost:port command + Then returns the response for command. + + Mark Koennecke, October 2019 +""" + +import struct +import socket + +def packPmacCommand(command): + # 0x40 = VR_DOWNLOAD + # 0xBF = VR_PMAC_GETRESPONSE + buf = struct.pack('BBHHH',0x40,0xBF,0,0,socket.htons(len(command))) + buf = buf + bytes(command,'utf-8') + return buf + +def readPmacReply(input): + msg = bytearray() + expectAck = True + while True: + b = input.recv(1) + bint = int.from_bytes(b,byteorder='little') + if bint == 2 or bint == 7: #STX or BELL + expectAck = False + continue + if expectAck and bint == 6: # ACK + return bytes(msg) + else: + if bint == 13 and not expectAck: # CR + return bytes(msg) + else: + msg.append(bint) + +if __name__ == "__main__": + from sys import argv + addr = argv[1].split(':') + s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) + s.connect((addr[0],int(addr[1]))) + buf = packPmacCommand(argv[2]) + s.send(buf) + reply = readPmacReply(s) + print(reply.decode('utf-8') + '\n') + diff --git a/utils/syncEL734Sub.py b/utils/syncEL734Sub.py new file mode 100755 index 0000000..df52660 --- /dev/null +++ b/utils/syncEL734Sub.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +""" +This little program synchronizes an EPICS substitutions file with values read +from the EL734 motor controller. Some research showed that the EPICS motorRecord +seems to have no means of reading configuration data like limits or speeds or such +from the device support. Than it is the easiest to read the data with this small +program and update the substitutions file with it. + +Mark Koennecke, January 2023 +""" + +import socket +import sys + +socke = None +sockfd = None + +# --------------- communication section +def connect(host, port): + global socke, sockfd + socke = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # socke.connect(('localhost', 5050)) + socke.connect((host, port)) + socke.settimeout(2.) + sockfd = socke.makefile(mode='rw', newline='\r') + sockfd.write('RMT 1\r') + sockfd.flush() + sockfd.write('ECHO 0\r') + sockfd.flush() + sockfd.readline() + +def transact(command): + global socke, sockfd + sockfd.write(command + '\r') + sockfd.flush() + return sockfd.readline() + +def find_commas(rawline): + comma_list = [] + for i in range(len(rawline)): + if rawline[i] == ',': + comma_list.append(i) + return comma_list + +def pretty_line(newlist, comma_list): + """ + adds spaces to match the tabbing of the pattern line + """ + newline = '' + for item, idx in zip(newlist, comma_list): + length = len(newline) + 1 + len(item) + if length < idx: + newline += ' ' * (idx - length) + newline += item + newline += ',' + newline += newlist[-1] + return newline[0:-1] + +def fix_line(par_list, index_list): + # import pdb; pdb.set_trace() + addridx = index_list.index('ADDR') + motNo = par_list[addridx] + limits = transact('H ' + motNo) + l = limits.split() + lowidx = index_list.index('DLLM') + par_list[lowidx] = l[0] + highidx = index_list.index('DHLM') + par_list[highidx] = l[1] + speed = transact('J ' + motNo) + vidx = index_list.index('VELO') + par_list[vidx] = speed.strip() + # vidx = index_list.index('VMAX') + # par_list[vidx] = speed.strip() + return par_list + +def scan_substitution_file(filename): + index_list = None + # import pdb; pdb.set_trace() + with open(filename, 'r') as fin: + rawline = fin.readline() + while rawline: + line = rawline.replace(' ','') + line = line.strip('{}') + l = line.split(',') + if line.find('DHLM') > 0: + index_list = l + comma_list = find_commas(rawline) + sys.stdout.write(rawline) + elif not index_list: + sys.stdout.write(rawline) + else: + if len(l) == len(index_list): + newlist = fix_line(l, index_list) + # newline = ','.join(newlist) + newline = pretty_line(newlist, comma_list) + sys.stdout.write('{' + newline) + else: + sys.stdout.write(rawline) + rawline = fin.readline() + +#------------------ main +if len(sys.argv) < 4: + print('Usage:\n\tsyncEL734sub.py \n') + sys.exit(1) + +connect(sys.argv[1], int(sys.argv[2])) +scan_substitution_file(sys.argv[3]) +socke.close() + + diff --git a/utils/syncPmacSub.py b/utils/syncPmacSub.py new file mode 100755 index 0000000..8af484a --- /dev/null +++ b/utils/syncPmacSub.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +""" +This little program synchronizes an EPICS substitutions file with values read +from the delta tau motor controller. Some research showed that the EPICS motorRecord +seems to have no means of reading configuration data like limits or speeds or such +from the device support. Than it is the easiest to read the data with this small +program and update the substitutions file with it. + +Mark Koennecke, January 2023 +""" + +import socket +import sys +from deltatau import packPmacCommand, readPmacReply + + +socke = None + +# --------------- communication section +def connect(host, port): + global socke, sockfd + socke = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # socke.connect(('localhost', 5050)) + socke.connect((host, port)) + socke.settimeout(1.) + +def transact(command): + global socke + data = packPmacCommand(command) + socke.send(data) + reply = readPmacReply(socke) + return reply.decode('utf-8') + +def find_commas(rawline): + comma_list = [] + for i in range(len(rawline)): + if rawline[i] == ',': + comma_list.append(i) + return comma_list + +def pretty_line(newlist, comma_list): + """ + adds spaces to match the tabbing of the patter line + """ + newline = '' + for item, idx in zip(newlist, comma_list): + length = len(newline) + 1 + len(item) + if length < idx: + newline += ' ' * (idx - length) + newline += item + newline += ',' + newline += newlist[-1] + return newline[0:-1] + +def fix_line(par_list, index_list): + # import pdb; pdb.set_trace() + addridx = index_list.index('ADDR') + motNo = int(par_list[addridx]) + lowlim = transact('Q%d14' % motNo) + lowidx = index_list.index('DLLM') + par_list[lowidx] = lowlim.strip() + highlim = transact('Q%d13' % motNo) + highidx = index_list.index('DHLM') + par_list[highidx] = highlim.strip() + return par_list + +def scan_substitution_file(filename): + index_list = None + # import pdb; pdb.set_trace() + with open(filename, 'r') as fin: + rawline = fin.readline() + while rawline: + line = rawline.replace(' ','') + line = line.strip('{}') + l = line.split(',') + if line.find('DHLM') > 0: + index_list = l + comma_list = find_commas(rawline) + sys.stdout.write(rawline) + elif not index_list: + sys.stdout.write(rawline) + else: + if len(l) == len(index_list): + newlist = fix_line(l, index_list) + # newline = ','.join(newlist) + newline = pretty_line(newlist, comma_list) + sys.stdout.write('{' + newline + '\n') + else: + sys.stdout.write(rawline) + rawline = fin.readline() + +#------------------ main +if len(sys.argv) < 4: + print('Usage:\n\tsyncPmacSub.py \n') + sys.exit(1) + +connect(sys.argv[1], int(sys.argv[2])) +scan_substitution_file(sys.argv[3]) +socke.close() + +