aboutsummaryrefslogtreecommitdiff
path: root/qolab/hardware
diff options
context:
space:
mode:
Diffstat (limited to 'qolab/hardware')
-rw-r--r--qolab/hardware/scope/sds800xhd.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/qolab/hardware/scope/sds800xhd.py b/qolab/hardware/scope/sds800xhd.py
index 436254f..fabf43e 100644
--- a/qolab/hardware/scope/sds800xhd.py
+++ b/qolab/hardware/scope/sds800xhd.py
@@ -167,6 +167,75 @@ class SDS800XHD(SDS1104X):
trRaw.config["tags"]["rawChanConfig"] = rawChanCfg
return trRaw
+ def getParsedPreamble(self):
+ """
+ Parse preamble generated by the scope.
+ It has a lot of information, number of points, scale, bits resolution, etc.
+
+ Note: preamble is channel specific! The prior code must set desired channel
+ with self.write(":WAVeform:SOURce C{chNum}")
+ """
+ preamble = {}
+ qstr = ":WAVeform:PREamble?"
+ if self.resource.interface_type == InterfaceType.usb:
+ # Setting chunk size to 496 bytes, it seems that SDS sends data
+ # in 512 bytes chunks via USB.
+ # Which is 8 packets of 64 bytes, but each packet takes 2 bytes for a header.
+ # Thus useful payload is 512-8*2 = 496
+ # see https://patchwork.ozlabs.org/project/qemu-devel/patch/20200317095049.28486-4-kraxel@redhat.com/
+ # Setting chunk_size for a large number has *catastrophic* results
+ # on data transfer rate, since we wait for more data
+ # which is not going to come until timeout expires
+ resp_bin = self.query_binary_values(
+ qstr,
+ datatype="c",
+ header_fmt="ieee",
+ container=np.array,
+ chunk_size=496,
+ )
+ else:
+ resp_bin = self.query_binary_values(
+ qstr, datatype="c", header_fmt="ieee", container=np.array
+ )
+ preamble["Npoints"] = resp_bin[116:120].view(np.int32).item()
+ preamble["firstPoint"] = resp_bin[132:136].view(np.int32).item()
+ preamble["sparsing"] = resp_bin[136:140].view(np.int32).item()
+ preamble["voltsPerDiv"] = resp_bin[156:160].view(np.float32).item()
+ preamble["verticalOffset"] = resp_bin[160:164].view(np.float32).item()
+ preamble["codePerDiv"] = resp_bin[164:168].view(np.float32).item()
+ preamble["adcBit"] = resp_bin[172:174].view(np.int16).item()
+ preamble["samplingTime"] = resp_bin[176:180].view(np.float32).item()
+ preamble["trigDelay"] = (
+ -resp_bin[180:188].view(np.float64).item()
+ ) # manual is wrong, it claims that this int64
+
+ return preamble, resp_bin
+
+ def getWaveform(
+ self, chNum, availableNpnts=None, maxRequiredPoints=None, decimate=True
+ ):
+ """
+ For decimate use see ``getRawWaveform``.
+
+ In short decimate=True is slower but more precise.
+ """
+ trRaw = self.getRawWaveform(
+ chNum,
+ availableNpnts=availableNpnts,
+ maxRequiredPoints=maxRequiredPoints,
+ decimate=decimate,
+ )
+ preamble = self.getParsedPreamble()
+ VoltageOffset = preamble["verticalOffset"]
+ VoltsPerDiv = preamble["voltsPerDiv"]
+ tr = trRaw
+ tr.values = trRaw.values * VoltsPerDiv / preamble["codePerDiv"] - VoltageOffset
+ tr.config["unit"] = "Volt"
+ tr.config["tags"]["VoltageOffset"] = VoltageOffset
+ tr.config["tags"]["VoltsPerDiv"] = VoltsPerDiv
+ tr.config["tags"]["Preamble"] = preamble
+ return tr
+
if __name__ == "__main__":
import pyvisa