57 lines
2.9 KiB
Python
57 lines
2.9 KiB
Python
"""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
|