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