board_config.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. """
  2. Configuration for each board
  3. """
  4. import os
  5. import sys
  6. if sys.version_info[:3] < (3,0):
  7. import ConfigParser as configparser
  8. else:
  9. import configparser
  10. import numpy as np
  11. import logging
  12. from PyQt4 import QtGui, QtCore
  13. from time import sleep
  14. from .communication import *
  15. from .... import config as kcg_config
  16. class BoardConfiguration(QtGui.QWidget):
  17. """
  18. The Main configuration class for boards.
  19. """
  20. callback_signal = QtCore.pyqtSignal(str, list)
  21. def __init__(self, identifier, config_file=None):
  22. from . import sequences
  23. super(BoardConfiguration, self).__init__()
  24. self.callback_signal.connect(self._notify_observers_receiver)
  25. self.identifier = identifier
  26. self._config = {}
  27. self._observers = {}
  28. self._observers_for_all = []
  29. self._observers_write = {}
  30. self._set_defaults()
  31. self._get_board_version()
  32. if self._config['board_version'] > 10:
  33. logging.critical('Unknown Board Version - gui not working! - restart with active board')
  34. print('Unknown Board Version - gui not working! - restart with active board')
  35. else:
  36. logging.info('Detected Board Version: {}'.format(self._config["board_version"]))
  37. print('Detected Board Version: {}'.format(self._config["board_version"]))
  38. self._sequences = sequences.read_sequence(self._config["board_version"])
  39. self.set_default_observers()
  40. if self.is_KAPTURE2():
  41. self.update('bunches_per_turn', kcg_config.bunches_per_turn)
  42. else:
  43. self._config['delay_330_factor'] = 150
  44. self._config['delay_330_max'] = 15
  45. self._config['chip_delay'] = [3,3,3,3]
  46. if config_file:
  47. self.load_config(config_file)
  48. #self.notify_all_observers(True)
  49. def _set_defaults(self):
  50. """
  51. Set default values
  52. """
  53. self._config = {
  54. 'board_version' : 7,
  55. 'lastDataSet': None,
  56. 'adc_number': 8,
  57. 'samplingrate': 1,
  58. 'bunches_per_turn': 184,
  59. 'header_byte_size': 32,
  60. 'chip_delay_max': 31,
  61. 'chip_delay' : [0,0,0,0,0,0,0,0],
  62. 'bunch_shift' : [2,2,2,2,2,2,2,2], #Offset by +2 to encode -2 to +2 range
  63. 'chip_delay_factor': 3,
  64. 'delay_330_max': 20, #technical 522 #be aware: changing this makes the Delay Calibration invalid!
  65. 'delay_330_factor': 330,
  66. 'delay_330_th': 0,
  67. 'delay_330_adc': 1,
  68. 'delay_330_fpga': 1,
  69. #-Kapture 2 only--------------------
  70. 'delay_25_max' : 23, #be aware: changing this makes the Delay Calibration invalid!
  71. 'delay_25_factor': 25,
  72. 'delay_25_th': 0,
  73. 'delay_25_adc': 10,
  74. 'delay_25_fpga': 0,
  75. #-Second FMC------------------
  76. 'delay_330_th_2': 0,
  77. 'delay_330_adc_2': 1,
  78. #'delay_330_fpga_2': 0,
  79. 'delay_25_th_2': 4,
  80. 'delay_25_adc_2': 10,
  81. #'delay_25_fpga_2': 0,
  82. 'default_25_th_2': 4,
  83. 'delay_cascade_max': 20,
  84. 'delay_cascade_factor': 330,
  85. 'delay_cascade': 0,
  86. 'delay_cascade_25': 14,
  87. #-Clock Division--------------
  88. 'clk_div': 6,
  89. 'clk_div_th': 6,
  90. 'clk_div_adc': 6,
  91. 'clk_div_fpga': 6,
  92. 'clk_div_cascade': 24,
  93. #-Kapture 1 only-------------------
  94. 'th_to_adc_cycles': 7,
  95. #'adc_1_delay_individual': -1,
  96. #----------------------------------
  97. 'turns_observe': 1000,
  98. 'turns_skip': 0,
  99. 'acquisition_count': 10,
  100. 'turns_wait_time': 15,
  101. 'trigger_skip': 0,
  102. 'trigger_timeout': 12,
  103. 'trigger_method': 1,
  104. 'use_trigger': False,
  105. 'build_spectrograms': False,
  106. 'pilot_bunch': True,
  107. 'header': True if kcg_config.save_header is True else False,
  108. #Kapture 2
  109. 'adc_offset': [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000],
  110. 'adc_gain': [0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000]
  111. }
  112. def _get_board_version(self):
  113. try:
  114. self._config["board_version"] = int(pci.read(self.identifier, reg='0x9030')[0])
  115. if self._config["board_version"] == 6:
  116. self._config["board_version"] = 5
  117. elif self._config["board_version"] == 7:
  118. self._config["adc_number"] = 8
  119. except Exception as e:
  120. self._config["board_version"] = 0xDEAD
  121. def is_KAPTURE2(self):
  122. return self._config["board_version"] >4
  123. ##########################################################################
  124. # .d8888b.
  125. # d88P Y88b
  126. # Y88b.
  127. # "Y888b. .d88b. .d88888888 888 .d88b. 88888b. .d8888b .d88b.
  128. # "Y88b.d8P Y8bd88" 888888 888d8P Y8b888 "88bd88P" d8P Y8b
  129. # "88888888888888 888888 88888888888888 888888 88888888
  130. # Y88b d88PY8b. Y88b 888Y88b 888Y8b. 888 888Y88b. Y8b.
  131. # "Y8888P" "Y8888 "Y88888 "Y88888 "Y8888 888 888 "Y8888P "Y8888
  132. # 888
  133. # 888
  134. # 888
  135. #
  136. def get_sequence_list(self):
  137. if self._sequences =={}:
  138. return "No Sequences"
  139. return self._sequences["sequence_names"]
  140. def get_init_order(self):
  141. if self._sequences =={}:
  142. return "No Sequences"
  143. return self._sequences["initialization_sequence_order"]
  144. def get_sequence_comment(self, sequence_name):
  145. if self._sequences =={}:
  146. return "No Sequences"
  147. return self._sequences[sequence_name]["Comment"]
  148. def get_sequence_status(self, sequence_name):
  149. if self._sequences =={}:
  150. return "No Sequences"
  151. return self._sequences[sequence_name]["status_val"]
  152. def run_sequence(self, name, progressbar=None):
  153. if self._sequences == {}:
  154. return False
  155. from . import sequences
  156. return sequences.run_sequence(self.identifier, self._sequences[name]["sequence"], progressbar)
  157. ##########################################################################
  158. ##########################################################################
  159. def load_config(self, filename):
  160. """
  161. Load a config from a file
  162. :param filename: the configuration file
  163. :return:
  164. """
  165. if filename:
  166. config = configparser.RawConfigParser()
  167. if not config.read(str(filename)):
  168. return False
  169. for key in list(self._config.keys()):
  170. try:
  171. if type(self._config[key]) == int:
  172. self._config[key] = config.getint('Config', key)
  173. elif type(self._config[key]) == bool:
  174. self._config[key] = config.getboolean('Config', key)
  175. logging.vinfo("Read '%s' for '%s' from '%s'"%(str(self._config[key]), key, str(filename)))
  176. except configparser.NoOptionError as e:
  177. pass
  178. except configparser.NoSectionError as e:
  179. pass
  180. return True
  181. else:
  182. return False
  183. def save_config(self, filename):
  184. """
  185. Save the current configuration to a file
  186. :param filename: the file to write to
  187. """
  188. if filename:
  189. # with open(filename, 'w') as f:
  190. try:
  191. f = open(filename, 'w')
  192. cp = configparser.RawConfigParser()
  193. cp.add_section('Config')
  194. for key in list(self._config.keys()):
  195. cp.set('Config', key, self._config[key])
  196. f.write('#\n'
  197. '# KCG (KAPTURE Control Gui) Configuration file\n'
  198. '#\n'
  199. '# (c) Karlsruhe Institute of Technology, 2015\n'
  200. '# All rights reserved.\n'
  201. '#\n'
  202. '# Applicable Gui Version(s): 1.0 - 1.0.2\n'
  203. '#\n'
  204. '# Saved at: ' + time.asctime() + '\n'
  205. '#\n\n')
  206. cp.write(f)
  207. except (IOError, TypeError):
  208. return False
  209. return True
  210. else:
  211. return False
  212. def get(self, key):
  213. """
  214. Get the configuration value for key
  215. :param key: the key to get the value for
  216. :return: the value of the configuration for key
  217. """
  218. if not key in self._config:
  219. raise NoSuchKeyError(key+" is not registered in BoardConfiguration for board "+str(self.identifier))
  220. return self._config.get(key, None)
  221. def dump(self):
  222. """
  223. Dump all configuration values
  224. :return: all configuration values as list
  225. """
  226. s = ""
  227. for key in list(self._config.keys()):
  228. s += key + ": " + str(self.get(key)) + ", "
  229. return s[:-1]
  230. ##########################################################################
  231. # .d88888b. 888
  232. # d88P" "Y88b888
  233. # 888 888888
  234. # 888 88888888b. .d8888b .d88b. 888d888888 888 .d88b. 888d888.d8888b
  235. # 888 888888 "88b88K d8P Y8b888P" 888 888d8P Y8b888P" 88K
  236. # 888 888888 888"Y8888b.88888888888 Y88 88P88888888888 "Y8888b.
  237. # Y88b. .d88P888 d88P X88Y8b. 888 Y8bd8P Y8b. 888 X88
  238. # "Y88888P" 88888P" 88888P' "Y8888 888 Y88P "Y8888 888 88888P'
  239. def set_default_observers(self):
  240. """
  241. Set observers that are always used
  242. """
  243. #def obsprint(x,y):
  244. # print(x, y)
  245. #self.observe_all(obsprint)
  246. self.observe_write(self._update_header, 'header')
  247. self.observe_write(self._update_pilot_bunch, 'pilot_bunch')
  248. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x9020'), 'turns_observe')
  249. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x9028'), 'turns_skip')
  250. if self._config['board_version'] > 4: # everything for KAPTURE 2
  251. self.observe_write(lambda x: pci.write(self.identifier, hex(x-2), '0x90E0'), 'bunches_per_turn')
  252. self.observe_write(self._set_adc_gain, 'adc_gain')
  253. self.observe_write(self._set_adc_offset, 'adc_offset')
  254. #Attention: the th delays are inverted! Means: due to the internal setup by increasing the value the sampling
  255. #would be earlier. This is not intuitive therefore the gui inverts the value by using the delay_max as offset.
  256. #Setup Long delay 330ps. Value needs to be shifted to the left because first bit is used to set halfstep
  257. self.observe_write(lambda x: pci.write(self.identifier, hex((x+5)<<1), '0x9090'), 'delay_330_adc')
  258. self.observe_write(lambda x: pci.write(self.identifier, hex((self._config['delay_330_max']-x+5)<<1), '0x90B0'), 'delay_330_th')
  259. self.observe_write(lambda x: pci.write(self.identifier, hex((x+5)<<1), '0x90C0'), 'delay_330_fpga')
  260. self.observe_write(lambda x: pci.write(self.identifier, hex((x+5)<<1), '0x90D0'), 'delay_cascade')
  261. #Setup short Delay 25ps.
  262. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x9094'), 'delay_25_adc')
  263. self.observe_write(lambda x: pci.write(self.identifier, hex(self._config['delay_25_max']-x), '0x90B4'), 'delay_25_th')
  264. #self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x90C4'), 'delay_25_fpga')
  265. #Setup Clock Div
  266. self.observe_write(self._set_clk_div_all , 'clk_div') #one to set it all - normaly they should be all the same
  267. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x9098'), 'clk_div_adc')
  268. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x90B8'), 'clk_div_th')
  269. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x90C8'), 'clk_div_fpga')
  270. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x90D8'), 'clk_div_cascade')
  271. self.observe_write(self._set_chip_delay, 'chip_delay')
  272. self.observe_write(self._set_samplingrate, 'samplingrate')
  273. self.observe_write(self._set_bunch_shift, 'bunch_shift')
  274. if self._config['adc_number'] > 4:
  275. #Setup Long delay 330ps. Value needs to be shifted to the left because first bit is used vor halfstep
  276. self.observe_write(lambda x: pci.write(self.identifier, hex((x+5)<<1), '0x90A0'), 'delay_330_adc_2')
  277. self.observe_write(lambda x: pci.write(self.identifier, hex((self._config['delay_330_max']-x+5)<<1), '0x90A8'), 'delay_330_th_2')
  278. #Setup short Delay 25ps
  279. self.observe_write(lambda x: pci.write(self.identifier, hex(x), '0x90A4'), 'delay_25_adc_2')
  280. self.observe_write(lambda x: pci.write(self.identifier, hex(self._config['delay_25_max']-x), '0x90AC'), 'delay_25_th_2')
  281. else:
  282. self.observe_write(self._set_fpga_delay, 'delay_330_fpga')
  283. self.observe_write(self._set_chip_delay, 'chip_delay')
  284. self.observe_write(self._set_th_delay, 'delay_330_th')
  285. self.observe_write(self._set_adc_delay, 'delay_330_adc')
  286. def notify_all_observers(self, write=False):
  287. """
  288. Notify all observers not only the ones that are affected by a change
  289. """
  290. for key, value in list(self._config.items()):
  291. self._notify_observers(key, value, write)
  292. # observers = self._observers.get(key, None)
  293. # if observers:
  294. # for (who, callback) in observers:
  295. # callback(self.get(key))
  296. def update(self, key, value, entry=None, write=True):
  297. """
  298. Update the value for key in the configuration
  299. :param key: the key to update
  300. :param value: the value to set the configuration for key to
  301. :param entry: if key is array to select the array index.
  302. """
  303. if entry is not None:
  304. self._config[key][entry] = value
  305. else:
  306. self._config[key] = value
  307. self._notify_observers(key, self._config[key], write)
  308. def updateSilent(self, key, value, entry=None):
  309. """
  310. Update the configuration without notifying observers
  311. :param key: the key to updae
  312. :param value: the value to set the configuration of key to
  313. :param entry: if key is array to select the array index.
  314. """
  315. if entry is not None:
  316. self._config[key][entry] = value
  317. else:
  318. self._config[key] = value
  319. def observe(self, who, callback, key):
  320. """
  321. Register an observer. (A callback that is called when the according configuration value changes)
  322. :param who: who is observing
  323. :param callback: the callback to call on change of the configuration value
  324. :param key: the key to observe
  325. """
  326. if key not in list(self._config.keys()):
  327. raise ObserverError(str("Key '%s' is unknown." % key))
  328. if self._observers.get(key, None) is None:
  329. self._observers[key] = []
  330. self._observers[key].append([who, callback])
  331. def observe_all(self, callback):
  332. """
  333. Register a observer that is called when any key changes
  334. :param callback: the callback to register
  335. """
  336. if callback not in self._observers_for_all:
  337. self._observers_for_all.append(callback)
  338. else:
  339. raise ObserverError("Observer already registered")
  340. def observe_write(self, callback, key):
  341. """
  342. Register an observer that writes the value for Key on the Board
  343. :param callback: the callback to call on change of the configuration value
  344. :param key: the key to observe
  345. """
  346. if key not in list(self._config.keys()):
  347. raise ObserverError(str("Key '%s' is unknown." % key))
  348. if self._observers_write.get(key, None) is None:
  349. self._observers_write[key] = []
  350. self._observers_write[key].append(callback)
  351. def unobserve(self, who, key=None):
  352. """
  353. Remove an observer
  354. :param who: the observing entity
  355. :param key: the key to remove it from
  356. """
  357. if key is not None:
  358. observers = np.array(self._observers.get(key, None))
  359. if observers is None:
  360. return
  361. if who not in observers[:, 0]:
  362. return
  363. for i, _obs in enumerate(self._observers[key]):
  364. if _obs[0] is who:
  365. del self._observers[key][i]
  366. if not self._observers[key]:
  367. del self._observers[key]
  368. return
  369. for _key in list(self._observers.keys()):
  370. for i, _obs in enumerate(self._observers[_key]):
  371. if _obs[0] is who:
  372. del self._observers[_key][i]
  373. if not self._observers[_key]:
  374. del self._observers[_key]
  375. def unobserve_all_observer(self, callback):
  376. """
  377. Unobserve an observer that observes all keys.
  378. :param callback: the callback to unobserve
  379. """
  380. if callback in self._observers_for_all:
  381. del self._observers_for_all[self._observers_for_all.index(callback)]
  382. def _notify_observers_receiver(self, key, args):
  383. """
  384. The pyqt signal slot for notifications of observers
  385. :param key: the key that changed
  386. :param value: the new value
  387. """
  388. observers = self._observers.get(str(key), None)
  389. value = args[0]
  390. write = args[1]
  391. if observers is not None:
  392. for (who, callback) in observers:
  393. try:
  394. callback(value)
  395. except Exception as e:
  396. log.error('Observer Callback error: {}'.format(e))
  397. for cb in self._observers_for_all:
  398. try:
  399. cb(key, value)
  400. except:
  401. pass
  402. if write:
  403. observers = self._observers_write.get(str(key), None)
  404. if observers is not None:
  405. for callback in observers:
  406. try:
  407. #log.debug('write ' + key , args)
  408. callback(value)
  409. except Exception as e:
  410. log.error('Observer Callback error: {}'.format(e))
  411. time.sleep(0.025)
  412. def _notify_observers(self, key, value, write=True):
  413. """
  414. Notify observers. This emits a pyqt signal to make it thread save
  415. :param key: the key that changed
  416. :param value: the new value
  417. """
  418. #print("_notify_observers", key, value, write)
  419. self.callback_signal.emit(key, [value, write])
  420. def make_uint(self, value, maximum, name=None):
  421. """
  422. Convert a value to an uint
  423. :param value: the value
  424. :param maximum: the maximum of the returned value
  425. :param name: the name of this value
  426. :return: the converted value
  427. """
  428. if value is None:
  429. raise ValueError(str("%s Value is invalid (None)" % name))
  430. val = None
  431. try:
  432. val = int(value)
  433. except ValueError:
  434. raise ValueError(str("%s Value is not a valid number" % name))
  435. if maximum is not None:
  436. if val > maximum:
  437. raise ValueError(str("%s Value is too large (>%i)" % (name, maximum)))
  438. if val < 0:
  439. raise ValueError(str("%s Values below 0 are not allowed" % name))
  440. return val
  441. def _set_clk_div_all(self, value):
  442. self.update('clk_div_adc', value)
  443. self.update('clk_div_th', value)
  444. self.update('clk_div_fpga', value)
  445. self.update('clk_div_cascade', value)
  446. def _set_chip_delay(self, values):
  447. """
  448. Set the chip_delays on the board
  449. :param values: the value to set the delays to
  450. """
  451. _values = []
  452. for value in values[:4]:
  453. _values.append(self.make_uint(value, self.get('chip_delay_max'), 'ADC_Value'))
  454. #print("ADC1: ", values, _values)
  455. reg_value = ''
  456. mask = ''
  457. # Chip Delays are stored as 'ADC_4 ADC_3 ADC_2 ADC_1' in the register.
  458. # Therefore, we need to traverse the factors array in reverse order
  459. for value in _values: #reversed(_values): # not for Kapture 2
  460. if value is not None:
  461. reg_value += '{0:02x}'.format(value)
  462. mask += 'ff'
  463. else:
  464. reg_value += '00'
  465. mask += '00'
  466. if self._config['adc_number'] > 4:
  467. pci.write(self.identifier, reg_value, '0x9084', hex_mask=mask)
  468. else:
  469. pci.write(self.identifier, reg_value, '0x9080', hex_mask=mask)
  470. s = "Setting ADC Delays:"
  471. for (adc, value) in enumerate(_values):
  472. s += ' ADC_%i Fine Delay: %i,' % (adc, value)
  473. s = s[:-1] # cut away the last dangling ','
  474. logging.vinfo(s)
  475. if self._config['adc_number'] > 4:
  476. _values = []
  477. for value in values[4:]:
  478. _values.append(self.make_uint(value, self.get('chip_delay_max'), 'ADC_Value'))
  479. #print("ADC 2", values, _values)
  480. reg_value = ''
  481. mask = ''
  482. # Chip Delays are stored as 'ADC_4 ADC_3 ADC_2 ADC_1' in the register.
  483. # Therefore, we need to traverse the factors array in reverse order
  484. for value in _values: #reversed(_values): # not for Kapture 2
  485. if value is not None:
  486. reg_value += '{0:02x}'.format(value)
  487. mask += 'ff'
  488. else:
  489. reg_value += '00'
  490. mask += '00'
  491. pci.write(self.identifier, reg_value, '0x9080', hex_mask=mask)
  492. s = "Setting ADC Delays:"
  493. for (adc, value) in enumerate(_values):
  494. s += ' ADC_%i Fine Delay: %i,' % (adc+4, value)
  495. s = s[:-1] # cut away the last dangling ','
  496. logging.vinfo(s)
  497. def _set_bunch_shift(self, values):
  498. #print("Setting bunch shifts: ", values)
  499. base_reg = 0x9320
  500. for i, val in enumerate(values):
  501. reg = hex(base_reg+(i*4))
  502. set = "0x{0:08x}".format(val)
  503. logging.vinfo("Setting %s to %s"%(reg,set))
  504. pci.write(self.identifier, set, reg)
  505. def _update_header(self, state):
  506. """
  507. Set the flag to write Header to files when acquiring.
  508. :param state: True to enabling header and False to disable
  509. :return: -
  510. """
  511. try:
  512. control = pci.read(self.identifier, 1, '0x9040')[0]
  513. control_bits = '{0:032b}'.format(int(control, 16))
  514. if state:
  515. control_bits = control_bits[:3] + '1' + control_bits[4:]
  516. else:
  517. control_bits = control_bits[:3] + '0' + control_bits[4:]
  518. dec_val_bits = int(control_bits, 2)
  519. pci.write(self.identifier, hex(dec_val_bits), '0x9040')
  520. except BoardError as e:
  521. reason = str(e) if str(e) != '' else "Unknown"
  522. logging.error("Error in Board Communication, was unable to write value to board "+reason)
  523. def _update_pilot_bunch(self, state):
  524. """
  525. Set the flag to write Header to files when acquiring.
  526. :param state: True to enabling header and False to disable
  527. :return: -
  528. """
  529. try:
  530. control = pci.read(self.identifier, 1, '0x9040')[0]
  531. control_bits = '{0:032b}'.format(int(control, 16))
  532. if state:
  533. control_bits = control_bits[:1] + '1' + control_bits[2:]
  534. else:
  535. control_bits = control_bits[:1] + '0' + control_bits[2:]
  536. dec_val_bits = int(control_bits, 2)
  537. pci.write(self.identifier, hex(dec_val_bits), '0x9040')
  538. except BoardError as e:
  539. reason = str(e) if str(e) != '' else "Unknown"
  540. logging.error("Error in Board Communication, was unable to write value to board "+reason)
  541. def _set_adc_gain(self, x):
  542. self._select_adc(1)
  543. pci.write(self.identifier, '46{:04x}'.format(int(x[0])), '0x9064')
  544. pci.write(self.identifier, '56{:04x}'.format(int(x[1])), '0x9064')
  545. self._select_adc(3)
  546. pci.write(self.identifier, '46{:04x}'.format(int(x[2])), '0x9064')
  547. pci.write(self.identifier, '56{:04x}'.format(int(x[3])), '0x9064')
  548. if len(x) > 4:
  549. logging.vinfo("Gain update not defined for more than 4 adc")
  550. def _set_adc_offset(self, x):
  551. #ADC1
  552. self._select_adc(1)
  553. pci.write(self.identifier, '44{:04x}'.format(int(x[0])), '0x9064')
  554. pci.write(self.identifier, '54{:04x}'.format(int(x[1])), '0x9064')
  555. self._select_adc(3)
  556. pci.write(self.identifier, '44{:04x}'.format(int(x[2])), '0x9064')
  557. pci.write(self.identifier, '54{:04x}'.format(int(x[3])), '0x9064')
  558. if len(x) > 4:
  559. logging.vinfo("Offset update not defined for more than 4 adc")
  560. def _select_adc(self, nr):
  561. val = 0
  562. if nr == 0:
  563. val = 0
  564. if nr < 3:
  565. val = 4
  566. elif nr < 5:
  567. val = 2
  568. pci.write(self.identifier, hex(val), '0x9044')
  569. def _set_samplingrate(self, rate):
  570. return
  571. if rate == 1:
  572. #500 MHz
  573. self.update('delay_25_adc', 10)
  574. self.update('delay_330_adc', 1)
  575. self.update('delay_25_adc_2', 10)
  576. self.update('delay_330_adc_2', 1)
  577. elif rate == 2:
  578. #1 GHz
  579. self.update('delay_25_adc', 10)
  580. self.update('delay_330_adc', 0)
  581. self.update('delay_25_adc_2', 10)
  582. self.update('delay_330_adc_2', 0)
  583. def set_startup(self):
  584. #print('board_config setting startup')
  585. #self.update('delay_330_th', 0)
  586. #sleep(0.1)
  587. #self.update('delay_25_th', 0)
  588. #sleep(0.1)
  589. self.update('delay_330_th_2', 0)
  590. sleep(0.1)
  591. self.update('delay_25_th_2', 3)
  592. sleep(0.1)
  593. self.update('delay_25_th_2', 4)
  594. sleep(0.1)
  595. self.update('chip_delay', [0,0,0,0, 0,0,0,0])
  596. sleep(0.1)
  597. #Bunch Shifts are offset by +2 to encode -2 to +2 as 0x0 to 0x4 in hardware
  598. self.update('bunch_shift', [2,2,2,2, 2,2,2,2])
  599. sleep(0.1)
  600. self.update('adc_gain', [0,0,0,0, 0,0,0,0])
  601. sleep(0.1)
  602. self.update('header', 1)
  603. sleep(0.1)
  604. self.update('pilot_bunch', 1)
  605. logging.vinfo('Startup Config Set')
  606. def read_from_board(self):
  607. """
  608. Read values from board and update them in the configuration (Mainly used for skip init functionality)
  609. """
  610. try:
  611. #settings = ['chip_1_delay','chip_2_delay','chip_3_delay','chip_4_delay']
  612. # --[ read fine/chip delays ]
  613. adc_number = self._config["adc_number"]
  614. val = pci.read(self.identifier, reg='9080')[0]
  615. if adc_number > 4:
  616. val = val + pci.read(self.identifier, reg='9084')[0]
  617. tmp = np.zeros(adc_number)
  618. for i in range(adc_number):
  619. selector = [3,2,1,0,7,6,5,4]
  620. tmp[selector[i]] = int(val[(adc_number-1-i)*2:(adc_number-i)*2], 16)
  621. self.update('chip_delay', tmp , write=False)
  622. # --[ read bunch shifts ] --
  623. bunch_shifts = pci.read(self.identifier, reg='9320', amount=4, decimal=True)
  624. if adc_number > 4:
  625. bunch_shifts = bunch_shifts + pci.read(self.identifier, reg='9330', amount=4, decimal=True)
  626. self.update('bunch_shift', bunch_shifts, write=False)
  627. # --[ read and set th delay ]--
  628. val = pci.read(self.identifier, reg='90B0')[0]
  629. self.update('delay_330_th', self._config['delay_330_max'] - ((int(val, 16)>>1)-5), write=False)
  630. val = pci.read(self.identifier, reg='90B4')[0]
  631. self.update('delay_25_th', self._config['delay_25_max'] - int(val, 16), write=False)
  632. val = pci.read(self.identifier, reg='90B8')[0]
  633. self.update('clk_div_th', int(val, 16), write=False)
  634. # --[ read and set adc delay ]--
  635. val = pci.read(self.identifier, reg='9090')[0]
  636. self.update('delay_330_adc', (int(val, 16)>>1)-5, write=False)
  637. val = pci.read(self.identifier, reg='9094')[0]
  638. self.update('delay_25_adc', int(val, 16), write=False)
  639. val = pci.read(self.identifier, reg='9098')[0]
  640. self.update('clk_div_adc', int(val, 16), write=False)
  641. # --[ read and set fpga delay ]--
  642. val = pci.read(self.identifier, reg='90C0')[0]
  643. self.update('delay_330_fpga', (int(val, 16)>>1)-5, write=False)
  644. #val = pci.read(self.identifier, reg='90C4')[0]
  645. #self.update('delay_25_fpga', int(val, 16), write=False)
  646. val = pci.read(self.identifier, reg='90C8')[0]
  647. self.update('clk_div_fpga', int(val, 16), write=False)
  648. # --[ read and set number of turns to acquire ]--
  649. val = pci.read(self.identifier, reg='9020')[0]
  650. self.update('turns_observe', int(val, 16), write=False)
  651. # --[ read and set number of turns to skip ]--
  652. val = pci.read(self.identifier, reg='9028')[0]
  653. self.update('turns_skip', int(val, 16), write=False)
  654. # --[ read FMC 2 ] --
  655. # --[ FMC2 read and set th delay ]--
  656. val = pci.read(self.identifier, reg='90A8')[0]
  657. self.update('delay_330_th_2', ((int(val, 16)>>1)-5), write=False)
  658. val = pci.read(self.identifier, reg='90AC')[0]
  659. self.update('delay_25_th_2', int(val, 16), write=False)
  660. # --[ FCM 2 read and set adc delay ]--
  661. val = pci.read(self.identifier, reg='90A0')[0]
  662. self.update('delay_330_adc_2', ((int(val, 16)>>1)-5), write=False)
  663. val = pci.read(self.identifier, reg='90A4')[0]
  664. self.update('delay_25_adc_2', int(val, 16), write=False)
  665. # --[ read and update header ]--
  666. control = pci.read(self.identifier, 1, '0x9040')[0]
  667. control_bits = '{0:032b}'.format(int(control, 16))
  668. if control_bits[3] == '1':
  669. self.update('header', True, write=False)
  670. else:
  671. self.update('header', False, write=False)
  672. except IndexError:
  673. error(0x002, "Could not Read data from Board. Pci returned wrong amount of data.")
  674. # 888 d8P d8888 8888888b. 88888888888 888 888 8888888b. 8888888888 d888
  675. # 888 d8P d88888 888 Y88b 888 888 888 888 Y88b 888 d8888
  676. # 888 d8P d88P888 888 888 888 888 888 888 888 888 888
  677. # 888d88K d88P 888 888 d88P 888 888 888 888 d88P 8888888 888
  678. # 8888888b d88P 888 8888888P" 888 888 888 8888888P" 888 888
  679. # 888 Y88b d88P 888 888 888 888 888 888 T88b 888 888888 888
  680. # 888 Y88b d8888888888 888 888 Y88b. .d88P 888 T88b 888 888
  681. # 888 Y88b d88P 888 888 888 "Y88888P" 888 T88b 8888888888 8888888
  682. #
  683. #
  684. #
  685. def _set_fpga_delay(self, value):
  686. """
  687. observer function to set the fpga_delays on the board
  688. :param value: the value to set the delays to
  689. """
  690. time_factor = self.make_uint(value, self.get('delay_330_max'), 'FPGA_Delay')
  691. reg_value = "0x000501" + '{0:01x}'.format(time_factor) + "0"
  692. pci.write(self.identifier, reg_value, '0x9060')
  693. logging.vinfo("Set FPGA clock delay %i * %i --> %i picoseconds" % (time_factor, self.get('delay_330_factor'), time_factor*self.get('delay_330_factor')))
  694. #self.update('fpga_delay', value)
  695. def _set_th_delay(self, value):
  696. """
  697. Set the track and hold delay on the board
  698. :param value: the value to set the delay to
  699. """
  700. time_factor = self.make_uint(value, self.get('delay_330_max'), 'TH_Delay')
  701. reg_value = "0x000501" + '{0:01x}'.format(time_factor) + "3"
  702. pci.write(self.identifier, reg_value, '0x9060')
  703. logging.vinfo("Set T/H Signal delay %i * %i --> %i picoseconds" % (time_factor, self.get('delay_330_factor'), time_factor*self.get('delay_330_factor')))
  704. self.update('delay_330_adc', time_factor)
  705. def _set_adc_delay(self, value):
  706. """
  707. Set the adc delay for the given adc on the board
  708. :param value: the value to set the delay to
  709. """
  710. def write_delay(value, channel):
  711. '''write the delays to the board'''
  712. value = self.make_uint(value, self.get('delay_330_max'), 'ADC Delay')
  713. cmd = '00501' + '%01x' % value + str(channel+4)
  714. pci.write(self.identifier, cmd, reg='0x9060')
  715. time.sleep(0.005)
  716. delay = value + self.get('th_to_adc_cycles')
  717. if delay > self.get('delay_330_max'):
  718. delay -= self.get('delay_330_max') + 1
  719. if self._config['adc_number'] == 4:
  720. for adc in range(self._config['adc_number']):
  721. write_delay(delay, adc)
  722. s = "Setting ADC_%i delay %i * %i --> %i picoseconds" % ((adc+1), delay, self.get('delay_330_factor'), delay*self.get('delay_330_factor'))
  723. logging.vinfo(s)
  724. else:
  725. logging.vinfo("adc_delay update not defined for more than 4 adc")