Linux IIO development
 help / color / mirror / Atom feed
From: ASSI <Stromeko@nexgo.de>
To: linux-iio@vger.kernel.org
Subject: Re: [PATCH v9 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures
Date: Sat, 12 Jul 2025 16:49:13 +0200	[thread overview]
Message-ID: <875xfx8nx2.fsf@Gerda.invalid> (raw)
In-Reply-To: 87a55azgdr.fsf@Gerda.invalid

ASSI writes:
> I'll try my suggestion of a tapered wait later, perhaps over the
> weekend, now that I don't need to reboot to play around with the module
> code.

That works and indeed even slightly reduces the acquisition times with
my slow sensor specimen, so it does not always need the maximum time
(but very close).  I've also implemented switching off unused channels
during the read through the simple sysfs interface, which does not
support to read all channels in a single measurement.  The temperature
reading is required for both humidity and pressure compensation so it
can only be set to oversampling=1 but not switched off.  For
oversampling=1 on all channels unfortunately the overhead of doing this
almost compensates for the savings made in measurement time, but any
other setting will be a net win:

| oversampling | max/full | max/skip | time/full | time/skip |
|              |     [ms] |     [ms] |      [ms] |      [ms] |
|--------------+----------+----------+-----------+-----------|
|           16 |      339 |      120 |       315 |       127 |
|            8 |      174 |       65 |       166 |        76 |
|            4 |       90 |       38 |        94 |        53 |
|            2 |       49 |       24 |        59 |        41 |
|            1 |       28 |       17 |        36 |        33 |

I suspect the overhead at lower oversampling factors is significantly
lower for SPI interfaced sensors that I cannot currently test.  I've
left a constant in the code to control the skip threshold if anybody
wants to play with it, but the final solution will probably be to either
skip always or make it even more configurable by exposing this facility
via sysfs.  Getting the original channel config restored on all exit
paths is a bit stilted and calls for a bit of refactoring (or even a
goto) but for now this should suffice. Patch:

--8<---------------cut here---------------start------------->8---
--- /usr/src/linux-6.15.5-1//drivers/iio/pressure/bmp280-core.c
+++ bmp280-6.15.5-1/bmp280-core.c
@@ -618,19 +618,77 @@
 	struct bmp280_data *data = iio_priv(indio_dev);
 	int chan_value;
 	int ret;
+	int prev_oversampling_humid, prev_oversampling_press, prev_oversampling_temp;
+	int temp_oversampling_humid, temp_oversampling_press, temp_oversampling_temp;
+	int switch_off, switch_threshold = -1;
 
 	guard(mutex)(&data->lock);
 
+	prev_oversampling_humid = temp_oversampling_humid = data->oversampling_humid;
+	prev_oversampling_press = temp_oversampling_press = data->oversampling_press;
+	prev_oversampling_temp  = temp_oversampling_temp  = data->oversampling_temp;
+
 	switch (mask) {
 	case IIO_CHAN_INFO_PROCESSED:
+		/* switch off unused channels */
+		switch_off = 0;
+		switch (chan->type) {
+		case IIO_HUMIDITYRELATIVE:
+			temp_oversampling_press = 0-1;
+			switch_off |= (prev_oversampling_press > switch_threshold);
+			temp_oversampling_temp  = 1-1; /* can't be switched off as it is needed for compensation */
+			break;
+		case IIO_PRESSURE:
+			temp_oversampling_humid = 0-1;
+			switch_off |= (prev_oversampling_humid > switch_threshold);
+			temp_oversampling_temp  = 1-1; /* can't be switched off as it is needed for compensation */
+			break;
+		case IIO_TEMP:
+			temp_oversampling_humid = 0-1;
+			temp_oversampling_press = 0-1;
+			switch_off = (prev_oversampling_humid > switch_threshold)  |  (prev_oversampling_press > switch_threshold);
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (switch_off) {
+			data->oversampling_humid = temp_oversampling_humid;
+			data->oversampling_press = temp_oversampling_press;
+			data->oversampling_temp  = temp_oversampling_temp;
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->oversampling_humid = prev_oversampling_humid;
+				data->oversampling_press = prev_oversampling_press;
+				data->oversampling_temp  = prev_oversampling_temp;
+				data->chip_info->chip_config(data);
+				return ret;
+			}
+		}
+
 		ret = data->chip_info->set_mode(data, BMP280_FORCED);
-		if (ret)
+		if (ret) {
+			data->oversampling_humid = prev_oversampling_humid;
+			data->oversampling_press = prev_oversampling_press;
+			data->oversampling_temp  = prev_oversampling_temp;
+			data->chip_info->chip_config(data);
 			return ret;
+		}
 
 		ret = data->chip_info->wait_conv(data);
 		if (ret)
 			return ret;
 
+		/* restore channel configuration */
+		if (switch_off) {
+			data->oversampling_humid = prev_oversampling_humid;
+			data->oversampling_press = prev_oversampling_press;
+			data->oversampling_temp  = prev_oversampling_temp;
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				return ret;
+			}
+		}
+
 		switch (chan->type) {
 		case IIO_HUMIDITYRELATIVE:
 			ret = data->chip_info->read_humid(data, &chan_value);
@@ -660,13 +718,60 @@
 			return -EINVAL;
 		}
 	case IIO_CHAN_INFO_RAW:
-		ret = data->chip_info->set_mode(data, BMP280_FORCED);
-		if (ret)
-			return ret;
+		/* switch off unused channels */
+		switch_off = 0;
+		switch (chan->type) {
+		case IIO_HUMIDITYRELATIVE:
+			temp_oversampling_press = 0-1;
+			switch_off |= (prev_oversampling_press > switch_threshold);
+			temp_oversampling_temp  = 1-1; /* can't be switched off as it is needed for compensation */
+			break;
+		case IIO_PRESSURE:
+			temp_oversampling_humid = 0-1;
+			switch_off |= (prev_oversampling_humid > switch_threshold);
+			temp_oversampling_temp  = 1-1; /* can't be switched off as it is needed for compensation */
+			break;
+		case IIO_TEMP:
+			temp_oversampling_humid = 0-1;
+			temp_oversampling_press = 0-1;
+			switch_off = (prev_oversampling_humid > switch_threshold)  |  (prev_oversampling_press > switch_threshold);
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (switch_off) {
+			data->oversampling_humid = temp_oversampling_humid;
+			data->oversampling_press = temp_oversampling_press;
+			data->oversampling_temp  = temp_oversampling_temp;
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				data->oversampling_humid = prev_oversampling_humid;
+				data->oversampling_press = prev_oversampling_press;
+				data->oversampling_temp  = prev_oversampling_temp;
+				data->chip_info->chip_config(data);
+				return ret;
+			}
+		}
 
 		ret = data->chip_info->wait_conv(data);
-		if (ret)
+		if (ret) {
+			data->oversampling_humid = prev_oversampling_humid;
+			data->oversampling_press = prev_oversampling_press;
+			data->oversampling_temp  = prev_oversampling_temp;
+			data->chip_info->chip_config(data);
 			return ret;
+		}
+
+		/* restore channel configuration */
+		if (switch_off) {
+			data->oversampling_humid = prev_oversampling_humid;
+			data->oversampling_press = prev_oversampling_press;
+			data->oversampling_temp  = prev_oversampling_temp;
+			ret = data->chip_info->chip_config(data);
+			if (ret) {
+				return ret;
+			}
+		}
 
 		switch (chan->type) {
 		case IIO_HUMIDITYRELATIVE:
@@ -1040,15 +1145,15 @@
 {
 	unsigned int reg, meas_time_us;
 	int ret;
+	int meas_cycles = 4;
+
+	meas_time_us = BMP280_MEAS_OFFSET;
 
 	/* Check if we are using a BME280 device */
 	if (data->oversampling_humid)
-		meas_time_us = BMP280_PRESS_HUMID_MEAS_OFFSET +
+		meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
 				BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
 
-	else
-		meas_time_us = 0;
-
 	/* Pressure measurement time */
 	meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
 			BIT(data->oversampling_press) * BMP280_MEAS_DUR;
@@ -1056,14 +1161,18 @@
 	/* Temperature measurement time */
 	meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
 
-	/* Waiting time according to the BM(P/E)2 Sensor API */
-	fsleep(meas_time_us);
+	do {
+		/* Waiting time according to the BM(P/E)2 Sensor API */
+		fsleep(meas_time_us);
+
+		ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+		if (ret) {
+			dev_err(data->dev, "failed to read status register.\n");
+			return ret;
+		}
 
-	ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
-	if (ret) {
-		dev_err(data->dev, "failed to read status register.\n");
-		return ret;
-	}
+		meas_time_us >>= 3;
+	} while ((reg & BMP280_REG_STATUS_MEAS_BIT) && --meas_cycles);
 
 	if (reg & BMP280_REG_STATUS_MEAS_BIT) {
 		dev_err(data->dev, "Measurement cycle didn't complete.\n");

--- /usr/src/linux-6.15.5-1//drivers/iio/pressure/bmp280.0
+++ bmp280-6.15.5-1/bmp280.h
@@ -269,9 +269,9 @@
 #define BMP280_MODE_FORCED		1
 #define BMP280_MODE_NORMAL		3
 
-#define BMP280_MEAS_OFFSET		1250
-#define BMP280_MEAS_DUR			2300
-#define BMP280_PRESS_HUMID_MEAS_OFFSET	575
+#define BMP280_MEAS_OFFSET		1095 /* ceil(1250/(1+2^-3+2^-6+2^-9) */
+#define BMP280_MEAS_DUR			2013 /* ceil(2300/(1+2^-3+2^-6+2^-9) */
+#define BMP280_PRESS_HUMID_MEAS_OFFSET	504  /* ceil( 575/(1+2^-3+2^-6+2^-9) */
 
 /* BME280 specific registers */
 #define BME280_REG_HUMIDITY_LSB		0xFE
--8<---------------cut here---------------end--------------->8---


Regards,
Achim.
-- 
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

Factory and User Sound Singles for Waldorf Q+, Q and microQ:
http://Synth.Stromeko.net/Downloads.html#WaldorfSounds


  reply	other threads:[~2025-07-12 14:49 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-17 23:30 [PATCH v9 0/4] pressure: bmp280: Minor cleanup and interrupt support Vasileios Amoiridis
2024-10-17 23:30 ` [PATCH v9 1/4] iio: pressure: bmp280: Use sleep and forced mode for oneshot captures Vasileios Amoiridis
2025-06-28 18:45   ` ASSI
2025-06-28 20:57     ` David Lechner
2025-06-29  7:43       ` ASSI
2025-07-11 19:17       ` ASSI
2025-07-12 14:49         ` ASSI [this message]
2025-07-21 19:15           ` ASSI
2025-07-26 18:34           ` ASSI
2025-07-27 19:08             ` ASSI
2024-10-17 23:30 ` [PATCH v9 2/4] dt-bindings: iio: pressure: bmp085: Add interrupts for BMP3xx and BMP5xx devices Vasileios Amoiridis
2024-10-17 23:30 ` [PATCH v9 3/4] iio: pressure: bmp280: Add data ready trigger support Vasileios Amoiridis
2024-10-17 23:30 ` [PATCH v9 4/4] iio: pressure: bmp280: Move bmp085 interrupt to new configuration Vasileios Amoiridis
2024-10-19 13:55 ` [PATCH v9 0/4] pressure: bmp280: Minor cleanup and interrupt support Jonathan Cameron
2025-08-03 14:07 ` [bmp280 v1 0/6] Fixes and enhancements for the bmp280 driver Achim Gratz
2025-08-03 14:07   ` [bmp280 v1 1/6] iio: pressure: bmp280: correct meas_time_us calculation Achim Gratz
2025-08-06 15:46     ` Jonathan Cameron
2025-08-06 17:53       ` ASSI
2025-08-10 18:04         ` Jonathan Cameron
2025-08-03 14:07   ` [bmp280 v1 2/6] iio: pressure: bmp280: reduce overhead on read with MODE_FORCED Achim Gratz
2025-08-03 20:12     ` Andy Shevchenko
2025-08-06 15:58     ` Jonathan Cameron
2025-08-06 18:00       ` ASSI
2025-08-03 14:07   ` [bmp280 v1 3/6] iio: pressure: bmp280: implement sampling_frequency for BMx280 Achim Gratz
2025-08-03 20:26     ` Andy Shevchenko
2025-08-04 17:29       ` ASSI
2025-08-10 18:11         ` Jonathan Cameron
2025-08-10 19:12           ` ASSI
2025-08-11 19:48             ` Jonathan Cameron
2025-08-12 19:53               ` ASSI
2025-08-17 15:10                 ` Jonathan Cameron
2025-08-17 16:36                   ` ASSI
2025-08-03 14:08   ` [bmp280 v1 4/6] iio: pressure: bmp280: enable filter settings " Achim Gratz
2025-08-03 20:28     ` Andy Shevchenko
2025-08-04 17:14       ` ASSI
2025-08-10 18:13     ` Jonathan Cameron
2025-08-10 19:01       ` ASSI
2025-08-11 20:14         ` Jonathan Cameron
2025-08-12 19:34           ` ASSI
2025-08-17 14:51             ` Jonathan Cameron
2025-08-03 14:08   ` [bmp280 v1 5/6] iio: pressure: bmp280: remove code duplication Achim Gratz
2025-08-03 20:30     ` Andy Shevchenko
2025-08-10 18:19     ` Jonathan Cameron
2025-08-03 14:08   ` [bmp280 v1 6/6] iio: pressure: bmp280: implement sampling_frequency calculation for BMx280 Achim Gratz
2025-08-03 20:37     ` Andy Shevchenko
2025-08-04 17:20       ` ASSI
2025-08-03 19:20   ` [bmp280 v1 0/6] Fixes and enhancements for the bmp280 driver Andy Shevchenko
2025-08-10 18:58 ` [RFC PATCH v2 0/9] " Achim Gratz
2025-08-10 18:58   ` [RFC PATCH v2 1/9] iio: pressure: bmp280: correct meas_time_us calculation Achim Gratz
2025-08-17 15:16     ` Jonathan Cameron
2025-08-10 18:58   ` [RFC PATCH v2 2/9] iio: pressure: bmp280: implement adaptive wait for BMx280 devices Achim Gratz
2025-08-10 19:49     ` Andy Shevchenko
2025-08-16 18:42       ` ASSI
2025-08-10 18:58   ` [RFC PATCH v2 3/9] iio: pressure: bmp280: implement adaptive wait for BMP380 devices Achim Gratz
2025-08-10 18:58   ` [RFC PATCH v2 4/9] iio: pressure: bmp280: refactoring Achim Gratz
2025-08-17 15:23     ` Jonathan Cameron
2025-08-10 18:58   ` [RFC PATCH v2 5/9] iio: pressure: bmp280: remove code duplication Achim Gratz
2025-08-10 18:58   ` [RFC PATCH v2 6/9] iio: pressure: bmp280: enable filter settings for BMx280 Achim Gratz
2025-08-17 16:37     ` Jonathan Cameron
2025-08-10 18:58   ` [RFC PATCH v2 7/9] iio: pressure: bmp280: implement sampling_frequency " Achim Gratz
2025-08-17 16:53     ` Jonathan Cameron
2025-08-17 17:36       ` ASSI
2025-08-10 18:58   ` [RFC PATCH v2 8/9] iio: pressure: bmp280: implement sampling_frequency calculation " Achim Gratz
2025-08-17 17:04     ` Jonathan Cameron
2025-08-17 17:40       ` ASSI
2025-08-18 17:52         ` Jonathan Cameron
2025-08-10 18:58   ` [RFC PATCH v2 9/9] iio: pressure: bmp280: test longer autosuspend (WIP) Achim Gratz
2025-08-17 17:05     ` Jonathan Cameron
2025-08-17 17:44       ` ASSI
2025-08-11 12:14   ` [RFC PATCH v2 0/9] Fixes and enhancements for the bmp280 driver Andy Shevchenko
2025-08-11 20:17   ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=875xfx8nx2.fsf@Gerda.invalid \
    --to=stromeko@nexgo.de \
    --cc=linux-iio@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox