from .sampler import Sampler from .controller import SamplerController """ Random implementation notes: - Circular buffers can keep overwriting. We only need a setting to say how many samples to save after trigger occurs. - Data valid from samplers to FIFOs can simply be gated via the enable signal. Everything can just run all the time to keep things simple - can we correct clock skew on the sample clock via Lattice primitives? I think it's possible. I doubt it matters. Would need significant calibration effort to even have it be accurate. - Trigger system should wait a couple clocks after trigger acquired to disable FIFOs, just in case the CDC sync happens a bit late for some ADC channels Configurable parameters: - trigger_run_len: number of samples to acquire after triggered sample (can technically be arbitrarily large, circular buffer handles data loss, should be larger than trigger_thresh_time to make sure buffers don't get weird) - trigger_thresh_value: minimum peak to peak value to consider triggered - trigger_thresh_time: minimum num samples that peak must be above threshold to count as a trigger (trigger sample number is the first sample above the threshold value) (must be >= 1) - trigger_decay_value: decay value to subtract from peak values to potentially reduce false triggers - trigger_decay_period: number of samples per decay application Implementation of trigger (psuedocode), happens every sample update: if triggered: if num_samples + 1 >= trigger_run: disable_trigger() return num_samples += 1 return if sample > max: max = sample elif sample < min: min = sample if (max - min) > trigger_thresh_value: if triggered_for + 1 >= trigger_thresh_time: triggered = True num_samples = 0 return triggered_for += 1 decay_wait = 0 else: triggered_for = 0 decay_wait += 1 if trigger_decay_period == 0 or decay_wait == trigger_thresh_time: decay_wait = 0 if (max - trigger_decay_value) > (min + trigger_decay_value): max -= trigger_decay_value min += trigger_decay_value """