bitsTable.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. """
  2. This defines the Tables used as Bits display
  3. """
  4. from PyQt4 import QtGui, QtCore
  5. import logging
  6. from backend import board
  7. from backend.board import available_boards
  8. import backendinterface as bif
  9. import kcgwidget as kcgw
  10. tr = kcgw.tr
  11. class BitsDisplayTable(QtGui.QTableWidget):
  12. """
  13. Widget to use to display the Bits (as table)
  14. """
  15. def __init__(self, value, parent=None, optimalSize=True):
  16. QtGui.QTableWidget.__init__(self, parent)
  17. self.numbers = str(value)
  18. if len(self.numbers) == 0:
  19. raise ValueError("Cant create a table for a value of length 0.")
  20. self.length = len(self.numbers)
  21. self.do_style()
  22. if optimalSize is True:
  23. self.do_optimal_size()
  24. def do_style(self):
  25. self.horizontalHeader().setDefaultSectionSize(35)
  26. self.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
  27. self.horizontalHeader().setVisible(True)
  28. self.verticalHeader().setDefaultSectionSize(17)
  29. self.verticalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
  30. self.verticalHeader().setVisible(False)
  31. self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
  32. self.setRowCount(1)
  33. self.setColumnCount(self.length)
  34. # If self.length would be 5, this line would generate ('4', '3',
  35. # '2', '1', '0')
  36. headers = tuple([str(i) for i in reversed(range(0, self.length))])
  37. self.setHorizontalHeaderLabels(headers)
  38. for i in range(len(self.numbers)):
  39. item = QtGui.QTableWidgetItem(self.numbers[i])
  40. item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
  41. self.setItem(0, i, item)
  42. def width(self):
  43. width = 6
  44. if self.verticalHeader().isHidden() is False:
  45. width = self.verticalHeader().width() + 6
  46. for i in range(self.columnCount()):
  47. width = width + self.columnWidth(i)
  48. return width
  49. def height(self):
  50. height = 6
  51. if self.horizontalHeader().isHidden() is False:
  52. height = self.horizontalHeader().height() + 6
  53. for i in range(self.rowCount()):
  54. height = height + self.rowHeight(i)
  55. return height
  56. def do_optimal_size(self):
  57. size = QtCore.QSize(self.width(), self.height())
  58. self.setMaximumSize(size)
  59. self.setMinimumSize(size)
  60. def stretch_to_width(self, width_in):
  61. width = self.width()
  62. if width >= width_in:
  63. return
  64. factor = width_in/float(width)
  65. error = 0
  66. for i in range(self.length):
  67. current_cell_size = self.columnWidth(i)
  68. new_cell_size = int(current_cell_size * factor)
  69. error += new_cell_size - (current_cell_size * factor)
  70. if (error >= 1.0) or (error <= -1.0):
  71. new_cell_size -= int(error)
  72. error -= int(error)
  73. self.horizontalHeader().resizeSection(i, new_cell_size)
  74. self.do_optimal_size()
  75. def set_item(self, row, col, value):
  76. item = QtGui.QTableWidgetItem(str(value))
  77. item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
  78. width = self._get_table_item_width(QtGui.QTableWidgetItem(value))
  79. if width > self.columnWidth(col):
  80. self.horizontalHeader().resizeSection(col, width)
  81. self.setItem(row, col, item)
  82. def set_numbers(self, value):
  83. new_numbers = str(value)
  84. if len(new_numbers) == 0:
  85. raise ValueError("Cant create a table for a value of length 0.")
  86. if len(new_numbers) != len(self.numbers):
  87. raise ValueError("New Values for table don't match size."
  88. "Expected size %i but got %i" % (len(self.numbers), len(new_numbers)))
  89. self.numbers = new_numbers
  90. for i in range(len(self.numbers)):
  91. item = self.item(0, i)
  92. item.setText(self.numbers[i])
  93. def set_label(self, start, end, label, color=None):
  94. if (start < 0) or (end > self.columnCount()-1) or (start > end):
  95. raise ValueError("Invalid Start and End positions for Label: %s" % label)
  96. if self.rowCount() < 2:
  97. self.insertRow(1)
  98. for i in range(self.length):
  99. self.setItem(1, i, QtGui.QTableWidgetItem(''))
  100. span = (end-start)+1
  101. if span > 1:
  102. self.setSpan(1, start, 1, span)
  103. item = QtGui.QTableWidgetItem(label)
  104. item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
  105. if color:
  106. item.setBackground(color)
  107. self.setItem(1, start, item)
  108. # Check if the label is larger then then cells it spans and resize the cells
  109. # accordingly, if the label ends up larger then the cells.
  110. label_width = self._get_table_item_width(QtGui.QTableWidgetItem(label))
  111. cells_width = 0
  112. for i in range(start, end+1):
  113. cells_width = cells_width + self.columnWidth(i)
  114. if label_width > cells_width:
  115. new_cell_size = label_width/span
  116. for i in range(start, end+1):
  117. self.horizontalHeader().resizeSection(i, new_cell_size)
  118. self.do_optimal_size()
  119. def grey_out_column(self, column):
  120. if (column < 0) or (column > self.length):
  121. raise ValueError("Supplied column is out of range for this table")
  122. for i in range(self.rowCount()):
  123. self.item(i, column).setForeground(QtGui.QColor(120, 120, 120))
  124. self.item(i, column).setBackground(QtGui.QColor(200, 200, 200))
  125. def undo_grey_out_column(self, column):
  126. if (column < 0) or (column > self.length):
  127. raise ValueError("Supplied column is out of range for this table")
  128. for i in range(self.rowCount()):
  129. self.item(i, column).setForeground(QtGui.QColor(0, 0, 0))
  130. self.item(i, column).setBackground(QtGui.QColor(255, 255, 255))
  131. # Create a table just to insert our item and show how large its width ends up...
  132. # We have to use this stupid workaround since QTableWidgetItem has no width() property...
  133. def _get_table_item_width(self, item):
  134. table = QtGui.QTableWidget()
  135. table.horizontalHeader().setResizeMode(QtGui.QHeaderView.ResizeToContents)
  136. table.setRowCount(1)
  137. table.setColumnCount(1)
  138. table.setItem(0, 0, item)
  139. width = table.columnWidth(0)
  140. table.deleteLater()
  141. return width
  142. class BitsEditTable(BitsDisplayTable):
  143. def __init__(self, value, parent=None, optimalSize=True):
  144. BitsDisplayTable.__init__(self, value, parent, optimalSize)
  145. self.checkboxes = []
  146. self.populate_checkboxes()
  147. self.verticalHeader().setDefaultSectionSize(35)
  148. self.do_optimal_size()
  149. def populate_checkboxes(self):
  150. for i in range(self.length):
  151. widget = QtGui.QWidget()
  152. self.checkboxes += [QtGui.QCheckBox()]
  153. layout = QtGui.QHBoxLayout(widget)
  154. layout.addWidget(self.checkboxes[i])
  155. layout.setAlignment(QtCore.Qt.AlignCenter)
  156. layout.setContentsMargins(0, 0, 0, 0)
  157. widget.setLayout(layout)
  158. self.setCellWidget(0, i, widget)
  159. def set_numbers(self, value):
  160. new_numbers = str(value)
  161. if len(new_numbers) == 0:
  162. raise ValueError("Cant create a table for a value of length 0.")
  163. if len(new_numbers) != len(self.numbers):
  164. raise ValueError("New Values for table dont match size."
  165. "Expected size %i but got %i" % (len(self.numbers), len(new_numbers)))
  166. self.numbers = new_numbers
  167. for i in range(len(self.numbers)):
  168. if self.numbers[i] == '1':
  169. self.checkboxes[i].setChecked(True)
  170. else:
  171. self.checkboxes[i].setChecked(False)
  172. def get_bits(self):
  173. bits = ''
  174. for i in range(self.length):
  175. if self.checkboxes[i].isChecked():
  176. bits += '1'
  177. else:
  178. bits += '0'
  179. return bits
  180. def get_bit(self, bit):
  181. if bit > self.length:
  182. return None
  183. return self.checkboxes[(self.length - bit) - 1].isChecked()
  184. def clear_all_bits(self):
  185. for i in range(self.length):
  186. self.checkboxes[i].setChecked(False)
  187. class AdvancedBoardInterface(QtGui.QWidget):
  188. def __init__(self, parent=None, board_id=None):
  189. QtGui.QWidget.__init__(self, parent)
  190. self.parent = parent
  191. self.do_layout()
  192. self.data_flow_pipeline_status = None
  193. # self.do_status_update() # Do not update status at init - gets updated whenever page is "opened"
  194. if board_id is None:
  195. print "No Valid board id specified for AdvancedBoardInterface."
  196. raise ValueError("No Valid board id specified for AdvancedBoardInterface.")
  197. self.board_id = board_id
  198. def do_layout(self):
  199. self.table_grid = QtGui.QGridLayout()
  200. self.setLayout(self.table_grid)
  201. self.table_grid.addWidget(QtGui.QLabel("Status1 Register 0x9050 (Readonly)"), 0, 0)
  202. self.t1 = QtGui.QScrollArea()
  203. self.table_grid.addWidget(self.t1, 1, 0)
  204. self.status1_table = BitsDisplayTable(32*'0', self)
  205. self.do_status1_table_layout(self.status1_table)
  206. # self.table_grid.addWidget(self.status1_table, 1, 0)
  207. self.t1.setWidget(self.status1_table)
  208. self.t1.setFixedHeight(self.status1_table.height()+24)
  209. self.table_grid.addWidget(QtGui.QLabel("Status2 Register 0x9054 (Readonly)"), 2, 0)
  210. self.t2 = QtGui.QScrollArea()
  211. self.table_grid.addWidget(self.t2, 3, 0)
  212. self.status2_table = BitsDisplayTable(32*'0', self)
  213. self.do_status2_table_layout(self.status2_table)
  214. # self.table_grid.addWidget(self.status2_table, 3, 0)
  215. self.t2.setWidget(self.status2_table)
  216. self.t2.setFixedHeight(self.status2_table.height()+24)
  217. self.table_grid.addWidget(QtGui.QLabel("Status3 Register 0x9058 (Readonly)"), 4, 0)
  218. self.t3 = QtGui.QScrollArea()
  219. self.table_grid.addWidget(self.t3, 5, 0)
  220. self.status3_table = BitsDisplayTable(32*'0', self)
  221. self.do_status3_table_layout(self.status3_table)
  222. # self.table_grid.addWidget(self.status3_table, 5, 0)
  223. self.t3.setWidget(self.status3_table)
  224. self.t3.setFixedHeight(self.status3_table.height()+24)
  225. # self.table_grid.addItem(QtGui.QSpacerItem(1, 20), 6, 0)
  226. self.table_grid.addWidget(QtGui.QLabel("Control Register 0x9040"), 7, 0)
  227. buttons_box = QtGui.QHBoxLayout()
  228. buttons_box.setAlignment(QtCore.Qt.AlignLeft)
  229. self.write_control_button = QtGui.QPushButton("Write Values to board")
  230. self.write_control_button.setMaximumWidth(200)
  231. buttons_box.addWidget(self.write_control_button)
  232. self.clear_control_button = QtGui.QPushButton("Clear Input")
  233. self.clear_control_button.setMaximumWidth(200)
  234. buttons_box.addWidget(self.clear_control_button)
  235. self.check_status_control_button = QtGui.QPushButton("Check Status")
  236. self.check_status_control_button.setMaximumWidth(200)
  237. buttons_box.addWidget(self.check_status_control_button)
  238. buttons_widget = QtGui.QWidget()
  239. buttons_widget.setLayout(buttons_box)
  240. self.table_grid.addWidget(buttons_widget, 8, 0)
  241. self.tedit = QtGui.QScrollArea()
  242. self.table_grid.addWidget(self.tedit, 9, 0)
  243. self.control_table = BitsEditTable(32*'0', self)
  244. self.do_control_table_layout(self.control_table)
  245. self.tedit.setWidget(self.control_table)
  246. self.tedit.setFixedHeight(self.control_table.height()+24)
  247. # self.table_grid.addWidget(self.control_table, 9, 0)
  248. self.write_control_button.clicked.connect(self.send_control_to_board)
  249. self.clear_control_button.clicked.connect(self.control_table.clear_all_bits)
  250. self.check_status_control_button.clicked.connect(self.do_status_update)
  251. self.check_status_control_button.setShortcut("F5")
  252. width1 = self.status1_table.width()
  253. width2 = self.status2_table.width()
  254. width3 = self.status3_table.width()
  255. width4 = self.control_table.width()
  256. max_width = max(width1, max(width2, max(width3, width4)))
  257. self.status1_table.stretch_to_width(max_width)
  258. self.status2_table.stretch_to_width(max_width)
  259. self.status3_table.stretch_to_width(max_width)
  260. self.control_table.stretch_to_width(max_width)
  261. def send_control_to_board(self):
  262. if bif._bif_continuous_read_is_enabled(self.board_id, tr("Heading", "Write Registers")):
  263. logging.log("Cant write to board while continuous readout is active")
  264. return
  265. bits = self.control_table.get_bits()
  266. # print bits
  267. dec_val_bits = int(bits, 2)
  268. # print dec_val_bits
  269. # self.parent.text_area.write("Writing to board Register 0x9040: %s" % ('0x{0:08x}'.format(dec_val_bits)))
  270. logging.info("Writing to board Register 0x9040: %s" % ('0x{0:08x}'.format(dec_val_bits)))
  271. try:
  272. board.write_pci(self.board_id, hex(dec_val_bits), '0x9040')
  273. except board.BoardError as e:
  274. QtGui.QMessageBox.critical(self, "Board communication",
  275. "Was unable to write value to board!\nReason: "+str(e)+"\nBoard: "+str(self.board_id))
  276. # self.parent.do_status_readout()
  277. self.do_status_update()
  278. def do_status1_table_layout(self, table):
  279. # from right to left
  280. table.set_label(29, 31, "FSM_Data_Pipeline_Status", QtCore.Qt.green)
  281. table.grey_out_column(28)
  282. table.set_label(27, 27, "FULL", QtCore.Qt.green)
  283. table.set_label(26, 26, "EMPTY", QtCore.Qt.green)
  284. table.grey_out_column(25)
  285. table.grey_out_column(24)
  286. table.set_label(14, 23, "RD_data_Counts", QtCore.Qt.green)
  287. table.set_label(13, 13, "OVR_ADC", QtGui.QColor(210, 210, 0))
  288. table.grey_out_column(12)
  289. table.grey_out_column(11)
  290. table.grey_out_column(10)
  291. table.grey_out_column(9)
  292. table.grey_out_column(8)
  293. table.set_label(7, 7, "PLL_LD", QtGui.QColor(210, 210, 0))
  294. table.grey_out_column(6)
  295. table.set_label(2, 5, "Master Control", QtCore.Qt.green)
  296. table.grey_out_column(1)
  297. table.set_label(0, 0, "1")
  298. def do_status2_table_layout(self, table):
  299. #from right to left
  300. table.set_label(31, 31, "FIFO 128 255 empty", QtCore.Qt.green)
  301. table.set_label(30, 30, "FIFO 128 255 full", QtCore.Qt.green)
  302. table.grey_out_column(29)
  303. table.grey_out_column(28)
  304. table.set_label(17, 27, "wr data count 128 255", QtGui.QColor(210, 210, 0))
  305. table.grey_out_column(16)
  306. table.set_label(15, 15, "FIFO 255 64 empty", QtCore.Qt.green)
  307. table.set_label(14, 14, "FIFO 255 64 full", QtCore.Qt.green)
  308. table.grey_out_column(13)
  309. table.grey_out_column(12)
  310. table.set_label(2, 11, "rd data count 255 64", QtGui.QColor(210, 210, 0))
  311. table.grey_out_column(1)
  312. table.grey_out_column(0)
  313. def do_status3_table_layout(self, table):
  314. #from right to left
  315. table.set_label(29, 31, "FSM_ARBITER_DDR3", QtCore.Qt.green)
  316. table.grey_out_column(28)
  317. table.set_label(25, 27, "FSM_WR_DDR3", QtCore.Qt.green)
  318. table.grey_out_column(24)
  319. table.set_label(21, 23, "FSM_R_DDR3", QtCore.Qt.green)
  320. table.grey_out_column(20)
  321. table.set_label(16, 19, "BC_ERROR", QtGui.QColor(210, 210, 0))
  322. table.set_label(1, 15, "Number of wrong BC", QtGui.QColor(255, 255, 0))
  323. table.grey_out_column(0)
  324. def do_control_table_layout(self, table):
  325. #from right to left
  326. table.set_label(31, 31, "reset", QtGui.QColor(0, 255, 255))
  327. table.grey_out_column(30)
  328. table.grey_out_column(29)
  329. table.grey_out_column(28)
  330. table.set_label(27, 27, "ADC_1(A+D)", QtGui.QColor(0, 255, 255))
  331. table.set_label(26, 26, "ADC_2(A+D)2", QtGui.QColor(0, 255, 255))
  332. table.set_label(25, 25, "T/H_1", QtGui.QColor(210, 210, 0))
  333. table.set_label(24, 24, "T/H_2", QtGui.QColor(210, 210, 0))
  334. table.set_label(23, 23, "T/H_3", QtGui.QColor(210, 210, 0))
  335. table.set_label(22, 22, "T/H_4", QtGui.QColor(210, 210, 0))
  336. table.set_label(21, 21, "EN_data_Trans", QtCore.Qt.yellow)
  337. table.set_label(20, 20, "EN_readout", QtCore.Qt.yellow)
  338. table.set_label(18, 19, "ADC_1", QtCore.Qt.yellow)
  339. table.set_label(16, 17, "ADC_2", QtCore.Qt.yellow)
  340. table.set_label(14, 15, "ADC_3", QtCore.Qt.yellow)
  341. table.set_label(12, 13, "ADC_4", QtCore.Qt.yellow)
  342. table.grey_out_column(11)
  343. table.grey_out_column(10)
  344. table.grey_out_column(9)
  345. table.grey_out_column(8)
  346. table.grey_out_column(7)
  347. table.grey_out_column(6)
  348. table.grey_out_column(5)
  349. table.grey_out_column(4)
  350. table.set_label(3, 3, "Header", QtCore.Qt.green)
  351. table.grey_out_column(2)
  352. table.set_label(1, 1, "Pilot Bunch by FPGA", QtGui.QColor(0, 255, 255))
  353. table.set_label(0, 0, "FPGA Temp monitor Reset", QtGui.QColor(0, 255, 255))
  354. def update_status(self, registers):
  355. try:
  356. self.status1_table.set_numbers('{0:032b}'.format(registers[0]))
  357. self.status2_table.set_numbers('{0:032b}'.format(registers[1]))
  358. self.status3_table.set_numbers('{0:032b}'.format(registers[2]))
  359. except Exception:
  360. return
  361. def do_status_update(self):
  362. if board.get_board_status(self.board_id).board_connected:
  363. registers = board.pci.read(self.board_id, 3, '0x9050', decimal=True)
  364. # TODO: KEEPING read_pci as this entire thing will be removed hopefully
  365. self.update_status(registers)
  366. control = board.pci.read(self.board_id, 1, '0x9040')[0]
  367. control_bits = '{0:032b}'.format(int(control, 16))
  368. self.control_table.set_numbers(control_bits)
  369. class AdvanceControlView(kcgw.KCGWidgets):
  370. def __init__(self):
  371. super(AdvanceControlView, self).__init__()
  372. self.layout = QtGui.QHBoxLayout()
  373. self.setLayout(self.layout)
  374. self.tabs = QtGui.QTabWidget()
  375. self.layout.addWidget(self.tabs)
  376. self.tables = []
  377. for bid in available_boards:
  378. self.tables.append(AdvancedBoardInterface(board_id=bid))
  379. self.tabs.addTab(self.tables[-1], str(bid))
  380. def pages_update_function(self):
  381. for table in self.tables:
  382. table.do_status_update()