From 3ad975dfc9fe67d03c9edf2e0b40fce2415a1c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 22 Feb 2018 13:42:59 +0100 Subject: [PATCH] fcap updated --- gex/units/FCAP.py | 214 +++++++++++++++++++++++++++++++++++++++++----- pcap.py | 35 ++++++-- 2 files changed, 223 insertions(+), 26 deletions(-) diff --git a/gex/units/FCAP.py b/gex/units/FCAP.py index a951519..825cc47 100644 --- a/gex/units/FCAP.py +++ b/gex/units/FCAP.py @@ -1,26 +1,59 @@ import gex CMD_STOP = 0 -CMD_PWM_CONT_START = 1 -CMD_PWM_BURST_START = 2 -CMD_PWM_CONT_READ = 10 + +# Measuring a waveform +CMD_INDIRECT_CONT_START = 1 # keep measuring, read on demand +CMD_INDIRECT_BURST_START = 2 # wait and reply + +# Counting pulses +CMD_DIRECT_CONT_START = 3 # keep measuring, read on demand +CMD_DIRECT_BURST_START = 4 # wait and reply +CMD_FREECOUNT_START = 5 # keep counting pulses until stopped, read on reply + +CMD_MEASURE_SINGLE_PULSE = 6 +CMD_FREECOUNT_CLEAR = 7 + +# Results readout for continuous modes +CMD_INDIRECT_CONT_READ = 10 +CMD_DIRECT_CONT_READ = 11 +CMD_FREECOUNT_READ = 12 + +CMD_SET_POLARITY = 20 +CMD_SET_DIR_PRESC = 21 +CMD_SET_INPUT_FILTER = 22 +CMD_SET_DIR_MSEC = 23 + +CMD_RESTORE_DEFAULTS = 30 + class FCAP_Report: def __init__(self): - self.period = 0 - self.ontime = 0 - self.frequency = 0 - self.duty = 0 + self.period = None # s + self.ontime = None # s + self.frequency = None # Hz + self.duty = None # [-] # Raw data (can be used to avoid distortion by float arithmetics) - self.period_raw = 0 - self.ontime_raw = 0 - self.sample_count = 0 - self.clock_freq = 0 + self.period_raw = None + self.ontime_raw = None + self.sample_count = None + self.clock_freq = None # Hz + self.meas_time_ms = None def __str__(self): - return "{\n f = %f Hz\n T = %f s\n Ton = %f s\n duty = %f\n}" % \ - (self.frequency, self.period, self.ontime, self.duty) + s = "{\n" + if self.frequency is not None: + s += " f = %f Hz\n" % self.frequency + if self.period is not None: + s += " T = %f s\n" % self.period + if self.ontime is not None: + s += " Ton = %f s\n" % self.ontime + if self.duty is not None: + s += " duty = %f\n" % self.duty + s += "}" + + return s class FCAP(gex.Unit): """ @@ -34,17 +67,95 @@ class FCAP(gex.Unit): """ Stop any ongoing capture """ self._send(CMD_STOP, confirm=confirm) + def configure(self, + polarity=None, + presc=None, + filter=None, + msec=None, + confirm=True): + """ + Re-configure some capture parameters. None = unchanged + + polarity: 0,1 active level + presc: 1,2,4,8 pulse counter prescaller + filter: 0-15 digital input filter + msec: <65535 milliseconds for direct capture + """ + + if polarity is not None: + pb = gex.PayloadBuilder() + pb.u8(polarity) # 0,1 + self._send(CMD_SET_POLARITY, pld=pb.close(), confirm=confirm) + + if presc is not None: + pb = gex.PayloadBuilder() + pb.u8(presc) + self._send(CMD_SET_DIR_PRESC, pld=pb.close(), confirm=confirm) + + if filter is not None: + pb = gex.PayloadBuilder() + pb.u8(filter) + self._send(CMD_SET_INPUT_FILTER, pld=pb.close(), confirm=confirm) + + if msec is not None: + pb = gex.PayloadBuilder() + pb.u16(msec) + self._send(CMD_SET_DIR_MSEC, pld=pb.close(), confirm=confirm) + + def config_reset(self, confirm=True): + """ Reset all config to persistent defaults and switch to IDLE mode. """ + self._send(CMD_RESTORE_DEFAULTS, confirm=confirm) + def indirect_start(self, confirm=True): """ Start continuous PWM measurement """ - self._send(CMD_PWM_CONT_START, confirm=confirm) + self._send(CMD_INDIRECT_CONT_START, confirm=confirm) + + def counter_start(self, presc=None, confirm=True): + """ Start the free-running counter """ + + pb = gex.PayloadBuilder() + pb.u8(presc or 0) + self._send(CMD_FREECOUNT_START, pld=pb.close(), confirm=confirm) + + def counter_read(self): + """ Read the free counter value """ + + resp = self._query(CMD_FREECOUNT_READ) + pp = gex.PayloadParser(resp.data) + return pp.u32() + + def counter_clear(self): + """ + Restart the free-running counter, returns current value before the clear. + This should lose at most 1 tick for signals where f < core clock speed + """ + + resp = self._query(CMD_FREECOUNT_CLEAR) + pp = gex.PayloadParser(resp.data) + return pp.u32() + + def direct_start(self, msec=None, presc=None, confirm=True): + """ + Start continuous PWM measurement + + msec - measurement time (ms), <65535 + presc - pre-divider, 1,2,4,8. + + arg None = unchanged + """ + + pb = gex.PayloadBuilder() + pb.u16(msec or 0) + pb.u8(presc or 0) + self._send(CMD_DIRECT_CONT_START, pld=pb.close(), confirm=confirm) def indirect_read(self): """ - Read the current continuous measurement values - Returns value of the last measurement in continuous mode + Read the current indirect continuous measurement values + Returns value of the last measurement in continuous indirect mode """ - resp = self._query(CMD_PWM_CONT_READ) + resp = self._query(CMD_INDIRECT_CONT_READ) pp = gex.PayloadParser(resp.data) mhz = pp.u16() @@ -65,11 +176,59 @@ class FCAP(gex.Unit): # returned in microseconds return rp - def indirect_single(self, timeout=5): + def _process_direct_resp(self, resp): + pp = gex.PayloadParser(resp.data) + + presc = pp.u8() + msec = pp.u16() + count = pp.u32() * presc + + rp = FCAP_Report() + + if count > 0: + sec = msec / 1000 + freq = count / sec + period = 1 / freq + + rp.period = period + rp.frequency = freq + + rp.sample_count = count * presc + rp.meas_time_ms = msec + + return rp + + def direct_read(self): """ - Perform a burst measure with averaging (sum/count) + Read the current direct continuous measurement values + Returns value of the last measurement in continuous direct mode + """ + + resp = self._query(CMD_DIRECT_CONT_READ) + return self._process_direct_resp(resp) + + def measure_pulse(self, polarity=None, timeout=5): """ - return self.indirect_burst(count=1, timeout=timeout) + Measure a pulse. Optionally set polarity + """ + + if polarity is not None: + self.configure(polarity=polarity) + + resp = self._query(CMD_MEASURE_SINGLE_PULSE, timeout=timeout) + pp = gex.PayloadParser(resp.data) + + mhz = pp.u16() + ontime = pp.u32() + + rp = FCAP_Report() + rp.ontime = ontime / (mhz * 1e6) # in seconds + + rp.clock_freq = mhz * 1e6 + rp.sample_count = 1 + rp.ontime_raw = ontime + + return rp def indirect_burst(self, count, timeout=5): """ @@ -79,7 +238,7 @@ class FCAP(gex.Unit): pb = gex.PayloadBuilder() pb.u16(count) - resp = self._query(CMD_PWM_BURST_START, pld=pb.close(), timeout=timeout) + resp = self._query(CMD_INDIRECT_BURST_START, pld=pb.close(), timeout=timeout) pp = gex.PayloadParser(resp.data) mhz = pp.u16() @@ -100,3 +259,16 @@ class FCAP(gex.Unit): return rp + def direct_burst(self, msec=1000, presc=None): + """ + Perform direct burst measurement + """ + + pb = gex.PayloadBuilder() + pb.u16(msec) + pb.u8(presc or 0) + + resp = self._query(CMD_DIRECT_BURST_START, + pld=pb.close(), + timeout=(msec/1000)+1) + return self._process_direct_resp(resp) diff --git a/pcap.py b/pcap.py index 381466c..ca38a66 100644 --- a/pcap.py +++ b/pcap.py @@ -6,13 +6,38 @@ with gex.Client(gex.TrxRawUSB()) as client: fcap = gex.FCAP(client, 'fcap') fcap.stop() + fcap.indirect_start() + # + time.sleep(2) + print(fcap.indirect_read()) + + # fcap.stop() + # #print(fcap.indirect_burst(3, timeout=20)) + + # r=fcap.indirect_burst(1000, timeout=5) + # print(r) + # print(r.period_raw) + + # fcap.configure(filter=0) - while True: - time.sleep(1) - print(fcap.indirect_read()) - #print(fcap.indirect_burst(3, timeout=20)) + # print(fcap.measure_pulse()) - # print(fcap.indirect_burst(10, timeout=20)) + # print(fcap.direct_burst(10)) + # + # fcap.direct_start(1000, 0) + # time.sleep(2) + # + # print(fcap.direct_read()) + # + # fcap.counter_start() + # time.sleep(1) + # print(fcap.counter_clear()) + # time.sleep(1) + # print(fcap.counter_read()) + # time.sleep(1) + # print(fcap.counter_clear()) + # time.sleep(1) + # print(fcap.counter_clear())