12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036 |
- #! python
- import sys
- import os
- import argparse
- import logging
- import time
- from PyQt4 import QtGui, QtCore
- from matplotlib.figure import Figure
- from matplotlib.backends.backend_qt4agg import (
- FigureCanvasQTAgg as FigureCanvas,
- NavigationToolbar2QTAgg as NavigationToolbar)
- from heb.board import write_pci
- import heb.io
- import heb.plot
- import heb.board
- import numpy as np
- from array import array as pArr
- import struct
- import matplotlib.cm as cm
- import matplotlib.colors as colors
- OPT_3D_MAP = "3D Map"
- OPT_TRAIN = "Train"
- OPT_COMBINED = "Combined"
- OPT_FFT = "Fourier transform"
- # OPT_RECONSTRUCTED = "Reconstructed"
- OPT_ADC_1 = "ADC 1"
- OPT_ADC_2 = "ADC 2"
- OPT_ADC_3 = "ADC 3"
- OPT_ADC_4 = "ADC 4"
- def enable_wait_cursor():
- QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
- def disable_wait_cursor():
- QtGui.QApplication.restoreOverrideCursor()
- class Spinbox(QtGui.QSpinBox):
- def __init__(self, minimum, maximum, default):
- QtGui.QSpinBox.__init__(self)
- self.setMinimum(minimum)
- self.setMaximum(maximum)
- self.setValue(default)
- def setValueSilent(self, value):
- self.blockSignals(True)
- self.setValue(value)
- self.blockSignals(False)
- class GraphicalLED(QtGui.QWidget):
- def __init__(self, parent=None, colorRGB=(255, 0, 0), height=20, width=20):
- QtGui.QWidget.__init__(self, parent)
- self.width = width
- self.height = height
- self.color = QtGui.QColor(colorRGB[0], colorRGB[1], colorRGB[2])
- self.center = QtCore.QPoint(width, height)
- self.setMinimumSize(2 * width, 2 * height)
- self.setMaximumSize(2 * width, 2 * height)
- def paintEvent(self, event):
- paint = QtGui.QPainter()
- paint.begin(self)
- paint.setRenderHint(QtGui.QPainter.Antialiasing)
- # draw a grey 'socket' for the LED
- paint.setPen(QtGui.QColor(160, 160, 160))
- paint.setBrush(QtGui.QColor(180, 180, 180))
- paint.drawEllipse(self.center, self.width, self.height)
- # draw the body of the LED
- paint.setBrush(self.color)
- paint.drawEllipse(self.center, self.width*0.85, self.height*0.85)
- # Some versions of Qt4 differ in the way their QLinearGradients
- # work... But i don't want to remove the functionality :)
- if False:
- self.draw_light_reflex(paint)
- def draw_light_reflex(self, paint):
- # set up a light reflex ellipse on the LED
- paint.translate(self.center)
- paint.rotate(-45.0)
- paint.setPen(QtGui.QColor(255, 255, 255, 0))
- highlight_center = QtCore.QPoint(0, self.width*(-0.34))
- # light reflex is pure white and fades to transparent at top of LED
- gradient = QtGui.QLinearGradient(highlight_center*1.5, QtCore.QPoint(0, 0))
- gradient.setColorAt(0.0, QtGui.QColor(255, 255, 255, 120))
- gradient.setColorAt(1.0, QtGui.QColor(255, 255, 255, 0))
- # draw the light reflex using the gradient brush
- paint.setBrush(gradient)
- paint.drawEllipse(highlight_center, self.width*0.63, self.width*0.42)
- paint.end()
- def set_color(self, colorRGB=(255, 0, 0)):
- self.color = QtGui.QColor(colorRGB[0], colorRGB[1], colorRGB[2])
- self.update()
- class BitsDisplayTable(QtGui.QTableWidget):
- def __init__(self, value, parent=None, optimalSize=True):
- QtGui.QTableWidget.__init__(self, parent)
- self.numbers = str(value)
- if len(self.numbers) == 0:
- raise ValueError("Cant create a table for a value of length 0.")
- self.length = len(self.numbers)
- self.do_style()
- if optimalSize is True:
- self.do_optimal_size()
- def do_style(self):
- self.horizontalHeader().setDefaultSectionSize(35)
- self.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
- self.horizontalHeader().setVisible(True)
- self.verticalHeader().setDefaultSectionSize(17)
- self.verticalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
- self.verticalHeader().setVisible(False)
- self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
- self.setRowCount(1)
- self.setColumnCount(self.length)
- # If self.length would be 5, this line would generate ('4', '3',
- # '2', '1', '0')
- headers = tuple([str(i) for i in reversed(range(0, self.length))])
- self.setHorizontalHeaderLabels(headers)
- for i in range(len(self.numbers)):
- item = QtGui.QTableWidgetItem(self.numbers[i])
- item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
- self.setItem(0, i, item)
- def width(self):
- width = 6
- if self.verticalHeader().isHidden() is False:
- width = self.verticalHeader().width() + 6
- for i in range(self.columnCount()):
- width = width + self.columnWidth(i)
- return width
- def height(self):
- height = 6
- if self.horizontalHeader().isHidden() is False:
- height = self.horizontalHeader().height() + 6
- for i in range(self.rowCount()):
- height = height + self.rowHeight(i)
- return height
- def do_optimal_size(self):
- size = QtCore.QSize(self.width(), self.height())
- self.setMaximumSize(size)
- self.setMinimumSize(size)
- def stretch_to_width(self, width_in):
- width = self.width()
- if width >= width_in:
- return
- factor = width_in/float(width)
- error = 0
- for i in range(self.length):
- current_cell_size = self.columnWidth(i)
- new_cell_size = int(current_cell_size * factor)
- error += new_cell_size - (current_cell_size * factor)
- if (error >= 1.0) or (error <= -1.0):
- new_cell_size -= int(error)
- error -= int(error)
- self.horizontalHeader().resizeSection(i, new_cell_size)
- self.do_optimal_size()
- def set_item(self, row, col, value):
- item = QtGui.QTableWidgetItem(str(value))
- item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
- width = self._get_table_item_width(QtGui.QTableWidgetItem(value))
- if width > self.columnWidth(col):
- self.horizontalHeader().resizeSection(col, width)
- self.setItem(row, col, item)
- def set_numbers(self, value):
- new_numbers = str(value)
- if len(new_numbers) == 0:
- raise ValueError("Cant create a table for a value of length 0.")
- if len(new_numbers) != len(self.numbers):
- raise ValueError("New Values for table don't match size."
- "Expected size %i but got %i" % (len(self.numbers), len(new_numbers)))
- self.numbers = new_numbers
- for i in range(len(self.numbers)):
- item = self.item(0, i)
- item.setText(self.numbers[i])
- def set_label(self, start, end, label, color=None):
- if (start < 0) or (end > self.columnCount()-1) or (start > end):
- raise ValueError("Invalid Start and End positions for Label: %s" % label)
- if self.rowCount() < 2:
- self.insertRow(1)
- for i in range(self.length):
- self.setItem(1, i, QtGui.QTableWidgetItem(''))
- span = (end-start)+1
- if span > 1:
- self.setSpan(1, start, 1, span)
- item = QtGui.QTableWidgetItem(label)
- item.setTextAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
- if color:
- item.setBackground(color)
- self.setItem(1, start, item)
- # Check if the label is larger then then cells it spans and resize the cells
- # accordingly, if the label ends up larger then the cells.
- label_width = self._get_table_item_width(QtGui.QTableWidgetItem(label))
- cells_width = 0
- for i in range(start, end+1):
- cells_width = cells_width + self.columnWidth(i)
- if label_width > cells_width:
- new_cell_size = label_width/span
- for i in range(start, end+1):
- self.horizontalHeader().resizeSection(i, new_cell_size)
- self.do_optimal_size()
- def grey_out_column(self, column):
- if (column < 0) or (column > self.length):
- raise ValueError("Supplied column is out of range for this table")
- for i in range(self.rowCount()):
- self.item(i, column).setForeground(QtGui.QColor(120, 120, 120))
- self.item(i, column).setBackground(QtGui.QColor(200, 200, 200))
- def undo_grey_out_column(self, column):
- if (column < 0) or (column > self.length):
- raise ValueError("Supplied column is out of range for this table")
- for i in range(self.rowCount()):
- self.item(i, column).setForeground(QtGui.QColor(0, 0, 0))
- self.item(i, column).setBackground(QtGui.QColor(255, 255, 255))
- # Create a table just to insert our item and show how large its width ends up...
- # We have to use this stupid workaround since QTableWidgetItem has no width() property...
- def _get_table_item_width(self, item):
- table = QtGui.QTableWidget()
- table.horizontalHeader().setResizeMode(QtGui.QHeaderView.ResizeToContents)
- table.setRowCount(1)
- table.setColumnCount(1)
- table.setItem(0, 0, item)
- width = table.columnWidth(0)
- table.deleteLater()
- return width
- class BitsEditTable(BitsDisplayTable):
- def __init__(self, value, parent=None, optimalSize=True):
- BitsDisplayTable.__init__(self, value, parent, optimalSize)
- self.checkboxes = []
- self.populate_checkboxes()
- self.verticalHeader().setDefaultSectionSize(35)
- self.do_optimal_size()
- def populate_checkboxes(self):
- for i in range(self.length):
- widget = QtGui.QWidget()
- self.checkboxes += [QtGui.QCheckBox()]
- layout = QtGui.QHBoxLayout(widget)
- layout.addWidget(self.checkboxes[i])
- layout.setAlignment(QtCore.Qt.AlignCenter)
- layout.setContentsMargins(0, 0, 0, 0)
- widget.setLayout(layout)
- self.setCellWidget(0, i, widget)
- def set_numbers(self, value):
- new_numbers = str(value)
- if len(new_numbers) == 0:
- raise ValueError("Cant create a table for a value of length 0.")
- if len(new_numbers) != len(self.numbers):
- raise ValueError("New Values for table dont match size."
- "Expected size %i but got %i" % (len(self.numbers), len(new_numbers)))
- self.numbers = new_numbers
- for i in range(len(self.numbers)):
- if self.numbers[i] == '1':
- self.checkboxes[i].setChecked(True)
- else:
- self.checkboxes[i].setChecked(False)
- def get_bits(self):
- bits = ''
- for i in range(self.length):
- if self.checkboxes[i].isChecked():
- bits += '1'
- else:
- bits += '0'
- return bits
- def get_bit(self, bit):
- if bit > self.length:
- return None
- return self.checkboxes[(self.length - bit) - 1].isChecked()
- def clear_all_bits(self):
- for i in range(self.length):
- self.checkboxes[i].setChecked(False)
- class PlotCanvas(FigureCanvas):
- def __init__(self, parent=None, width=5, height=4, dpi=100):
- self.figure = Figure(figsize=(width, height), dpi=dpi)
- FigureCanvas.__init__(self, self.figure)
- self.setParent(parent)
- FigureCanvas.setSizePolicy(self,
- QtGui.QSizePolicy.Expanding,
- QtGui.QSizePolicy.Expanding)
- FigureCanvas.updateGeometry(self)
- def update_figure(self, opt_widgets, data, frm, to, label=None):
- adcs = [w for w in (('ADC {}'.format(i), i) for i in range(1, 5))
- if opt_widgets[w[0]].isChecked()]
- def is_active(mode):
- return opt_widgets[mode].isChecked() and adcs
- if not data or frm == to:
- return
- self.figure.clear()
- self.figure.subplots_adjust(right=0.9)
- self.figure.suptitle(os.path.basename(data.filename))
- if is_active(OPT_3D_MAP):
- self.plot_heatmaps(adcs, data, frm, to)
- if is_active(OPT_TRAIN):
- args = {'label': label} if label else {}
- self.plot_train(adcs, data, frm, to, **args)
- if opt_widgets[OPT_COMBINED].isChecked() and adcs:
- self.plot_combined(adcs, data, frm, to, False)
- if is_active(OPT_FFT):
- self.plot_fft(adcs, data, frm, to)
- self.draw()
- def plot_heatmaps(self, adcs, data, frm, to):
- n_adcs = len(adcs)
- n_rows = 2 if n_adcs > 2 else 1
- n_cols = 2 if n_adcs > 1 else 1
- for i, (name, adc) in enumerate(adcs):
- axis = self.figure.add_subplot(n_rows, n_cols, i+1)
- axis.set_title(name)
- heatmap = data.heatmap(adc, frm, to)
- image = heb.plot.heatmap(heatmap, axis)
- bar_axis = self.figure.add_axes([0.85, 0.15, 0.05, 0.7])
- self.figure.subplots_adjust(right=0.8)
- self.figure.colorbar(image, cax=bar_axis)
- def plot_train(self, adcs, data, frm, to, **kwargs):
- n_adcs = len(adcs)
- n_rows = 2 if n_adcs > 2 else 1
- n_cols = 2 if n_adcs > 1 else 1
- for i, (name, adc) in enumerate(adcs):
- axis = self.figure.add_subplot(n_rows, n_cols, i+1)
- heb.plot.train(data, axis, adc, frm, to, **kwargs)
- def plot_combined(self, adcs, data, frm, to, show_reconstructed):
- axis = self.figure.add_subplot(111)
- heb.plot.combined(data, axis, adcs, frm, to, show_reconstructed)
- def plot_fft(self, adcs, data, frm, to):
- n_adcs = len(adcs)
- n_rows = 2 if n_adcs > 2 else 1
- n_cols = 2 if n_adcs > 1 else 1
- for i, (name, adc) in enumerate(adcs):
- axis = self.figure.add_subplot(n_rows, n_cols, i+1)
- axis.set_title(name)
- image = heb.plot.fft(data, axis, adc, frm, to) # <-- This needs to also pass the 'skipped' value!
- bar_axis = self.figure.add_axes([0.85, 0.15, 0.05, 0.7])
- self.figure.subplots_adjust(right=0.8)
- self.figure.colorbar(image, cax=bar_axis)
- class SimpleStatusDisplay(QtGui.QWidget):
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
- self.do_layout()
- def do_layout(self):
- self.setWindowTitle("Board Status")
- status_displays = QtGui.QGridLayout()
- status_displays.addWidget(QtGui.QLabel("Board Status Readouts"))
- # First Label + LED Group
- self.data_flow_pipeline_led = GraphicalLED(self, (128, 128, 128), 10, 10)
- led_group_1_layout = QtGui.QGridLayout(self)
- label_group_1 = QtGui.QLabel("DataFlow Pipeline")
- label_group_1.setMinimumWidth(100)
- led_group_1_layout.addWidget(label_group_1, 0, 1)
- led_group_1_layout.addWidget(self.data_flow_pipeline_led, 0, 0)
- led_group_1_layout.setColumnStretch(2, 1)
- led_group_1_widget = QtGui.QWidget(self)
- led_group_1_widget.setLayout(led_group_1_layout)
- status_displays.addWidget(led_group_1_widget, 1, 0)
- # Second Label + LED Group
- self.master_ctrl_led = GraphicalLED(self, (128, 128, 128), 10, 10)
- led_group_2_layout = QtGui.QGridLayout(self)
- label_group_2 = QtGui.QLabel("Master Control")
- label_group_2.setMinimumWidth(100)
- led_group_2_layout.addWidget(label_group_2, 0, 1)
- led_group_2_layout.addWidget(self.master_ctrl_led, 0, 0)
- led_group_2_layout.setColumnStretch(2, 1)
- led_group_2_widget = QtGui.QWidget(self)
- led_group_2_widget.setLayout(led_group_2_layout)
- status_displays.addWidget(led_group_2_widget, 2, 0)
- # Third Label + LED Group
- self.data_check_led = GraphicalLED(self, (128, 128, 128), 10, 10)
- led_group_3_layout = QtGui.QGridLayout(self)
- label_group_3 = QtGui.QLabel("Data Check")
- label_group_3.setMinimumWidth(100)
- led_group_3_layout.addWidget(label_group_3, 0, 1)
- led_group_3_layout.addWidget(self.data_check_led, 0, 0)
- led_group_3_layout.setColumnStretch(2, 1)
- led_group_3_widget = QtGui.QWidget(self)
- led_group_3_widget.setLayout(led_group_3_layout)
- status_displays.addWidget(led_group_3_widget, 3, 0)
- # Fourth Label + LED Group
- self.pll_ld_led = GraphicalLED(self, (128, 128, 128), 10, 10)
- led_group_4_layout = QtGui.QGridLayout(self)
- label_group_4 = QtGui.QLabel("PLL_LD")
- label_group_4.setMinimumWidth(100)
- led_group_4_layout.addWidget(label_group_4, 0, 1)
- led_group_4_layout.addWidget(self.pll_ld_led, 0, 0)
- led_group_4_layout.setColumnStretch(2, 1)
- led_group_4_widget = QtGui.QWidget(self)
- led_group_4_widget.setLayout(led_group_4_layout)
- status_displays.addWidget(led_group_4_widget, 4, 0)
- status_displays.setColumnStretch(5, 2)
- status_displays.setRowStretch(5, 1)
- self.setLayout(status_displays)
- def update_status(self, registers):
- try:
- bits = []
- bits += ['{0:032b}'.format(registers[0])]
- bits += ['{0:032b}'.format(registers[1])]
- bits += ['{0:032b}'.format(registers[2])]
- s1 = heb.board.get_dec_from_bits(bits[0], 2, 0)
- if s1 == 0:
- # Pipeline in reset mode
- self.data_flow_pipeline_led.set_color((255, 255, 0))
- elif s1 == 1:
- # Pipeline is idle
- self.data_flow_pipeline_led.set_color((0, 190, 0))
- elif s1 == 6:
- # Pipeline in error state
- self.data_flow_pipeline_led.set_color((255, 0, 0))
- else:
- # Should not happen!
- self.data_flow_pipeline_led.set_color((128, 128, 128))
- s2 = heb.board.get_dec_from_bits(bits[0], 29, 26)
- if s2 == 0:
- # Master Control in reset mode
- self.master_ctrl_led.set_color((255, 255, 0))
- elif s2 == 1:
- # Master Control is idle
- self.master_ctrl_led.set_color((0, 190, 0))
- elif s2 == 8:
- # Master Control in error state
- self.master_ctrl_led.set_color((255, 0, 0))
- else:
- # Should not happen!
- self.master_ctrl_led.set_color((128, 128, 128))
- s3 = heb.board.get_dec_from_bits(bits[2], 15, 12)
- if s3 == 15:
- # Data Check Idle
- self.data_check_led.set_color((0, 190, 0))
- else:
- # Data Check Error
- self.data_check_led.set_color((255, 255, 0))
- s4 = int(bits[0][7])
- if s4 == 0:
- # PLL_LD not active
- self.pll_ld_led.set_color((255, 255, 0))
- elif s4 == 1:
- # PLL_LD is active
- self.pll_ld_led.set_color((0, 190, 0))
- except IndexError:
- QtGui.QMessageBox.critical(self, "Status Update Error", "Not enough registers give for status update.")
- return
- class AdvancedBoardInterface(QtGui.QWidget):
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
- self.parent = parent
- self.do_layout()
- self.data_flow_pipeline_status = None
- def do_layout(self):
- table_grid = QtGui.QGridLayout()
- table_grid.addWidget(QtGui.QLabel("Status1 Register 0x9050 (Readonly)"), 0, 0)
- self.status1_table = BitsDisplayTable(32*'0', self)
- self.do_status1_table_layout(self.status1_table)
- table_grid.addWidget(self.status1_table, 1, 0)
- table_grid.addWidget(QtGui.QLabel("Status2 Register 0x9054 (Readonly)"), 2, 0)
- self.status2_table = BitsDisplayTable(32*'0', self)
- self.do_status2_table_layout(self.status2_table)
- table_grid.addWidget(self.status2_table, 3, 0)
- table_grid.addWidget(QtGui.QLabel("Status3 Register 0x9058 (Readonly)"), 4, 0)
- self.status3_table = BitsDisplayTable(32*'0', self)
- self.do_status3_table_layout(self.status3_table)
- table_grid.addWidget(self.status3_table, 5, 0)
- table_grid.addItem(QtGui.QSpacerItem(1, 20), 6, 0)
- table_grid.addWidget(QtGui.QLabel("Control Register 0x9040"), 7, 0)
- buttons_box = QtGui.QHBoxLayout()
- buttons_box.setAlignment(QtCore.Qt.AlignLeft)
- self.write_control_button = QtGui.QPushButton("Write Values to board")
- self.write_control_button.setMaximumWidth(200)
- buttons_box.addWidget(self.write_control_button)
- self.clear_control_button = QtGui.QPushButton("Clear Input")
- self.clear_control_button.setMaximumWidth(200)
- buttons_box.addWidget(self.clear_control_button)
- self.check_status_control_button = QtGui.QPushButton("Check Status")
- self.check_status_control_button.setMaximumWidth(200)
- buttons_box.addWidget(self.check_status_control_button)
- buttons_widget = QtGui.QWidget()
- buttons_widget.setLayout(buttons_box)
- table_grid.addWidget(buttons_widget, 8, 0)
- self.control_table = BitsEditTable(32*'0', self)
- self.do_control_table_layout(self.control_table)
- table_grid.addWidget(self.control_table, 9, 0)
- self.write_control_button.clicked.connect(self.send_control_to_board)
- self.clear_control_button.clicked.connect(self.control_table.clear_all_bits)
- self.check_status_control_button.clicked.connect(self.parent.do_status_readout)
- width1 = self.status1_table.width()
- width2 = self.status2_table.width()
- width3 = self.status3_table.width()
- width4 = self.control_table.width()
- max_width = max(width1, max(width2, max(width3, width4)))
- self.status1_table.stretch_to_width(max_width)
- self.status2_table.stretch_to_width(max_width)
- self.status3_table.stretch_to_width(max_width)
- self.control_table.stretch_to_width(max_width)
- self.setLayout(table_grid)
- def send_control_to_board(self):
- if not self.parent._check_for_no_continuous_read():
- logging.log("Cant write to board while continuous readout is active")
- return
- bits = self.control_table.get_bits()
- dec_val_bits = int(bits, 2)
- self.parent.text_area.write("Writing to board Register 0x9040: %s" % ('0x{0:08x}'.format(dec_val_bits)))
- try:
- heb.board.write_pci(hex(dec_val_bits), '0x9040')
- except heb.board.BoardError as e:
- QtGui.QMessageBox.critical(self, "Board communication",
- "Was unable to write value to board!\nReason: "+str(e))
- self.parent.do_status_readout()
- def do_status1_table_layout(self, table):
- # from right to left
- table.set_label(29, 31, "FSM_Data_Pipeline_Status", QtCore.Qt.green)
- table.grey_out_column(28)
- table.set_label(27, 27, "FULL", QtCore.Qt.green)
- table.set_label(26, 26, "EMPTY", QtCore.Qt.green)
- table.grey_out_column(25)
- table.grey_out_column(24)
- table.set_label(14, 23, "RD_data_Counts", QtCore.Qt.green)
- table.set_label(13, 13, "OVR_ADC", QtGui.QColor(210, 210, 0))
- table.grey_out_column(12)
- table.grey_out_column(11)
- table.grey_out_column(10)
- table.grey_out_column(9)
- table.grey_out_column(8)
- table.set_label(7, 7, "PLL_LD", QtGui.QColor(210, 210, 0))
- table.grey_out_column(6)
- table.set_label(2, 5, "Master Control", QtCore.Qt.green)
- table.grey_out_column(1)
- table.set_label(0, 0, "1")
- def do_status2_table_layout(self, table):
- #from right to left
- table.set_label(31, 31, "FIFO 128 255 empty", QtCore.Qt.green)
- table.set_label(30, 30, "FIFO 128 255 full", QtCore.Qt.green)
- table.grey_out_column(29)
- table.grey_out_column(28)
- table.set_label(17, 27, "wr data count 128 255", QtGui.QColor(210, 210, 0))
- table.grey_out_column(16)
- table.set_label(15, 15, "FIFO 255 64 empty", QtCore.Qt.green)
- table.set_label(14, 14, "FIFO 255 64 full", QtCore.Qt.green)
- table.grey_out_column(13)
- table.grey_out_column(12)
- table.set_label(2, 11, "rd data count 255 64", QtGui.QColor(210, 210, 0))
- table.grey_out_column(1)
- table.grey_out_column(0)
- def do_status3_table_layout(self, table):
- #from right to left
- table.set_label(29, 31, "FSM_ARBITER_DDR3", QtCore.Qt.green)
- table.grey_out_column(28)
- table.set_label(25, 27, "FSM_WR_DDR3", QtCore.Qt.green)
- table.grey_out_column(24)
- table.set_label(21, 23, "FSM_R_DDR3", QtCore.Qt.green)
- table.grey_out_column(20)
- table.set_label(16, 19, "BC_ERROR", QtGui.QColor(210, 210, 0))
- table.set_label(1, 15, "Number of wrong BC", QtGui.QColor(255, 255, 0))
- table.grey_out_column(0)
- def do_control_table_layout(self, table):
- #from right to left
- table.set_label(31, 31, "reset", QtGui.QColor(0, 255, 255))
- table.grey_out_column(30)
- table.grey_out_column(29)
- table.grey_out_column(28)
- table.set_label(27, 27, "ADC_1(A+D)", QtGui.QColor(0, 255, 255))
- table.set_label(26, 26, "ADC_2(A+D)2", QtGui.QColor(0, 255, 255))
- table.set_label(25, 25, "T/H_1", QtGui.QColor(210, 210, 0))
- table.set_label(24, 24, "T/H_2", QtGui.QColor(210, 210, 0))
- table.set_label(23, 23, "T/H_3", QtGui.QColor(210, 210, 0))
- table.set_label(22, 22, "T/H_4", QtGui.QColor(210, 210, 0))
- table.set_label(21, 21, "EN_data_Trans", QtCore.Qt.yellow)
- table.set_label(20, 20, "EN_readout", QtCore.Qt.yellow)
- table.set_label(18, 19, "ADC_1", QtCore.Qt.yellow)
- table.set_label(16, 17, "ADC_2", QtCore.Qt.yellow)
- table.set_label(14, 15, "ADC_3", QtCore.Qt.yellow)
- table.set_label(12, 13, "ADC_4", QtCore.Qt.yellow)
- table.grey_out_column(11)
- table.grey_out_column(10)
- table.grey_out_column(9)
- table.grey_out_column(8)
- table.grey_out_column(7)
- table.grey_out_column(6)
- table.grey_out_column(5)
- table.grey_out_column(4)
- table.set_label(3, 3, "Header", QtCore.Qt.green)
- table.grey_out_column(2)
- table.set_label(1, 1, "Pilot Bunch by FPGA", QtGui.QColor(0, 255, 255))
- table.set_label(0, 0, "FPGA Temp monitor Reset", QtGui.QColor(0, 255, 255))
- def update_status(self, registers):
- try:
- self.status1_table.set_numbers('{0:032b}'.format(registers[0]))
- self.status2_table.set_numbers('{0:032b}'.format(registers[1]))
- self.status3_table.set_numbers('{0:032b}'.format(registers[2]))
- except:
- return
- class PopupDialog(QtGui.QDialog):
- def __init__(self, text, parent=None):
- QtGui.QDialog.__init__(self, parent)
- self.text = text
- self.setWindowTitle("User action required")
- self.do_layout()
- self.return_value = False
- def do_layout(self):
- size = QtCore.QSize(200, 200)
- #self.setMaximumSize(size)
- self.setMinimumSize(size)
- box = QtGui.QVBoxLayout()
- self.text_label = QtGui.QLabel(self.text)
- self.text_label.setAlignment(QtCore.Qt.AlignCenter)
- box.addWidget(self.text_label)
- self.okay_btn = QtGui.QPushButton("Okay")
- self.okay_btn.setStyleSheet("padding: 15px;")
- self.okay_btn.clicked.connect(self.on_okay)
- box.addWidget(self.okay_btn)
- box.addSpacerItem(QtGui.QSpacerItem(1, 20))
- self.cancel_btn = QtGui.QPushButton("Cancel")
- self.cancel_btn.setStyleSheet("padding: 15px;")
- self.cancel_btn.clicked.connect(self.on_cancel)
- box.addWidget(self.cancel_btn)
- self.setLayout(box)
- def on_okay(self):
- self.return_value = True
- self.close()
- def on_cancel(self):
- self.close()
- def get_return_value(self):
- return self.return_value
- class RegisterBitsDialog(QtGui.QDialog):
- def __init__(self, n_bits, parent=None):
- QtGui.QDialog.__init__(self, parent)
- self.n_bits = n_bits
- self.setWindowTitle("Register Bit Input Helper")
- self.do_layout()
- self.return_bits = None
- def do_layout(self):
- size = QtCore.QSize(200, 200)
- #self.setMaximumSize(size)
- self.setMinimumSize(size)
- box = QtGui.QVBoxLayout()
- self.table = BitsEditTable("0"*self.n_bits)
- box.addWidget(self.table)
- self.okay_btn = QtGui.QPushButton("Okay")
- self.okay_btn.setStyleSheet("padding: 15px;")
- self.okay_btn.clicked.connect(self.on_okay)
- box.addWidget(self.okay_btn)
- box.addSpacerItem(QtGui.QSpacerItem(1, 20))
- self.cancel_btn = QtGui.QPushButton("Cancel")
- self.cancel_btn.setStyleSheet("padding: 15px;")
- self.cancel_btn.clicked.connect(self.on_cancel)
- box.addWidget(self.cancel_btn)
- self.setLayout(box)
- def on_okay(self):
- self.return_bits = self.table.get_bits()
- self.close()
- def on_cancel(self):
- self.close()
- def get_return_value(self):
- return self.return_bits
- class FileLikeQTextEdit(QtGui.QTextEdit):
- def __init__(self, parent=None):
- QtGui.QTextEdit.__init__(self, parent)
- def write(self, str_in):
- self.append(str_in)
- def flush(self):
- pass
- def close(self):
- pass
- class LogHandler(logging.Handler):
- def __init__(self, text_area):
- logging.Handler.__init__(self)
- self.text_area = text_area
- def emit(self, record):
- self.text_area.write(self.format(record))
- class ApplicationWindow(QtGui.QMainWindow):
- def __init__(self, args):
- QtGui.QMainWindow.__init__(self)
- self.args = args
- self.board_config = heb.board.BoardConfiguration(self.args.config if self.args.config else None)
- self.opt_widgets = {}
- self.data = None
- self.continuous_read = False
- self.do_layout()
- self.register_observers()
- if args.input:
- self.read_and_update_data_from_file(args.input)
- def new_checkbox(self, name, func):
- checkbox = QtGui.QCheckBox(name)
- checkbox.clicked.connect(func)
- self.opt_widgets[name] = checkbox
- return checkbox
- def new_radiobutton(self, name, func):
- button = QtGui.QRadioButton(name)
- button.clicked.connect(func)
- self.opt_widgets[name] = button
- return button
- def new_datawidget(self):
- splitter = QtGui.QSplitter(self)
- self.canvas = PlotCanvas(splitter)
- self.mpl_toolbar = NavigationToolbar(self.canvas, splitter)
- canvas_box = QtGui.QVBoxLayout()
- canvas_box.addWidget(self.canvas)
- canvas_box.addWidget(self.mpl_toolbar)
- canvas_widget = QtGui.QWidget()
- canvas_widget.setLayout(canvas_box)
- sidebar = QtGui.QGridLayout()
- data_view_groupbox = QtGui.QGroupBox()
- data_view_groupbox.setTitle('Data View Settings')
- data_view_layout = QtGui.QGridLayout()
- data_view_layout.setVerticalSpacing(5)
- data_view_layout.addWidget(self.new_radiobutton(OPT_3D_MAP, self.on_option_change), 1, 0)
- data_view_layout.addWidget(self.new_radiobutton(OPT_TRAIN, self.on_option_change), 2, 0)
- data_view_layout.addWidget(self.new_radiobutton(OPT_FFT, self.on_option_change), 3, 0)
- data_view_layout.addWidget(self.new_radiobutton(OPT_COMBINED, self.on_option_change), 4, 0)
- # sidebar.addWidget(self.new_checkbox(OPT_RECONSTRUCTED, self.on_option_change))
- data_view_layout.addWidget(self.new_checkbox(OPT_ADC_1, self.on_option_change), 1, 1)
- data_view_layout.addWidget(self.new_checkbox(OPT_ADC_2, self.on_option_change), 2, 1)
- data_view_layout.addWidget(self.new_checkbox(OPT_ADC_3, self.on_option_change), 3, 1)
- data_view_layout.addWidget(self.new_checkbox(OPT_ADC_4, self.on_option_change), 4, 1)
- self.from_spinbox = Spinbox(0, 999, 0)
- self.from_spinbox.valueChanged.connect(self.on_option_change)
- self.to_spinbox = Spinbox(-1, 10000000, 1000)
- self.to_spinbox.valueChanged.connect(self.on_to_changed)
- data_view_layout.addWidget(QtGui.QLabel("Data range"), 5, 0)
- data_view_layout.addWidget(self.from_spinbox, 6, 0)
- data_view_layout.addWidget(self.to_spinbox, 6, 1)
- self.opt_widgets[OPT_ADC_1].setChecked(True)
- data_view_groupbox.setLayout(data_view_layout)
- sidebar.addWidget(data_view_groupbox, 0, 0, 1, 2) # Span both columns
- adc_settings_groupbox = QtGui.QGroupBox()
- adc_settings_groupbox.setTitle('Timing Settings')
- adc_delay_grid = QtGui.QGridLayout()
- adc_delay_grid.setVerticalSpacing(5)
- adc_delay_grid.addWidget(QtGui.QLabel("T/H Delay"), 0, 1, 1, 2)
- self.th_delay_spinbox = Spinbox(0, 15, 0)
- self.th_delay_spinbox.setMaximumWidth(80)
- self.th_delay_spinbox.valueChanged.connect(self.on_adc_delay_changed)
- adc_delay_grid.addWidget(self.th_delay_spinbox, 1, 1)
- adc_delay_grid.addWidget(QtGui.QLabel("Coarse Delay"), 1, 0)
- adc_delay_grid.addWidget(QtGui.QLabel("ADC_1"), 2, 1)
- adc_delay_grid.addWidget(QtGui.QLabel("ADC_2"), 2, 2)
- adc_delay_grid.addWidget(QtGui.QLabel("ADC_3"), 2, 3)
- adc_delay_grid.addWidget(QtGui.QLabel("ADC_4"), 2, 4)
- self.adc_1_delay_spinbox = Spinbox(0, 31, 0)
- self.adc_1_delay_spinbox.setMaximumWidth(80)
- self.adc_1_delay_spinbox.valueChanged.connect(self.on_adc_delay_changed)
- self.adc_2_delay_spinbox = Spinbox(0, 31, 0)
- self.adc_2_delay_spinbox.setMaximumWidth(80)
- self.adc_2_delay_spinbox.valueChanged.connect(self.on_adc_delay_changed)
- self.adc_3_delay_spinbox = Spinbox(0, 31, 0)
- self.adc_3_delay_spinbox.setMaximumWidth(80)
- self.adc_3_delay_spinbox.valueChanged.connect(self.on_adc_delay_changed)
- self.adc_4_delay_spinbox = Spinbox(0, 31, 0)
- self.adc_4_delay_spinbox.setMaximumWidth(80)
- self.adc_4_delay_spinbox.valueChanged.connect(self.on_adc_delay_changed)
- adc_delay_grid.addWidget(QtGui.QLabel("Fine Delay"), 3, 0)
- adc_delay_grid.addWidget(self.adc_1_delay_spinbox, 3, 1)
- adc_delay_grid.addWidget(self.adc_2_delay_spinbox, 3, 2)
- adc_delay_grid.addWidget(self.adc_3_delay_spinbox, 3, 3)
- adc_delay_grid.addWidget(self.adc_4_delay_spinbox, 3, 4)
- self.adc_1_delay_text = QtGui.QLineEdit()
- self.adc_1_delay_text.setReadOnly(True)
- self.adc_1_delay_text.setMaximumWidth(80)
- self.adc_2_delay_text = QtGui.QLineEdit()
- self.adc_2_delay_text.setReadOnly(True)
- self.adc_2_delay_text.setMaximumWidth(80)
- self.adc_3_delay_text = QtGui.QLineEdit()
- self.adc_3_delay_text.setReadOnly(True)
- self.adc_3_delay_text.setMaximumWidth(80)
- self.adc_4_delay_text = QtGui.QLineEdit()
- self.adc_4_delay_text.setReadOnly(True)
- self.adc_4_delay_text.setMaximumWidth(80)
- adc_delay_grid.addWidget(QtGui.QLabel("Total Delay"), 4, 0)
- adc_delay_grid.addWidget(self.adc_1_delay_text, 4, 1)
- adc_delay_grid.addWidget(self.adc_2_delay_text, 4, 2)
- adc_delay_grid.addWidget(self.adc_3_delay_text, 4, 3)
- adc_delay_grid.addWidget(self.adc_4_delay_text, 4, 4)
- adc_settings_groupbox.setLayout(adc_delay_grid)
- sidebar.addWidget(adc_settings_groupbox, 1, 0, 1, 2) # Span both columns
- self.set_adc_delay_spinboxes_active(False)
- aquisition_settings_groupbox = QtGui.QGroupBox()
- aquisition_settings_groupbox.setTitle('Acquisition Settings')
- aquisition_settings_layout = QtGui.QGridLayout()
- aquisition_settings_layout.setVerticalSpacing(5)
- self.simulate_checkbox = QtGui.QCheckBox("Simulate Pilot Bunch")
- aquisition_settings_layout.addWidget(self.simulate_checkbox, 0, 0)
- self.number_of_orbits_spinbox = Spinbox(1, 10000000, 0)
- self.number_of_orbits_spinbox.valueChanged.connect(self.on_number_of_orbits_changed)
- aquisition_settings_layout.addWidget(self.number_of_orbits_spinbox, 1, 0)
- aquisition_settings_layout.addWidget(QtGui.QLabel("Number of orbits to observe"), 1, 1)
- self.number_of_skipped_orbits_spinbox = Spinbox(0, 100, 0)
- self.number_of_skipped_orbits_spinbox.valueChanged.connect(self.on_number_of_skipped_orbits_changed)
- aquisition_settings_layout.addWidget(self.number_of_skipped_orbits_spinbox, 2, 0)
- aquisition_settings_layout.addWidget(QtGui.QLabel("Number of orbits to skip"), 2, 1)
- aquisition_settings_groupbox.setLayout(aquisition_settings_layout)
- sidebar.addWidget(aquisition_settings_groupbox, 2, 0, 1, 2)
- data_consistency_groupbox = QtGui.QGroupBox()
- data_consistency_groupbox.setTitle('Data Consistency')
- data_consistency_layout = QtGui.QHBoxLayout()
- self.data_consistency_led = GraphicalLED(self, (128, 128, 128), 10, 10)
- data_consistency_layout.addWidget(self.data_consistency_led)
- data_consistency_layout.addWidget(QtGui.QLabel("Consistency Indicator"))
- data_consistency_groupbox.setLayout(data_consistency_layout)
- sidebar.addWidget(data_consistency_groupbox, 3, 0, 1, 2)
- read_data_toolbox = QtGui.QToolBox()
- single_and_timed_read_layout = QtGui.QGridLayout()
- single_and_timed_read_layout.setVerticalSpacing(10)
- single_and_timed_read_layout.addWidget(QtGui.QLabel("Read every n-Milliseconds"), 0, 0)
- self.continuous_read_interval_spinbox = Spinbox(0, 10000, 100)
- self.continuous_read_checkbox = self.new_checkbox("Continuous Readout", self.on_continuous_read)
- single_and_timed_read_layout.addWidget(self.continuous_read_interval_spinbox, 1, 0)
- single_and_timed_read_layout.addWidget(self.continuous_read_checkbox, 1, 1)
- self.start_button = QtGui.QPushButton("Single Read")
- self.start_button.clicked.connect(self.on_single_read)
- single_and_timed_read_layout.addWidget(self.start_button, 2, 0)
- single_and_timed_read_layout.setRowStretch(2, 1) # Otherwise, the label in row 0 will take all the space...
- single_and_timed_read_wdgt = QtGui.QWidget()
- single_and_timed_read_wdgt.setLayout(single_and_timed_read_layout)
- read_data_toolbox.addItem(single_and_timed_read_wdgt, 'Single and Continuous Readout')
- acquisition_layout = QtGui.QGridLayout()
- acquisition_layout.setVerticalSpacing(10)
- self.acquisitions_spinbox = Spinbox(1, 10000000, 10)
- acquisition_layout.addWidget(self.acquisitions_spinbox, 0, 0)
- acquisition_layout.addWidget(QtGui.QLabel("Count"), 0, 1)
- self.wait_time_spinbox = Spinbox(1, 60, 15)
- acquisition_layout.addWidget(self.wait_time_spinbox, 1, 0)
- acquisition_layout.addWidget(QtGui.QLabel("Wait (s)"), 1, 1)
- self.spectrogram_checkbox = QtGui.QCheckBox("Build Spectrograms")
- acquisition_layout.addWidget(self.spectrogram_checkbox, 2, 0)
- self.acquire_button = QtGui.QPushButton("Acquire")
- self.acquire_button.clicked.connect(self.on_acquire)
- acquisition_layout.addWidget(self.acquire_button, 3, 0)
- self.stop_button = QtGui.QPushButton("Stop")
- self.stop_button.setEnabled(False)
- self.stop_button.clicked.connect(self.on_stop)
- acquisition_layout.addWidget(self.stop_button, 3, 1)
- self.acquisition_progressbar = QtGui.QProgressBar()
- acquisition_layout.addWidget(self.acquisition_progressbar, 4, 0, 1, 2)
- acquisition_wdgt = QtGui.QWidget()
- acquisition_wdgt.setLayout(acquisition_layout)
- read_data_toolbox.addItem(acquisition_wdgt, 'Acquisition')
- timescan_layout = QtGui.QGridLayout()
- timescan_layout.setVerticalSpacing(10)
- self.scan_button = QtGui.QPushButton("Time scan")
- self.scan_button.clicked.connect(self.on_scan)
- timescan_layout.addWidget(self.scan_button, 0, 0)
- self.scan_stop_button = QtGui.QPushButton("Stop scan")
- self.scan_stop_button.setEnabled(False)
- timescan_layout.addWidget(self.scan_stop_button, 0, 1)
- self.timescan_progressbar = QtGui.QProgressBar()
- timescan_layout.addWidget(self.timescan_progressbar, 1, 0, 1, 2)
- timescan_layout.addWidget(QtGui.QLabel('Coarse Scan Range'), 2, 0, 1, 2)
- self.time_scan_coarse_from = Spinbox(0, self.board_config.get('th_delay_max'), 0)
- timescan_layout.addWidget(self.time_scan_coarse_from, 3, 0)
- self.time_scan_coarse_to = Spinbox(0, self.board_config.get('th_delay_max'), self.board_config.get('th_delay_max'))
- timescan_layout.addWidget(self.time_scan_coarse_to, 3, 1)
- timescan_layout.addWidget(QtGui.QLabel('Fine Scan Range'), 4, 0, 1, 2)
- self.time_scan_fine_from = Spinbox(0, self.board_config.get('chip_delay_max'), 0)
- timescan_layout.addWidget(self.time_scan_fine_from, 5, 0)
- self.time_scan_fine_to = Spinbox(0, self.board_config.get('chip_delay_max'), self.board_config.get('chip_delay_max'))
- timescan_layout.addWidget(self.time_scan_fine_to, 5, 1)
- timescan_wdgt = QtGui.QWidget()
- timescan_wdgt.setLayout(timescan_layout)
- read_data_toolbox.addItem(timescan_wdgt, 'Time Scan')
- read_data_toolbox.setMinimumHeight(240)
- sidebar.addWidget(read_data_toolbox, 4, 0, 1, 2)
- sidebar.setVerticalSpacing(10)
- sidebar.setRowStretch(5, 1)
- sidebar_group = QtGui.QGroupBox("sidebar")
- sidebar_group.setLayout(sidebar)
- sidebar_group.setFlat(True)
- splitter.addWidget(canvas_widget)
- splitter.addWidget(sidebar_group)
- splitter.setStretchFactor(0, 4)
- splitter.setStretchFactor(1, 2)
- return splitter
- def do_layout(self):
- self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
- self.setWindowTitle("HEB analysis")
- self.file_menu = QtGui.QMenu('&File', self)
- self.file_menu.addAction('&Open Datafile', self.on_open,
- QtCore.Qt.CTRL + QtCore.Qt.Key_O)
- self.file_menu.addAction('O&pen Config', self.on_open_config,
- QtCore.Qt.CTRL + QtCore.Qt.Key_P)
- self.file_menu.addAction('&Save Config', self.on_save_config,
- QtCore.Qt.CTRL + QtCore.Qt.Key_S)
- self.file_menu.addAction('&Quit', self.on_close,
- QtCore.Qt.CTRL + QtCore.Qt.Key_Q)
- self.menuBar().addMenu(self.file_menu)
- self.tab_views = QtGui.QTabWidget(self)
- self.setCentralWidget(self.tab_views)
- # Group the board control buttons together
- control_buttons = QtGui.QGridLayout()
- control_buttons.addWidget(QtGui.QLabel("Board Control"), 0, 0)
- self.start_board_button = QtGui.QPushButton("Start Board")
- self.start_board_button.clicked.connect(self.on_start_board)
- control_buttons.addWidget(self.start_board_button, 1, 0)
- self.calibrate_board_button = QtGui.QPushButton("Calibrate")
- self.calibrate_board_button.clicked.connect(self.on_calibrate_board)
- self.calibrate_board_button.setEnabled(False)
- control_buttons.addWidget(self.calibrate_board_button, 2, 0)
- self.sync_board_button = QtGui.QPushButton("Synchronize")
- self.sync_board_button.clicked.connect(self.on_sync_board)
- self.sync_board_button.setEnabled(False)
- control_buttons.addWidget(self.sync_board_button, 3, 0)
- self.set_defaults_button = QtGui.QPushButton("Set Defaults")
- self.set_defaults_button.clicked.connect(self.on_set_defaults)
- self.set_defaults_button.setEnabled(False)
- control_buttons.addWidget(self.set_defaults_button, 4, 0)
- self.soft_reset_button = QtGui.QPushButton("Soft Reset")
- self.soft_reset_button.clicked.connect(self.on_soft_reset)
- self.soft_reset_button.setEnabled(False)
- control_buttons.addWidget(self.soft_reset_button, 5, 0)
- self.stop_board_button = QtGui.QPushButton("Board Off")
- self.stop_board_button.clicked.connect(self.on_stop_board)
- control_buttons.addWidget(self.stop_board_button, 6, 0)
- #self.show_advanced_tick = QtGui.QCheckBox("Show advanced Interface")
- #self.show_advanced_tick.setEnabled(True)
- #self.show_advanced_tick.clicked.connect(self.do_show_advanced_interface)
- #control_buttons.addWidget(self.show_advanced_tick, 6, 0)
- control_buttons.setRowStretch(7, 1)
- buttons_widget = QtGui.QWidget()
- buttons_widget.setLayout(control_buttons)
- buttons_widget.setMinimumWidth(200)
- buttons_widget.setMaximumWidth(200)
- # Group the Simple status display together with the "Check Status" button
- status_box = QtGui.QGridLayout()
- self.simple_status_display = SimpleStatusDisplay()
- status_box.addWidget(self.simple_status_display, 0, 0)
- self.get_status_button = QtGui.QPushButton("Check Status")
- self.get_status_button.setEnabled(True)
- self.get_status_button.clicked.connect(self.do_status_readout)
- self.get_status_button.setMinimumWidth(150)
- self.get_status_button.setMaximumWidth(150)
- status_box.addWidget(self.get_status_button, 1, 0)
- status_box.setRowStretch(2, 1)
- simple_status_widget = QtGui.QWidget()
- simple_status_widget.setLayout(status_box)
- #Text Area for logging of inconsistent readouts
- self.error_text_area = FileLikeQTextEdit(self)
- self.error_text_area.setFont(QtGui.QFont('monospace', 9))
- self.error_text_area.setTextColor(QtCore.Qt.red)
- self.error_text_area.setMaximumWidth(300)
- self.error_text_area.setReadOnly(True)
- clear_error_text_btn = QtGui.QPushButton("Clear List")
- clear_error_text_btn.clicked.connect(self.error_text_area.clear)
- error_text_box = QtGui.QVBoxLayout()
- error_text_box.addWidget(QtGui.QLabel("Inconsistent Files List"))
- error_text_box.addWidget(self.error_text_area)
- error_text_box.addWidget(clear_error_text_btn)
- error_text_wdgt = QtGui.QWidget()
- error_text_wdgt.setLayout(error_text_box)
- #Now bundle the Board Control buttons and the Status LEDS together
- top_box = QtGui.QHBoxLayout()
- top_box.addWidget(buttons_widget)
- top_box.addWidget(simple_status_widget)
- top_box.addWidget(error_text_wdgt)
- top_box.insertStretch(-1, 1)
- top_box_w = QtGui.QWidget()
- top_box_w.setLayout(top_box)
- #Create the Timing Indication Block
- self.fpga_delay_table = BitsDisplayTable('0', self)
- self.fpga_delay_table.set_label(0, 0, "FPGA Delay")
- self.th_delay_table = BitsDisplayTable('0', self)
- self.th_delay_table.set_label(0, 0, "T/H Delay")
- self.fpga_temperature = QtGui.QLineEdit()
- self.fpga_temperature.setMaximumWidth(60)
- self.fpga_temperature.setReadOnly(True)
- self.adc_delay_table = BitsDisplayTable(4*'0', self)
- self.adc_delay_table.set_label(0, 0, "ADC 1")
- self.adc_delay_table.set_label(1, 1, "ADC 2")
- self.adc_delay_table.set_label(2, 2, "ADC 3")
- self.adc_delay_table.set_label(3, 3, "ADC 4")
- timing_line_1 = QtGui.QHBoxLayout()
- timing_line_1.setAlignment(QtCore.Qt.AlignLeft)
- timing_line_1.addWidget(self.fpga_delay_table)
- timing_line_1.addWidget(self.th_delay_table)
- timing_line_1.addWidget(self.adc_delay_table)
- timing_line_1_wdgt = QtGui.QWidget()
- timing_line_1_wdgt.setLayout(timing_line_1)
- timing_line_2 = QtGui.QGridLayout()
- timing_line_2.addWidget(QtGui.QLabel("FPGA Temperature"), 0, 0)
- timing_line_2.addWidget(self.fpga_temperature, 0, 1)
- timing_line_2.setColumnStretch(2, 1)
- timing_line_2_wdgt = QtGui.QWidget()
- timing_line_2_wdgt.setLayout(timing_line_2)
- timing_box = QtGui.QVBoxLayout()
- timing_box.addWidget(QtGui.QLabel(" Timings in Pico Seconds"), 0, QtCore.Qt.AlignLeft)
- timing_box.addWidget(timing_line_1_wdgt, 0, QtCore.Qt.AlignLeft)
- timing_box.addWidget(timing_line_2_wdgt, 0, QtCore.Qt.AlignLeft)
- timing_box_wdgt = QtGui.QWidget()
- timing_box_wdgt.setLayout(timing_box)
- #Create the the "Write Registers" block
- sub_box = QtGui.QGridLayout()
- sub_box.addWidget(QtGui.QLabel("Register Address"), 0, 0)
- sub_box.addWidget(QtGui.QLabel("Register Value"), 0, 1)
- self.adv_register_address = QtGui.QLineEdit()
- self.adv_register_address.setText("0x9040")
- self.adv_register_address.setInputMask(r"\0\xHhhhhhhh")
- sub_box.addWidget(self.adv_register_address, 1, 0)
- self.adv_register_value = QtGui.QLineEdit()
- self.adv_register_value.setText("0x0")
- self.adv_register_value.setInputMask(r"\0\xHhhhhhhh")
- sub_box.addWidget(self.adv_register_value, 1, 1)
- helper_btn = QtGui.QPushButton("Open Input Help")
- helper_btn.clicked.connect(self.show_input_helper)
- sub_box.addWidget(helper_btn, 2, 0)
- adv_write_reg_val_btn = QtGui.QPushButton("Write Value")
- adv_write_reg_val_btn.clicked.connect(self.write_register_adv)
- sub_box.addWidget(adv_write_reg_val_btn, 2, 1)
- sub_box.setRowStretch(3, 1)
- self.sub_box_w = QtGui.QWidget()
- self.sub_box_w.setLayout(sub_box)
- self.sub_box_w.setVisible(False)
- #Pack Board Control / Status LEDs / Timing Indication / "Write Register" together
- control_block = QtGui.QGridLayout()
- control_block.addWidget(top_box_w, 0, 0)
- control_block.addWidget(timing_box_wdgt, 1, 0)
- control_block.addWidget(self.sub_box_w, 3, 0)
- control_block.setRowStretch(2, 1)
- control_block_wdgt = QtGui.QWidget()
- control_block_wdgt.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
- control_block_wdgt.setLayout(control_block)
- #Split the area vertically and add a text area in the bottom half
- splitter = QtGui.QSplitter()
- splitter.setOrientation(QtCore.Qt.Vertical)
- splitter.addWidget(control_block_wdgt)
- self.text_area = FileLikeQTextEdit(self)
- self.text_area.setFont(QtGui.QFont('monospace', 9))
- self.text_area.setReadOnly(True)
- splitter.addWidget(self.text_area)
- # Let log handler write to text area
- log_handler = LogHandler(self.text_area)
- log_handler.setFormatter(logging.Formatter('%(asctime)s - %(funcName)s(): %(message)s'))
- logger = logging.getLogger()
- logger.addHandler(log_handler)
- logger.setLevel(logging.INFO)
- self.board_config.logger = logger
- # Create a widget for the Advanced Board Interface
- self.advanced_interface = AdvancedBoardInterface(self)
- self.advanced_interface.setVisible(False)
- #set up tabs for the main window
- self.tab_views.addTab(splitter, "Control")
- self.tab_views.addTab(self.advanced_interface, "Registers")
- self.tab_views.addTab(self.new_datawidget(), "Data")
- self.tab_views.setCurrentIndex(2)
- def do_show_advanced_interface(self):
- show = self.show_advanced_tick.isChecked()
- self.advanced_interface.setVisible(show)
- self.sub_box_w.setVisible(show)
- def register_observers(self):
- sbo = self.board_config.observe
- sbo(self.adc_1_delay_spinbox, self.adc_1_delay_spinbox.setValueSilent, 'chip_1_delay')
- sbo(self.adc_2_delay_spinbox, self.adc_2_delay_spinbox.setValueSilent, 'chip_2_delay')
- sbo(self.adc_3_delay_spinbox, self.adc_3_delay_spinbox.setValueSilent, 'chip_3_delay')
- sbo(self.adc_4_delay_spinbox, self.adc_4_delay_spinbox.setValueSilent, 'chip_4_delay')
- sbo(self.adc_1_delay_text, lambda x: self.adc_1_delay_text.setText('%i + %i' % (self.board_config.get('th_delay')*self.board_config.get('th_delay_factor'),x*self.board_config.get('chip_delay_factor'))), 'chip_1_delay')
- sbo(self.adc_2_delay_text, lambda x: self.adc_2_delay_text.setText('%i + %i'%(self.board_config.get('th_delay')*self.board_config.get('th_delay_factor'),x*self.board_config.get('chip_delay_factor'))), 'chip_2_delay')
- sbo(self.adc_3_delay_text, lambda x: self.adc_3_delay_text.setText('%i + %i'%(self.board_config.get('th_delay')*self.board_config.get('th_delay_factor'),x*self.board_config.get('chip_delay_factor'))), 'chip_3_delay')
- sbo(self.adc_4_delay_text, lambda x: self.adc_4_delay_text.setText('%i + %i'%(self.board_config.get('th_delay')*self.board_config.get('th_delay_factor'),x*self.board_config.get('chip_delay_factor'))), 'chip_4_delay')
- sbo(self.fpga_delay_table, lambda x: self.fpga_delay_table.set_item(0, 0, x*self.board_config.get('fpga_delay_factor')), 'fpga_delay')
- sbo(self.th_delay_table, lambda x: self.th_delay_table.set_item(0, 0, x*self.board_config.get('th_delay_factor')), 'th_delay')
- sbo(self.th_delay_spinbox, self.th_delay_spinbox.setValueSilent, 'th_delay')
- sbo(self.number_of_orbits_spinbox, self.number_of_orbits_spinbox.setValueSilent, 'orbits_observe')
- sbo(self.number_of_skipped_orbits_spinbox, self.number_of_skipped_orbits_spinbox.setValueSilent, 'orbits_skip')
- sbo(self.adc_delay_table, lambda x: self.adc_delay_table.set_item(0, 0, x * self.board_config.get('adc_delay_factor')), 'adc_1_delay')
- sbo(self.adc_delay_table, lambda x: self.adc_delay_table.set_item(0, 1, x * self.board_config.get('adc_delay_factor')), 'adc_2_delay')
- sbo(self.adc_delay_table, lambda x: self.adc_delay_table.set_item(0, 2, x * self.board_config.get('adc_delay_factor')), 'adc_3_delay')
- sbo(self.adc_delay_table, lambda x: self.adc_delay_table.set_item(0, 3, x * self.board_config.get('adc_delay_factor')), 'adc_4_delay')
- def do_status_readout(self):
- try:
- registers = heb.board.read_pci(3, '0x9050', decimal=True)
- self.simple_status_display.update_status(registers)
- self.advanced_interface.update_status(registers)
- control = heb.board.read_pci(1, '0x9040')[0]
- control_bits = '{0:032b}'.format(int(control, 16))
- self.advanced_interface.control_table.set_numbers(control_bits)
- if control_bits[22:26] == "1111":
- self.start_board_button.setEnabled(False)
- self.soft_reset_button.setEnabled(True)
- self.calibrate_board_button.setEnabled(True)
- else:
- self.start_board_button.setEnabled(True)
- self.soft_reset_button.setEnabled(False)
- self.calibrate_board_button.setEnabled(False)
- fpga_temp_raw_hex = heb.board.read_pci(1,'0x9110')[0]
- fpga_temp_raw_hex = fpga_temp_raw_hex[-3:]
- fpga_temp_raw_bin = '{0:012b}'.format(int(fpga_temp_raw_hex, 16))
- fpga_temp_encoded = heb.board.get_dec_from_bits(fpga_temp_raw_bin, 9, 0)
- fpga_temp_celsius = '{0:2.2f}'.format(((fpga_temp_encoded*503.975)/1024)-273.15)
- self.fpga_temperature.setText(fpga_temp_celsius + " C")
- except heb.board.BoardError as e:
- logging.error("Reading board status failed: {}".format(str(e)))
- def write_register_adv(self):
- # First cast both texts to integers (base 16) and let python check
- # if the entered values are valid hex-numbers
- try:
- addr = int("%s"%self.adv_register_address.text(), 16)
- except ValueError as e:
- logging.error("Register address is invalid!")
- self.adv_register_address.setStyleSheet("QLineEdit { background-color : #FF6666; }")
- return
- try:
- value = int("%s"%self.adv_register_value.text(), 16)
- except ValueError as e:
- logging.error("Register value is invalid!")
- self.adv_register_value.setStyleSheet("QLineEdit { background-color : #FF6666; }")
- return
- # Now use the numbers
- addr = "%s"%self.adv_register_address.text()
- value = "%s"%self.adv_register_value.text()
- self.adv_register_address.setStyleSheet("QLineEdit { background-color : white; }")
- self.adv_register_value.setStyleSheet("QLineEdit { background-color : white; }")
- try:
- heb.board.write_pci(value, addr)
- except heb.board.BoardError as e:
- QtGui.QMessageBox.critical(self, "Board communication", "'pci' " + str(e))
- logging.error("Could not write values to board due to an error!")
- return
- # Intercept writes to the "Timing" Registers to catch the input and put it into their
- # respective displays
- if addr == "0x9060":
- if value[:8] == "0x000501":
- #We are writing a timing value. Decide which one
- if value[-1:] == "0":
- #FPGA
- self.board_config.update('fpga_delay', int(value[8:9], 16))
- elif value[-1:] == "3":
- #T/H
- self.board_config.update('th_delay', int(value[8:9], 16))
- elif value[-1:] == "4":
- #ADC_1
- self.board_config.update('adc_1_delay', int(value[8:9], 16))
- elif value[-1:] == "5":
- #ADC_2
- self.board_config.update('adc_1_delay', int(value[8:9], 16))
- elif value[-1:] == "6":
- #ADC_3
- self.board_config.update('adc_1_delay', int(value[8:9], 16))
- elif value[-1:] == "7":
- #ADC_4
- self.board_config.update('adc_1_delay', int(value[8:9], 16))
-
- self.do_status_readout()
- logging.info("Written '%s' to register '%s'." % (value, addr))
- def show_input_helper(self):
- dialog = RegisterBitsDialog(32)
- dialog.exec_()
- dialog.deleteLater()
- bits = dialog.get_return_value()
- if bits:
- hex_str = hex(int(bits, 2))
- self.adv_register_value.setText(hex_str)
- def _check_for_no_continuous_read(self):
- if self.continuous_read is True:
- dialog = PopupDialog("Continuous Read is currently active!\n"
- "Stop continuous read and still perform this action?")
- dialog.exec_()
- dialog.deleteLater()
- ret = dialog.get_return_value()
- if ret is False:
- return False
- else:
- self._set_continuous_read_inactive()
- self.continuous_read_checkbox.setChecked(False)
- return True
- else:
- return True
- def on_start_board(self):
- enable_wait_cursor()
- if not self._check_for_no_continuous_read():
- disable_wait_cursor()
- return
- try:
- if heb.board.is_active():
- disable_wait_cursor()
- self.do_status_readout()
- return
- logging.info("##### Activating Board #####")
- heb.board.start_dma()
- #cmd = ['pci', '--list-dma-engines']
- #logging.info(heb.board.safe_call(cmd))
- heb.board.write_pci('0x20001000', '0x9100')
- heb.board.write_pci('0x05', '0x9040')
- time.sleep(1.0)
- dialog1 = PopupDialog("Switch On the power supply --> FIRST <--")
- dialog1.exec_()
- dialog1.deleteLater()
- if not dialog1.get_return_value():
- logging.error("Starting procedure canceled")
- disable_wait_cursor()
- return
- logging.info("Switch ON T/Hs")
- heb.board.write_pci('0x3C1', '0x9040')
- logging.info("9040: " + str(heb.board.read_pci(1, '0x9040')[0]))
- time.sleep(0.1)
- dialog2 = PopupDialog("Switch On the power supply --> SECOND <--")
- dialog2.exec_()
- dialog2.deleteLater()
- if not dialog2.get_return_value():
- self.test_area.write("Starting procedure canceled")
- disable_wait_cursor()
- return
- logging.info("Switch ON ADCs")
- heb.board.write_pci('0x3F1', '0x9040')
- logging.info("9040: " + str(heb.board.read_pci(1, '0x9040')[0]))
- time.sleep(0.1)
- heb.board.write_pci('0x3F0', '0x9040')
- logging.info("9040: " + str(heb.board.read_pci(1, '0x9040')[0]))
- time.sleep(1.0)
- logging.info("Board started successfully!")
- except heb.board.BoardError as e:
- logging.error("Starting board failed: {}".format(str(e)))
- disable_wait_cursor()
- self.do_status_readout()
- def on_calibrate_board(self):
- enable_wait_cursor()
- if not self._check_for_no_continuous_read():
- disable_wait_cursor()
- return
- try:
- logging.info("##### Calibrating Board #####")
- logging.info("Removing Board Reset")
- heb.board.write_pci('0x2000003f0', '0x9040')
- time.sleep(0.5)
- logging.info("SPI Fanout Programming...")
- heb.board.write_pci('0x083', '0x9068')
- time.sleep(0.5)
- heb.board.write_pci('0x6a2', '0x9068')
- time.sleep(0.5)
- logging.info("PLL calibration start...")
- logging.info("PLL Reset...")
- heb.board.write_pci('0x80000000', '0x9060')
- time.sleep(0.5)
- logging.info("Set CH_0 (FPGA) clock FPGA ...")
- heb.board.write_pci('0x00050000', '0x9060')
- time.sleep(0.5)
- logging.info("Set CH_3 clock fanout ...")
- heb.board.write_pci('0x00050003', '0x9060')
- time.sleep(0.5)
- logging.info("Set CH_4 clock ADC 1 ...")
- heb.board.write_pci('0x00050004', '0x9060')
- time.sleep(0.5)
- logging.info("Set CH_5 clock ADC 2 ...")
- heb.board.write_pci('0x00050005', '0x9060')
- time.sleep(0.5)
- logging.info("Set CH_6 clock ADC 3 ...")
- heb.board.write_pci('0x00050006', '0x9060')
- time.sleep(0.5)
- logging.info("Set CH_7 clock ADC 4 ...")
- heb.board.write_pci('0x00050007', '0x9060')
- time.sleep(0.5)
- logging.info("Set R8 ...")
- heb.board.write_pci('0x10000908', '0x9060')
- time.sleep(0.5)
- logging.info("Set R11 ...")
- heb.board.write_pci('0x0082800B', '0x9060')
- time.sleep(0.5)
- logging.info("Set R13 ...")
- heb.board.write_pci('0x029F400D', '0x9060')
- time.sleep(0.5)
- logging.info("Set R14 (F_out and Global_EN => ON) ...")
- heb.board.write_pci('0x0830040E', '0x9060')
- time.sleep(0.5)
- logging.info("Set R15 ...")
- heb.board.write_pci('0xD000100F', '0x9060')
- time.sleep(0.5)
- except heb.board.BoardError as e:
- logging.error("Calibration failed: {}".format(str(e)))
- disable_wait_cursor()
- self.do_status_readout()
- return
- logging.info("Board Calibration successful!")
- self.sync_board_button.setEnabled(True)
- disable_wait_cursor()
- self.do_status_readout()
- def on_sync_board(self):
- enable_wait_cursor()
- if not self._check_for_no_continuous_read():
- disable_wait_cursor()
- return
- try:
- logging.info("##### Synchronize PLLs #####")
- logging.info("Send the PLL sync signals ...")
- heb.board.write_pci('0x1003f0', '0x9040')
- time.sleep(1.0)
- logging.info("Done!")
- heb.board.write_pci('0x0003f0', '0x9040')
- except heb.board.BoardError as e:
- logging.error("Synchronization failed: {}".format(str(e)))
- disable_wait_cursor()
- self.do_status_readout()
- return
- logging.info("Board synchronization successful!")
- self.set_defaults_button.setEnabled(True)
- disable_wait_cursor()
- self.do_status_readout()
- def on_set_defaults(self):
- enable_wait_cursor()
- if not self._check_for_no_continuous_read():
- disable_wait_cursor()
- return
- try:
- logging.info("##### Setting default Values #####")
- logging.info("Set Defaults delay value in the board...")
- #Set_FPGA_clock_delay.sh 0
- self.board_config.set_fpga_delay(self.board_config.get('fpga_delay'))
- time.sleep(0.1)
- #Set_Delay_chip.sh 16 16 16 16
- factors = [self.board_config.get('chip_1_delay'), self.board_config.get('chip_2_delay'),
- self.board_config.get('chip_3_delay'), self.board_config.get('chip_4_delay')]
- self.board_config.set_chip_delay([0, 1, 2, 3], factors)
- time.sleep(0.6)
- #Set_TH_Delay.sh 12
- self.board_config.set_th_delay(self.board_config.get('th_delay'))
- time.sleep(0.1)
- #Set_ADC_1_Delay.sh 4
- self.board_config.set_adc_delay(0, self.board_config.get('adc_1_delay'))
- time.sleep(0.1)
- #Set_ADC_2_Delay.sh 4
- self.board_config.set_adc_delay(1, self.board_config.get('adc_2_delay'))
- time.sleep(0.1)
- #Set_ADC_3_Delay.sh 4
- self.board_config.set_adc_delay(2, self.board_config.get('adc_3_delay'))
- time.sleep(0.1)
- #Set_ADC_4_Delay.sh 4
- self.board_config.set_adc_delay(3, self.board_config.get('adc_4_delay'))
- time.sleep(0.1)
- heb.board.write_pci('{0:08x}'.format(self.board_config.get('orbits_observe')), '0x9020')
- self.number_of_orbits_spinbox.setValueSilent(self.board_config.get('orbits_observe'))
- heb.board.write_pci('{0:08x}'.format(self.board_config.get('orbits_skip')), '0x9028')
- self.number_of_skipped_orbits_spinbox.setValueSilent(self.board_config.get('orbits_skip'))
- except heb.board.BoardError as e:
- logging.error("Setting defaults failed: {}".format(str(e)))
- disable_wait_cursor()
- self.do_status_readout()
- return
- logging.info("Default values set successfully!")
- self.set_adc_delay_spinboxes_active(True)
- disable_wait_cursor()
- self.do_status_readout()
- def on_stop_board(self):
- enable_wait_cursor()
- if not self._check_for_no_continuous_read():
- disable_wait_cursor()
- return
- try:
- logging.info("##### Switching Off Board #####")
- heb.board.write_pci('0x01', '0x9040')
- heb.board.stop_dma()
- cmd = ['pci', '--list-dma-engines']
- logging.info(heb.board.safe_call(cmd))
- time.sleep(0.5)
- except heb.board.BoardError as e:
- logging.error("Sequence failed: {}".format(str(e)))
- disable_wait_cursor()
- self.do_status_readout()
- return
- logging.info("Board switched off successfully!")
- self.start_board_button.setEnabled(True)
- self.calibrate_board_button.setEnabled(False)
- self.sync_board_button.setEnabled(False)
- self.set_defaults_button.setEnabled(False)
- self.set_adc_delay_spinboxes_active(False)
- disable_wait_cursor()
- self.do_status_readout()
- def on_soft_reset(self):
- enable_wait_cursor()
- if not self._check_for_no_continuous_read():
- disable_wait_cursor()
- return
- try:
- logging.info("Soft-Resetting Board ...")
- heb.board.write_pci('0x1', '0x9040', hex_mask='0x1')
- time.sleep(1)
- heb.board.write_pci('0x0', '0x9040', hex_mask='0x1')
- except heb.board.BoardError as e:
- logging.error("Sequence failed: {}".format(str(e)))
- disable_wait_cursor()
- self.do_status_readout()
- return
- logging.info("Soft-Reset successful.")
- disable_wait_cursor()
- self.do_status_readout()
- return
- def disable_acquisition_input(self):
- self.start_button.setEnabled(False)
- self.acquire_button.setEnabled(False)
- def enable_acquisition_input(self):
- self.start_button.setEnabled(True)
- self.acquire_button.setEnabled(True)
- def set_adc_delay_spinboxes_active(self, value=True):
- self.th_delay_spinbox.setEnabled(value)
- self.adc_1_delay_spinbox.setEnabled(value)
- self.adc_2_delay_spinbox.setEnabled(value)
- self.adc_3_delay_spinbox.setEnabled(value)
- self.adc_4_delay_spinbox.setEnabled(value)
- def on_single_read(self):
- self.continuous_read_checkbox.setEnabled(False)
- self.disable_acquisition_input()
- self.read_data_and_safe()
- self.enable_acquisition_input()
- self.continuous_read_checkbox.setEnabled(True)
- def _set_continuous_read_active(self):
- self.start_button.setEnabled(False)
- self.acquire_button.setEnabled(False)
- self.scan_button.setEnabled(False)
- self.continuous_read = True
- def _set_continuous_read_inactive(self):
- if self.continuous_read:
- self.continuous_read = False
- self.timer.stop()
- self.start_button.setEnabled(True)
- self.acquire_button.setEnabled(True)
- self.scan_button.setEnabled(True)
- def on_continuous_read(self):
- if self.continuous_read_checkbox.isChecked():
- self._set_continuous_read_active()
- self.do_continuous_read()
- else:
- self._set_continuous_read_inactive()
- def do_continuous_read(self):
- self.timer = QtCore.QTimer()
- logging.info("Start continuous read")
- def continuous_read_step():
- if self.continuous_read:
- self.read_data()
- self.timer.start(self.continuous_read_interval_spinbox.value())
- else:
- self.timer.stop()
- self.timer.timeout.connect(continuous_read_step)
- self.timer.start(self.continuous_read_interval_spinbox.value())
- def read_and_update(self, read_func, *args):
- enable_wait_cursor()
- # Remove all references as soon as possible
- if self.data:
- del self.data
- self.data = None
- header = self.advanced_interface.control_table.get_bit(28)
- self.data = read_func(*args, force=self.args.force_read, header=header, cache=self.args.cache_data)
- if heb.io.is_data_consistent(self.data):
- self.data_consistency_led.set_color((0, 190, 0))
- else:
- self.data_consistency_led.set_color((255, 0, 0))
- if read_func is heb.io.read_from_file:
- self.error_text_area.write(str(args[0]))
- disable_wait_cursor()
- frm = self.from_spinbox.value()
- to = self.to_spinbox.value()
- self.canvas.update_figure(self.opt_widgets, self.data, frm, to)
- def read_and_update_data_from_file(self, filename):
- self.read_and_update(heb.io.read_from_file, str(filename))
- def read_and_update_data_from_string(self, raw_data):
- self.read_and_update(heb.io.read_from_string, raw_data)
- def read_data_and_safe(self):
- now = time.time()
- filename = '{:0.3f}.out'.format(now)
- try:
- simulate = self.simulate_checkbox.isChecked()
- heb.board.acquire_data(filename, simulate=simulate, duration=2.0)
- #heb.board.run_status('/home/heb/StatusComparison.sh')
- self.read_and_update_data_from_file(filename)
- except heb.board.BoardError as e:
- logging.error("Reading failed: {}".format(str(e)))
- def read_data(self):
- try:
- if self.simulate_checkbox.isChecked():
- heb.board.start_pilot_bunch_emulator()
- heb.board.start_acquisition()
- heb.board.wait_for_revolutions()
- heb.board.stop_acquisition()
- heb.board.enable_transfer()
- cmd = ['pci', '-r', 'dma0', '-o', '/dev/stdout', '--multipacket']
- data_raw = heb.board.safe_call(cmd)
- heb.board.flush_dma()
- # Sadly, the PCI software also outputs the Information, that it has
- # written data to the desired file. This is recorded by our
- # software and needs to be removed, so we split the returned string
- # at the 'Writting data to file blah, blah" Btw: YES this
- # 'Writting' is actually correct. No, i don't know why it is
- # grammatically wrong in the first place :D
- data_split = data_raw.split('Writting')[0]
- self.read_and_update_data_from_string(data_split)
- except heb.board.BoardError as e:
- logging.error("Reading failed: {}".format(str(e)))
- # return data
- def iterate_spectrograms(self, path):
- if not os.path.isdir("./"+str(path)):
- return
- transform = self.data.fft(1, frm=0, to=-1)
- for i in range(heb.BUNCHES_PER_TURN-1):
- filename = os.path.join(".", str(path), "%i.hsp" % i)
- write_header = False
- if not os.path.isfile(filename):
- write_header = True
- f = open(filename, 'ab')
- if write_header:
- f.write("#hsp\n") # heb spectrogram magic number
- #f.write(b'\x40') # 64bit
- #f.write('64') # 64bit
- #f.write(sytruct.pack('>I', self.number_of_skipped_orbits_spinbox.value()))
- f.write("#"+str(self.number_of_skipped_orbits_spinbox.value()))
- f.write("\n")
- line = transform[i,:]
- # f.write(struct.pack('>I', len(line)))
- #f.write(str(len(line)))
- f.write('{:0.3f} '.format(time.time()))
- #data = pArr('d', line)
- #data.tofile(f)
- for e in line:
- f.write("%s "%np.absolute(e))
- f.write("\n")
- f.close()
- def stop_acquisition(self):
- self.timer.stop()
- self.enable_acquisition_input()
- self.continuous_read_checkbox.setEnabled(True)
- self.acquisition_progressbar.reset()
- def on_acquire(self):
- self.disable_acquisition_input()
- self.continuous_read_checkbox.setEnabled(False)
- self.stop_button.setEnabled(True)
- self.timer = QtCore.QTimer()
- num_acquisitions = self.acquisitions_spinbox.value()
- self.acquisition_progressbar.setRange(1, num_acquisitions)
- spectrogram_dir = "./spectrograms_{:0.3f}".format(time.time())
- if self.spectrogram_checkbox.isChecked():
- os.mkdir(spectrogram_dir)
- # We increase already once because we do a single acquisition before the
- # timer is started, otherwise we have to wait until the timer fires the
- # first time.
- self.current_acquisition = 1
- self.read_data_and_safe()
- if self.spectrogram_checkbox.isChecked():
- self.iterate_spectrograms(spectrogram_dir)
- def on_timeout():
- if self.current_acquisition < num_acquisitions:
- self.current_acquisition += 1
- self.acquisition_progressbar.setValue(self.current_acquisition)
- self.read_data_and_safe()
- self.iterate_spectrograms(spectrogram_dir)
- else:
- self.stop_acquisition()
- self.timer.timeout.connect(on_timeout)
- self.timer.start(self.wait_time_spinbox.value() * 1000)
- def on_stop(self):
- self.stop_acquisition()
- def on_scan(self):
- c_frm = self.time_scan_coarse_from.value()
- c_to = self.time_scan_coarse_to.value()
- if c_frm > c_to:
- logging.info('Coarse Scan Interval is invalid: (%i > %i)' % (c_frm, c_to))
- return
- f_frm = self.time_scan_fine_from.value()
- f_to = self.time_scan_fine_to.value()
- if f_frm > f_to:
- logging.info('Fine Scan Interval is invalid: (%i > %i)' % (f_frm, f_to))
- return
- self.disable_acquisition_input()
- self.continuous_read_checkbox.setEnabled(False)
- self.scan_button.setEnabled(False)
- self.set_adc_delay_spinboxes_active(False)
- self.canvas.figure.clear()
- th_old = self.board_config.get('th_delay')
- adc_1_old = self.board_config.get('adc_1_delay')
- adc_2_old = self.board_config.get('adc_2_delay')
- adc_3_old = self.board_config.get('adc_3_delay')
- adc_4_old = self.board_config.get('adc_4_delay')
- minimum = [None, None, None, None]
- maximum = np.zeros((4, 3))
- heatmap = np.zeros((4, (f_to - f_frm + 1), (c_to - c_frm + 1)))
- self.timescan_progressbar.setRange(1, ((f_to - f_frm) + 1) * ((c_to - c_frm) + 1))
- self.stop_requested = False
- def time_scan_stop():
- self.stop_requested = True
- self.board_config.set_delay(th_old)
- self.board_config.set_chip_delay([0, 1, 2, 3], [adc_1_old, adc_2_old, adc_3_old, adc_4_old])
- self.enable_acquisition_input()
- self.continuous_read_checkbox.setEnabled(True)
- self.scan_button.setEnabled(True)
- self.scan_stop_button.setEnabled(False)
- self.set_adc_delay_spinboxes_active(True)
- self.timescan_progressbar.reset()
- self.scan_stop_button.clicked.connect(time_scan_stop)
- self.scan_stop_button.setEnabled(True)
- c_step = 0
- for coarse in range(c_frm, c_to + 1):
- try:
- self.board_config.set_delay(coarse)
- except heb.board.BoardError as e:
- QtGui.QMessageBox.critical(self, "Board communication", str(e))
- time_scan_stop()
- return
-
- f_step = 0
- for fine in range(f_frm, f_to + 1):
- self.board_config.set_chip_delay([0, 1, 2, 3], [fine, fine, fine, fine])
- try:
- if self.simulate_checkbox.isChecked() is True:
- heb.board.start_pilot_bunch_emulator()
- heb.board.start_acquisition()
- heb.board.wait_for_revolutions()
- heb.board.stop_acquisition()
- heb.board.enable_transfer()
- cmd = ['pci', '-r', 'dma0', '-o', '/dev/stdout', '--multipacket']
- data_raw = heb.board.safe_call(cmd)
- heb.board.flush_dma()
- #Sadly, the PCI software also outputs the Information, that it has written data to the desired file.
- #This is recorded by our software and needs to be removed, so we split the returned string at the
- # "Writting data to file blah, blah" string.
- #Btw: YES this 'Writting' is actually correct. Its a typo in the 'pci' driver...
- data_split = data_raw.split('Writting')[0]
- data = heb.io.read_from_string(data_split, force=True, cache=False)
- except heb.board.BoardError as e:
- QtGui.QMessageBox.critical(self, "Board communication", str(e))
- time_scan_stop()
- return
- for adc in range(4):
- buckets = data.array[:, adc:adc+1].reshape(-1)
- heatmap[adc, f_step, c_step] = float(buckets.sum())/buckets.shape[0]
- if heatmap[adc, f_step, c_step] > maximum[adc, 0]:
- maximum[adc, 0] = heatmap[adc, f_step, c_step]
- maximum[adc, 1] = coarse
- maximum[adc, 2] = fine
- if minimum[adc] is None or minimum[adc] > heatmap[adc, f_step, c_step]:
- minimum[adc] = heatmap[adc, f_step, c_step]
- self.timescan_progressbar.setValue(((c_step * (f_to - f_frm + 1)) + f_step) + 1)
- #GUI is blocked in our tight loop. Give it an opportunity to handle events
- QtGui.QApplication.processEvents()
- if self.stop_requested is True:
- # Time Scan Stop is already performed by button press. Nothing else to do but leave
- return
- f_step += 1
- c_step += 1
- self.canvas.figure.clear()
- self.canvas.figure.suptitle("Timing Analysis")
- if True:
- now = time.time()
- filename = 'timescan_{:0.3f}.out'.format(now)
- f = open(filename, 'wr')
- for adc in range(4):
- if True:
- f.write("#ADC_%s\n" % adc)
- for coarse, curr_cor in enumerate(np.transpose(heatmap[adc])):
- for fine, value in enumerate(curr_cor):
- f.write("%i;%i;%f\n" % ((coarse+c_frm), (fine+f_frm), value))
- f.write('\n')
- axis = self.canvas.figure.add_subplot(2, 2, adc+1)
- image = axis.imshow(heatmap[adc, :, :], interpolation='nearest', aspect='auto')
- axis.set_xticks(range((c_to - c_frm) + 1))
- axis.set_xticklabels(range(c_frm, c_to + 1))
- axis.set_yticks(range((f_to - f_frm) + 1))
- axis.set_yticklabels(range(f_frm, f_to + 1))
- axis.invert_yaxis()
- if adc > 1:
- axis.set_xlabel('Coarse Delay')
- if adc is 0 or adc is 2:
- axis.set_ylabel('Fine Delay')
- axis.set_title("ADC_%i, C:%i, F:%i" % (adc+1, maximum[adc, 1], maximum[adc, 2]))
- if True:
- f.close()
- f = open(filename+'.gnuplot', 'wr')
- f.write('set datafile separator ";"\n')
- f.write('set multiplot layout 2,2\n')
- f.write('unset key\n')
- for i in range(4):
- f.write('set label 1 "ADC_%i" at graph 0.7,0.95 font ",8"\n'%(i+1))
- f.write('plot "%s" every :::%i::%i using 3 with lines\n'%(filename, i, i))
- f.write('unset multiplot\n')
- f.close()
- bar_axis = self.canvas.figure.add_axes([0.85, 0.15, 0.05, 0.7])
- self.canvas.figure.subplots_adjust(right=0.8)
- self.canvas.figure.colorbar(image, cax=bar_axis)
- self.canvas.draw()
- time_scan_stop()
- def on_to_changed(self, value):
- if value > 0:
- self.from_spinbox.setMaximum(value - 1)
- self.on_option_change()
- def on_option_change(self):
- frm = self.from_spinbox.value()
- to = self.to_spinbox.value()
- enable_wait_cursor()
- self.canvas.update_figure(self.opt_widgets, self.data, frm, to)
- disable_wait_cursor()
- def on_adc_delay_changed(self):
- try:
- self.board_config.set_delay(self.th_delay_spinbox.value())
- factors = [self.adc_1_delay_spinbox.value(), self.adc_2_delay_spinbox.value(),
- self.adc_3_delay_spinbox.value(), self.adc_4_delay_spinbox.value()]
- self.board_config.set_chip_delay([0, 1, 2, 3], factors)
- except heb.board.BoardError as e:
- logging.error("ADC fine delay failed: {}".format(str(e)))
- self.do_status_readout()
- return
- def on_number_of_orbits_changed(self):
- number = self.number_of_orbits_spinbox.value()
- hex_str = hex(number)
- try:
- heb.board.write_pci(hex_str, '0x9020')
- except heb.board.BoardError as e:
- logging.error("Setting orbits failed: {}".format(str(e)))
- self.do_status_readout()
- return
- def on_number_of_skipped_orbits_changed(self):
- number = self.number_of_skipped_orbits_spinbox.value()
- hex_str = hex(number)
- try:
- heb.board.write_pci(hex_str, '0x9028')
- except heb.board.BoardError as e:
- logging.error("Could not set ob skipped orbits due to an error!")
- self.do_status_readout()
- return
- def on_open(self):
- filename = QtGui.QFileDialog.getOpenFileName(self, 'Open Datafile', '')
- if filename:
- self.read_and_update_data_from_file(filename)
- def on_open_config(self):
- filename = QtGui.QFileDialog.getOpenFileName(self, 'Open Configuration', '')
- if filename:
- self.board_config.load_config(filename)
- self.on_set_defaults()
- def on_save_config(self):
- filename = QtGui.QFileDialog.getSaveFileName(self, 'Save Configuration', '')
- if filename:
- self.board_config.save_config(filename)
- def on_close(self):
- self.close()
- def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('-i', '--input', metavar='FILE', type=str,
- help="HEB file")
- parser.add_argument('-c', '--config', metavar='FILE', type=str,
- help="Board Configuration File")
- parser.add_argument('--force-read', action='store_true',
- help="Ignore cache and force re-computation.")
- parser.add_argument('--check', action='store_true',
- help="Check contents of file before proceeding")
- parser.add_argument('--cache-data', action='store_true',
- help="Save already processed NumPy arrays")
- parser.add_argument('-v', '--verbose', action='store_true',
- help="Increase verbosity.")
- args = parser.parse_args()
- if args.verbose:
- logging.basicConfig(level=logging.DEBUG)
- else:
- logging.basicConfig(level=logging.INFO)
- app = QtGui.QApplication(sys.argv)
- window = ApplicationWindow(args)
- window.show()
- try:
- window.do_status_readout()
- except heb.board.BoardError as e:
- QtGui.QMessageBox.critical(window, "Board Communication Error",
- "Could not communicate with the Board!\nError was: 'pci' " + str(e)
- + "\nMake sure the HEB Board is connected correctly and run 'Check Status'.")
- sys.exit(app.exec_())
- if __name__ == '__main__':
- main()
|