]> sigrok.org Git - libsigrok.git/blob - hardware/atten-pps3xxx/api.c
atten-pps3xxx: Full support for the PPS3203T-3S.
[libsigrok.git] / hardware / atten-pps3xxx / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Bert Vermeulen <bert@biot.com>
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 <string.h>
21 #include <errno.h>
22 #include "protocol.h"
23
24 /*
25  * The default serial communication settings on the device are 9600
26  * baud, 9 data bits. The 9th bit isn't actually used, and the vendor
27  * software uses Mark parity to absorb the extra bit.
28  *
29  * Since 9 data bits is not a standard available in POSIX, we use two
30  * stop bits to skip over the extra bit instead.
31  */
32 #define SERIALCOMM "9600/8n2"
33
34 static const int32_t hwopts[] = {
35         SR_CONF_CONN,
36         SR_CONF_SERIALCOMM,
37 };
38
39 static const int32_t devopts[] = {
40         SR_CONF_POWER_SUPPLY,
41         SR_CONF_CONTINUOUS,
42 };
43
44 static const int32_t devopts_sdi[] = {
45         SR_CONF_POWER_SUPPLY,
46         SR_CONF_CONTINUOUS,
47         SR_CONF_OUTPUT_CHANNEL,
48         SR_CONF_OVER_CURRENT_PROTECTION,
49 };
50
51 static const int32_t devopts_pg[] = {
52         SR_CONF_POWER_SUPPLY,
53         SR_CONF_CONTINUOUS,
54         SR_CONF_OUTPUT_VOLTAGE,
55         SR_CONF_OUTPUT_VOLTAGE_MAX,
56         SR_CONF_OUTPUT_CURRENT,
57         SR_CONF_OUTPUT_CURRENT_MAX,
58         SR_CONF_OUTPUT_ENABLED,
59 };
60
61 static const char *channel_modes[] = {
62         "Independent",
63         "Series",
64         "Parallel",
65 };
66
67 static struct pps_model models[] = {
68         { PPS_3203T_3S, "PPS3203T-3S",
69                 CHANMODE_INDEPENDENT | CHANMODE_SERIES | CHANMODE_PARALLEL,
70                 3,
71                 {
72                         /* Channel 1 */
73                         { { 0, 32, 0.01 }, { 0, 3, 0.001 } },
74                         /* Channel 2 */
75                         { { 0, 32, 0.01 }, { 0, 3, 0.001 } },
76                         /* Channel 3 */
77                         { { 0, 6, 0.01 }, { 0, 3, 0.001 } },
78                 },
79         },
80 };
81
82
83 SR_PRIV struct sr_dev_driver atten_pps3203_driver_info;
84 static struct sr_dev_driver *di = &atten_pps3203_driver_info;
85
86 static int init(struct sr_context *sr_ctx)
87 {
88         return std_init(sr_ctx, di, LOG_PREFIX);
89 }
90
91 static GSList *scan(GSList *options, int modelid)
92 {
93         struct sr_dev_inst *sdi;
94         struct drv_context *drvc;
95         struct dev_context *devc;
96         struct sr_config *src;
97         struct sr_probe *probe;
98         struct sr_probe_group *pg;
99         struct sr_serial_dev_inst *serial;
100         GSList *l, *devices;
101         struct pps_model *model;
102         uint8_t packet[PACKET_SIZE];
103         unsigned int i;
104         int ret;
105         const char *conn, *serialcomm;
106         char channel[10];
107
108         devices = NULL;
109         drvc = di->priv;
110         drvc->instances = NULL;
111
112         conn = serialcomm = NULL;
113         for (l = options; l; l = l->next) {
114                 src = l->data;
115                 switch (src->key) {
116                 case SR_CONF_CONN:
117                         conn = g_variant_get_string(src->data, NULL);
118                         break;
119                 case SR_CONF_SERIALCOMM:
120                         serialcomm = g_variant_get_string(src->data, NULL);
121                         break;
122                 }
123         }
124         if (!conn)
125                 return NULL;
126         if (!serialcomm)
127                 serialcomm = SERIALCOMM;
128
129         if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
130                 return NULL;
131
132         if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
133                 return NULL;
134         serial_flush(serial);
135
136         /* This is how the vendor software probes for hardware. */
137         memset(packet, 0, PACKET_SIZE);
138         packet[0] = 0xaa;
139         packet[1] = 0xaa;
140         if (serial_write(serial, packet, PACKET_SIZE) == -1) {
141                 sr_err("Unable to write while probing for hardware: %s",
142                                 strerror(errno));
143                 return NULL;
144         }
145         /* The device responds with a 24-byte packet when it receives a packet.
146          * At 9600 baud, 300ms is long enough for it to have arrived. */
147         g_usleep(300 * 1000);
148         memset(packet, 0, PACKET_SIZE);
149         if ((ret = serial_read_nonblocking(serial, packet, PACKET_SIZE)) < 0) {
150                 sr_err("Unable to read while probing for hardware: %s",
151                                 strerror(errno));
152                 return NULL;
153         }
154         if (ret != PACKET_SIZE || packet[0] != 0xaa || packet[1] != 0xaa) {
155                 /* Doesn't look like an Atten PPS. */
156                 return NULL;
157         }
158
159         model = NULL;
160         for (i = 0; i < ARRAY_SIZE(models); i++) {
161                 if (models[i].modelid == modelid) {
162                         model = &models[i];
163                         break;
164                 }
165         }
166         if (!model) {
167                 sr_err("Unknown modelid %d", modelid);
168                 return NULL;
169         }
170
171         sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, "Atten", model->name, NULL);
172         sdi->driver = di;
173         sdi->inst_type = SR_INST_SERIAL;
174         sdi->conn = serial;
175         for (i = 0; i < MAX_CHANNELS; i++) {
176                 snprintf(channel, 10, "CH%d", i + 1);
177                 probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel);
178                 sdi->probes = g_slist_append(sdi->probes, probe);
179                 pg = g_malloc(sizeof(struct sr_probe_group));
180                 pg->name = g_strdup(channel);
181                 pg->probes = g_slist_append(NULL, probe);
182                 pg->priv = NULL;
183                 sdi->probe_groups = g_slist_append(sdi->probe_groups, pg);
184         }
185
186         devc = g_malloc0(sizeof(struct dev_context));
187         devc->model = model;
188         devc->config = g_malloc0(sizeof(struct per_channel_config) * model->num_channels);
189         sdi->priv = devc;
190         drvc->instances = g_slist_append(drvc->instances, sdi);
191         devices = g_slist_append(devices, sdi);
192
193         serial_close(serial);
194         if (!devices)
195                 sr_serial_dev_inst_free(serial);
196
197         return devices;
198 }
199
200 static GSList *scan_3203(GSList *options)
201 {
202         return scan(options, PPS_3203T_3S);
203 }
204
205 static GSList *dev_list(void)
206 {
207         return ((struct drv_context *)(di->priv))->instances;
208 }
209
210 static int dev_clear(void)
211 {
212         return std_dev_clear(di, NULL);
213 }
214
215 static int cleanup(void)
216 {
217         return dev_clear();
218 }
219
220 static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi,
221                 const struct sr_probe_group *probe_group)
222 {
223         struct dev_context *devc;
224         struct sr_probe *probe;
225         int channel, ret;
226
227         if (!sdi)
228                 return SR_ERR_ARG;
229
230         devc = sdi->priv;
231
232         ret = SR_OK;
233         if (!probe_group) {
234                 /* No probe group: global options. */
235                 switch (key) {
236                 case SR_CONF_OUTPUT_CHANNEL:
237                         *data = g_variant_new_string(channel_modes[devc->channel_mode - 1]);
238                         break;
239                 case SR_CONF_OVER_CURRENT_PROTECTION:
240                         *data = g_variant_new_boolean(devc->over_current_protection);
241                         break;
242                 default:
243                         return SR_ERR_NA;
244                 }
245         } else {
246                 /* We only ever have one channel per probe group in this driver. */
247                 probe = probe_group->probes->data;
248                 channel = probe->index;
249
250                 switch (key) {
251                 case SR_CONF_OUTPUT_VOLTAGE:
252                         *data = g_variant_new_double(devc->config[channel].output_voltage_last);
253                         break;
254                 case SR_CONF_OUTPUT_VOLTAGE_MAX:
255                         *data = g_variant_new_double(devc->config[channel].output_voltage_max);
256                         break;
257                 case SR_CONF_OUTPUT_CURRENT:
258                         *data = g_variant_new_double(devc->config[channel].output_current_last);
259                         break;
260                 case SR_CONF_OUTPUT_CURRENT_MAX:
261                         *data = g_variant_new_double(devc->config[channel].output_current_max);
262                         break;
263                 case SR_CONF_OUTPUT_ENABLED:
264                         *data = g_variant_new_boolean(devc->config[channel].output_enabled);
265                         break;
266                 default:
267                         return SR_ERR_NA;
268                 }
269         }
270
271         return ret;
272 }
273
274 static int find_str(const char *str, const char **strings, int array_size)
275 {
276         int idx, i;
277
278         idx = -1;
279         for (i = 0; i < array_size; i++) {
280                 if (!strcmp(str, strings[i])) {
281                         idx = i;
282                         break;
283                 }
284         }
285
286         return idx;
287 }
288
289 static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi,
290                 const struct sr_probe_group *probe_group)
291 {
292         struct dev_context *devc;
293         struct sr_probe *probe;
294         gdouble dval;
295         int channel, ret, ival;
296         const char *sval;
297         gboolean bval;
298
299         if (sdi->status != SR_ST_ACTIVE)
300                 return SR_ERR_DEV_CLOSED;
301
302         ret = SR_OK;
303         devc = sdi->priv;
304         if (!probe_group) {
305                 /* No probe group: global options. */
306                 switch (key) {
307                 case SR_CONF_OUTPUT_CHANNEL:
308                         sval = g_variant_get_string(data, NULL);
309                         if ((ival = find_str(sval, channel_modes,
310                                                         ARRAY_SIZE(channel_modes))) == -1) {
311                                 ret = SR_ERR_ARG;
312                                 break;
313                         }
314                         if (devc->model->channel_modes && (1 << ival) == 0) {
315                                 /* Not supported on this model. */
316                                 ret = SR_ERR_ARG;
317                         }
318                         if (ival == devc->channel_mode_set)
319                                 /* Nothing to do. */
320                                 break;
321                         devc->channel_mode_set = ival;
322                         if (devc->acquisition_running)
323                                 send_config(sdi);
324                         break;
325                 case SR_CONF_OVER_CURRENT_PROTECTION:
326                         bval = g_variant_get_boolean(data);
327                         if (bval == devc->over_current_protection_set)
328                                 /* Nothing to do. */
329                                 break;
330                         devc->over_current_protection_set = bval;
331                         if (devc->acquisition_running)
332                                 send_config(sdi);
333                         break;
334                 default:
335                         return SR_ERR_NA;
336                 }
337         } else {
338                 /* Probe group specified: per-channel options. */
339                 /* We only ever have one channel per probe group in this driver. */
340                 probe = probe_group->probes->data;
341                 channel = probe->index;
342
343                 switch (key) {
344                 case SR_CONF_OUTPUT_VOLTAGE_MAX:
345                         dval = g_variant_get_double(data);
346                         if (dval < 0 || dval > devc->model->channels[channel].voltage[1])
347                                 ret = SR_ERR_ARG;
348                         devc->config[channel].output_voltage_max = dval;
349                         if (devc->acquisition_running)
350                                 send_config(sdi);
351                         break;
352                 case SR_CONF_OUTPUT_CURRENT_MAX:
353                         dval = g_variant_get_double(data);
354                         if (dval < 0 || dval > devc->model->channels[channel].current[1])
355                                 ret = SR_ERR_ARG;
356                         devc->config[channel].output_current_max = dval;
357                         if (devc->acquisition_running)
358                                 send_config(sdi);
359                         break;
360                 case SR_CONF_OUTPUT_ENABLED:
361                         bval = g_variant_get_boolean(data);
362                         if (bval == devc->config[channel].output_enabled_set)
363                                 /* Nothing to do. */
364                                 break;
365                         devc->config[channel].output_enabled_set = bval;
366                         if (devc->acquisition_running)
367                                 send_config(sdi);
368                         break;
369                 default:
370                         ret = SR_ERR_NA;
371                 }
372         }
373
374
375         return ret;
376 }
377
378 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
379                 const struct sr_probe_group *probe_group)
380 {
381         struct dev_context *devc;
382         struct sr_probe *probe;
383         GVariant *gvar;
384         GVariantBuilder gvb;
385         int channel, ret, i;
386
387         /* Always available, even without sdi. */
388         if (key == SR_CONF_SCAN_OPTIONS) {
389                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
390                                 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
391                 return SR_OK;
392         }
393
394         if (!sdi) {
395                 if (key == SR_CONF_DEVICE_OPTIONS) {
396                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
397                                         devopts, ARRAY_SIZE(devopts), sizeof(int32_t));
398                         return SR_OK;
399
400                 } else {
401                         /* Everything else needs an sdi. */
402                         return SR_ERR_ARG;
403                 }
404         }
405         devc = sdi->priv;
406
407         ret = SR_OK;
408         if (!probe_group) {
409                 /* No probe group: global options. */
410                 switch (key) {
411                 case SR_CONF_DEVICE_OPTIONS:
412                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
413                                         devopts_sdi, ARRAY_SIZE(devopts_sdi), sizeof(int32_t));
414                         break;
415                 case SR_CONF_OUTPUT_CHANNEL:
416                         if (devc->model->channel_modes == CHANMODE_INDEPENDENT) {
417                                 /* The 1-channel models. */
418                                 *data = g_variant_new_strv(channel_modes, 1);
419                         } else {
420                                 /* The other models support all modes. */
421                                 *data = g_variant_new_strv(channel_modes, ARRAY_SIZE(channel_modes));
422                         }
423                         break;
424                 default:
425                         return SR_ERR_NA;
426                 }
427         } else {
428                 /* Probe group specified: per-channel options. */
429                 if (!sdi)
430                         return SR_ERR_ARG;
431                 /* We only ever have one channel per probe group in this driver. */
432                 probe = probe_group->probes->data;
433                 channel = probe->index;
434
435                 switch (key) {
436                 case SR_CONF_DEVICE_OPTIONS:
437                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
438                                         devopts_pg, ARRAY_SIZE(devopts_pg), sizeof(int32_t));
439                         break;
440                 case SR_CONF_OUTPUT_VOLTAGE_MAX:
441                         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
442                         /* Min, max, step. */
443                         for (i = 0; i < 3; i++) {
444                                 gvar = g_variant_new_double(devc->model->channels[channel].voltage[i]);
445                                 g_variant_builder_add_value(&gvb, gvar);
446                         }
447                         *data = g_variant_builder_end(&gvb);
448                         break;
449                 case SR_CONF_OUTPUT_CURRENT_MAX:
450                         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
451                         /* Min, max, step. */
452                         for (i = 0; i < 3; i++) {
453                                 gvar = g_variant_new_double(devc->model->channels[channel].current[i]);
454                                 g_variant_builder_add_value(&gvb, gvar);
455                         }
456                         *data = g_variant_builder_end(&gvb);
457                         break;
458                 default:
459                         return SR_ERR_NA;
460                 }
461         }
462
463         return ret;
464 }
465
466 static int dev_acquisition_start(const struct sr_dev_inst *sdi,
467                 void *cb_data)
468 {
469         struct dev_context *devc;
470         struct sr_serial_dev_inst *serial;
471         uint8_t packet[PACKET_SIZE];
472
473         (void)cb_data;
474
475         if (sdi->status != SR_ST_ACTIVE)
476                 return SR_ERR_DEV_CLOSED;
477
478         devc = sdi->priv;
479         memset(devc->packet, 0x44, PACKET_SIZE);
480         devc->packet_size = 0;
481
482         devc->acquisition_running = TRUE;
483
484         serial = sdi->conn;
485         serial_source_add(serial, G_IO_IN, 50, atten_pps3xxx_receive_data, (void *)sdi);
486         std_session_send_df_header(cb_data, LOG_PREFIX);
487
488         /* Send a "probe" configuration packet now. */
489         memset(packet, 0, PACKET_SIZE);
490         packet[0] = 0xaa;
491         packet[1] = 0xaa;
492         send_packet(sdi, packet);
493
494         return SR_OK;
495 }
496
497 static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
498 {
499         struct dev_context *devc;
500
501         (void)cb_data;
502
503         if (sdi->status != SR_ST_ACTIVE)
504                 return SR_ERR_DEV_CLOSED;
505
506         devc = sdi->priv;
507         devc->acquisition_running = FALSE;
508
509         return SR_OK;
510 }
511
512 SR_PRIV struct sr_dev_driver atten_pps3203_driver_info = {
513         .name = "atten-pps3203",
514         .longname = "Atten PPS3203T-3S",
515         .api_version = 1,
516         .init = init,
517         .cleanup = cleanup,
518         .scan = scan_3203,
519         .dev_list = dev_list,
520         .dev_clear = dev_clear,
521         .config_get = config_get,
522         .config_set = config_set,
523         .config_list = config_list,
524         .dev_open = std_serial_dev_open,
525         .dev_close = std_serial_dev_close,
526         .dev_acquisition_start = dev_acquisition_start,
527         .dev_acquisition_stop = dev_acquisition_stop,
528         .priv = NULL,
529 };