// SPDX-License-Identifier: GPL-2.0 /* * Driver for an envelope detector using a DAC and a comparator * * Copyright (C) 2016 Axentia Technologies AB * * Author: Peter Rosin <peda@axentia.se>
*/
/* * The DAC is used to find the peak level of an alternating voltage input * signal by a binary search using the output of a comparator wired to * an interrupt pin. Like so: * _ * | \ * input +------>-------|+ \ * | \ * .-------. | }---. * | | | / | * | dac|-->--|- / | * | | |_/ | * | | | * | | | * | irq|------<-------' * | | * '-------'
*/
/* * The envelope_detector_comp_latch function works together with the compare * interrupt service routine below (envelope_detector_comp_isr) as a latch * (one-bit memory) for if the interrupt has triggered since last calling * this function. * The ..._comp_isr function disables the interrupt so that the cpu does not * need to service a possible interrupt flood from the comparator when no-one * cares anyway, and this ..._comp_latch function reenables them again if * needed.
*/ staticint envelope_detector_comp_latch(struct envelope *env)
{ int comp;
/* * The irq was disabled, and is reenabled just now. * But there might have been a pending irq that * happened while the irq was disabled that fires * just as the irq is reenabled. That is not what * is desired.
*/
enable_irq(env->comp_irq);
/* So, synchronize this possibly pending irq... */
synchronize_irq(env->comp_irq);
staticvoid envelope_detector_setup_compare(struct envelope *env)
{ int ret;
/* * Do a binary search for the peak input level, and stop * when that level is "trapped" between two adjacent DAC * values. * When invert is active, use the midpoint floor so that * env->level ends up as env->low when the termination * criteria below is fulfilled, and use the midpoint * ceiling when invert is not active so that env->level * ends up as env->high in that case.
*/
env->level = (env->high + env->low + !env->invert) / 2;
if (env->high == env->low + 1) {
complete(&env->done); return;
}
/* Set a "safe" DAC level (if there is such a thing)... */
ret = iio_write_channel_raw(env->dac, env->invert ? 0 : env->dac_max); if (ret < 0) goto err;
/* ...clear the comparison result... */
envelope_detector_comp_latch(env);
/* ...set the real DAC level... */
ret = iio_write_channel_raw(env->dac, env->level); if (ret < 0) goto err;
/* ...and wait for a bit to see if the latch catches anything. */
schedule_delayed_work(&env->comp_timeout,
msecs_to_jiffies(env->comp_interval)); return;
/* Adjust low/high depending on the latch content... */ if (!envelope_detector_comp_latch(env) ^ !env->invert)
env->low = env->level; else
env->high = env->level;
/* ...and continue the search. */
envelope_detector_setup_compare(env);
}
staticint envelope_detector_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct envelope *env = iio_priv(indio_dev); int ret;
switch (mask) { case IIO_CHAN_INFO_RAW: /* * When invert is active, start with high=max+1 and low=0 * since we will end up with the low value when the * termination criteria is fulfilled (rounding down). And * start with high=max and low=-1 when invert is not active * since we will end up with the high value in that case. * This ensures that the returned value in both cases are * in the same range as the DAC and is a value that has not * triggered the comparator.
*/
mutex_lock(&env->read_lock);
env->high = env->dac_max + env->invert;
env->low = -1 + env->invert;
envelope_detector_setup_compare(env);
wait_for_completion(&env->done); if (env->level < 0) {
ret = env->level; goto err_unlock;
}
*val = env->invert ? env->dac_max - env->level : env->level;
mutex_unlock(&env->read_lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: return iio_read_channel_scale(env->dac, val, val2);
}
mutex_lock(&env->read_lock); if (invert != env->invert)
ret = irq_set_irq_type(env->comp_irq, trigger); if (!ret) {
env->invert = invert;
ret = len;
}
mutex_unlock(&env->read_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.