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