"""Two-input transistor pair analyzer, independent of driver feedback.""" import sigrokdecode as srd from common.setgui_decoders.transistor_pair import PairTimingChecker class Decoder(srd.Decoder): api_version = 3 id = 'transistor_pair' name = 'Transistor pair' longname = 'Transistor pair: mintime / deadtime / overlap' desc = 'Checks ON/OFF pulse limits, deadtime, overlap, frequency and duty.' license = 'gplv2+' inputs = ['logic'] outputs = [] tags = ['Clock/timing', 'Util'] channels = ( {'id': 'vin1', 'name': 'Vin1', 'desc': 'First transistor command'}, {'id': 'vin2', 'name': 'Vin2', 'desc': 'Second transistor command'}, ) options = ( {'id': 'vin1_active', 'desc': 'Vin1 active level', 'default': 'high', 'values': ('high', 'low')}, {'id': 'vin2_active', 'desc': 'Vin2 active level', 'default': 'high', 'values': ('high', 'low')}, {'id': 'vin1_mintime_ns', 'desc': 'Vin1 minimum ON time (ns)', 'default': 0}, {'id': 'vin2_mintime_ns', 'desc': 'Vin2 minimum ON time (ns)', 'default': 0}, {'id': 'vin1_minoff_ns', 'desc': 'Vin1 minimum OFF time (ns)', 'default': 0}, {'id': 'vin2_minoff_ns', 'desc': 'Vin2 minimum OFF time (ns)', 'default': 0}, {'id': 'deadtime_12_ns', 'desc': 'Minimum deadtime Vin1 -> Vin2 (ns)', 'default': 0}, {'id': 'deadtime_21_ns', 'desc': 'Minimum deadtime Vin2 -> Vin1 (ns)', 'default': 0}, ) annotations = ( ('vin1-on', 'Vin1 ON duration'), ('vin2-on', 'Vin2 ON duration'), ('deadtime', 'Deadtime'), ('failure', 'FAULT'), ('vin1-off', 'Vin1 OFF duration'), ('vin2-off', 'Vin2 OFF duration'), ('vin1-period', 'Vin1 period / frequency / duty'), ('vin2-period', 'Vin2 period / frequency / duty'), ) annotation_rows = ( ('deadtime', 'Deadtime', (2,)), ('faults', 'FAULT: overlap / timing', (3,)), ('vin1', 'Vin1 mintime / OFF', (0, 4)), ('vin2', 'Vin2 mintime / OFF', (1, 5)), ('pwm1', 'Vin1 period / frequency / duty', (6,)), ('pwm2', 'Vin2 period / frequency / duty', (7,)), ) def __init__(self): self.reset() def reset(self): self.samplerate = None self.checker = None def metadata(self, key, value): if key == srd.SRD_CONF_SAMPLERATE: self.samplerate = value def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) def _put_events(self, events): for event in events: kind = event['kind'] channel = event.get('channel', 1) - 1 ann = (3 if kind in ('mintime_fail', 'deadtime_fail', 'off_fail', 'overlap') else 2 if kind == 'deadtime' else channel if kind == 'mintime_ok' else 4 + channel if kind == 'off_time' else 6 + channel) self.put(event['start'], event['end'], self.out_ann, [ann, [event['text'], event['short']]]) def decode(self): if not self.samplerate: raise ValueError('Cannot decode without samplerate.') if not self.has_channel(0) or not self.has_channel(1): raise ValueError('Connect both Vin1 and Vin2.') numeric = {name: self.options[name] for name in ( 'vin1_mintime_ns', 'vin2_mintime_ns', 'vin1_minoff_ns', 'vin2_minoff_ns', 'deadtime_12_ns', 'deadtime_21_ns')} self.checker = PairTimingChecker(self.samplerate, self.options['vin1_active'] == 'high', self.options['vin2_active'] == 'high', **numeric) # Do not retain DSView's mutable native wait tuple. pins = list(self.wait({})) self._put_events(self.checker.update(self.samplenum, *pins)) while True: pins = list(self.wait([{0: 'e'}, {1: 'e'}])) self._put_events(self.checker.update(self.samplenum, *pins)) def end(self): if self.checker is not None: self._put_events(self.checker.finish(self.samplenum))