]> sigrok.org Git - libsigrok.git/blame - src/hardware/uni-t-ut181a/api.c
uni-t-ut181a: implement device driver for the UNI-T UT181A multimeter
[libsigrok.git] / src / hardware / uni-t-ut181a / api.c
CommitLineData
3094e9d8
GS
1/*
2 * This file is part of the libsigrok project.
3 *
ebc51109 4 * Copyright (C) 2019-2020 Gerhard Sittig <gerhard.sittig@gmx.net>
3094e9d8
GS
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <config.h>
21#include "protocol.h"
22
ebc51109
GS
23static const uint32_t scanopts[] = {
24 SR_CONF_CONN,
25 SR_CONF_SERIALCOMM,
26};
3094e9d8 27
ebc51109
GS
28static const uint32_t drvopts[] = {
29 SR_CONF_MULTIMETER,
30 SR_CONF_THERMOMETER, /* Supports two temperature probes and diffs. */
31};
3094e9d8 32
ebc51109
GS
33static const uint32_t devopts[] = {
34 SR_CONF_CONN | SR_CONF_GET,
35 SR_CONF_CONTINUOUS,
36 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
37 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
38 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
39 SR_CONF_DATA_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
40 SR_CONF_DATALOG | SR_CONF_GET,
41 SR_CONF_MEASURED_QUANTITY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
42 SR_CONF_RANGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
43};
3094e9d8 44
ebc51109
GS
45static const char *channel_names[] = {
46 [UT181A_CH_MAIN] = "P1",
47 [UT181A_CH_AUX1] = "P2",
48 [UT181A_CH_AUX2] = "P3",
49 [UT181A_CH_AUX3] = "P4",
50 [UT181A_CH_BAR] = "bar",
51#if UT181A_WITH_TIMESTAMP
52 [UT181A_CH_TIME] = "TS",
53#endif
54};
55
56/*
57 * (Re-)retrieve the list of recordings and their names. These can change
58 * without the driver's being aware, the set is under user control.
59 *
60 * TODO Need to re-allocate the list of recording names when a larger
61 * recordings count is seen than previously allocated? This implementation
62 * assumes a known maximum number of recordings, the manual is vague on
63 * these limits.
64 */
65static int ut181a_update_recordings(const struct sr_dev_inst *sdi)
66{
67 struct dev_context *devc;
68 struct sr_serial_dev_inst *serial;
69 size_t rec_count, rec_idx;
70 int ret;
3094e9d8 71
ebc51109
GS
72 if (!sdi)
73 return SR_ERR_ARG;
74 devc = sdi->priv;
75 serial = sdi->conn;
76
77 ret = ut181a_send_cmd_get_recs_count(serial);
78 if (ret < 0)
79 return ret;
80 ret = ut181a_configure_waitfor(devc, FALSE, 0, 0,
81 FALSE, TRUE, FALSE, FALSE);
82 if (ret < 0)
83 return ret;
84 ret = ut181a_waitfor_response(sdi, 100);
85 if (ret < 0)
86 return ret;
87
88 rec_count = devc->wait_state.data_value;
89 if (rec_count > ARRAY_SIZE(devc->record_names))
90 rec_count = ARRAY_SIZE(devc->record_names);
91 for (rec_idx = 0; rec_idx < rec_count; rec_idx++) {
92 devc->info.rec_info.rec_idx = rec_idx;
93 ret = ut181a_send_cmd_get_rec_info(serial, rec_idx);
94 if (ret < 0)
95 return ret;
96 ret = ut181a_configure_waitfor(devc,
97 FALSE, CMD_CODE_GET_REC_INFO, 0,
98 FALSE, FALSE, FALSE, FALSE);
99 if (ret < 0)
100 return ret;
101 ret = ut181a_waitfor_response(sdi, 100);
102 if (ret < 0)
103 return ret;
104 }
105 devc->record_count = rec_count;
106 devc->data_source_count = DATA_SOURCE_REC_FIRST + devc->record_count;
3094e9d8 107
ebc51109 108 return SR_OK;
3094e9d8
GS
109}
110
ebc51109
GS
111/*
112 * Retrieve the device's current state. Run monitor mode for some time
113 * until the 'mode' (meter's current function) became available. There
114 * is no other way of querying the meter's current state.
115 */
116static int ut181a_query_initial_state(struct sr_dev_inst *sdi, int timeout_ms)
3094e9d8 117{
ebc51109
GS
118 struct dev_context *devc;
119 struct sr_serial_dev_inst *serial;
120 gint64 deadline;
121 int ret;
3094e9d8 122
ebc51109
GS
123 if (!sdi)
124 return SR_ERR_ARG;
125 devc = sdi->priv;
126 serial = sdi->conn;
127
128 devc->info.meas_head.mode = 0;
129 ret = ut181a_send_cmd_monitor(serial, TRUE);
130 if (ret < 0)
131 return ret;
132 ret = ut181a_configure_waitfor(devc, FALSE, 0, 0,
133 TRUE, FALSE, FALSE, FALSE);
134 if (ret < 0)
135 return ret;
136 deadline = g_get_monotonic_time();
137 deadline += timeout_ms * 1000;
138 while (1) {
139 ret = ut181a_waitfor_response(sdi, 100);
140 if (ret < 0)
141 return ret;
142 if (devc->info.meas_head.mode)
143 break;
144 if (g_get_monotonic_time() >= deadline)
145 return SR_ERR_DATA;
146 }
147 (void)ut181a_send_cmd_monitor(serial, FALSE);
148 ret = ut181a_configure_waitfor(devc, TRUE, 0, 0,
149 FALSE, FALSE, FALSE, FALSE);
150 if (ret < 0)
151 return ret;
152 (void)ut181a_waitfor_response(sdi, 100);
3094e9d8
GS
153
154 return SR_OK;
155}
156
ebc51109 157static GSList *scan(struct sr_dev_driver *di, GSList *options)
3094e9d8 158{
ebc51109
GS
159 const char *conn, *serialcomm;
160 struct sr_config *src;
161 GSList *l, *devices;
162 struct sr_serial_dev_inst *serial;
163 int ret;
164 char conn_id[64];
165 struct sr_dev_inst *sdi;
166 struct dev_context *devc;
167 size_t idx, ds_idx;
168
169 /*
170 * Implementor's note:
171 * Do _not_ add a default conn value here. Always expect users to
172 * specify the connection. Never match in the absence of a user spec.
173 *
174 * Motivation: There is no way to identify the DMM itself. Neither
175 * are the cable nor its chip unique to the device. They are not even
176 * specific to the series or the vendor. The DMM ships with a generic
177 * CP2110 USB-to-UART bridge. Attempts to auto probe will disturb
178 * other types of devices which may be attached to the probed conn.
179 *
180 * On the other hand it's perfectly fine to communicate to the
181 * device and assume that the device model will accept the requests,
182 * once the user specified the connection (and the driver), and thus
183 * instructed this driver to start such activity.
184 */
185 conn = NULL;
186 serialcomm = "9600/8n1";
187 for (l = options; l; l = l->next) {
188 src = l->data;
189 switch (src->key) {
190 case SR_CONF_CONN:
191 conn = g_variant_get_string(src->data, NULL);
192 break;
193 case SR_CONF_SERIALCOMM:
194 serialcomm = g_variant_get_string(src->data, NULL);
195 break;
196 }
197 }
198 if (!conn)
199 return NULL;
3094e9d8 200
ebc51109
GS
201 devices = NULL;
202 serial = sr_serial_dev_inst_new(conn, serialcomm);
203 ret = serial_open(serial, SERIAL_RDWR);
204 snprintf(conn_id, sizeof(conn_id), "%s", serial->port);
205 serial_flush(serial);
206 /*
207 * We cannot identify the device at this point in time.
208 * Successful open shall suffice for now. More activity
209 * will communicate to the device later, after the driver
210 * instance got created. See below for details.
211 */
212 if (ret != SR_OK) {
213 serial_close(serial);
214 sr_serial_dev_inst_free(serial);
215 return devices;
216 }
3094e9d8 217
ebc51109
GS
218 sdi = g_malloc0(sizeof(*sdi));
219 sdi->status = SR_ST_INACTIVE;
220 sdi->vendor = g_strdup("UNI-T");
221 sdi->model = g_strdup("UT181A");
222 sdi->inst_type = SR_INST_SERIAL;
223 sdi->conn = serial;
224 sdi->connection_id = g_strdup(conn_id);
225 devc = g_malloc0(sizeof(*devc));
226 sdi->priv = devc;
227 sr_sw_limits_init(&devc->limits);
228 for (idx = 0; idx < ARRAY_SIZE(channel_names); idx++) {
229 sr_channel_new(sdi, idx, SR_CHANNEL_ANALOG, TRUE,
230 channel_names[idx]);
231 }
232
233 /*
234 * Run monitor mode for a while to determine the current state
235 * of the device (which cannot get queried by other means). This
236 * also deals with devices which happen to already be in monitor
237 * mode when we connect to them. As a byproduct this query drains
238 * potentially pending RX data, before getting recording details.
239 */
240 devc->disable_feed = 1;
241 ret = ut181a_query_initial_state(sdi, 2000);
242 if (ret < 0) {
243 serial_close(serial);
244 sr_serial_dev_inst_free(serial);
245 return devices;
246 }
247
248 /*
249 * Number of recordings and their names are dynamic and under
250 * the user's control. Prepare for a maximum number of string
251 * labels, and fetch (and re-fetch) their names and current
252 * count on demand.
253 */
254 devc->data_source_names[DATA_SOURCE_LIVE] = "Live";
255 devc->data_source_names[DATA_SOURCE_SAVE] = "Save";
256 for (idx = 0; idx < MAX_REC_COUNT; idx++) {
257 ds_idx = DATA_SOURCE_REC_FIRST + idx;
258 devc->data_source_names[ds_idx] = &devc->record_names[idx][0];
259 }
260 devc->data_source_count = DATA_SOURCE_REC_FIRST;
261 ret = ut181a_update_recordings(sdi);
262 devc->data_source_count = DATA_SOURCE_REC_FIRST + devc->record_count;
263 if (ret < 0) {
264 serial_close(serial);
265 sr_serial_dev_inst_free(serial);
266 return devices;
267 }
268
269 devc->disable_feed = 0;
270 serial_close(serial);
271
272 devices = g_slist_append(devices, sdi);
273
274 return std_scan_complete(di, devices);
3094e9d8
GS
275}
276
277static int config_get(uint32_t key, GVariant **data,
278 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
279{
ebc51109
GS
280 struct dev_context *devc;
281 const struct mqopt_item *mqitem;
282 GVariant *arr[2];
283 const char *range;
3094e9d8 284
3094e9d8
GS
285 (void)cg;
286
ebc51109 287 devc = sdi->priv;
3094e9d8 288 switch (key) {
ebc51109
GS
289 case SR_CONF_CONN:
290 *data = g_variant_new_string(sdi->connection_id);
291 break;
292 case SR_CONF_LIMIT_FRAMES:
293 case SR_CONF_LIMIT_SAMPLES:
294 case SR_CONF_LIMIT_MSEC:
295 if (!devc)
296 return SR_ERR_ARG;
297 return sr_sw_limits_config_get(&devc->limits, key, data);
298 case SR_CONF_DATA_SOURCE:
299 if (!devc)
300 return SR_ERR_ARG;
301 *data = g_variant_new_string(devc->data_source_names[devc->data_source]);
302 break;
303 case SR_CONF_DATALOG:
304 if (!devc)
305 return SR_ERR_ARG;
306 *data = g_variant_new_boolean(devc->is_recording ? TRUE : FALSE);
307 break;
308 case SR_CONF_MEASURED_QUANTITY:
309 if (!devc)
310 return SR_ERR_ARG;
311 mqitem = ut181a_get_mqitem_from_mode(devc->info.meas_head.mode);
312 if (!mqitem)
313 return SR_ERR_NA;
314 arr[0] = g_variant_new_uint32(mqitem->mq);
315 arr[1] = g_variant_new_uint64(mqitem->mqflags);
316 *data = g_variant_new_tuple(arr, ARRAY_SIZE(arr));
317 break;
318 case SR_CONF_RANGE:
319 if (!devc)
320 return SR_ERR_ARG;
321 range = ut181a_get_range_from_packet_bytes(devc);
322 if (!range || !*range)
323 return SR_ERR_NA;
324 *data = g_variant_new_string(range);
325 break;
3094e9d8
GS
326 default:
327 return SR_ERR_NA;
328 }
329
ebc51109 330 return SR_OK;
3094e9d8
GS
331}
332
333static int config_set(uint32_t key, GVariant *data,
334 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
335{
ebc51109
GS
336 struct dev_context *devc;
337 ssize_t idx;
338 GVariant *tuple_child;
339 enum sr_mq mq;
340 enum sr_mqflag mqflags;
341 uint16_t mode;
3094e9d8 342 int ret;
ebc51109
GS
343 size_t rec_no;
344 const char *range;
3094e9d8 345
3094e9d8
GS
346 (void)cg;
347
ebc51109 348 devc = sdi->priv;
3094e9d8 349 switch (key) {
ebc51109
GS
350 case SR_CONF_LIMIT_FRAMES:
351 case SR_CONF_LIMIT_SAMPLES:
352 case SR_CONF_LIMIT_MSEC:
353 if (!devc)
354 return SR_ERR_ARG;
355 return sr_sw_limits_config_set(&devc->limits, key, data);
356 case SR_CONF_DATA_SOURCE:
357 if (!devc)
358 return SR_ERR_ARG;
359 /* Prefer data source names for the lookup. */
360 idx = std_str_idx(data, devc->data_source_names, devc->data_source_count);
361 if (idx >= 0) {
362 devc->data_source = idx;
363 break;
364 }
365 /*
366 * Support record number (1-based) as a fallback. The DMM
367 * "supports" ambiguous recording names (keeps offering a
368 * previously stored name for each new recording, neither
369 * automatically increments nor suggests timestamps).
370 */
371 if (sr_atoi(g_variant_get_string(data, NULL), &ret) != SR_OK)
372 return SR_ERR_ARG;
373 if (ret <= 0)
374 return SR_ERR_ARG;
375 rec_no = ret;
376 if (rec_no > devc->record_count)
377 return SR_ERR_ARG;
378 devc->data_source = DATA_SOURCE_REC_FIRST + rec_no - 1;
379 break;
380 case SR_CONF_MEASURED_QUANTITY:
381 if (!devc)
382 return SR_ERR_ARG;
383 tuple_child = g_variant_get_child_value(data, 0);
384 mq = g_variant_get_uint32(tuple_child);
385 g_variant_unref(tuple_child);
386 tuple_child = g_variant_get_child_value(data, 1);
387 mqflags = g_variant_get_uint64(tuple_child);
388 g_variant_unref(tuple_child);
389 mode = ut181a_get_mode_from_mq_flags(mq, mqflags);
390 if (!mode)
391 return SR_ERR_NA;
392 ret = ut181a_send_cmd_setmode(sdi->conn, mode);
393 if (ret < 0)
394 return ret;
395 ret = ut181a_waitfor_response(sdi->conn, 100);
396 if (ret < 0)
397 return ret;
398 if (devc->info.rsp_head.rsp_type != RSP_TYPE_REPLY_CODE)
399 return SR_ERR_DATA;
400 if (!devc->info.reply_code.ok)
401 return SR_ERR_DATA;
402 break;
403 case SR_CONF_RANGE:
404 range = g_variant_get_string(data, NULL);
405 return ut181a_set_range_from_text(sdi, range);
3094e9d8 406 default:
ebc51109 407 return SR_ERR_NA;
3094e9d8
GS
408 }
409
ebc51109 410 return SR_OK;
3094e9d8
GS
411}
412
413static int config_list(uint32_t key, GVariant **data,
414 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
415{
ebc51109 416 struct dev_context *devc;
3094e9d8
GS
417 int ret;
418
ebc51109 419 devc = sdi ? sdi->priv : NULL;
3094e9d8 420 switch (key) {
ebc51109
GS
421 case SR_CONF_SCAN_OPTIONS:
422 case SR_CONF_DEVICE_OPTIONS:
423 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
424 case SR_CONF_DATA_SOURCE:
425 if (!devc)
426 return SR_ERR_NA;
427 ret = ut181a_update_recordings(sdi);
428 if (ret < 0)
429 return ret;
430 *data = g_variant_new_strv(devc->data_source_names, devc->data_source_count);
431 break;
432 case SR_CONF_MEASURED_QUANTITY:
433 *data = ut181a_get_mq_flags_list();
434 break;
435 case SR_CONF_RANGE:
436 *data = ut181a_get_ranges_list();
437 break;
3094e9d8
GS
438 default:
439 return SR_ERR_NA;
440 }
441
ebc51109 442 return SR_OK;
3094e9d8
GS
443}
444
445static int dev_acquisition_start(const struct sr_dev_inst *sdi)
446{
ebc51109
GS
447 struct dev_context *devc;
448 struct sr_serial_dev_inst *serial;
449 int ret;
450 size_t rec_idx;
451
452 devc = sdi->priv;
453 serial = sdi->conn;
454 serial_flush(serial);
455
456 /*
457 * Send an acquisition start command which depends on the
458 * currently selected data source. Enter monitor mode for
459 * Live readings, get saved or recorded data otherwise. The
460 * latter require queries for sample counts, then run chunked
461 * download sequences (single item for Save, set of samples
462 * for Recordings).
463 */
464 if (devc->data_source == DATA_SOURCE_LIVE) {
465 ret = ut181a_send_cmd_monitor(serial, TRUE);
466 } else if (devc->data_source == DATA_SOURCE_SAVE) {
467 /*
468 * There is only one sequence of saved measurements in
469 * the device, but its length is yet unknown. Determine
470 * the number of saved items, and initiate the reception
471 * of the first value. Completion of data reception will
472 * drive subsequent progress.
473 */
474 ret = ut181a_send_cmd_get_save_count(serial);
475 if (ret < 0)
476 return ret;
477 ret = ut181a_configure_waitfor(devc, FALSE, 0, 0,
478 FALSE, FALSE, TRUE, FALSE);
479 if (ret < 0)
480 return ret;
481 ret = ut181a_waitfor_response(sdi, 200);
482 if (ret < 0)
483 return ret;
484 devc->info.save_info.save_count = devc->wait_state.data_value;
485 devc->info.save_info.save_idx = 0;
486 ret = ut181a_send_cmd_get_saved_value(serial, 0);
487 } else if (devc->data_source >= DATA_SOURCE_REC_FIRST) {
488 /*
489 * When we get here, the data source got selected, which
490 * includes an update of the device's list of recordings.
491 * So the index should be good, just the number of samples
492 * in that recording is yet unknown. Get the sample count
493 * and initiate the reception of the first chunk, completed
494 * reception of a chunk advances through the sequence.
495 */
496 rec_idx = devc->data_source - DATA_SOURCE_REC_FIRST;
497 if (rec_idx >= devc->record_count)
498 return SR_ERR_DATA;
499 devc->info.rec_info.rec_count = devc->record_count;
500 devc->info.rec_info.rec_idx = rec_idx;
501 devc->info.rec_info.auto_next = 0;
502 devc->info.rec_info.auto_feed = 1;
503 ret = ut181a_send_cmd_get_rec_info(serial, rec_idx);
504 if (ret < 0)
505 return ret;
506 ret = ut181a_configure_waitfor(devc,
507 FALSE, CMD_CODE_GET_REC_INFO, 0,
508 FALSE, FALSE, FALSE, FALSE);
509 if (ret < 0)
510 return ret;
511 ret = ut181a_waitfor_response(sdi, 200);
512 if (ret < 0)
513 return ret;
514 devc->info.rec_data.samples_total = devc->wait_state.data_value;
515 devc->info.rec_data.samples_curr = 0;
516 ret = ut181a_send_cmd_get_rec_samples(serial, rec_idx, 0);
517 }
518 if (ret < 0)
519 return ret;
520
521 sr_sw_limits_acquisition_start(&devc->limits);
522 devc->recv_count = 0;
523 std_session_send_df_header(sdi);
3094e9d8 524
ebc51109
GS
525 serial_source_add(sdi->session, serial, G_IO_IN, 10,
526 ut181a_handle_events, (void *)sdi);
3094e9d8
GS
527
528 return SR_OK;
529}
530
531static int dev_acquisition_stop(struct sr_dev_inst *sdi)
532{
3094e9d8 533
ebc51109
GS
534 sdi->status = SR_ST_STOPPING;
535 /* Initiate stop here. Activity happens in ut181a_handle_events(). */
3094e9d8
GS
536
537 return SR_OK;
538}
539
540static struct sr_dev_driver uni_t_ut181a_driver_info = {
541 .name = "uni-t-ut181a",
542 .longname = "UNI-T UT181A",
543 .api_version = 1,
544 .init = std_init,
545 .cleanup = std_cleanup,
546 .scan = scan,
547 .dev_list = std_dev_list,
548 .dev_clear = std_dev_clear,
549 .config_get = config_get,
550 .config_set = config_set,
551 .config_list = config_list,
ebc51109
GS
552 .dev_open = std_serial_dev_open,
553 .dev_close = std_serial_dev_close,
3094e9d8
GS
554 .dev_acquisition_start = dev_acquisition_start,
555 .dev_acquisition_stop = dev_acquisition_stop,
556 .context = NULL,
557};
558SR_REGISTER_DEV_DRIVER(uni_t_ut181a_driver_info);