1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/i2c.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/ztest.h>
10 #include "sensor.h"
11
12 #define SENSOR_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(bosch_bme680)
13 #define I2C_TEST_NODE DT_PARENT(SENSOR_NODE)
14 #define DEVICE_ADDRESS (uint8_t) DT_REG_ADDR(SENSOR_NODE)
15
16 static const struct device *const i2c_device = DEVICE_DT_GET(I2C_TEST_NODE);
17 static struct calibration_coeffs cal_coeffs;
18 static int32_t t_fine;
19
20 /* Read data from the senors register */
read_sensor_register(uint8_t register_address)21 static uint8_t read_sensor_register(uint8_t register_address)
22 {
23 int err;
24 uint8_t response = 0;
25
26 err = i2c_reg_read_byte(i2c_device, DEVICE_ADDRESS, register_address, &response);
27 zassert_equal(err, 0, "i2c_read(%x)' failed with error: %d\n", register_address, err);
28 TC_PRINT("I2C read reg, addr: 0x%x, val: 0x%x\n", register_address, response);
29 return response;
30 }
31
32 /* Burst read data from the sensor registers */
burst_read_sensor_registers(uint8_t starting_register_address,uint8_t number_of_bytes,uint8_t * data_buffer)33 static void burst_read_sensor_registers(uint8_t starting_register_address, uint8_t number_of_bytes,
34 uint8_t *data_buffer)
35 {
36 int err;
37
38 zassert_true(number_of_bytes <= MAX_BURST_READ_SIZE,
39 "Too many bytes to read %d, max burst read size is set to: %d",
40 number_of_bytes, MAX_BURST_READ_SIZE);
41 err = i2c_burst_read(i2c_device, DEVICE_ADDRESS, starting_register_address, data_buffer,
42 number_of_bytes);
43 zassert_equal(err, 0, "i2c_burst_read(%x, %x)' failed with error: %d\n",
44 starting_register_address, number_of_bytes, err);
45 TC_PRINT("I2C burst read, start addr: 0x%x, number of bytes: %d\n",
46 starting_register_address, number_of_bytes);
47 }
48
49 /* Write sensor register */
write_sensor_register(uint8_t register_address,int8_t value)50 static void write_sensor_register(uint8_t register_address, int8_t value)
51 {
52 int err;
53
54 err = i2c_reg_write_byte(i2c_device, DEVICE_ADDRESS, register_address, value);
55 zassert_equal(err, 0, "i2c_reg_write_byte(%x, %x)' failed with error: %d\n",
56 register_address, value, err);
57 TC_PRINT("I2C reg write, addr: 0x%x, val: 0x%x\n", register_address, value);
58 }
59
60 /* Set IIR filter for the temperature and pressure measurements */
set_sensor_iir_filter(void)61 static void set_sensor_iir_filter(void)
62 {
63 uint8_t response = 0;
64
65 TC_PRINT("Set IIR filter\n");
66 response = read_sensor_register(CONF_REGISTER_ADDRESS);
67 response &= ~IIR_FILER_ORDER_BIT_MASK;
68 response |= IIR_FILER_COEFF_3 << IIR_FILER_ORDER_BIT_SHIFT;
69 write_sensor_register(CONF_REGISTER_ADDRESS, response);
70 read_sensor_register(CONF_REGISTER_ADDRESS);
71 }
72
73 /* Read calibration coefficients for temperature, humifity and pressure */
read_calibration_coeffs(struct calibration_coeffs * coeffs)74 static void read_calibration_coeffs(struct calibration_coeffs *coeffs)
75 {
76 uint8_t register_data[MAX_BURST_READ_SIZE] = {0};
77
78 /* Humidity */
79 TC_PRINT("Reading humidity calibration coefficients\n");
80 burst_read_sensor_registers(HUMI_PAR_REGISTERS_START_ADDRESS, HUMI_PAR_REGISTERS_COUNT,
81 register_data);
82 coeffs->par_h1 = (uint16_t)(((uint16_t)register_data[HUMI_PAR_H1_MSB_BUF_POSITION] << 4) |
83 (register_data[HUMI_PAR_H1_LSB_BUF_POSITION] &
84 HUMI_PAR_H1_LSB_BIT_MASK));
85 coeffs->par_h2 = (uint16_t)(((uint16_t)register_data[HUMI_PAR_H2_MSB_BUF_POSITION] << 4) |
86 ((register_data[HUMI_PAR_H2_LSB_BUF_POSITION]) >> 4));
87
88 coeffs->par_h3 = (uint8_t)register_data[HUMI_PAR_H3_BUF_POSITION];
89 coeffs->par_h4 = (uint8_t)register_data[HUMI_PAR_H4_BUF_POSITION];
90 coeffs->par_h5 = (uint8_t)register_data[HUMI_PAR_H5_BUF_POSITION];
91 coeffs->par_h6 = (uint8_t)register_data[HUMI_PAR_H6_BUF_POSITION];
92 coeffs->par_h7 = (uint8_t)register_data[HUMI_PAR_H7_BUF_POSITION];
93
94 /* Temperature */
95 TC_PRINT("Reading temperature calibration coefficients\n");
96 burst_read_sensor_registers(TEMP_PAR_T1_REGISTER_ADDRESS_LSB, 2, register_data);
97 coeffs->par_t1 = (uint16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]);
98 burst_read_sensor_registers(TEMP_PAR_T2_REGISTER_ADDRESS_LSB, 2, register_data);
99 coeffs->par_t2 = (uint16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]);
100 coeffs->par_t3 = (uint8_t)read_sensor_register(TEMP_PAR_T3_REGISTER_ADDRESS);
101
102 /* Pressure */
103 TC_PRINT("Reading pressure calibration coefficients\n");
104 burst_read_sensor_registers(PRES_PAR_P1_REGISTER_ADDRESS_LSB, 4, register_data);
105 coeffs->par_p1 = (uint16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]);
106 coeffs->par_p2 = (int16_t)(((uint16_t)register_data[3] << 8) | (uint16_t)register_data[2]);
107 coeffs->par_p3 = (int8_t)read_sensor_register(PRES_PAR_P3_REGISTER_ADDRESS);
108 burst_read_sensor_registers(PRES_PAR_P4_REGISTER_ADDRESS_LSB, 4, register_data);
109 coeffs->par_p4 = (int16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]);
110 coeffs->par_p5 = (int16_t)(((uint16_t)register_data[3] << 8) | (uint16_t)register_data[2]);
111 coeffs->par_p6 = (int8_t)read_sensor_register(PRES_PAR_P6_REGISTER_ADDRESS);
112 coeffs->par_p7 = (int8_t)read_sensor_register(PRES_PAR_P7_REGISTER_ADDRESS);
113 burst_read_sensor_registers(PRES_PAR_P8_REGISTER_ADDRESS_LSB, 4, register_data);
114 coeffs->par_p8 = (int16_t)(((uint16_t)register_data[1] << 8) | (uint16_t)register_data[0]);
115 coeffs->par_p9 = (int16_t)(((uint16_t)register_data[3] << 8) | (uint16_t)register_data[2]);
116 coeffs->par_p10 = read_sensor_register(PRES_PAR_P10_REGISTER_ADDRESS);
117 }
118
119 /* Configure temperature, pressure and humidity measurements */
configure_measurements(void)120 static void configure_measurements(void)
121 {
122 unsigned char response = 0;
123
124 TC_PRINT("Configure measurements\n");
125
126 /* Humidity */
127 response = read_sensor_register(CTRL_HUM_REGISTER_ADDRESS);
128 response &= ~HUMIDITY_OVERSAMPLING_BIT_MSK;
129 response |= HUMIDITY_OVERSAMPLING_1X << HUMIDITY_OVERSAMPLING_BIT_SHIFT;
130 write_sensor_register(CTRL_HUM_REGISTER_ADDRESS, response);
131
132 /* Temperature*/
133 response = read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS);
134 response &= ~TEMP_OVERSAMPLING_BIT_MSK;
135 response |= TEMPERATURE_OVERSAMPLING_2X << TEMP_OVERSAMPLING_BIT_SHIFT;
136
137 write_sensor_register(CTRL_MEAS_REGISTER_ADDRESS, response);
138
139 /* Pressure */
140 response = read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS);
141 response &= ~PRES_OVERSAMPLING_BIT_MSK;
142 response |= PRESSURE_OVERSAMPLING_16X << PRES_OVERSAMPLING_BIT_SHIFT;
143
144 write_sensor_register(CTRL_MEAS_REGISTER_ADDRESS, response);
145 read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS);
146 set_sensor_iir_filter();
147 }
148
149 /* Set the sensor operation mode */
set_sensor_mode(uint8_t sensor_mode)150 static void set_sensor_mode(uint8_t sensor_mode)
151 {
152 unsigned char response = 0;
153
154 TC_PRINT("Set sensor mode to: 0x%x\n", sensor_mode);
155
156 response = read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS);
157 response &= ~CTRL_MEAS_MODE_BIT_MSK;
158 response |= sensor_mode << CTRL_MEAS_MODE_BIT_SHIFT;
159 write_sensor_register(CTRL_MEAS_REGISTER_ADDRESS, response);
160 read_sensor_register(CTRL_MEAS_REGISTER_ADDRESS);
161 }
162
163 /* Read the raw ADC temperature measurement result */
read_adc_temperature(void)164 static uint32_t read_adc_temperature(void)
165 {
166 uint32_t adc_temperature = 0;
167
168 TC_PRINT("Reading ADC temperature\n");
169 adc_temperature = (uint32_t)(((uint32_t)read_sensor_register(TEMP_ADC_DATA_MSB_0) << 12) |
170 ((uint32_t)read_sensor_register(TEMP_ADC_DATA_LSB_0) << 4) |
171 ((uint32_t)read_sensor_register(TEMP_ADC_DATA_XLSB_0) >> 4));
172
173 return adc_temperature;
174 }
175
176 /* Read the raw ADC pressure measurement result */
read_adc_pressure(void)177 static uint32_t read_adc_pressure(void)
178 {
179 uint32_t pres_adc = 0;
180
181 TC_PRINT("Reading ADC pressure\n");
182 pres_adc = (uint32_t)(((uint32_t)read_sensor_register(PRES_ADC_DATA_MSB_0) << 12) |
183 ((uint32_t)read_sensor_register(PRES_ADC_DATA_LSB_0) << 4) |
184 ((uint32_t)read_sensor_register(PRES_ADC_DATA_XLSB_0) >> 4));
185
186 return pres_adc;
187 }
188
189 /* Read the raw ADC humidity measurement result */
read_adc_humidity(void)190 static uint16_t read_adc_humidity(void)
191 {
192 uint16_t hum_adc = 0;
193
194 TC_PRINT("Reading ADC humidity\n");
195 hum_adc = (uint16_t)(((uint16_t)read_sensor_register(HUM_ADC_DATA_MSB_0) << 8) |
196 (uint16_t)read_sensor_register(HUM_ADC_DATA_LSB_0));
197
198 return hum_adc;
199 }
200
ZTEST(i2c_controller_to_sensor,test_i2c_basic_memory_read)201 ZTEST(i2c_controller_to_sensor, test_i2c_basic_memory_read)
202 {
203 int err;
204 uint32_t i2c_config = I2C_SPEED_SET(CONFIG_TEST_I2C_SPEED) | I2C_MODE_CONTROLLER;
205 uint8_t entire_sensor_memory[SENSOR_MEMORY_SIZE_IN_BYTES] = {0};
206
207 TC_PRINT("Device address 0x%x\n", DEVICE_ADDRESS);
208 TC_PRINT("I2C speed setting: %d\n", CONFIG_TEST_I2C_SPEED);
209
210 err = i2c_configure(i2c_device, i2c_config);
211 zassert_equal(err, 0, "i2c_configure' failed with error: %d\n", err);
212
213 err = i2c_read(i2c_device, entire_sensor_memory, SENSOR_MEMORY_SIZE_IN_BYTES,
214 DEVICE_ADDRESS);
215 zassert_equal(err, 0, "i2c_read' failed with error: %d\n", err);
216 }
217
ZTEST(i2c_controller_to_sensor,test_i2c_nack_handling)218 ZTEST(i2c_controller_to_sensor, test_i2c_nack_handling)
219 {
220 int err;
221 uint8_t test_data;
222
223 TC_PRINT("Device address 0x%x\n", DEVICE_ADDRESS);
224
225 err = i2c_read(i2c_device, &test_data, 1, DEVICE_ADDRESS + 1);
226 zassert_equal(err, -EIO, "Invalid device address not detected, err: %d\n", err);
227
228 err = i2c_reg_read_byte(i2c_device, DEVICE_ADDRESS, CHIP_ID_REGISTER_ADDRESS, &test_data);
229 zassert_equal(err, 0, "Failed to read device register after previous address NACK: %d\n",
230 err);
231 }
232
ZTEST(i2c_controller_to_sensor,test_i2c_bus_recovery)233 ZTEST(i2c_controller_to_sensor, test_i2c_bus_recovery)
234 {
235 int err;
236 uint8_t test_data;
237
238 TC_PRINT("Device address 0x%x\n", DEVICE_ADDRESS);
239
240 err = i2c_recover_bus(i2c_device);
241 zassert_equal(err, 0, "'i2c_recover_bus' failed with error: %d\n", err);
242
243 err = i2c_reg_read_byte(i2c_device, DEVICE_ADDRESS, CHIP_ID_REGISTER_ADDRESS, &test_data);
244 zassert_equal(err, 0, "Failed to read device register after bus recovery: %d\n", err);
245 }
246
ZTEST(i2c_controller_to_sensor,test_i2c_controlled_sensor_operation)247 ZTEST(i2c_controller_to_sensor, test_i2c_controlled_sensor_operation)
248 {
249 int err;
250 uint8_t response = 0;
251 int16_t temperature = 0;
252 uint32_t pressure = 0;
253 uint32_t humidity = 0;
254 uint32_t i2c_config = I2C_SPEED_SET(CONFIG_TEST_I2C_SPEED) | I2C_MODE_CONTROLLER;
255 uint8_t measurements_left = MEASUREMENT_CYCLES + 1;
256
257 TC_PRINT("Device address 0x%x\n", DEVICE_ADDRESS);
258 TC_PRINT("I2C speed setting: %d\n", CONFIG_TEST_I2C_SPEED);
259
260 err = i2c_configure(i2c_device, i2c_config);
261 zassert_equal(err, 0, "i2c_configure' failed with error: %d\n", err);
262
263 response = read_sensor_register(CHIP_ID_REGISTER_ADDRESS);
264 TC_PRINT("Chip_Id: %d\n", response);
265
266 response = read_sensor_register(VARIANT_ID_REGISTER_ADDRESS);
267 TC_PRINT("Variant_Id: %d\n", response);
268
269 write_sensor_register(RESET_REGISTER_ADDRESS, RESET_DEVICE);
270 k_sleep(K_MSEC(SLEEP_TIME_MS));
271
272 read_calibration_coeffs(&cal_coeffs);
273
274 configure_measurements();
275 set_sensor_mode(FORCED_MODE);
276
277 while (measurements_left) {
278 response = read_sensor_register(MEAS_STATUS_0_REG_ADDRESS);
279 TC_PRINT("Meas status 0, meas in progress: %d, new data: %d\n",
280 response & MEASUREMENT_IN_PROGRESS_BIT_MASK,
281 response & MEASUREMENT_NEW_DATA_BIT_MASK);
282 if (response & MEASUREMENT_NEW_DATA_BIT_MASK) {
283 temperature =
284 calculate_temperature(read_adc_temperature(), &t_fine, &cal_coeffs);
285 pressure = calculate_pressure(read_adc_pressure(), t_fine, &cal_coeffs);
286 humidity = calculate_humidity(read_adc_humidity(), t_fine, &cal_coeffs);
287 TC_PRINT("Temperature: %d.%d C deg\n", temperature / 100,
288 temperature % 100);
289 TC_PRINT("Pressure: %d hPa\n", pressure / 100);
290 TC_PRINT("Humidity: %d %%\n", humidity / 1000);
291 set_sensor_mode(FORCED_MODE);
292
293 /* Check if the results are within reasonable ranges
294 * for laboratory room usage
295 * This is asserted to catch values
296 * that may be results of an erroneous
297 * bus operation (corrupted read or write)
298 */
299 zassert_true(
300 (temperature / 100 >= 5) && (temperature / 100 <= 55),
301 "Temperature is outside of the allowed range for labroatory use");
302 zassert_true((pressure / 100 >= 700) && (pressure / 100 <= 1300),
303 "Pressure is outside of the allowed range for labroatory use");
304 zassert_true((humidity / 1000 >= 10) && (humidity / 1000 <= 90),
305 "Humidity is outside of the allowed range for labroatory use");
306 measurements_left--;
307 }
308 k_sleep(K_MSEC(SLEEP_TIME_MS));
309 }
310 }
311
312 /*
313 * Test setup
314 */
test_setup(void)315 void *test_setup(void)
316 {
317 zassert_true(device_is_ready(i2c_device), "i2c device is not ready");
318 return NULL;
319 }
320
321 ZTEST_SUITE(i2c_controller_to_sensor, NULL, test_setup, NULL, NULL, NULL);
322