Skip to content
Snippets Groups Projects
Commit eafb5add authored by Guenter Quast's avatar Guenter Quast
Browse files

rpOsci.py: added a data acquistion mode

parent 63085462
Branches
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OscDisplay</class>
<widget class="QWidget" name="OscDisplay">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="plotWidget" native="true">
<layout class="QVBoxLayout" name="plotLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="controlWidget" native="true">
<layout class="QVBoxLayout" name="controlLayout">
<item>
<spacer name="spacer_0">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="cursorWidget" native="true">
<layout class="QGridLayout" name="cursorLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="ch1Label">
<property name="text">
<string>channel 1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="ch1Value">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="ch2Label">
<property name="text">
<string>channel 2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="ch2Value">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="timeLabel">
<property name="text">
<string>time axis</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="timeValue">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="spacer_1">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="modeLabel">
<property name="text">
<string>trigger mode</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="modeWidget" native="true">
<layout class="QHBoxLayout" name="modeLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="normalButton">
<property name="text">
<string>normal</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="autoButton">
<property name="text">
<string>auto</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="sourceLabel">
<property name="text">
<string>trigger source</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="sourceWidget" native="true">
<layout class="QHBoxLayout" name="sourceLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="ch1Button">
<property name="text">
<string>channel 1</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="ch2Button">
<property name="text">
<string>channel 2</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="slopeLabel">
<property name="text">
<string>trigger slope</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="slopeWidget" native="true">
<layout class="QHBoxLayout" name="slopeLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QRadioButton" name="risingButton">
<property name="text">
<string>rising</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="fallingButton">
<property name="text">
<string>falling</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="levelLabel">
<property name="text">
<string>trigger level</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="levelValue">
<property name="minimum">
<number>-4090</number>
</property>
<property name="maximum">
<number>4090</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>500</number>
</property>
</widget>
</item>
<item>
<spacer name="spacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="startButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="startDAQButton">
<property name="text">
<string>Start DAQ</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="loadButton">
<property name="text">
<string>Load</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
......@@ -6,7 +6,6 @@
This code is compatible with release 20240204 of the alpine linux image
https://github.com/pavel-demin/red-pitaya-notes/releases/tag/20240204
"""
# Communication with server process is achieved via command codes:
......@@ -33,7 +32,6 @@
# code 29: start generator
# code 30: stop generator
import argparse
import os
import sys
......@@ -65,7 +63,7 @@ else:
Ui_MCPHA, QMainWindow = loadUiType("rpControl.ui")
Ui_LogDisplay, QWidget = loadUiType("mcpha_log.ui")
Ui_OscDisplay, QWidget = loadUiType("mcpha_osc.ui")
Ui_OscDisplay, QWidget = loadUiType("mcpha_daq.ui")
Ui_GenDisplay, QWidget = loadUiType("mcpha_gen.ui")
if sys.platform != "win32":
......@@ -123,7 +121,7 @@ class rpControl(QMainWindow, Ui_MCPHA):
self.startTimer = QTimer(self) # timer for network connectin
self.startTimer.timeout.connect(self.start_timeout)
self.readTimer = QTimer(self) # for readout
self.readTimer.timeout.connect(self.read_osci)
self.readTimer.timeout.connect(self.update_oscDisplay)
# transfer command-line arguments to gui
self.osc.levelValue.setValue(self.trigger_level)
......@@ -226,7 +224,7 @@ class rpControl(QMainWindow, Ui_MCPHA):
self.set_negator(0, self.neg1Check.isChecked())
self.set_negator(1, self.neg2Check.isChecked())
#
# finally, start readout timer calling read_osci()
# finally, start readout timer calling update_oscDisplay()
self.readTimer.start(self.readInterval)
def command(self, code, number, value):
......@@ -243,7 +241,7 @@ class rpControl(QMainWindow, Ui_MCPHA):
view[:] = np.frombuffer(self.socket.read(size), np.uint8)
return True
def read_osci(self):
def update_oscDisplay(self):
"""data transfer from RP, triggered by QTimer readTimer
"""
if self.osc_reset:
......@@ -267,9 +265,39 @@ class rpControl(QMainWindow, Ui_MCPHA):
self.log.print("failed to read oscilloscope data")
return
def start_oscDaq(self):
"""continuous data transfer from RedPitaya
"""
# depends on
# self.setup_redPdaq()
# osc.process_data()
self.osc.setup_redPdaq()
if self.osc_reset:
self.reset_osc()
if self.osc_start:
self.start_osc()
while self.daq_waiting:
# check status
self.read_status()
if not self.read_data(self.status):
self.log.print("failed to read status")
return
if not self.status[8] & 1:
self.command(20, 0, 0) # read oscilloscope data
if self.read_data(self.osc.buffer):
## self.osc.update()
self.osc.process_data()
self.reset_osc()
self.start_osc()
else:
self.log.print("failed to read oscilloscope data")
return
def mark_start_osc(self):
self.osc_start = True
self.osc_waiting = True
# self.osc_waiting = True
def mark_reset_osc(self):
self.osc_reset = True
......@@ -288,6 +316,7 @@ class rpControl(QMainWindow, Ui_MCPHA):
def stop_osc(self):
self.reset_osc()
self.osc_waiting = False
self.daq_waiting = False
def set_rate(self, index):
# set RP decimation factor
......@@ -383,6 +412,9 @@ class OscDisplay(QWidget, Ui_OscDisplay):
functions=(self.adc2mV, self.mV2adc))
self.ax_y2.set_ylabel("Voltage [mV]", color='grey', size='x-large')
# gq end
self.osctxt= self.ax.text(0.1, 0.96, ' ', transform=self.ax.transAxes,
color="darkblue", alpha=0.7)
x = np.arange(self.tot)
(self.curve2,) = self.ax.plot(x, self.buffer[1::2],
color="#00CCCC", label="chan 2")
......@@ -421,6 +453,7 @@ class OscDisplay(QWidget, Ui_OscDisplay):
self.fallingButton.toggled.connect(self.rpControl.set_trg_slope)
self.levelValue.valueChanged.connect(self.set_trg_level)
self.startButton.clicked.connect(self.start)
self.startDAQButton.clicked.connect(self.rpControl.start_oscDaq)
self.saveButton.clicked.connect(self.save)
self.loadButton.clicked.connect(self.load)
self.canvas.mpl_connect("motion_notify_event", self.on_motion)
......@@ -471,16 +504,87 @@ class OscDisplay(QWidget, Ui_OscDisplay):
self.log.print("oscilloscope started")
# toggle startButton: turn to 'Stop'
self.startButton.setText("Stop")
self.startButton.setStyleSheet("color: red")
self.startButton.clicked.disconnect()
self.startButton.clicked.connect(self.stop)
self.startDAQButton.setEnabled(False)
def setup_redPdaq(self):
"""start oscilloscope in daq mode
"""
if self.rpControl.idle:
return
# statisics
self.NTrig = 0
self.dN = 0
self.Nprev = self.NTrig
self.T0 = time.time()
self.Tprev = self.T0
self.dT = 0.
# extract parameters from gui
self.trg_mode = int(self.autoButton.isChecked())
self.trg_source = int(self.ch2Button.isChecked())
self.trg_slope = int(self.fallingButton.isChecked())
self.trg_level = self.levelValue.value()
self.rpControl.set_trg_mode(self.trg_mode)
self.rpControl.set_trg_source(self.trg_source)
self.rpControl.set_trg_slope(self.trg_slope)
self.rpControl.set_trg_level(self.trg_level)
self.rpControl.set_osc_pre(self.pre)
self.rpControl.set_osc_tot(self.tot)
self.rpControl.mark_reset_osc()
self.rpControl.mark_start_osc()
self.rpControl.osc_waiting = False
self.rpControl.daq_waiting = True
self.log.print("daq started")
# toggle startButton: turn to 'Stop'
self.startButton.setText("Stop")
self.startButton.setStyleSheet("color: red")
self.startButton.clicked.disconnect()
self.startButton.clicked.connect(self.stop)
self.startDAQButton.setEnabled(False)
def stop(self):
self.rpControl.stop_osc()
self.startButton.setText("Start")
self.startButton.setStyleSheet("color: black")
self.startButton.clicked.disconnect()
self.startButton.clicked.connect(self.start)
self.startDAQButton.setEnabled(True)
self.log.print("oscilloscope stopped")
def process_data(self):
# count number of Triggers and keep account of timing
self.NTrig += 1
t = time.time()
dt = t - self.Tprev
self.Tprev = t
self.dT += dt
# copy data
chan1 = self.buffer[0::2]
chan2 = self.buffer[1::2]
#
# do something with data (e.g. pass to sub-process via mpQueue)
#
# ....
#
# output status once per second
if self.dT >= 1.:
dN = self.NTrig - self.Nprev
r = dN/self.dT
self.Nprev = self.NTrig
T_active = t - self.T0
self.dT = 0.
status_txt = "active: {:.1f}s Trigger rate: {:.2f} Hz, Data Rate: {:.4g} MB/s".format(T_active, r, 4*r*len(chan1)*1e-6)
print(status_txt, end='\r')
self.osctxt.set_text(status_txt)
# update graph on display
self.curve1.set_ydata(chan1)
self.curve2.set_ydata(chan2)
self.xunit = "[{:d} ns / sample]".format(8*rpControl.rates[self.rpControl.rateValue.currentIndex()])
self.ax.set_xlabel("sample number " + self.xunit)
self.canvas.draw()
def update(self):
self.curve1.set_ydata(self.buffer[0::2])
self.curve2.set_ydata(self.buffer[1::2])
......@@ -658,7 +762,7 @@ def runQt():
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
if __name__ == '__main__': # --------------------------------------------
# run the application with Qt5 interface
runQt()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment