diff options
author | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2024-10-11 23:31:50 -0400 |
---|---|---|
committer | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2024-10-11 23:31:50 -0400 |
commit | 12b448386d965996e75466a05af1cef700d449ea (patch) | |
tree | 1334fa673ff851f64da918fabc8fa6deb19f3248 /qolab/hardware/scope | |
parent | 36aaf315c48238e9d9b2e0924594506dba105c24 (diff) | |
download | qolab-12b448386d965996e75466a05af1cef700d449ea.tar.gz qolab-12b448386d965996e75466a05af1cef700d449ea.zip |
implement getTrace and channel preamble parser
Diffstat (limited to 'qolab/hardware/scope')
-rw-r--r-- | qolab/hardware/scope/sds800xhd.py | 69 |
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 |