lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <a9c8457f-a364-46e2-9e31-ceab0e1c9894@baylibre.com>
Date: Wed, 13 Aug 2025 17:52:04 -0500
From: David Lechner <dlechner@...libre.com>
To: Ben Collins <bcollins@...ter.com>, Jonathan Cameron <jic23@...nel.org>,
 Nuno Sรก <nuno.sa@...log.com>,
 Andy Shevchenko <andy@...nel.org>
Cc: linux-iio@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v2 5/5] iio: mcp9600: Add support for IIR filter

On 8/13/25 10:15 AM, Ben Collins wrote:
> MCP9600 supports an IIR filter with 7 levels. Add IIR attribute
> to allow get/set of this value.
> 
> Signed-off-by: Ben Collins <bcollins@...ter.com>
> ---
>  drivers/iio/temperature/mcp9600.c | 43 +++++++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c
> index 5ead565f1bd8c..5bed3a35ae65e 100644
> --- a/drivers/iio/temperature/mcp9600.c
> +++ b/drivers/iio/temperature/mcp9600.c
> @@ -31,6 +31,7 @@
>  #define MCP9600_STATUS_ALERT(x)		BIT(x)
>  #define MCP9600_SENSOR_CFG		0x5
>  #define MCP9600_SENSOR_TYPE_MASK	GENMASK(6, 4)
> +#define MCP9600_FILTER_MASK		GENMASK(2, 0)
>  #define MCP9600_ALERT_CFG1		0x8
>  #define MCP9600_ALERT_CFG(x)		(MCP9600_ALERT_CFG1 + (x - 1))
>  #define MCP9600_ALERT_CFG_ENABLE	BIT(0)
> @@ -111,6 +112,7 @@ static const struct iio_event_spec mcp9600_events[] = {
>  			.address = MCP9600_HOT_JUNCTION,		       \
>  			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	       \
>  					      BIT(IIO_CHAN_INFO_SCALE) |       \
> +					      BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |  \
>  					      BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE), \
>  			.event_spec = &mcp9600_events[hj_ev_spec_off],	       \
>  			.num_event_specs = hj_num_ev,			       \
> @@ -149,6 +151,7 @@ static const struct iio_chan_spec mcp9600_channels[][2] = {
>  struct mcp9600_data {
>  	struct i2c_client *client;
>  	u32 thermocouple_type;
> +	u32 filter_level;
>  };
>  
>  static int mcp9600_read(struct mcp9600_data *data,
> @@ -186,6 +189,9 @@ static int mcp9600_read_raw(struct iio_dev *indio_dev,
>  	case IIO_CHAN_INFO_THERMOCOUPLE_TYPE:
>  		*val = mcp9600_tc_types[data->thermocouple_type];
>  		return IIO_VAL_CHAR;
> +	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
> +		*val = data->filter_level;

We can't just pass the raw value through for this. The ABI is defined
in Documentation/ABI/testing/sysfs-bus-iio and states that the value
is the frequency in Hz.

So we need to do the math to convert from the register value to
the required value.

I'm a bit rusty on my discrete time math, so I had chatgpt help me
do the transform of the function from the datasheet to a transfer
function and use that to find the frequency response.

It seemed to match what my textbook was telling me, so hopefully
it got it right.

Then it spit out the following program that can be used to make
a table of 3dB points for a given sampling frequency. If I read the
datasheet right, the sampling frequency depends on the number of
bits being read.

For example, for 3 Hz sample rate (18-bit samples), I got:

  n  f_3dB (Hz)
  1  0.58774
  2  0.24939
  3  0.12063
  4  0.05984
  5  0.02986
  6  0.01492
  7  0.00746

I had to skip n=0 though since that is undefined. Not sure how we
handle that since it means no filter. Maybe Jonathan can advise?


```python
import numpy as np
import pandas as pd

# Sampling rate (can be replaced with actual sampling rate if known)
fs = 1.0  # Hz

# Define alpha as a function of n
def alpha(n):
    return 2 / (2**n + 1)

# Compute 3 dB frequency for each n from 0 to 7
results = []

for n in range(0, 8):
    a = alpha(n)

    numerator = -(a**2 + 2*a - 2)
    denominator = 2 * (1 - a)
    cos_val = numerator / denominator

    if -1 <= cos_val <= 1:
        omega_3dB = np.arccos(cos_val)  # radians/sample
        f_3dB = (omega_3dB * fs) / (2 * np.pi)  # Hz
    else:
        f_3dB = np.nan  # Outside arccos domain

    results.append({
        "n": n,
        "alpha": round(a, 5),
        "f_3dB (Hz)": None if np.isnan(f_3dB) else round(f_3dB, 5)
    })

# Display the results
df = pd.DataFrame(results)
print(df)

```


Here is the chatgpt transcript for checking the math:
To find the **3 dB point** (i.e., the cutoff frequency) of the given digital low-pass filter, we need to analyze its frequency response. The equation you've provided is a common **first-order IIR low-pass filter**:

$$
Y_k = (1 - n) \cdot Y_{k-1} + n \cdot X_k
$$

Where:

* $Y_k$: current filtered output
* $Y_{k-1}$: previous filtered output
* $X_k$: current input (unfiltered)
* $n$: filter coefficient (0 < $n$ < 1)

---

### Step 1: Transfer Function

We can find the transfer function $H(z)$ using Z-transforms.

Take the Z-transform of both sides:

$$
Y(z) = (1 - n) \cdot z^{-1} Y(z) + n \cdot X(z)
$$

Solve for $H(z) = \frac{Y(z)}{X(z)}$:

$$
Y(z) \left(1 - (1 - n) z^{-1} \right) = n X(z)
$$

$$
H(z) = \frac{Y(z)}{X(z)} = \frac{n}{1 - (1 - n) z^{-1}}
$$

---

### Step 2: Frequency Response

Substitute $z = e^{j\omega}$ to find the frequency response:

$$
H(e^{j\omega}) = \frac{n}{1 - (1 - n) e^{-j\omega}}
$$

We want the magnitude response $|H(e^{j\omega})|$, and the **3 dB point** is defined where the magnitude drops to:

$$
|H(e^{j\omega_{3dB}})| = \frac{1}{\sqrt{2}} \cdot |H(e^{j0})|
$$

At $\omega = 0$:

$$
|H(e^{j0})| = \frac{n}{1 - (1 - n)} = 1
$$

So the 3 dB point occurs when:

$$
|H(e^{j\omega_{3dB}})| = \frac{1}{\sqrt{2}} \approx 0.707
$$

---

### Step 3: Solving Numerically (Approximation)

The magnitude of the frequency response is:

$$
|H(e^{j\omega})| = \frac{n}{\sqrt{1 - 2(1 - n)\cos(\omega) + (1 - n)^2}}
$$

Set this equal to 0.707:

$$
\frac{n}{\sqrt{1 - 2(1 - n)\cos(\omega) + (1 - n)^2}} = 0.707
$$

This is a transcendental equation and cannot be solved algebraically in closed-form. However, you can **solve numerically** for $\omega_{3dB}$ for a given $n$.

---

### Step 4: Approximate Formula for 3 dB Frequency

For small $n$, an **approximate formula** for the normalized cutoff frequency (in radians/sample) is:

$$
\omega_{3dB} \approx n
$$

In terms of frequency in Hz (assuming a sample rate $f_s$):

$$
f_{3dB} \approx \frac{n \cdot f_s}{2\pi}
$$

---

### โœ… Summary

* **Filter type**: First-order IIR low-pass
* **Filter equation**:

  $$
  Y_k = (1 - n) Y_{k-1} + n X_k
  $$
* **3 dB point (approximate in Hz)**:

  $$
  f_{3dB} \approx \frac{n \cdot f_s}{2\pi}
  $$

  where $f_s$ is the sampling rate in Hz

Let me know your value of $n$ and the sampling rate if you want a specific 3 dB frequency calculated.

---

You're given a **discrete-time system** defined by the difference equation:

$$
y[n] = \alpha \cdot x[n] + (1 - \alpha) \cdot y[n - 1]
$$

This is a classic **first-order IIR low-pass filter**, just like in your previous question.

---

### ๐Ÿ”น Step 1: Take the Z-transform

Using the properties of the Z-transform (assuming zero initial conditions):

* $\mathcal{Z}\{y[n]\} = Y(z)$
* $\mathcal{Z}\{y[n - 1]\} = z^{-1} Y(z)$
* $\mathcal{Z}\{x[n]\} = X(z)$

Substitute into the difference equation:

$$
Y(z) = \alpha X(z) + (1 - \alpha) z^{-1} Y(z)
$$

---

### ๐Ÿ”น Step 2: Solve for the Transfer Function

Rearrange:

$$
Y(z) - (1 - \alpha) z^{-1} Y(z) = \alpha X(z)
$$

Factor $Y(z)$:

$$
Y(z) \left(1 - (1 - \alpha) z^{-1} \right) = \alpha X(z)
$$

$$
H(z) = \frac{Y(z)}{X(z)} = \frac{\alpha}{1 - (1 - \alpha) z^{-1}}
$$

---

### โœ… Final Answer:

$$
\boxed{H(z) = \frac{\alpha}{1 - (1 - \alpha) z^{-1}}}
$$

This is the **transfer function** of the filter in the Z-domain.

Let me know if you want the frequency response, pole/zero plot, or time-domain behavior from this!



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ