Software APIs
i2c_host_hdc1080_humidity_temp_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 #include <assert.h>
5 
12 #include "sw/device/lib/runtime/irq.h"
15 #include "sw/device/lib/testing/i2c_testutils.h"
16 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 
21 #include "i2c_regs.h" // Generated.
22 
23 OTTF_DEFINE_TEST_CONFIG();
24 
25 enum {
26  kDeviceAddr = 0x40,
27 
28  // Registers
29  kTemperatureReg = 0x00,
30  kHumidityReg = 0x01,
31  kConfigurationReg = 0x02,
32  kManufacturerIdReg = 0xFE,
33  kDeviceIdReg = 0xFF,
34 
35  // Registers values
36  kManufacturerId = 0x5449,
37  kDeviceId = 0x1050,
38 
39  // Other
40  kDefaultTimeoutMicros = 100000,
41 };
42 
43 static dif_rv_core_ibex_t rv_core_ibex;
44 static dif_pinmux_t pinmux;
45 static dif_i2c_t i2c;
46 
47 static status_t read_manufacture_id(void) {
48  uint8_t reg = kManufacturerIdReg;
49  uint8_t data[2] = {0};
50  TRY(i2c_testutils_write(&i2c, kDeviceAddr, 1, &reg, true));
51  TRY(i2c_testutils_read(&i2c, kDeviceAddr, 2, data, kDefaultTimeoutMicros));
52  uint8_t manufacturer_id[2] = {kManufacturerId >> 8, kManufacturerId & 0xFF};
53  TRY_CHECK_ARRAYS_EQ(data, manufacturer_id, sizeof(data));
54  return OK_STATUS();
55 }
56 
57 static status_t read_product_id(void) {
58  uint8_t reg = kDeviceIdReg;
59  uint8_t data[2] = {0};
60  TRY(i2c_testutils_write(&i2c, kDeviceAddr, 1, &reg, true));
61  TRY(i2c_testutils_read(&i2c, kDeviceAddr, 2, data, kDefaultTimeoutMicros));
62  uint8_t device_id[2] = {kDeviceId >> 8, kDeviceId & 0xFF};
63  TRY_CHECK_ARRAYS_EQ(data, device_id, sizeof(data));
64  return OK_STATUS();
65 }
66 
67 static status_t read_temperature(void) {
68  uint8_t reg = kTemperatureReg;
69  uint8_t data[2] = {0};
70  TRY(i2c_testutils_write(&i2c, kDeviceAddr, 1, &reg, true));
71  TRY(i2c_testutils_read(&i2c, kDeviceAddr, 2, data, kDefaultTimeoutMicros));
72 
73  // HDC1080 temperature formula: T = -40 + 165 * (raw / 2^16)
74  // Using fixed-point math for calculations.
75  int32_t temperature_raw = (data[0] << 8) | data[1];
76  int32_t temperature_fixed = (-40 * (1 << 16)) + (165 * temperature_raw);
77  temperature_fixed /= (1 << 16);
78 
79  // Check if the temperature is within a plausible range for our CI setup.
80  CHECK(temperature_fixed >= 15 && temperature_fixed <= 40,
81  "Temperature out of range: %d", temperature_fixed);
82 
83  return OK_STATUS();
84 }
85 
86 static status_t read_humidity(void) {
87  uint8_t reg = kHumidityReg;
88  uint8_t data[2] = {0};
89  TRY(i2c_testutils_write(&i2c, kDeviceAddr, 1, &reg, true));
90  TRY(i2c_testutils_read(&i2c, kDeviceAddr, 2, data, kDefaultTimeoutMicros));
91 
92  uint16_t humidity_raw = (uint16_t)(data[0] << 8) | data[1];
93  int32_t humidity_fixed = (100 * humidity_raw) / (1 << 16);
94 
95  // Check if the humidity is within a plausible range for our CI setup.
96  CHECK(humidity_fixed >= 5 && humidity_fixed <= 95,
97  "Humidity out of range: %d", humidity_fixed);
98 
99  return OK_STATUS();
100 }
101 
102 static status_t test_init(void) {
103  mmio_region_t base_addr =
105 
106  TRY(dif_rv_core_ibex_init(base_addr, &rv_core_ibex));
107 
109  TRY(dif_i2c_init(base_addr, &i2c));
110 
112  TRY(dif_pinmux_init(base_addr, &pinmux));
113 
114  TRY(i2c_testutils_select_pinmux(&pinmux, 2, I2cPinmuxPlatformIdCw310Pmod));
115 
117 
118  return OK_STATUS();
119 }
120 
121 bool test_main(void) {
122  status_t test_result;
123  CHECK_STATUS_OK(test_init());
124 
125  // TODO: test kDifI2cSpeedFastPlus
126  // (Bug lowrisc/opentitan#18764)
128 
129  test_result = OK_STATUS();
130  for (size_t i = 0; i < ARRAYSIZE(speeds); ++i) {
131  CHECK_STATUS_OK(i2c_testutils_set_speed(&i2c, speeds[i]));
132  EXECUTE_TEST(test_result, read_manufacture_id);
133  EXECUTE_TEST(test_result, read_product_id);
134  EXECUTE_TEST(test_result, read_temperature);
135  EXECUTE_TEST(test_result, read_humidity);
136  }
137 
138  return status_ok(test_result);
139 }