"""Independent complementary transistor input timing; no ACK/Vstat dependency.""" import math from .gate_timing import InputTimingChecker, format_ns class PairTimingChecker(InputTimingChecker): def __init__(self, samplerate, vin1_active_high=True, vin2_active_high=True, vin1_mintime_ns=0, vin2_mintime_ns=0, deadtime_12_ns=0, deadtime_21_ns=0, vin1_minoff_ns=0, vin2_minoff_ns=0): super().__init__(samplerate, vin1_active_high, vin2_active_high, vin1_mintime_ns, vin2_mintime_ns) self.deadtime_min = (float(deadtime_12_ns), float(deadtime_21_ns)) self.minoff = (float(vin1_minoff_ns), float(vin2_minoff_ns)) if any(not math.isfinite(v) or v < 0 for v in self.deadtime_min + self.minoff): raise ValueError('Timing limits must be finite and non-negative') self.last_on = [None, None] self.last_off = [None, None] def update(self, sample, vin1, vin2): sample = int(sample) previous = self.levels[:] if self.levels is not None else None events = super().update(sample, vin1, vin2) for event in events: if event['kind'] == 'deadtime': source = event['from_channel'] - 1 limit = self.deadtime_min[source] if event['duration_ns'] < limit: event['kind'] = 'deadtime_fail' event['text'] = 'FAULT: ' + event['text'] + ' < minimum ' + format_ns(limit) event['short'] = 'FAULT: deadtime' if previous is None: return events for i in range(2): if previous[i] and not self.levels[i]: self.last_off[i] = sample elif not previous[i] and self.levels[i]: off = self.last_off[i] on = self.last_on[i] if off is not None: duration = (sample - off) * 1e9 / self.samplerate failed = duration < self.minoff[i] events.append(self._event('off_fail' if failed else 'off_time', off, sample, '%s: Vin%d OFF (minimum %s)' % ('FAULT' if failed else 'OK', i + 1, format_ns(self.minoff[i])), channel=i+1)) if on is not None and off is not None and on < off < sample: period = sample - on frequency = self.samplerate / period duty = 100.0 * (off - on) / period text = 'Vin%d: period %s, %.3f Hz, duty %.2f%%' % ( i + 1, format_ns(period * 1e9 / self.samplerate), frequency, duty) events.append(dict(kind='period', start=on, end=sample, text=text, short='%.3f Hz / %.2f%%' % (frequency, duty), channel=i+1, frequency_hz=frequency, duty_percent=duty)) self.last_on[i] = sample return events