#!/usr/bin/env python3 import csv import subprocess import io import itertools import warnings import statistics import time count = lambda le_iter: sum(1 for _ in le_iter) DEFAULT_SAMPLING_RATE = 1e6 # sps def sigrok_capture(duration:'milliseconds', sampling_rate=DEFAULT_SAMPLING_RATE, driver='dreamsourcelab-dslogic', config=None, channel=0): proc = subprocess.run(['sigrok-cli', '--driver', driver, '--time', f'{duration}ms', '--config', (f'{config},' if config else '') + f'samplerate={int(sampling_rate/1e3)}k', '--channels', str(channel), '--output-format', 'csv'], check=True, stdout=subprocess.PIPE) lines = proc.stdout.splitlines() return lines[lines.index(b'logic')+1:] def debounce(lines, sampling_rate=DEFAULT_SAMPLING_RATE, debounce_interval=1e-3): debounce_len = debounce_interval * sampling_rate cumline = None cumsum = None for line, group in itertools.groupby(lines): group_len = count(group) if cumline is None: cumline, cumsum = line, group_len if group_len < debounce_len: cumsum += group_len else: yield bool(int(cumline.decode())), cumsum cumline, cumsum = line, group_len yield bool(int(cumline.decode())), cumsum def calc_frequency(intervals, sampling_rate=DEFAULT_SAMPLING_RATE): # make sure intervals alternate true/false if not all( a != b for a, b in zip(intervals[0::2], intervals[1::2])): raise ValueError('Intervals do not alternate!') sums = [ DEFAULT_SAMPLING_RATE / (a[1] + b[1]) for a, b in zip(intervals[0::2], intervals[1::2]) ] return statistics.mean(sums), statistics.stdev(sums) if __name__ == '__main__': while True: capture = sigrok_capture(1500) intervals = list(debounce(capture)) intervals = intervals[2:-1] # ignore partial first and last intervals # Ignore last interval if we have an uneven number of intervals if intervals[-1] == intervals[0]: intervals = intervals[:-1] try: mean, stdev = calc_frequency(intervals) print(f'\033[38;5;244m{time.strftime("%H:%M:%S")} \033[93m{mean*1e3:> 9.3f} \033[38;5;244m± {stdev*1e3:> 8.3f} mHz\033[0m') except ValueError as e: warnings.warn(*e.args)