tests/qtest: adc128d818: test voltage and temperature conversion
Cover single-ended voltage conversion across all channels, voltage and temperature boundary and clamping cases, and scaling against an external voltage reference. Signed-off-by: Emmanuel Blot <emmanuel.blot@free.fr> Link: https://lore.kernel.org/qemu-devel/20260707091609.97759-4-emmanuel.blot@free.fr Signed-off-by: Cédric Le Goater <clg@redhat.com>
Emmanuel Blot committed
Jul 7, 2026 at 11:15 UTC
c7300dca454f266a5cc52ea08775db50489cc755
1 file changed
+189
tests/qtest/adc128d818-test.c
+189
@@ -150,6 +150,186 @@ static void test_ain_property(void *obj, void *data, QGuestAllocator *alloc)
150
g_assert_cmpint(value, ==, 37500);
151
}
152
153
+/* Voltage conversion */
154
+static void test_voltage_conversion(void *obj, void *data,
155
+ QGuestAllocator *alloc)
156
+{
157
+ QI2CDevice *dev = (QI2CDevice *)obj;
158
+ uint16_t reading;
159
+
160
+ qmp_adc128d818_set("ain0", 1280);
161
+ g_test_message("Injected ain0 = 1280 mV");
162
+ i2c_set8(dev, REG_CONFIG, CONFIG_START);
163
+
164
+ reading = i2c_get16(dev, REG_CH_READING_BASE);
165
+ g_test_message("Read ch0: raw 0x%04x -> %u mV", reading,
166
+ (reading >> 4u) * INTERNAL_VREF_MV / 4096u);
167
+ g_assert_cmphex(reading, ==, 0x8000);
168
+
169
+ qmp_adc128d818_set("ain1", 2560);
170
+ g_test_message("Injected ain1 = 2560 mV");
171
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 1u);
172
+ g_test_message("Read ch1: raw 0x%04x -> %u mV", reading,
173
+ (reading >> 4u) * INTERNAL_VREF_MV / 4096u);
174
+ g_assert_cmphex(reading, ==, 0xFFF0);
175
+
176
+ qmp_adc128d818_set("ain2", 0);
177
+ g_test_message("Injected ain2 = 0 mV");
178
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 2u);
179
+ g_test_message("Read ch2: raw 0x%04x -> %u mV", reading,
180
+ (reading >> 4u) * INTERNAL_VREF_MV / 4096u);
181
+ g_assert_cmphex(reading, ==, 0x0000);
182
+}
183
+
184
+/* Temperature conversion (mode 0, channel 7 = temperature) */
185
+static void
186
+test_temperature_conversion(void *obj, void *data, QGuestAllocator *alloc)
187
+{
188
+ QI2CDevice *dev = (QI2CDevice *)obj;
189
+ uint16_t reading;
190
+
191
+ qmp_adc128d818_set("temperature", 25000);
192
+ g_test_message("Injected temperature = 25000 mC (25.0 deg C)");
193
+ i2c_set8(dev, REG_CONFIG, CONFIG_START);
194
+
195
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
196
+ g_test_message("Read ch7: raw 0x%04x -> %d mC", reading,
197
+ (int16_t)(reading & 0xFF80u) * 500 / 128);
198
+ g_assert_cmphex(reading, ==, 0x1900);
199
+}
200
+
201
+/* Channels with distinct voltages */
202
+static void test_all_channels(void *obj, void *data, QGuestAllocator *alloc)
203
+{
204
+ QI2CDevice *dev = (QI2CDevice *)obj;
205
+ static const uint16_t ain_mv[NUM_CHANNELS] = {
206
+ 0, 320, 640, 960, 1280, 1920, 2240, 2560
207
+ };
208
+ static const uint16_t expect[NUM_CHANNELS] = {
209
+ 0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xC000, 0xE000, 0xFFF0
210
+ };
211
+ uint16_t reading;
212
+ unsigned ch;
213
+
214
+ i2c_set8(dev, REG_CONFIG, CONFIG_INITIALIZATION);
215
+ i2c_set8(dev, REG_ADV_CONFIG, ADV_CONFIG_MODE_1);
216
+
217
+ for (ch = 0u; ch < NUM_CHANNELS; ch++) {
218
+ char name[8];
219
+ snprintf(name, sizeof(name), "ain%u", ch);
220
+ qmp_adc128d818_set(name, ain_mv[ch]);
221
+ }
222
+
223
+ i2c_set8(dev, REG_CONFIG, CONFIG_START);
224
+
225
+ for (ch = 0u; ch < NUM_CHANNELS; ch++) {
226
+ reading = i2c_get16(dev, REG_CH_READING_BASE + ch);
227
+ g_test_message("ch%u: ain %u mV -> raw 0x%04x (expect 0x%04x)",
228
+ ch, ain_mv[ch], reading, expect[ch]);
229
+ g_assert_cmphex(reading, ==, expect[ch]);
230
+ }
231
+}
232
+
233
+/* Voltage conversion edge cases */
234
+static void test_voltage_edges(void *obj, void *data, QGuestAllocator *alloc)
235
+{
236
+ QI2CDevice *dev = (QI2CDevice *)obj;
237
+ uint16_t reading;
238
+
239
+ i2c_set8(dev, REG_CONFIG, CONFIG_INITIALIZATION);
240
+ i2c_set8(dev, REG_ADV_CONFIG, ADV_CONFIG_MODE_1);
241
+
242
+ qmp_adc128d818_set("ain0", 3000);
243
+ i2c_set8(dev, REG_CONFIG, CONFIG_START);
244
+
245
+ reading = i2c_get16(dev, REG_CH_READING_BASE);
246
+ g_test_message("Over-range 3000 mV: raw 0x%04x (expect 0xFFF0)", reading);
247
+ g_assert_cmphex(reading, ==, 0xFFF0);
248
+
249
+ qmp_adc128d818_set("ain1", 1);
250
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 1u);
251
+ g_test_message("1 mV: raw 0x%04x (expect 0x0010)", reading);
252
+ g_assert_cmphex(reading, ==, 0x0010);
253
+
254
+ qmp_adc128d818_set("ain2", 640);
255
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 2u);
256
+ g_test_message("640 mV (quarter): raw 0x%04x (expect 0x4000)", reading);
257
+ g_assert_cmphex(reading, ==, 0x4000);
258
+
259
+ qmp_adc128d818_set("ain3", 1920);
260
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 3u);
261
+ g_test_message("1920 mV (3/4): raw 0x%04x (expect 0xC000)", reading);
262
+ g_assert_cmphex(reading, ==, 0xC000);
263
+}
264
+
265
+/* Temperature conversion edge cases */
266
+static void test_temperature_edges(void *obj, void *data,
267
+ QGuestAllocator *alloc)
268
+{
269
+ QI2CDevice *dev = (QI2CDevice *)obj;
270
+ uint16_t reading;
271
+
272
+ i2c_set8(dev, REG_CONFIG, CONFIG_INITIALIZATION);
273
+
274
+ qmp_adc128d818_set("temperature", 0);
275
+ i2c_set8(dev, REG_CONFIG, CONFIG_START);
276
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
277
+ g_test_message("0 C: raw 0x%04x (expect 0x0000)", reading);
278
+ g_assert_cmphex(reading, ==, 0x0000);
279
+
280
+ qmp_adc128d818_set("temperature", -25000);
281
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
282
+ g_test_message("-25 C: raw 0x%04x (expect 0xE700)", reading);
283
+ g_assert_cmphex(reading, ==, 0xE700);
284
+
285
+ qmp_adc128d818_set("temperature", 127500);
286
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
287
+ g_test_message("+127.5 C: raw 0x%04x (expect 0x7F80)", reading);
288
+ g_assert_cmphex(reading, ==, 0x7F80);
289
+
290
+ qmp_adc128d818_set("temperature", -128000);
291
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
292
+ g_test_message("-128 C: raw 0x%04x (expect 0x8000)", reading);
293
+ g_assert_cmphex(reading, ==, 0x8000);
294
+
295
+ qmp_adc128d818_set("temperature", 200000);
296
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
297
+ g_test_message("200 C (clamped): raw 0x%04x (expect 0x7F80)", reading);
298
+ g_assert_cmphex(reading, ==, 0x7F80);
299
+
300
+ qmp_adc128d818_set("temperature", -200000);
301
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 7u);
302
+ g_test_message("-200 C (clamped): raw 0x%04x (expect 0x8000)", reading);
303
+ g_assert_cmphex(reading, ==, 0x8000);
304
+}
305
+
306
+/* External voltage reference */
307
+static void test_ext_vref(void *obj, void *data, QGuestAllocator *alloc)
308
+{
309
+ QI2CDevice *dev = (QI2CDevice *)obj;
310
+ uint16_t reading;
311
+
312
+ i2c_set8(dev, REG_CONFIG, CONFIG_INITIALIZATION);
313
+ i2c_set8(dev, REG_ADV_CONFIG, ADV_CONFIG_MODE_1);
314
+
315
+ qmp_adc128d818_set("ext-vref-mv", 4096);
316
+ i2c_set8(dev, REG_ADV_CONFIG, ADV_CONFIG_EXT_REF_EN | ADV_CONFIG_MODE_1);
317
+
318
+ qmp_adc128d818_set("ain0", 1000);
319
+ i2c_set8(dev, REG_CONFIG, CONFIG_START);
320
+
321
+ reading = i2c_get16(dev, REG_CH_READING_BASE);
322
+ g_test_message("1000 mV / 4096 mV VREF: raw 0x%04x (expect 0x3E80)",
323
+ reading);
324
+ g_assert_cmphex(reading, ==, 0x3E80);
325
+
326
+ qmp_adc128d818_set("ain1", 2048);
327
+ reading = i2c_get16(dev, REG_CH_READING_BASE + 1u);
328
+ g_test_message("2048 mV / 4096 mV VREF: raw 0x%04x (expect 0x8000)",
329
+ reading);
330
+ g_assert_cmphex(reading, ==, 0x8000);
331
+}
332
+
333
static void adc128d818_register_nodes(void)
334
{
335
QOSGraphEdgeOptions opts = {
@@ -165,5 +345,14 @@ static void adc128d818_register_nodes(void)
345
qos_add_test("defaults", "adc128d818", test_defaults, NULL);
346
qos_add_test("soft-reset", "adc128d818", test_soft_reset, NULL);
347
qos_add_test("ain-property", "adc128d818", test_ain_property, NULL);
348
+ qos_add_test("voltage-conversion", "adc128d818", test_voltage_conversion,
349
+ NULL);
350
+ qos_add_test("temperature-conversion", "adc128d818",
351
+ test_temperature_conversion, NULL);
352
+ qos_add_test("all-channels", "adc128d818", test_all_channels, NULL);
353
+ qos_add_test("voltage-edges", "adc128d818", test_voltage_edges, NULL);
354
+ qos_add_test("temperature-edges", "adc128d818", test_temperature_edges,
355
+ NULL);
356
+ qos_add_test("ext-vref", "adc128d818", test_ext_vref, NULL);
357
}
358
libqos_init(adc128d818_register_nodes);