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