]> sigrok.org Git - libsigrok.git/blob - hardware/hameg-hmo/protocol.c
scpi: Add CMD_GET_SAMPLE_RATE to the command enum.
[libsigrok.git] / hardware / hameg-hmo / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.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 "protocol.h"
21
22 static const char *hameg_scpi_dialect[] = {
23         [SCPI_CMD_GET_DIG_DATA]             = ":POD%d:DATA?",
24         [SCPI_CMD_GET_TIMEBASE]             = ":TIM:SCAL?",
25         [SCPI_CMD_SET_TIMEBASE]             = ":TIM:SCAL %s",
26         [SCPI_CMD_GET_COUPLING]             = ":CHAN%d:COUP?",
27         [SCPI_CMD_SET_COUPLING]             = ":CHAN%d:COUP %s",
28         [SCPI_CMD_GET_ANALOG_DATA]          = ":CHAN%d:DATA?",
29         [SCPI_CMD_GET_VERTICAL_DIV]         = ":CHAN%d:SCAL?",
30         [SCPI_CMD_SET_VERTICAL_DIV]         = ":CHAN%d:SCAL %s",
31         [SCPI_CMD_GET_DIG_POD_STATE]        = ":POD%d:STAT?",
32         [SCPI_CMD_SET_DIG_POD_STATE]        = ":POD%d:STAT %d",
33         [SCPI_CMD_GET_TRIGGER_SLOPE]        = ":TRIG:A:EDGE:SLOP?",
34         [SCPI_CMD_SET_TRIGGER_SLOPE]        = ":TRIG:A:EDGE:SLOP %s",
35         [SCPI_CMD_GET_TRIGGER_SOURCE]       = ":TRIG:A:SOUR?",
36         [SCPI_CMD_SET_TRIGGER_SOURCE]       = ":TRIG:A:SOUR %s",
37         [SCPI_CMD_GET_DIG_CHAN_STATE]       = ":LOG%d:STAT?",
38         [SCPI_CMD_SET_DIG_CHAN_STATE]       = ":LOG%d:STAT %d",
39         [SCPI_CMD_GET_VERTICAL_OFFSET]      = ":CHAN%d:POS?",
40         [SCPI_CMD_GET_HORIZ_TRIGGERPOS]     = ":TIM:POS?",
41         [SCPI_CMD_SET_HORIZ_TRIGGERPOS]     = ":TIM:POS %E",
42         [SCPI_CMD_GET_ANALOG_CHAN_STATE]    = ":CHAN%d:STAT?",
43         [SCPI_CMD_SET_ANALOG_CHAN_STATE]    = ":CHAN%d:STAT %d",
44 };
45
46 static const int32_t hmo_hwcaps[] = {
47         SR_CONF_OSCILLOSCOPE,
48         SR_CONF_TRIGGER_SOURCE,
49         SR_CONF_TIMEBASE,
50         SR_CONF_NUM_TIMEBASE,
51         SR_CONF_TRIGGER_SLOPE,
52         SR_CONF_HORIZ_TRIGGERPOS,
53 };
54
55 static const int32_t hmo_analog_caps[] = {
56         SR_CONF_NUM_VDIV,
57         SR_CONF_COUPLING,
58         SR_CONF_VDIV,
59 };
60
61 static const char *hmo_coupling_options[] = {
62         "AC",
63         "ACL",
64         "DC",
65         "DCL",
66         "GND",
67         NULL,
68 };
69
70 static const char *scope_trigger_slopes[] = {
71         "POS",
72         "NEG",
73         NULL,
74 };
75
76 static const char *hmo_compact2_trigger_sources[] = {
77         "CH1",
78         "CH2",
79         "LINE",
80         "EXT",
81         "D0",
82         "D1",
83         "D2",
84         "D3",
85         "D4",
86         "D5",
87         "D6",
88         "D7",
89         NULL,
90 };
91
92 static const char *hmo_compact4_trigger_sources[] = {
93         "CH1",
94         "CH2",
95         "CH3",
96         "CH4",
97         "LINE",
98         "EXT",
99         "D0",
100         "D1",
101         "D2",
102         "D3",
103         "D4",
104         "D5",
105         "D6",
106         "D7",
107         NULL,
108 };
109
110 static const uint64_t hmo_timebases[][2] = {
111         /* nanoseconds */
112         { 2, 1000000000 },
113         { 5, 1000000000 },
114         { 10, 1000000000 },
115         { 20, 1000000000 },
116         { 50, 1000000000 },
117         { 100, 1000000000 },
118         { 200, 1000000000 },
119         { 500, 1000000000 },
120         /* microseconds */
121         { 1, 1000000 },
122         { 2, 1000000 },
123         { 5, 1000000 },
124         { 10, 1000000 },
125         { 20, 1000000 },
126         { 50, 1000000 },
127         { 100, 1000000 },
128         { 200, 1000000 },
129         { 500, 1000000 },
130         /* milliseconds */
131         { 1, 1000 },
132         { 2, 1000 },
133         { 5, 1000 },
134         { 10, 1000 },
135         { 20, 1000 },
136         { 50, 1000 },
137         { 100, 1000 },
138         { 200, 1000 },
139         { 500, 1000 },
140         /* seconds */
141         { 1, 1 },
142         { 2, 1 },
143         { 5, 1 },
144         { 10, 1 },
145         { 20, 1 },
146         { 50, 1 },
147 };
148
149 static const uint64_t hmo_vdivs[][2] = {
150         /* millivolts */
151         { 1, 1000 },
152         { 2, 1000 },
153         { 5, 1000 },
154         { 10, 1000 },
155         { 20, 1000 },
156         { 50, 1000 },
157         { 100, 1000 },
158         { 200, 1000 },
159         { 500, 1000 },
160         /* volts */
161         { 1, 1 },
162         { 2, 1 },
163         { 5, 1 },
164         { 10, 1 },
165 };
166
167 static const char *scope_analog_probe_names[] = {
168         "CH1",
169         "CH2",
170         "CH3",
171         "CH4",
172 };
173
174 static const char *scope_digital_probe_names[] = {
175         "D0",
176         "D1",
177         "D2",
178         "D3",
179         "D4",
180         "D5",
181         "D6",
182         "D7",
183         "D8",
184         "D9",
185         "D10",
186         "D11",
187         "D12",
188         "D13",
189         "D14",
190         "D15",
191 };
192
193 static struct scope_config scope_models[] = {
194         {
195                 .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL},
196                 .analog_channels = 2,
197                 .digital_channels = 8,
198                 .digital_pods = 1,
199
200                 .analog_names = &scope_analog_probe_names,
201                 .digital_names = &scope_digital_probe_names,
202
203                 .hw_caps = &hmo_hwcaps,
204                 .num_hwcaps = ARRAY_SIZE(hmo_hwcaps),
205
206                 .analog_hwcaps = &hmo_analog_caps,
207                 .num_analog_hwcaps = ARRAY_SIZE(hmo_analog_caps),
208
209                 .coupling_options = &hmo_coupling_options,
210                 .trigger_sources = &hmo_compact2_trigger_sources,
211                 .trigger_slopes = &scope_trigger_slopes,
212
213                 .timebases = &hmo_timebases,
214                 .num_timebases = ARRAY_SIZE(hmo_timebases),
215
216                 .vdivs = &hmo_vdivs,
217                 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
218
219                 .num_xdivs = 12,
220                 .num_ydivs = 8,
221
222                 .scpi_dialect = &hameg_scpi_dialect,
223         },
224         {
225                 .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
226                 .analog_channels = 4,
227                 .digital_channels = 8,
228                 .digital_pods = 1,
229
230                 .analog_names = &scope_analog_probe_names,
231                 .digital_names = &scope_digital_probe_names,
232
233                 .hw_caps = &hmo_hwcaps,
234                 .num_hwcaps = ARRAY_SIZE(hmo_hwcaps),
235
236                 .analog_hwcaps = &hmo_analog_caps,
237                 .num_analog_hwcaps = ARRAY_SIZE(hmo_analog_caps),
238
239                 .coupling_options = &hmo_coupling_options,
240                 .trigger_sources = &hmo_compact4_trigger_sources,
241                 .trigger_slopes = &scope_trigger_slopes,
242
243                 .timebases = &hmo_timebases,
244                 .num_timebases = ARRAY_SIZE(hmo_timebases),
245
246                 .vdivs = &hmo_vdivs,
247                 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
248
249                 .num_xdivs = 12,
250                 .num_ydivs = 8,
251
252                 .scpi_dialect = &hameg_scpi_dialect,
253         },
254 };
255
256 static void scope_state_dump(struct scope_config *config,
257                              struct scope_state *state)
258 {
259         unsigned int i;
260         char *tmp;
261
262         for (i = 0; i < config->analog_channels; ++i) {
263                 tmp = sr_voltage_string((*config->vdivs)[state->analog_channels[i].vdiv][0],
264                                              (*config->vdivs)[state->analog_channels[i].vdiv][1]);
265                 sr_info("State of analog channel  %d -> %s : %s (coupling) %s (vdiv) %2.2e (offset)",
266                         i + 1, state->analog_channels[i].state ? "On" : "Off",
267                         (*config->coupling_options)[state->analog_channels[i].coupling],
268                         tmp, state->analog_channels[i].vertical_offset);
269         }
270
271         for (i = 0; i < config->digital_channels; ++i) {
272                 sr_info("State of digital channel %d -> %s", i,
273                         state->digital_channels[i] ? "On" : "Off");
274         }
275
276         for (i = 0; i < config->digital_pods; ++i) {
277                 sr_info("State of digital POD %d -> %s", i,
278                         state->digital_pods[i] ? "On" : "Off");
279         }
280
281         tmp = sr_period_string((*config->timebases)[state->timebase][0] *
282                                (*config->timebases)[state->timebase][1]);
283         sr_info("Current timebase: %s", tmp);
284         g_free(tmp);
285
286         sr_info("Current trigger: %s (source), %s (slope) %2.2e (offset)",
287                 (*config->trigger_sources)[state->trigger_source],
288                 (*config->trigger_slopes)[state->trigger_slope],
289                 state->horiz_triggerpos);
290 }
291
292 static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
293                 const char *command, const char *(*array)[], int *result)
294 {
295         char *tmp;
296         unsigned int i;
297
298         if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
299                 g_free(tmp);
300                 return SR_ERR;
301         }
302
303         for (i = 0; (*array)[i]; ++i) {
304                 if (!g_strcmp0(tmp, (*array)[i])) {
305                         *result = i;
306                         g_free(tmp);
307                         tmp = NULL;
308                         break;
309                 }
310         }
311
312         if (tmp) {
313                 g_free(tmp);
314                 return SR_ERR;
315         }
316
317         return SR_OK;
318 }
319
320 static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
321                                     struct scope_config *config,
322                                     struct scope_state *state)
323 {
324         unsigned int i, j;
325         float tmp_float;
326         char command[MAX_COMMAND_SIZE];
327
328         for (i = 0; i < config->analog_channels; ++i) {
329                 g_snprintf(command, sizeof(command),
330                            (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
331                            i + 1);
332
333                 if (sr_scpi_get_bool(scpi, command,
334                                      &state->analog_channels[i].state) != SR_OK)
335                         return SR_ERR;
336
337                 g_snprintf(command, sizeof(command),
338                            (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV],
339                            i + 1);
340
341                 if (sr_scpi_get_float(scpi, command, &tmp_float) != SR_OK)
342                         return SR_ERR;
343                 for (j = 0; j < config->num_vdivs; j++) {
344                         if (tmp_float == ((float) (*config->vdivs)[j][0] /
345                                           (*config->vdivs)[j][1])) {
346                                 state->analog_channels[i].vdiv = j;
347                                 break;
348                         }
349                 }
350                 if (i == config->num_vdivs)
351                         return SR_ERR;
352
353                 g_snprintf(command, sizeof(command),
354                            (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
355                            i + 1);
356
357                 if (sr_scpi_get_float(scpi, command,
358                                      &state->analog_channels[i].vertical_offset) != SR_OK)
359                         return SR_ERR;
360
361                 g_snprintf(command, sizeof(command),
362                            (*config->scpi_dialect)[SCPI_CMD_GET_COUPLING],
363                            i + 1);
364
365                 if (scope_state_get_array_option(scpi, command, config->coupling_options,
366                                          &state->analog_channels[i].coupling) != SR_OK)
367                         return SR_ERR;
368         }
369
370         return SR_OK;
371 }
372
373 static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
374                                      struct scope_config *config,
375                                      struct scope_state *state)
376 {
377         unsigned int i;
378         char command[MAX_COMMAND_SIZE];
379
380         for (i = 0; i < config->digital_channels; ++i) {
381                 g_snprintf(command, sizeof(command),
382                            (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
383                            i);
384
385                 if (sr_scpi_get_bool(scpi, command,
386                                      &state->digital_channels[i]) != SR_OK)
387                         return SR_ERR;
388         }
389
390         for (i = 0; i < config->digital_pods; ++i) {
391                 g_snprintf(command, sizeof(command),
392                            (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
393                            i + 1);
394
395                 if (sr_scpi_get_bool(scpi, command,
396                                      &state->digital_pods[i]) != SR_OK)
397                         return SR_ERR;
398         }
399
400         return SR_OK;
401 }
402
403 SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
404 {
405         struct dev_context *devc;
406         struct scope_state *state;
407         struct scope_config *config;
408         float tmp_float;
409         unsigned int i;
410
411         devc = sdi->priv;
412         config = devc->model_config;
413         state = devc->model_state;
414
415         sr_info("Fetching scope state");
416
417         if (analog_channel_state_get(sdi->conn, config, state) != SR_OK)
418                 return SR_ERR;
419
420         if (digital_channel_state_get(sdi->conn, config, state) != SR_OK)
421                 return SR_ERR;
422
423         if (sr_scpi_get_float(sdi->conn,
424                         (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
425                         &tmp_float) != SR_OK)
426                 return SR_ERR;
427
428         for (i = 0; i < config->num_timebases; i++) {
429                 if (tmp_float == ((float) (*config->timebases)[i][0] /
430                                   (*config->timebases)[i][1])) {
431                         state->timebase = i;
432                         break;
433                 }
434         }
435         if (i == config->num_timebases)
436                 return SR_ERR;
437
438         if (sr_scpi_get_float(sdi->conn,
439                         (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
440                         &state->horiz_triggerpos) != SR_OK)
441                 return SR_ERR;
442
443         if (scope_state_get_array_option(sdi->conn,
444                         (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SOURCE],
445                         config->trigger_sources, &state->trigger_source) != SR_OK)
446                 return SR_ERR;
447
448         if (scope_state_get_array_option(sdi->conn,
449                 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SLOPE],
450                 config->trigger_slopes, &state->trigger_slope) != SR_OK)
451                 return SR_ERR;
452
453         sr_info("Fetching finished.");
454
455         scope_state_dump(config, state);
456
457         return SR_OK;
458 }
459
460 static struct scope_state *scope_state_new(struct scope_config *config)
461 {
462         struct scope_state *state;
463
464         if (!(state = g_try_malloc0(sizeof(struct scope_state))))
465                 return NULL;
466
467         if (!(state->analog_channels = g_try_malloc0_n(config->analog_channels,
468                                     sizeof(struct analog_channel_state))))
469             goto fail;
470
471         if (!(state->digital_channels = g_try_malloc0_n(
472                         config->digital_channels, sizeof(gboolean))))
473             goto fail;
474
475         if (!(state->digital_pods = g_try_malloc0_n(config->digital_pods,
476                                                      sizeof(gboolean))))
477             goto fail;
478
479         return state;
480
481 fail:
482         if (state->analog_channels)
483                 g_free(state->analog_channels);
484         if (state->digital_channels)
485                 g_free(state->digital_channels);
486         if (state->digital_pods)
487                 g_free(state->digital_pods);
488         g_free(state);
489
490         return NULL;
491 }
492
493 SR_PRIV void hmo_scope_state_free(struct scope_state *state)
494 {
495         g_free(state->analog_channels);
496         g_free(state->digital_channels);
497         g_free(state->digital_pods);
498         g_free(state);
499 }
500
501 SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
502 {
503         char tmp[25];
504         int model_index;
505         unsigned int i, j;
506         struct sr_probe *probe;
507         struct dev_context *devc;
508
509         devc = sdi->priv;
510         model_index = -1;
511
512         /* Find the exact model. */
513         for (i = 0; i < ARRAY_SIZE(scope_models); i++) {
514                 for (j = 0; scope_models[i].name[j]; j++) {
515                         if (!strcmp(sdi->model, scope_models[i].name[j])) {
516                                 model_index = i;
517                                 break;
518                         }
519                 }
520                 if (model_index != -1)
521                         break;
522         }
523
524         if (model_index == -1) {
525                 sr_dbg("Unsupported HMO device.");
526                 return SR_ERR_NA;
527         }
528
529         if (!(devc->analog_groups = g_try_malloc0(sizeof(struct sr_probe_group) *
530                                                   scope_models[model_index].analog_channels)))
531                         return SR_ERR_MALLOC;
532
533         if (!(devc->digital_groups = g_try_malloc0(sizeof(struct sr_probe_group) *
534                                                    scope_models[model_index].digital_pods)))
535                         return SR_ERR_MALLOC;
536
537         /* Add analog channels. */
538         for (i = 0; i < scope_models[model_index].analog_channels; i++) {
539                 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
540                            (*scope_models[model_index].analog_names)[i])))
541                         return SR_ERR_MALLOC;
542                 sdi->probes = g_slist_append(sdi->probes, probe);
543
544                 devc->analog_groups[i].name =
545                         (char *)(*scope_models[model_index].analog_names)[i];
546                 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
547
548                 sdi->probe_groups = g_slist_append(sdi->probe_groups,
549                                                    &devc->analog_groups[i]);
550         }
551
552         /* Add digital probe groups. */
553         for (i = 0; i < scope_models[model_index].digital_pods; ++i) {
554                 g_snprintf(tmp, 25, "POD%d", i);
555                 devc->digital_groups[i].name = g_strdup(tmp);
556                 sdi->probe_groups = g_slist_append(sdi->probe_groups,
557                                    &devc->digital_groups[i < 8 ? 0 : 1]);
558         }
559
560         /* Add digital channels. */
561         for (i = 0; i < scope_models[model_index].digital_channels; i++) {
562                 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
563                            (*scope_models[model_index].digital_names)[i])))
564                         return SR_ERR_MALLOC;
565                 sdi->probes = g_slist_append(sdi->probes, probe);
566
567                 devc->digital_groups[i < 8 ? 0 : 1].probes = g_slist_append(
568                         devc->digital_groups[i < 8 ? 0 : 1].probes, probe);
569         }
570
571         devc->model_config = &scope_models[model_index];
572         devc->frame_limit = 0;
573
574         if (!(devc->model_state = scope_state_new(devc->model_config)))
575                 return SR_ERR_MALLOC;
576
577         return SR_OK;
578 }
579
580 SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
581 {
582         struct sr_probe *probe;
583         struct sr_dev_inst *sdi;
584         struct dev_context *devc;
585         struct sr_datafeed_packet packet;
586         GArray *data;
587         struct sr_datafeed_analog analog;
588         struct sr_datafeed_logic logic;
589
590         (void)fd;
591
592         if (!(sdi = cb_data))
593                 return TRUE;
594
595         if (!(devc = sdi->priv))
596                 return TRUE;
597
598         if (revents == G_IO_IN) {
599                 probe = devc->current_probe->data;
600
601                 switch (probe->type) {
602                 case SR_PROBE_ANALOG:
603                         if (sr_scpi_get_floatv(sdi->conn, NULL, &data) != SR_OK) {
604                                 if (data)
605                                         g_array_free(data, TRUE);
606
607                                 return TRUE;
608                         }
609
610                         packet.type = SR_DF_FRAME_BEGIN;
611                         sr_session_send(sdi, &packet);
612
613                         analog.probes = g_slist_append(NULL, probe);
614                         analog.num_samples = data->len;
615                         analog.data = (float *) data->data;
616                         analog.mq = SR_MQ_VOLTAGE;
617                         analog.unit = SR_UNIT_VOLT;
618                         analog.mqflags = 0;
619                         packet.type = SR_DF_ANALOG;
620                         packet.payload = &analog;
621                         sr_session_send(cb_data, &packet);
622                         g_slist_free(analog.probes);
623                         g_array_free(data, TRUE);
624                         break;
625                 case SR_PROBE_LOGIC:
626                         if (sr_scpi_get_uint8v(sdi->conn, NULL, &data) != SR_OK) {
627                                 if (data)
628                                         g_free(data);
629                                 return TRUE;
630                         }
631
632                         packet.type = SR_DF_FRAME_BEGIN;
633                         sr_session_send(sdi, &packet);
634
635                         logic.length = data->len;
636                         logic.unitsize = 1;
637                         logic.data = data->data;
638                         packet.type = SR_DF_LOGIC;
639                         packet.payload = &logic;
640                         sr_session_send(cb_data, &packet);
641                         g_array_free(data, TRUE);
642                         break;
643                 default:
644                         sr_err("Invalid probe type.");
645                         break;
646                 }
647
648                 packet.type = SR_DF_FRAME_END;
649                 sr_session_send(sdi, &packet);
650
651                 if (devc->current_probe->next) {
652                         devc->current_probe = devc->current_probe->next;
653                         hmo_request_data(sdi);
654                 } else if (++devc->num_frames == devc->frame_limit) {
655                         sdi->driver->dev_acquisition_stop(sdi, cb_data);
656                 } else {
657                         devc->current_probe = devc->enabled_probes;
658                         hmo_request_data(sdi);
659                 }
660         }
661
662         return TRUE;
663 }