From 8bf44fcbb44721b155ae4473362ee9493b2e3eaa Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Thu, 19 Mar 2020 07:57:37 +0200 Subject: [PATCH 01/24] adalm2000: Initial driver skeleton. --- Makefile.am | 6 ++ configure.ac | 1 + src/hardware/adalm2000/api.c | 154 ++++++++++++++++++++++++++++++ src/hardware/adalm2000/protocol.c | 41 ++++++++ src/hardware/adalm2000/protocol.h | 35 +++++++ 5 files changed, 237 insertions(+) create mode 100644 src/hardware/adalm2000/api.c create mode 100644 src/hardware/adalm2000/protocol.c create mode 100644 src/hardware/adalm2000/protocol.h diff --git a/Makefile.am b/Makefile.am index 9bab81dd3..d084e2fd8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -214,6 +214,12 @@ src_libdrivers_tail_la_SOURCES = src/driver_list_stop.c src_libdrivers_la_SOURCES = src/drivers.c +if HW_ADALM2000 +src_libdrivers_la_SOURCES += \ + src/hardware/adalm2000/protocol.h \ + src/hardware/adalm2000/protocol.c \ + src/hardware/adalm2000/api.c +endif if HW_AGILENT_DMM src_libdrivers_la_SOURCES += \ src/hardware/agilent-dmm/protocol.h \ diff --git a/configure.ac b/configure.ac index ba2d45133..1e8eda210 100644 --- a/configure.ac +++ b/configure.ac @@ -257,6 +257,7 @@ m4_define([_SR_DRIVER], [ m4_define([SR_DRIVER], [_SR_DRIVER([$1], [$2], m4_expand([AS_TR_CPP([HW_$2])]), [$3])]) +SR_DRIVER([ADALM2000], [adalm2000]) SR_DRIVER([Agilent DMM], [agilent-dmm], [serial_comm]) SR_DRIVER([Appa 55II], [appa-55ii], [serial_comm]) SR_DRIVER([Arachnid Labs Re:load Pro], [arachnid-labs-re-load-pro], [serial_comm]) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c new file mode 100644 index 000000000..039c32c41 --- /dev/null +++ b/src/hardware/adalm2000/api.c @@ -0,0 +1,154 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2020 Analog Devices Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "protocol.h" + +static struct sr_dev_driver adalm2000_driver_info; + +static GSList *scan(struct sr_dev_driver *di, GSList *options) +{ + struct drv_context *drvc; + GSList *devices; + + (void)options; + + devices = NULL; + drvc = di->context; + drvc->instances = NULL; + + /* TODO: scan for devices, either based on a SR_CONF_CONN option + * or on a USB scan. */ + + return devices; +} + +static int dev_open(struct sr_dev_inst *sdi) +{ + (void)sdi; + + /* TODO: get handle from sdi->conn and open it. */ + + return SR_OK; +} + +static int dev_close(struct sr_dev_inst *sdi) +{ + (void)sdi; + + /* TODO: get handle from sdi->conn and close it. */ + + return SR_OK; +} + +static int config_get(uint32_t key, GVariant **data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) +{ + int ret; + + (void)sdi; + (void)data; + (void)cg; + + ret = SR_OK; + switch (key) { + /* TODO */ + default: + return SR_ERR_NA; + } + + return ret; +} + +static int config_set(uint32_t key, GVariant *data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) +{ + int ret; + + (void)sdi; + (void)data; + (void)cg; + + ret = SR_OK; + switch (key) { + /* TODO */ + default: + ret = SR_ERR_NA; + } + + return ret; +} + +static int config_list(uint32_t key, GVariant **data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) +{ + int ret; + + (void)sdi; + (void)data; + (void)cg; + + ret = SR_OK; + switch (key) { + /* TODO */ + default: + return SR_ERR_NA; + } + + return ret; +} + +static int dev_acquisition_start(const struct sr_dev_inst *sdi) +{ + /* TODO: configure hardware, reset acquisition state, set up + * callbacks and send header packet. */ + + (void)sdi; + + return SR_OK; +} + +static int dev_acquisition_stop(struct sr_dev_inst *sdi) +{ + /* TODO: stop acquisition. */ + + (void)sdi; + + return SR_OK; +} + +static struct sr_dev_driver adalm2000_driver_info = { + .name = "adalm2000", + .longname = "ADALM2000", + .api_version = 1, + .init = std_init, + .cleanup = std_cleanup, + .scan = scan, + .dev_list = std_dev_list, + .dev_clear = std_dev_clear, + .config_get = config_get, + .config_set = config_set, + .config_list = config_list, + .dev_open = dev_open, + .dev_close = dev_close, + .dev_acquisition_start = dev_acquisition_start, + .dev_acquisition_stop = dev_acquisition_stop, + .context = NULL, +}; +SR_REGISTER_DEV_DRIVER(adalm2000_driver_info); diff --git a/src/hardware/adalm2000/protocol.c b/src/hardware/adalm2000/protocol.c new file mode 100644 index 000000000..2a3828beb --- /dev/null +++ b/src/hardware/adalm2000/protocol.c @@ -0,0 +1,41 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2020 Analog Devices Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "protocol.h" + +SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data) +{ + const struct sr_dev_inst *sdi; + struct dev_context *devc; + + (void)fd; + + if (!(sdi = cb_data)) + return TRUE; + + if (!(devc = sdi->priv)) + return TRUE; + + if (revents == G_IO_IN) { + /* TODO */ + } + + return TRUE; +} diff --git a/src/hardware/adalm2000/protocol.h b/src/hardware/adalm2000/protocol.h new file mode 100644 index 000000000..f184294cd --- /dev/null +++ b/src/hardware/adalm2000/protocol.h @@ -0,0 +1,35 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2020 Analog Devices Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LIBSIGROK_HARDWARE_ADALM2000_PROTOCOL_H +#define LIBSIGROK_HARDWARE_ADALM2000_PROTOCOL_H + +#include +#include +#include +#include "libsigrok-internal.h" + +#define LOG_PREFIX "adalm2000" + +struct dev_context { +}; + +SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data); + +#endif From 163fc589a653602ce73c1c07699756855fa69eba Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:09:07 +0300 Subject: [PATCH 02/24] configure.ac: Add libm2k dependency. Build adalm2000 driver only if libm2k is found in the system. Signed-off-by: Teo Perisanu --- configure.ac | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1e8eda210..d762ae24e 100644 --- a/configure.ac +++ b/configure.ac @@ -140,6 +140,13 @@ AS_IF([test "x$sr_have_libieee1284" = xyes], SR_ARG_OPT_PKG([libgio], [LIBGIO], , [gio-2.0 >= 2.24.0]) +AC_LANG_PUSH([C++]) +PKG_CHECK_MODULES(LIBM2K, libm2k) +AC_DEFINE([HAVE_LIBM2K], [1], [Have libm2k dep.]) +SR_APPEND([sr_deps_avail], [libm2k]) +AM_CONDITIONAL([NEED_LIBM2K], [test "x$sr_have_libm2k" = xyes]) +AC_LANG_POP([C++]) + # See if any of the (potentially platform specific) libs are available # which provide some means of Bluetooth communication. AS_IF([test "x$sr_have_libbluez" = xyes], @@ -257,7 +264,7 @@ m4_define([_SR_DRIVER], [ m4_define([SR_DRIVER], [_SR_DRIVER([$1], [$2], m4_expand([AS_TR_CPP([HW_$2])]), [$3])]) -SR_DRIVER([ADALM2000], [adalm2000]) +SR_DRIVER([ADALM2000], [adalm2000], [libm2k]) SR_DRIVER([Agilent DMM], [agilent-dmm], [serial_comm]) SR_DRIVER([Appa 55II], [appa-55ii], [serial_comm]) SR_DRIVER([Arachnid Labs Re:load Pro], [arachnid-labs-re-load-pro], [serial_comm]) @@ -570,6 +577,8 @@ AC_SUBST([SR_PKGLIBS]) # Retrieve the compile and link flags for all modules combined. # Also, bail out at this point if any module dependency is not met. + +PKG_CHECK_MODULES([LIBSIGROK], [libm2k $SR_PKGLIBS]) PKG_CHECK_MODULES([LIBSIGROK], [glib-2.0 >= 2.32.0 $SR_PKGLIBS]) PKG_CHECK_MODULES([TESTS], [$SR_PKGLIBS_TESTS glib-2.0 $SR_PKGLIBS]) From 2929af4f5651b5dcb29aa001ffb1ee3323919ede Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:11:13 +0300 Subject: [PATCH 03/24] adalm2000: Add C wrapper files for libm2k. libm2k is a C++ library. In order to use it for the driver, a C code wrapper must be created. Signed-off-by: Teo Perisanu --- Makefile.am | 2 ++ src/hardware/adalm2000/libm2k.cpp | 23 +++++++++++++++++++++ src/hardware/adalm2000/libm2k.h | 33 +++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/hardware/adalm2000/libm2k.cpp create mode 100644 src/hardware/adalm2000/libm2k.h diff --git a/Makefile.am b/Makefile.am index d084e2fd8..326a5d4de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -216,6 +216,8 @@ src_libdrivers_la_SOURCES = src/drivers.c if HW_ADALM2000 src_libdrivers_la_SOURCES += \ + src/hardware/adalm2000/libm2k.h \ + src/hardware/adalm2000/libm2k.cpp \ src/hardware/adalm2000/protocol.h \ src/hardware/adalm2000/protocol.c \ src/hardware/adalm2000/api.c diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp new file mode 100644 index 000000000..6e7b7bc84 --- /dev/null +++ b/src/hardware/adalm2000/libm2k.cpp @@ -0,0 +1,23 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2020 Analog Devices Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "libm2k.h" + +extern "C" { +} diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h new file mode 100644 index 000000000..eb1f21d7e --- /dev/null +++ b/src/hardware/adalm2000/libm2k.h @@ -0,0 +1,33 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2020 Analog Devices Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LIBSIGROK_HARDWARE_ADALM2000_LIBM2K_H +#define LIBSIGROK_HARDWARE_ADALM2000_LIBM2K_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif +#endif //LIBSIGROK_HARDWARE_ADALM2000_LIBM2K_H From 57cce43ce5c9972c1eb4c0697f2dde111ce45829 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:20:06 +0300 Subject: [PATCH 04/24] adalm2000: List device options. adalm2000 has both a 16-channel logic analyzer and a 2-channel oscilloscope. There are some global attributes, but also each channel has several specific attributes. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 70 ++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 039c32c41..3f0411052 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -20,6 +20,28 @@ #include #include "protocol.h" + +static const uint32_t scanopts[] = { + SR_CONF_CONN, +}; + +static const uint32_t drvopts[] = { + SR_CONF_LOGIC_ANALYZER, + SR_CONF_OSCILLOSCOPE, +}; + +static const uint32_t devopts[] = { +}; + +static const uint32_t devopts_cg_analog_group[] = { +}; + +static const uint32_t devopts_cg_analog_channel[] = { +}; + +static const uint32_t devopts_cg[] = { +}; + static struct sr_dev_driver adalm2000_driver_info; static GSList *scan(struct sr_dev_driver *di, GSList *options) @@ -96,22 +118,42 @@ static int config_set(uint32_t key, GVariant *data, } static int config_list(uint32_t key, GVariant **data, - const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { - int ret; - - (void)sdi; - (void)data; - (void)cg; - - ret = SR_OK; - switch (key) { - /* TODO */ - default: - return SR_ERR_NA; + struct sr_channel *ch; + + if (!cg) { + switch (key) { + case SR_CONF_SCAN_OPTIONS: + case SR_CONF_DEVICE_OPTIONS: + return STD_CONFIG_LIST(key, data, sdi, cg, + scanopts, drvopts, + devopts); + + default: + return SR_ERR_NA; + } + } else { + ch = cg->channels->data; + + switch (key) { + case SR_CONF_DEVICE_OPTIONS: + if (ch->type == SR_CHANNEL_ANALOG) { + if (strcmp(cg->name, "Analog") == 0) { + *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_analog_group)); + } else { + *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_analog_channel)); + } + } else { + *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg)); + } + break; + default: + return SR_ERR_NA; + } } - - return ret; + return SR_OK; } static int dev_acquisition_start(const struct sr_dev_inst *sdi) From 8ac1da28077edac039d79cb58916cae93234b6e9 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:25:20 +0300 Subject: [PATCH 05/24] adalm2000: Detect devices. Add the initial structure of the device. Scan for each USB connected board. Also an IP can be provided, in order to create a connection. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 105 +++++++++++++++++++++++++++--- src/hardware/adalm2000/libm2k.cpp | 23 +++++++ src/hardware/adalm2000/libm2k.h | 12 ++++ src/hardware/adalm2000/protocol.h | 20 ++++++ 4 files changed, 152 insertions(+), 8 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 3f0411052..5965bc914 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -46,19 +46,108 @@ static struct sr_dev_driver adalm2000_driver_info; static GSList *scan(struct sr_dev_driver *di, GSList *options) { - struct drv_context *drvc; - GSList *devices; + struct dev_context *devc; + struct sr_dev_inst *sdi; + struct sr_channel *ch; - (void)options; + struct sr_channel_group *cg, *acg; + struct sr_config *src; + GSList *l, *devices; + struct CONTEXT_INFO **devlist; + unsigned int i, j, len; + char *conn; + char channel_name[16]; + char ip[30]; + gboolean ip_connection; + + conn = NULL; + ip_connection = FALSE; + + for (l = options; l; l = l->next) { + src = l->data; + switch (src->key) { + case SR_CONF_CONN: + conn = (char *) g_variant_get_string(src->data, NULL); + break; + } + } + if (conn) { + if (strstr(conn, "tcp")) { + strtok(conn, "/"); + snprintf(ip, 30, "ip:%s", strtok(NULL, "/")); + ip_connection = TRUE; + } + } devices = NULL; - drvc = di->context; - drvc->instances = NULL; - /* TODO: scan for devices, either based on a SR_CONF_CONN option - * or on a USB scan. */ + len = sr_libm2k_context_get_all(&devlist); + + for (i = 0; i < len; i++) { + struct CONTEXT_INFO *info = (struct CONTEXT_INFO *) devlist[i]; + + sdi = g_malloc0(sizeof(struct sr_dev_inst)); + devc = g_malloc0(sizeof(struct dev_context)); + + sdi->status = SR_ST_INACTIVE; + sdi->vendor = g_strdup(info->manufacturer); + sdi->model = g_strdup(info->product); + sdi->serial_num = g_strdup(info->serial); + sdi->connection_id = g_strdup(info->uri); + if (ip_connection) { + sdi->conn = g_strdup(ip); + } else { + sdi->conn = g_strdup(info->uri); + } + + cg = g_malloc0(sizeof(struct sr_channel_group)); + cg->name = g_strdup("Logic"); + + for (j = 0; j < DEFAULT_NUM_LOGIC_CHANNELS; j++) { + snprintf(channel_name, 16, "DIO%d", j); + ch = sr_channel_new(sdi, j, SR_CHANNEL_LOGIC, TRUE, + channel_name); + cg->channels = g_slist_append(cg->channels, ch); + } + sdi->channel_groups = g_slist_append(NULL, cg); + + acg = g_malloc0(sizeof(struct sr_channel_group)); + acg->name = g_strdup("Analog"); + sdi->channel_groups = g_slist_append(sdi->channel_groups, acg); + + for (j = 0; j < DEFAULT_NUM_ANALOG_CHANNELS; j++) { + snprintf(channel_name, 16, "A%d", j); + + cg = g_malloc0(sizeof(struct sr_channel_group)); + cg->name = g_strdup(channel_name); + + ch = sr_channel_new(sdi, j, + SR_CHANNEL_ANALOG, TRUE, + channel_name); + + acg->channels = g_slist_append(acg->channels, ch); - return devices; + cg->channels = g_slist_append(cg->channels, ch); + sdi->channel_groups = g_slist_append( + sdi->channel_groups, cg); + + } + devc->m2k = NULL; + devc->logic_unitsize = 2; + devc->buffersize = 1 << 16; + sr_analog_init(&devc->packet, &devc->encoding, &devc->meaning, + &devc->spec, 6); + + devc->meaning.mq = SR_MQ_VOLTAGE; + devc->meaning.unit = SR_UNIT_VOLT; + devc->meaning.mqflags = 0; + + sdi->priv = devc; + sdi->inst_type = SR_INST_USB; + + devices = g_slist_append(devices, sdi); + } + return std_scan_complete(di, devices); } static int dev_open(struct sr_dev_inst *sdi) diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 6e7b7bc84..606c82e8d 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -18,6 +18,29 @@ */ #include "libm2k.h" +#include +#include +#include extern "C" { +/* Context */ +int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info) +{ + auto ctxs = libm2k::context::getContextsInfo(); + + struct CONTEXT_INFO **ctxs_info = (struct CONTEXT_INFO **) malloc( + ctxs.size() * sizeof(struct CONTEXT_INFO *)); + for (unsigned int i = 0; i < ctxs.size(); ++i) { + ctxs_info[i] = (struct CONTEXT_INFO *) malloc(sizeof(struct CONTEXT_INFO)); + ctxs_info[i]->id_vendor = ctxs[i]->id_vendor.c_str(); + ctxs_info[i]->id_product = ctxs[i]->id_product.c_str(); + ctxs_info[i]->manufacturer = ctxs[i]->manufacturer.c_str(); + ctxs_info[i]->product = ctxs[i]->product.c_str(); + ctxs_info[i]->serial = ctxs[i]->serial.c_str(); + ctxs_info[i]->uri = ctxs[i]->uri.c_str(); + } + *info = ctxs_info; + return ctxs.size(); +} + } diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index eb1f21d7e..9cbf3f1a1 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -26,6 +26,18 @@ extern "C" { #endif +struct CONTEXT_INFO { + const char *id_vendor; + const char *id_product; + const char *manufacturer; + const char *product; + const char *serial; + const char *uri; +}; + +/* Context */ +int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info); + #ifdef __cplusplus } diff --git a/src/hardware/adalm2000/protocol.h b/src/hardware/adalm2000/protocol.h index f184294cd..9969f675d 100644 --- a/src/hardware/adalm2000/protocol.h +++ b/src/hardware/adalm2000/protocol.h @@ -27,7 +27,27 @@ #define LOG_PREFIX "adalm2000" +#define DEFAULT_NUM_LOGIC_CHANNELS 16 +#define DEFAULT_NUM_ANALOG_CHANNELS 2 + struct dev_context { + struct M2k *m2k; + + uint64_t start_time; + int64_t spent_us; + uint64_t limit_msec; + uint64_t limit_frames; + uint64_t limit_samples; + uint64_t sent_samples; + uint64_t buffersize; + uint32_t logic_unitsize; + gboolean avg; + uint64_t avg_samples; + + struct sr_datafeed_analog packet; + struct sr_analog_encoding encoding; + struct sr_analog_meaning meaning; + struct sr_analog_spec spec; }; SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data); From e4d3f7e96486eefebd9a95ed0343057ad5494d1e Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:26:15 +0300 Subject: [PATCH 06/24] adalm2000: Open a device. After the device is opened, an ADC calibration is performed. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 10 ++++++++-- src/hardware/adalm2000/libm2k.cpp | 17 +++++++++++++++++ src/hardware/adalm2000/libm2k.h | 4 ++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 5965bc914..c3d721356 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -152,9 +152,15 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) static int dev_open(struct sr_dev_inst *sdi) { - (void)sdi; + struct dev_context *devc; - /* TODO: get handle from sdi->conn and open it. */ + devc = sdi->priv; + devc->m2k = sr_libm2k_context_open(sdi->conn); + if (!devc->m2k) { + sr_err("Failed to open device"); + return SR_ERR; + } + sr_libm2k_context_adc_calibrate(devc->m2k); return SR_OK; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 606c82e8d..27736f423 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -24,6 +24,23 @@ extern "C" { /* Context */ +M2k *sr_libm2k_context_open(const char *uri) +{ + libm2k::context::M2k *ctx; + if (strlen(uri) == 0) { + ctx = libm2k::context::m2kOpen(); + } else { + ctx = libm2k::context::m2kOpen(uri); + } + return (M2k *) ctx; +} + +void sr_libm2k_context_adc_calibrate(struct M2k *m2k) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + ctx->calibrateADC(); +} + int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info) { auto ctxs = libm2k::context::getContextsInfo(); diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 9cbf3f1a1..2f5dfb258 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -36,6 +36,10 @@ struct CONTEXT_INFO { }; /* Context */ +struct M2k *sr_libm2k_context_open(const char *uri); + +void sr_libm2k_context_adc_calibrate(struct M2k *m2k); + int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info); From e4d063ecee54f138c92869456cc33eb1892f32f8 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:28:07 +0300 Subject: [PATCH 07/24] adalm2000: Close a device. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 11 +++++++++-- src/hardware/adalm2000/libm2k.cpp | 12 ++++++++++++ src/hardware/adalm2000/libm2k.h | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index c3d721356..bea368c8e 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -167,10 +167,17 @@ static int dev_open(struct sr_dev_inst *sdi) static int dev_close(struct sr_dev_inst *sdi) { - (void)sdi; + struct dev_context *devc; + int ret; - /* TODO: get handle from sdi->conn and close it. */ + devc = sdi->priv; + sr_info("Closing device on ..."); + ret = sr_libm2k_context_close(&(devc->m2k)); + if (ret) { + sr_err("Failed to close device"); + return SR_ERR; + } return SR_OK; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 27736f423..b44f00e3a 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -35,6 +35,18 @@ M2k *sr_libm2k_context_open(const char *uri) return (M2k *) ctx; } +int sr_libm2k_context_close(struct M2k **m2k) +{ + if (*m2k == nullptr) { + return 0; + } + auto ctx = (libm2k::context::M2k *) *m2k; + + libm2k::context::contextClose(ctx, false); + *m2k = nullptr; + return 0; +} + void sr_libm2k_context_adc_calibrate(struct M2k *m2k) { libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 2f5dfb258..ea4422cd0 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -38,6 +38,8 @@ struct CONTEXT_INFO { /* Context */ struct M2k *sr_libm2k_context_open(const char *uri); +int sr_libm2k_context_close(struct M2k **m2k); + void sr_libm2k_context_adc_calibrate(struct M2k *m2k); int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info); From 43bda99f1815dd9855d5dc1f331ff395ee950fe3 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:34:31 +0300 Subject: [PATCH 08/24] adalm2000: Get the number of enabled channels. Retrieve the number of enabled channels for the logic analyzer or for the oscilloscope. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/protocol.c | 19 +++++++++++++++++++ src/hardware/adalm2000/protocol.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/hardware/adalm2000/protocol.c b/src/hardware/adalm2000/protocol.c index 2a3828beb..d4033941b 100644 --- a/src/hardware/adalm2000/protocol.c +++ b/src/hardware/adalm2000/protocol.c @@ -20,6 +20,25 @@ #include #include "protocol.h" +SR_PRIV int adalm2000_nb_enabled_channels(const struct sr_dev_inst *sdi, int type) +{ + struct sr_channel *ch; + int nb_channels; + GSList *l; + + nb_channels = 0; + + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + if (ch->type == type) { + if (ch->enabled) { + nb_channels++; + } + } + } + return nb_channels; +} + SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data) { const struct sr_dev_inst *sdi; diff --git a/src/hardware/adalm2000/protocol.h b/src/hardware/adalm2000/protocol.h index 9969f675d..65b06df4b 100644 --- a/src/hardware/adalm2000/protocol.h +++ b/src/hardware/adalm2000/protocol.h @@ -50,6 +50,8 @@ struct dev_context { struct sr_analog_spec spec; }; +SR_PRIV int adalm2000_nb_enabled_channels(const struct sr_dev_inst *sdi, int type); + SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data); #endif From 02f3ab4c01b55a213e32b0374f67af4e8112ee11 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:45:34 +0300 Subject: [PATCH 09/24] adalm2000: Add samplerate configuration. The available samplerates are the common values between the LA and the OSC. Always set the same samplerate for both components. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 109 +++++++++++++++++++++++------- src/hardware/adalm2000/libm2k.cpp | 41 +++++++++++ src/hardware/adalm2000/libm2k.h | 10 +++ 3 files changed, 136 insertions(+), 24 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index bea368c8e..64d8785a4 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -31,6 +31,7 @@ static const uint32_t drvopts[] = { }; static const uint32_t devopts[] = { + SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, }; static const uint32_t devopts_cg_analog_group[] = { @@ -42,6 +43,15 @@ static const uint32_t devopts_cg_analog_channel[] = { static const uint32_t devopts_cg[] = { }; +static const uint64_t samplerates[] = { + SR_KHZ(1), + SR_KHZ(10), + SR_KHZ(100), + SR_MHZ(1), + SR_MHZ(10), + SR_MHZ(100), +}; + static struct sr_dev_driver adalm2000_driver_info; static GSList *scan(struct sr_dev_driver *di, GSList *options) @@ -182,41 +192,88 @@ static int dev_close(struct sr_dev_inst *sdi) } static int config_get(uint32_t key, GVariant **data, - const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { - int ret; + unsigned int idx, samplerate; + gboolean analog_enabled, digital_enabled; + struct sr_channel *ch; + struct dev_context *devc; + if (!sdi) { + return SR_ERR_ARG; + } - (void)sdi; - (void)data; - (void)cg; - - ret = SR_OK; - switch (key) { - /* TODO */ - default: - return SR_ERR_NA; + devc = sdi->priv; + + if (!cg) { + switch (key) { + case SR_CONF_SAMPLERATE: + digital_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_LOGIC) > 0) + ? TRUE : FALSE; + samplerate = sr_libm2k_analog_samplerate_get(devc->m2k); + if (digital_enabled) { + sr_libm2k_digital_samplerate_set(devc->m2k, samplerate); + } + *data = g_variant_new_uint64(samplerate); + break; + + default: + return SR_ERR_NA; + } + } else { + ch = cg->channels->data; + idx = ch->index; + switch (key) { + default: + return SR_ERR_NA; + } } - return ret; + return SR_OK; } static int config_set(uint32_t key, GVariant *data, - const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) { - int ret; + int ch_idx; + gboolean analog_enabled, digital_enabled; + struct sr_channel *ch; + struct dev_context *devc; - (void)sdi; - (void)data; - (void)cg; - - ret = SR_OK; - switch (key) { - /* TODO */ - default: - ret = SR_ERR_NA; + if (!sdi) { + return SR_ERR_ARG; } - return ret; + devc = sdi->priv; + + if (!cg) { + switch (key) { + case SR_CONF_SAMPLERATE: + analog_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_ANALOG) > 0) + ? TRUE : FALSE; + digital_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_LOGIC) > 0) + ? TRUE : FALSE; + if (analog_enabled) { + sr_libm2k_analog_samplerate_set(devc->m2k, g_variant_get_uint64(data)); + } + if (digital_enabled) { + sr_libm2k_digital_samplerate_set(devc->m2k, g_variant_get_uint64(data)); + } + break; + default: + return SR_ERR_NA; + } + } else { + ch = cg->channels->data; + ch_idx = ch->index; + + switch (key) { + default: + return SR_ERR_NA; + } + } + return SR_OK; } static int config_list(uint32_t key, GVariant **data, @@ -233,6 +290,10 @@ static int config_list(uint32_t key, GVariant **data, scanopts, drvopts, devopts); + case SR_CONF_SAMPLERATE: + *data = std_gvar_samplerates( + ARRAY_AND_SIZE(samplerates)); + break; default: return SR_ERR_NA; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index b44f00e3a..d3df0634c 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -20,9 +20,24 @@ #include "libm2k.h" #include #include +#include +#include #include extern "C" { + +libm2k::digital::M2kDigital *getDigital(struct M2k *m2k) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + return ctx->getDigital(); +} + +libm2k::analog::M2kAnalogIn *getAnalogIn(struct M2k *m2k) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + return ctx->getAnalogIn(); +} + /* Context */ M2k *sr_libm2k_context_open(const char *uri) { @@ -72,4 +87,30 @@ int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info) return ctxs.size(); } +/* Analog */ +double sr_libm2k_analog_samplerate_get(struct M2k *m2k) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + return analogIn->getSampleRate(); +} + +double sr_libm2k_analog_samplerate_set(struct M2k *m2k, double samplerate) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + return analogIn->setSampleRate(samplerate); +} + +/* Digital */ +double sr_libm2k_digital_samplerate_get(struct M2k *m2k) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + return digital->getSampleRateIn(); +} + +double sr_libm2k_digital_samplerate_set(struct M2k *m2k, double samplerate) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + return digital->setSampleRateIn(samplerate); +} + } diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index ea4422cd0..543f4096e 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -45,6 +45,16 @@ void sr_libm2k_context_adc_calibrate(struct M2k *m2k); int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info); +/* Analog */ +double sr_libm2k_analog_samplerate_get(struct M2k *m2k); + +double sr_libm2k_analog_samplerate_set(struct M2k *m2k, double samplerate); + +/* Digital */ +double sr_libm2k_digital_samplerate_get(struct M2k *m2k); + +double sr_libm2k_digital_samplerate_set(struct M2k *m2k, double samplerate); + #ifdef __cplusplus } #endif From 1c993b69d42924d8141adac9f411a89e55e9474a Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:54:30 +0300 Subject: [PATCH 10/24] adalm2000: Add samples averaging configuration. Store the oversampling ratio. It will be actually set just before the acquisition starts. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 15 +++++++++++++++ src/hardware/adalm2000/libm2k.cpp | 12 ++++++++++++ src/hardware/adalm2000/libm2k.h | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 64d8785a4..32fe69f1b 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -32,6 +32,8 @@ static const uint32_t drvopts[] = { static const uint32_t devopts[] = { SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET, + SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET, }; static const uint32_t devopts_cg_analog_group[] = { @@ -171,6 +173,7 @@ static int dev_open(struct sr_dev_inst *sdi) return SR_ERR; } sr_libm2k_context_adc_calibrate(devc->m2k); + devc->avg_samples = sr_libm2k_analog_oversampling_ratio_get(devc->m2k); return SR_OK; } @@ -216,6 +219,12 @@ static int config_get(uint32_t key, GVariant **data, } *data = g_variant_new_uint64(samplerate); break; + case SR_CONF_AVERAGING: + *data = g_variant_new_boolean(devc->avg); + break; + case SR_CONF_AVG_SAMPLES: + *data = g_variant_new_uint64(devc->avg_samples); + break; default: return SR_ERR_NA; @@ -261,6 +270,12 @@ static int config_set(uint32_t key, GVariant *data, sr_libm2k_digital_samplerate_set(devc->m2k, g_variant_get_uint64(data)); } break; + case SR_CONF_AVERAGING: + devc->avg = g_variant_get_boolean(data); + break; + case SR_CONF_AVG_SAMPLES: + devc->avg_samples = g_variant_get_uint64(data); + break; default: return SR_ERR_NA; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index d3df0634c..1a8091a01 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -100,6 +100,18 @@ double sr_libm2k_analog_samplerate_set(struct M2k *m2k, double samplerate) return analogIn->setSampleRate(samplerate); } +int sr_libm2k_analog_oversampling_ratio_get(struct M2k *m2k) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + return analogIn->getOversamplingRatio(); +} + +void sr_libm2k_analog_oversampling_ratio_set(struct M2k *m2k, int oversampling) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->setOversamplingRatio(oversampling); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 543f4096e..1b785c8f8 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -50,6 +50,10 @@ double sr_libm2k_analog_samplerate_get(struct M2k *m2k); double sr_libm2k_analog_samplerate_set(struct M2k *m2k, double samplerate); +int sr_libm2k_analog_oversampling_ratio_get(struct M2k *m2k); + +void sr_libm2k_analog_oversampling_ratio_set(struct M2k *m2k, int oversampling); + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); From d061620a7d4b7e49577babeb99de0604663cff23 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 19:59:17 +0300 Subject: [PATCH 11/24] adalm2000: Add high resolution configuration. The oscilloscope has a range of -2.5V +2.5V in the high resolution mode. In the normal mode the range is between -25V and 25V. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 26 ++++++++++++++++++++++++-- src/hardware/adalm2000/libm2k.cpp | 14 ++++++++++++++ src/hardware/adalm2000/libm2k.h | 9 +++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 32fe69f1b..a2cdb99ea 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -40,6 +40,7 @@ static const uint32_t devopts_cg_analog_group[] = { }; static const uint32_t devopts_cg_analog_channel[] = { + SR_CONF_HIGH_RESOLUTION | SR_CONF_GET | SR_CONF_SET, }; static const uint32_t devopts_cg[] = { @@ -233,6 +234,16 @@ static int config_get(uint32_t key, GVariant **data, ch = cg->channels->data; idx = ch->index; switch (key) { + case SR_CONF_HIGH_RESOLUTION: + if (ch->type != SR_CHANNEL_ANALOG) { + return SR_ERR_ARG; + } + if (sr_libm2k_analog_range_get(devc->m2k, idx) == PLUS_MINUS_2_5V) { + *data = g_variant_new_boolean(TRUE); + } else { + *data = g_variant_new_boolean(FALSE); + } + break; default: return SR_ERR_NA; } @@ -245,8 +256,8 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - int ch_idx; - gboolean analog_enabled, digital_enabled; + int ch_idx, idx; + gboolean analog_enabled, digital_enabled, high_resolution; struct sr_channel *ch; struct dev_context *devc; @@ -284,6 +295,17 @@ static int config_set(uint32_t key, GVariant *data, ch_idx = ch->index; switch (key) { + case SR_CONF_HIGH_RESOLUTION: + if (ch->type != SR_CHANNEL_ANALOG) { + return SR_ERR_ARG; + } + high_resolution = g_variant_get_boolean(data); + if (high_resolution) { + sr_libm2k_analog_range_set(devc->m2k, ch_idx, PLUS_MINUS_2_5V); + } else { + sr_libm2k_analog_range_set(devc->m2k, ch_idx, PLUS_MINUS_25V); + } + break; default: return SR_ERR_NA; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 1a8091a01..059e8bcb7 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -112,6 +112,20 @@ void sr_libm2k_analog_oversampling_ratio_set(struct M2k *m2k, int oversampling) analogIn->setOversamplingRatio(oversampling); } +enum M2K_RANGE sr_libm2k_analog_range_get(struct M2k *m2k, unsigned int channel) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + return static_cast(analogIn->getRange( + static_cast(channel))); +} + +void sr_libm2k_analog_range_set(struct M2k *m2k, unsigned int channel, enum M2K_RANGE range) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->setRange(static_cast(channel), + static_cast(range)); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 1b785c8f8..00726f2f0 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -26,6 +26,11 @@ extern "C" { #endif +enum M2K_RANGE { + PLUS_MINUS_25V = 0, + PLUS_MINUS_2_5V = 1, +}; + struct CONTEXT_INFO { const char *id_vendor; const char *id_product; @@ -54,6 +59,10 @@ int sr_libm2k_analog_oversampling_ratio_get(struct M2k *m2k); void sr_libm2k_analog_oversampling_ratio_set(struct M2k *m2k, int oversampling); +enum M2K_RANGE sr_libm2k_analog_range_get(struct M2k *m2k, unsigned int channel); + +void sr_libm2k_analog_range_set(struct M2k *m2k, unsigned int channel, enum M2K_RANGE range); + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); From 8e508ac2a84a500aac064d9afa173102fef70434 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:03:30 +0300 Subject: [PATCH 12/24] adalm2000: Add acquisition boundaries. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index a2cdb99ea..c64d76c79 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -32,6 +32,8 @@ static const uint32_t drvopts[] = { static const uint32_t devopts[] = { SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET, + SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET, SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET, }; @@ -220,6 +222,12 @@ static int config_get(uint32_t key, GVariant **data, } *data = g_variant_new_uint64(samplerate); break; + case SR_CONF_LIMIT_SAMPLES: + *data = g_variant_new_uint64(devc->limit_samples); + break; + case SR_CONF_LIMIT_MSEC: + *data = g_variant_new_uint64(devc->limit_msec); + break; case SR_CONF_AVERAGING: *data = g_variant_new_boolean(devc->avg); break; @@ -281,6 +289,14 @@ static int config_set(uint32_t key, GVariant *data, sr_libm2k_digital_samplerate_set(devc->m2k, g_variant_get_uint64(data)); } break; + case SR_CONF_LIMIT_SAMPLES: + devc->limit_samples = g_variant_get_uint64(data); + devc->limit_msec = 0; + break; + case SR_CONF_LIMIT_MSEC: + devc->limit_msec = g_variant_get_uint64(data); + devc->limit_samples = 0; + break; case SR_CONF_AVERAGING: devc->avg = g_variant_get_boolean(data); break; From 03958ace195ad8fde2a8f3370fb9afe02a842a37 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:08:42 +0300 Subject: [PATCH 13/24] adalm2000: Add digital trigger. Add an extra trigger state - NO_TRIGGER. Add function to convert the libsigrok trigger to a libm2k trigger. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 14 +++++++++ src/hardware/adalm2000/libm2k.cpp | 50 +++++++++++++++++++++++++++++++ src/hardware/adalm2000/libm2k.h | 24 +++++++++++++++ src/hardware/adalm2000/protocol.c | 42 ++++++++++++++++++++++++++ src/hardware/adalm2000/protocol.h | 3 ++ 5 files changed, 133 insertions(+) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index c64d76c79..bd39e085d 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -36,6 +36,7 @@ static const uint32_t devopts[] = { SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET, SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET, + SR_CONF_TRIGGER_MATCH | SR_CONF_LIST, }; static const uint32_t devopts_cg_analog_group[] = { @@ -48,6 +49,14 @@ static const uint32_t devopts_cg_analog_channel[] = { static const uint32_t devopts_cg[] = { }; +static const int32_t trigger_matches[] = { + SR_TRIGGER_ZERO, + SR_TRIGGER_ONE, + SR_TRIGGER_RISING, + SR_TRIGGER_FALLING, + SR_TRIGGER_EDGE, +}; + static const uint64_t samplerates[] = { SR_KHZ(1), SR_KHZ(10), @@ -347,6 +356,11 @@ static int config_list(uint32_t key, GVariant **data, *data = std_gvar_samplerates( ARRAY_AND_SIZE(samplerates)); break; + case SR_CONF_TRIGGER_MATCH: + *data = std_gvar_array_i32( + ARRAY_AND_SIZE(trigger_matches)); + break; + default: return SR_ERR_NA; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 059e8bcb7..c059aa3f9 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include extern "C" { @@ -38,6 +40,12 @@ libm2k::analog::M2kAnalogIn *getAnalogIn(struct M2k *m2k) return ctx->getAnalogIn(); } +libm2k::M2kHardwareTrigger *getTrigger(struct M2k *m2k) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + return ctx->getDigital()->getTrigger(); +} + /* Context */ M2k *sr_libm2k_context_open(const char *uri) { @@ -139,4 +147,46 @@ double sr_libm2k_digital_samplerate_set(struct M2k *m2k, double samplerate) return digital->setSampleRateIn(samplerate); } +/* Digital trigger */ +void sr_libm2k_digital_trigger_source_set(struct M2k *m2k, enum DIGITAL_TRIGGER_SOURCE source) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setDigitalSource(static_cast(source)); +} + +enum M2K_TRIGGER_CONDITION_DIGITAL sr_libm2k_digital_trigger_condition_get(struct M2k *m2k, unsigned int chnIdx) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return static_cast(trigger->getDigitalCondition(chnIdx)); +} + +void sr_libm2k_digital_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx, uint32_t cond) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + libm2k::M2K_TRIGGER_CONDITION_DIGITAL condition; + switch (cond) { + case SR_TRIGGER_ZERO: + condition = libm2k::LOW_LEVEL_DIGITAL; + break; + case SR_TRIGGER_ONE: + condition = libm2k::HIGH_LEVEL_DIGITAL; + break; + case SR_TRIGGER_RISING: + condition = libm2k::RISING_EDGE_DIGITAL; + break; + case SR_TRIGGER_FALLING: + condition = libm2k::FALLING_EDGE_DIGITAL; + break; + case SR_TRIGGER_EDGE: + condition = libm2k::ANY_EDGE_DIGITAL; + break; + case SR_NO_TRIGGER: + condition = libm2k::NO_TRIGGER_DIGITAL; + break; + default: + condition = libm2k::NO_TRIGGER_DIGITAL; + } + trigger->setDigitalCondition(chnIdx, condition); +} + } diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 00726f2f0..f66efe9a9 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -26,6 +26,23 @@ extern "C" { #endif +#define SR_NO_TRIGGER -1 + +enum DIGITAL_TRIGGER_SOURCE { + SRC_TRIGGER_IN = 0, + SRC_ANALOG_IN = 1, + SRC_NONE = 2, +}; + +enum M2K_TRIGGER_CONDITION_DIGITAL { + RISING_EDGE_DIGITAL = 0, + FALLING_EDGE_DIGITAL = 1, + LOW_LEVEL_DIGITAL = 2, + HIGH_LEVEL_DIGITAL = 3, + ANY_EDGE_DIGITAL = 4, + NO_TRIGGER_DIGITAL = 5 +}; + enum M2K_RANGE { PLUS_MINUS_25V = 0, PLUS_MINUS_2_5V = 1, @@ -68,6 +85,13 @@ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); double sr_libm2k_digital_samplerate_set(struct M2k *m2k, double samplerate); +/* Digital trigger*/ +void sr_libm2k_digital_trigger_source_set(struct M2k *m2k, enum DIGITAL_TRIGGER_SOURCE source); + +enum M2K_TRIGGER_CONDITION_DIGITAL sr_libm2k_digital_trigger_condition_get(struct M2k *m2k, unsigned int chnIdx); + +void sr_libm2k_digital_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx, uint32_t cond); + #ifdef __cplusplus } #endif diff --git a/src/hardware/adalm2000/protocol.c b/src/hardware/adalm2000/protocol.c index d4033941b..2bd12210a 100644 --- a/src/hardware/adalm2000/protocol.c +++ b/src/hardware/adalm2000/protocol.c @@ -39,6 +39,48 @@ SR_PRIV int adalm2000_nb_enabled_channels(const struct sr_dev_inst *sdi, int typ return nb_channels; } +SR_PRIV int adalm2000_convert_trigger(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + struct sr_trigger *trigger; + struct sr_trigger_stage *stage; + struct sr_trigger_match *match; + struct sr_channel *ch; + const GSList *l, *m; + + devc = sdi->priv; + + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + if (ch->type == SR_CHANNEL_LOGIC) { + if (ch->enabled) { + sr_libm2k_digital_trigger_condition_set(devc->m2k, ch->index, + SR_NO_TRIGGER); + } + } + } + + if (!(trigger = sr_session_trigger_get(sdi->session))) { + return SR_OK; + } + + sr_libm2k_digital_streaming_flag_set(devc->m2k, 0); + for (l = trigger->stages; l; l = l->next) { + stage = l->data; + for (m = stage->matches; m; m = m->next) { + match = m->data; + if (!match->channel->enabled) { + /* Ignore disabled channels with a trigger. */ + continue; + } + sr_libm2k_digital_trigger_condition_set(devc->m2k, match->channel->index, + match->match); + } + } + + return SR_OK; +} + SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data) { const struct sr_dev_inst *sdi; diff --git a/src/hardware/adalm2000/protocol.h b/src/hardware/adalm2000/protocol.h index 65b06df4b..3287e8eaa 100644 --- a/src/hardware/adalm2000/protocol.h +++ b/src/hardware/adalm2000/protocol.h @@ -24,6 +24,7 @@ #include #include #include "libsigrok-internal.h" +#include "libm2k.h" #define LOG_PREFIX "adalm2000" @@ -52,6 +53,8 @@ struct dev_context { SR_PRIV int adalm2000_nb_enabled_channels(const struct sr_dev_inst *sdi, int type); +SR_PRIV int adalm2000_convert_trigger(const struct sr_dev_inst *sdi); + SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data); #endif From 727a300458ea1868e8b4240b128248a703d15a40 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:11:23 +0300 Subject: [PATCH 14/24] adalm2000: Add trigger source configuration. adalm2000 has a source trigger for the OSC and for each channel has a trigger mode. Handle both attributes depending on the trigger source. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 57 +++++++++++++++++++++++++++++++ src/hardware/adalm2000/libm2k.cpp | 26 ++++++++++++++ src/hardware/adalm2000/libm2k.h | 24 +++++++++++++ 3 files changed, 107 insertions(+) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index bd39e085d..1bf09aef0 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -40,6 +40,7 @@ static const uint32_t devopts[] = { }; static const uint32_t devopts_cg_analog_group[] = { + SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, }; static const uint32_t devopts_cg_analog_channel[] = { @@ -66,6 +67,15 @@ static const uint64_t samplerates[] = { SR_MHZ(100), }; +static const char *trigger_sources[] = { + "CHANNEL 1", + "CHANNEL 2", + "CHANNEL 1 OR CHANNEL 2", + "CHANNEL 1 AND CHANNEL 2", + "CHANNEL 1 XOR CHANNEL 2", + "NONE", +}; + static struct sr_dev_driver adalm2000_driver_info; static GSList *scan(struct sr_dev_driver *di, GSList *options) @@ -251,6 +261,15 @@ static int config_get(uint32_t key, GVariant **data, ch = cg->channels->data; idx = ch->index; switch (key) { + case SR_CONF_TRIGGER_SOURCE: + if (sr_libm2k_analog_trigger_mode_get(devc->m2k, 0) == ALWAYS && + sr_libm2k_analog_trigger_mode_get(devc->m2k, 1) == ALWAYS) { + *data = g_variant_new_string(trigger_sources[5]); + } else { + *data = g_variant_new_string( + trigger_sources[sr_libm2k_analog_trigger_source_get(devc->m2k)]); + } + break; case SR_CONF_HIGH_RESOLUTION: if (ch->type != SR_CHANNEL_ANALOG) { return SR_ERR_ARG; @@ -274,6 +293,7 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_channel_group *cg) { int ch_idx, idx; + char *trigger_source; gboolean analog_enabled, digital_enabled, high_resolution; struct sr_channel *ch; struct dev_context *devc; @@ -320,6 +340,40 @@ static int config_set(uint32_t key, GVariant *data, ch_idx = ch->index; switch (key) { + case SR_CONF_TRIGGER_SOURCE: + if (ch->type != SR_CHANNEL_ANALOG) { + return SR_ERR_ARG; + } + if ((idx = std_str_idx(data, ARRAY_AND_SIZE(trigger_sources))) < 0) { + return SR_ERR_ARG; + } + trigger_source = g_strdup(trigger_sources[idx]); + if (!strcmp(trigger_source, trigger_sources[0])) { + sr_libm2k_analog_trigger_source_set(devc->m2k, CH_1); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 0, ANALOG); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 1, ALWAYS); + } else if (!strcmp(trigger_source, trigger_sources[1])) { + sr_libm2k_analog_trigger_source_set(devc->m2k, CH_2); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 0, ALWAYS); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 1, ANALOG); + } else if (!strcmp(trigger_source, trigger_sources[2])) { + sr_libm2k_analog_trigger_source_set(devc->m2k, CH_1_OR_CH_2); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 0, ANALOG); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 1, ANALOG); + } else if (!strcmp(trigger_source, trigger_sources[3])) { + sr_libm2k_analog_trigger_source_set(devc->m2k, CH_1_AND_CH_2); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 0, ANALOG); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 1, ANALOG); + } else if (!strcmp(trigger_source, trigger_sources[4])) { + sr_libm2k_analog_trigger_source_set(devc->m2k, CH_1_XOR_CH_2); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 0, ANALOG); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 1, ANALOG); + } else { + sr_libm2k_analog_trigger_mode_set(devc->m2k, 0, ALWAYS); + sr_libm2k_analog_trigger_mode_set(devc->m2k, 1, ALWAYS); + } + g_free(trigger_source); + break; case SR_CONF_HIGH_RESOLUTION: if (ch->type != SR_CHANNEL_ANALOG) { return SR_ERR_ARG; @@ -379,6 +433,9 @@ static int config_list(uint32_t key, GVariant **data, *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg)); } break; + case SR_CONF_TRIGGER_SOURCE: + *data = g_variant_new_strv(ARRAY_AND_SIZE(trigger_sources)); + break; default: return SR_ERR_NA; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index c059aa3f9..4be17250a 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -134,6 +134,32 @@ void sr_libm2k_analog_range_set(struct M2k *m2k, unsigned int channel, enum M2K_ static_cast(range)); } +/* Analog trigger */ +enum ANALOG_TRIGGER_SOURCE sr_libm2k_analog_trigger_source_get(struct M2k *m2k) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return static_cast(trigger->getAnalogSource()); +} + +void sr_libm2k_analog_trigger_source_set(struct M2k *m2k, enum ANALOG_TRIGGER_SOURCE source) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setAnalogSource(static_cast(source)); +} + +enum ANALOG_TRIGGER_MODE sr_libm2k_analog_trigger_mode_get(struct M2k *m2k, unsigned int chnIdx) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return static_cast(trigger->getAnalogMode(chnIdx)); +} + +void sr_libm2k_analog_trigger_mode_set(struct M2k *m2k, unsigned int chnIdx, + enum ANALOG_TRIGGER_MODE mode) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setAnalogMode(chnIdx, static_cast(mode)); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index f66efe9a9..0751cf423 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -48,6 +48,20 @@ enum M2K_RANGE { PLUS_MINUS_2_5V = 1, }; +enum ANALOG_TRIGGER_SOURCE { + CH_1 = 0, + CH_2 = 1, + CH_1_OR_CH_2 = 2, + CH_1_AND_CH_2 = 3, + CH_1_XOR_CH_2 = 4, + SRC_DIGITAL_IN = 5, +}; + +enum ANALOG_TRIGGER_MODE { + ALWAYS = 0, + ANALOG = 1, +}; + struct CONTEXT_INFO { const char *id_vendor; const char *id_product; @@ -80,6 +94,16 @@ enum M2K_RANGE sr_libm2k_analog_range_get(struct M2k *m2k, unsigned int channel) void sr_libm2k_analog_range_set(struct M2k *m2k, unsigned int channel, enum M2K_RANGE range); +/* Analog trigger */ +enum ANALOG_TRIGGER_SOURCE sr_libm2k_analog_trigger_source_get(struct M2k *m2k); + +void sr_libm2k_analog_trigger_source_set(struct M2k *m2k, enum ANALOG_TRIGGER_SOURCE source); + +enum ANALOG_TRIGGER_MODE sr_libm2k_analog_trigger_mode_get(struct M2k *m2k, unsigned int chnIdx); + +void sr_libm2k_analog_trigger_mode_set(struct M2k *m2k, unsigned int chnIdx, + enum ANALOG_TRIGGER_MODE mode); + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); From 4a29dbf1f4827d63a183e28e9b1a0867d35cbbc3 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:12:59 +0300 Subject: [PATCH 15/24] adalm2000: Add trigger slope configuration. Convert the libsigrok trigger slope into libm2k trigger condition. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 39 ++++++++++++++++++++++++++++++- src/hardware/adalm2000/libm2k.cpp | 13 +++++++++++ src/hardware/adalm2000/libm2k.h | 12 ++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 1bf09aef0..dfe1d1fe7 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -44,6 +44,7 @@ static const uint32_t devopts_cg_analog_group[] = { }; static const uint32_t devopts_cg_analog_channel[] = { + SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_HIGH_RESOLUTION | SR_CONF_GET | SR_CONF_SET, }; @@ -76,6 +77,13 @@ static const char *trigger_sources[] = { "NONE", }; +static const char *trigger_slopes[] = { + "RISING", + "FALLING", + "LOW", + "HIGH", +}; + static struct sr_dev_driver adalm2000_driver_info; static GSList *scan(struct sr_dev_driver *di, GSList *options) @@ -270,6 +278,13 @@ static int config_get(uint32_t key, GVariant **data, trigger_sources[sr_libm2k_analog_trigger_source_get(devc->m2k)]); } break; + case SR_CONF_TRIGGER_SLOPE: + if (ch->type != SR_CHANNEL_ANALOG) { + return SR_ERR_ARG; + } + *data = g_variant_new_string( + trigger_slopes[sr_libm2k_analog_trigger_condition_get(devc->m2k, idx)]); + break; case SR_CONF_HIGH_RESOLUTION: if (ch->type != SR_CHANNEL_ANALOG) { return SR_ERR_ARG; @@ -293,7 +308,7 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_channel_group *cg) { int ch_idx, idx; - char *trigger_source; + char *trigger_source, *trigger_slope; gboolean analog_enabled, digital_enabled, high_resolution; struct sr_channel *ch; struct dev_context *devc; @@ -374,6 +389,25 @@ static int config_set(uint32_t key, GVariant *data, } g_free(trigger_source); break; + case SR_CONF_TRIGGER_SLOPE: + if (ch->type != SR_CHANNEL_ANALOG) { + return SR_ERR_ARG; + } + if ((idx = std_str_idx(data, ARRAY_AND_SIZE(trigger_slopes))) < 0) { + return SR_ERR_ARG; + } + trigger_slope = g_strdup(trigger_slopes[idx]); + if (strcmp(trigger_slope, trigger_slopes[0]) == 0) { + sr_libm2k_analog_trigger_condition_set(devc->m2k, ch_idx, RISING); + } else if (strcmp(trigger_slope, trigger_slopes[1]) == 0) { + sr_libm2k_analog_trigger_condition_set(devc->m2k, ch_idx, FALLING); + } else if (strcmp(trigger_slope, trigger_slopes[2]) == 0) { + sr_libm2k_analog_trigger_condition_set(devc->m2k, ch_idx, LOW); + } else if (strcmp(trigger_slope, trigger_slopes[3]) == 0) { + sr_libm2k_analog_trigger_condition_set(devc->m2k, ch_idx, HIGH); + } + g_free(trigger_slope); + break; case SR_CONF_HIGH_RESOLUTION: if (ch->type != SR_CHANNEL_ANALOG) { return SR_ERR_ARG; @@ -436,6 +470,9 @@ static int config_list(uint32_t key, GVariant **data, case SR_CONF_TRIGGER_SOURCE: *data = g_variant_new_strv(ARRAY_AND_SIZE(trigger_sources)); break; + case SR_CONF_TRIGGER_SLOPE: + *data = g_variant_new_strv(ARRAY_AND_SIZE(trigger_slopes)); + break; default: return SR_ERR_NA; } diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 4be17250a..89317f42a 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -160,6 +160,19 @@ void sr_libm2k_analog_trigger_mode_set(struct M2k *m2k, unsigned int chnIdx, trigger->setAnalogMode(chnIdx, static_cast(mode)); } +enum ANALOG_TRIGGER_CONDITION sr_libm2k_analog_trigger_condition_get(struct M2k *m2k, unsigned int chnIdx) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return static_cast(trigger->getAnalogCondition(chnIdx)); +} + +void sr_libm2k_analog_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx, + enum ANALOG_TRIGGER_CONDITION condition) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setAnalogCondition(chnIdx, static_cast(condition)); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 0751cf423..f5851c7c7 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -62,6 +62,13 @@ enum ANALOG_TRIGGER_MODE { ANALOG = 1, }; +enum ANALOG_TRIGGER_CONDITION { + RISING = 0, + FALLING = 1, + LOW = 2, + HIGH = 3, +}; + struct CONTEXT_INFO { const char *id_vendor; const char *id_product; @@ -104,6 +111,11 @@ enum ANALOG_TRIGGER_MODE sr_libm2k_analog_trigger_mode_get(struct M2k *m2k, unsi void sr_libm2k_analog_trigger_mode_set(struct M2k *m2k, unsigned int chnIdx, enum ANALOG_TRIGGER_MODE mode); +enum ANALOG_TRIGGER_CONDITION sr_libm2k_analog_trigger_condition_get(struct M2k *m2k, unsigned int chnIdx); + +void sr_libm2k_analog_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx, + enum ANALOG_TRIGGER_CONDITION condition); + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); From edb771ef4e945c194f8f7a3cd3b2c9892fde830d Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:14:48 +0300 Subject: [PATCH 16/24] adalm2000: Add trigger level configuration. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 12 ++++++++++++ src/hardware/adalm2000/libm2k.cpp | 12 ++++++++++++ src/hardware/adalm2000/libm2k.h | 4 ++++ 3 files changed, 28 insertions(+) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index dfe1d1fe7..d3820889c 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -46,6 +46,7 @@ static const uint32_t devopts_cg_analog_group[] = { static const uint32_t devopts_cg_analog_channel[] = { SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_HIGH_RESOLUTION | SR_CONF_GET | SR_CONF_SET, + SR_CONF_TRIGGER_LEVEL | SR_CONF_GET | SR_CONF_SET, }; static const uint32_t devopts_cg[] = { @@ -285,6 +286,9 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_string( trigger_slopes[sr_libm2k_analog_trigger_condition_get(devc->m2k, idx)]); break; + case SR_CONF_TRIGGER_LEVEL: + *data = g_variant_new_double(sr_libm2k_analog_trigger_level_get(devc->m2k, idx)); + break; case SR_CONF_HIGH_RESOLUTION: if (ch->type != SR_CHANNEL_ANALOG) { return SR_ERR_ARG; @@ -408,6 +412,14 @@ static int config_set(uint32_t key, GVariant *data, } g_free(trigger_slope); break; + case SR_CONF_TRIGGER_LEVEL: + analog_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_ANALOG) > 0) + ? TRUE : FALSE; + if (analog_enabled) { + sr_libm2k_analog_trigger_level_set(devc->m2k, ch_idx, + g_variant_get_double(data)); + } + break; case SR_CONF_HIGH_RESOLUTION: if (ch->type != SR_CHANNEL_ANALOG) { return SR_ERR_ARG; diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 89317f42a..30ed00b94 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -173,6 +173,18 @@ void sr_libm2k_analog_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx trigger->setAnalogCondition(chnIdx, static_cast(condition)); } +float sr_libm2k_analog_trigger_level_get(struct M2k *m2k, unsigned int chnIdx) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return static_cast(trigger->getAnalogLevel(chnIdx)); +} + +void sr_libm2k_analog_trigger_level_set(struct M2k *m2k, unsigned int chnIdx, float level) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setAnalogLevel(chnIdx, static_cast(level)); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index f5851c7c7..a3ee0f4e6 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -116,6 +116,10 @@ enum ANALOG_TRIGGER_CONDITION sr_libm2k_analog_trigger_condition_get(struct M2k void sr_libm2k_analog_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx, enum ANALOG_TRIGGER_CONDITION condition); +float sr_libm2k_analog_trigger_level_get(struct M2k *m2k, unsigned int chnIdx); + +void sr_libm2k_analog_trigger_level_set(struct M2k *m2k, unsigned int chnIdx, float level); + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); From b444e1f1075fb3f045d629b86384d4804c934bc1 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:16:35 +0300 Subject: [PATCH 17/24] adalm2000: Add capture ratio configuration. Transform the pre-capture ratio into a delay value for both OSC and LA. Always keep the same delay for both components. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 45 +++++++++++++++++++++++++++++-- src/hardware/adalm2000/libm2k.cpp | 24 +++++++++++++++++ src/hardware/adalm2000/libm2k.h | 8 ++++++ src/hardware/adalm2000/protocol.h | 1 + 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index d3820889c..2d162a2f3 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -37,6 +37,7 @@ static const uint32_t devopts[] = { SR_CONF_AVERAGING | SR_CONF_GET | SR_CONF_SET, SR_CONF_AVG_SAMPLES | SR_CONF_GET | SR_CONF_SET, SR_CONF_TRIGGER_MATCH | SR_CONF_LIST, + SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET, }; static const uint32_t devopts_cg_analog_group[] = { @@ -229,7 +230,8 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - unsigned int idx, samplerate; + unsigned int idx, capture_ratio, samplerate; + int delay; gboolean analog_enabled, digital_enabled; struct sr_channel *ch; struct dev_context *devc; @@ -262,7 +264,32 @@ static int config_get(uint32_t key, GVariant **data, case SR_CONF_AVG_SAMPLES: *data = g_variant_new_uint64(devc->avg_samples); break; + case SR_CONF_CAPTURE_RATIO: + analog_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_ANALOG) > 0) + ? TRUE : FALSE; + digital_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_LOGIC) > 0) + ? TRUE : FALSE; + + if (analog_enabled) { + delay = sr_libm2k_analog_trigger_delay_get(devc->m2k); + } else { + delay = sr_libm2k_digital_trigger_delay_get(devc->m2k); + } + if (delay > 0) { + delay = 0; + capture_ratio = 0; + } else { + capture_ratio = delay * 100 / MAX_NEG_DELAY; + } + if (analog_enabled) { + sr_libm2k_analog_trigger_delay_set(devc->m2k, 0); + } + if (digital_enabled) { + sr_libm2k_digital_trigger_delay_set(devc->m2k, delay); + } + *data = g_variant_new_uint64(capture_ratio); + break; default: return SR_ERR_NA; } @@ -311,7 +338,7 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - int ch_idx, idx; + int ch_idx, idx, delay; char *trigger_source, *trigger_slope; gboolean analog_enabled, digital_enabled, high_resolution; struct sr_channel *ch; @@ -345,6 +372,20 @@ static int config_set(uint32_t key, GVariant *data, devc->limit_msec = g_variant_get_uint64(data); devc->limit_samples = 0; break; + case SR_CONF_CAPTURE_RATIO: + analog_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_ANALOG) > 0) + ? TRUE : FALSE; + digital_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_LOGIC) > 0) + ? TRUE : FALSE; + delay = MAX_NEG_DELAY * + (int) g_variant_get_uint64(data) / 100; + if (analog_enabled) { + sr_libm2k_analog_trigger_delay_set(devc->m2k, delay); + } + if (digital_enabled) { + sr_libm2k_digital_trigger_delay_set(devc->m2k, delay); + } + break; case SR_CONF_AVERAGING: devc->avg = g_variant_get_boolean(data); break; diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 30ed00b94..8f997d18a 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -185,6 +185,18 @@ void sr_libm2k_analog_trigger_level_set(struct M2k *m2k, unsigned int chnIdx, fl trigger->setAnalogLevel(chnIdx, static_cast(level)); } +int sr_libm2k_analog_trigger_delay_get(struct M2k *m2k) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return trigger->getAnalogDelay(); +} + +void sr_libm2k_analog_trigger_delay_set(struct M2k *m2k, int delay) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setAnalogDelay(delay); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { @@ -240,4 +252,16 @@ void sr_libm2k_digital_trigger_condition_set(struct M2k *m2k, unsigned int chnId trigger->setDigitalCondition(chnIdx, condition); } +int sr_libm2k_digital_trigger_delay_get(struct M2k *m2k) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + return trigger->getDigitalDelay(); +} + +void sr_libm2k_digital_trigger_delay_set(struct M2k *m2k, int delay) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setDigitalDelay(delay); +} + } diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index a3ee0f4e6..9b8ede470 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -120,6 +120,10 @@ float sr_libm2k_analog_trigger_level_get(struct M2k *m2k, unsigned int chnIdx); void sr_libm2k_analog_trigger_level_set(struct M2k *m2k, unsigned int chnIdx, float level); +int sr_libm2k_analog_trigger_delay_get(struct M2k *m2k); + +void sr_libm2k_analog_trigger_delay_set(struct M2k *m2k, int delay); + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); @@ -132,6 +136,10 @@ enum M2K_TRIGGER_CONDITION_DIGITAL sr_libm2k_digital_trigger_condition_get(struc void sr_libm2k_digital_trigger_condition_set(struct M2k *m2k, unsigned int chnIdx, uint32_t cond); +int sr_libm2k_digital_trigger_delay_get(struct M2k *m2k); + +void sr_libm2k_digital_trigger_delay_set(struct M2k *m2k, int delay); + #ifdef __cplusplus } #endif diff --git a/src/hardware/adalm2000/protocol.h b/src/hardware/adalm2000/protocol.h index 3287e8eaa..b5a6745ee 100644 --- a/src/hardware/adalm2000/protocol.h +++ b/src/hardware/adalm2000/protocol.h @@ -30,6 +30,7 @@ #define DEFAULT_NUM_LOGIC_CHANNELS 16 #define DEFAULT_NUM_ANALOG_CHANNELS 2 +#define MAX_NEG_DELAY -8192 struct dev_context { struct M2k *m2k; From 10a10c2e9fdbb1e719fa24cf3a01c64c25b836bc Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:21:07 +0300 Subject: [PATCH 18/24] adalm2000: Wrap to C code the analogical acquisition functionality of libm2k. Add functions for creating the internal buffers, populating them, canceling any operation performed on them and destroying them. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/libm2k.cpp | 33 +++++++++++++++++++++++++++++++ src/hardware/adalm2000/libm2k.h | 8 ++++++++ 2 files changed, 41 insertions(+) diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 8f997d18a..0f290596a 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -134,6 +134,39 @@ void sr_libm2k_analog_range_set(struct M2k *m2k, unsigned int channel, enum M2K_ static_cast(range)); } +void sr_libm2k_analog_acquisition_start(struct M2k *m2k, unsigned int buffer_size) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->startAcquisition(buffer_size); +} + +float **sr_libm2k_analog_samples_get(struct M2k *m2k, uint64_t nb_samples) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + + const double *data = analogIn->getSamplesInterleaved(nb_samples); + float **samples = new float *[2]; + samples[0] = new float[nb_samples]; + samples[1] = new float[nb_samples]; + for (unsigned int i = 0, j = 0; i < nb_samples; i++, j += 2) { + samples[0][i] = (float) data[j]; + samples[1][i] = (float) data[j + 1]; + } + return samples; +} + +void sr_libm2k_analog_acquisition_cancel(struct M2k *m2k) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->cancelAcquisition(); +} + +void sr_libm2k_analog_acquisition_stop(struct M2k *m2k) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->stopAcquisition(); +} + /* Analog trigger */ enum ANALOG_TRIGGER_SOURCE sr_libm2k_analog_trigger_source_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 9b8ede470..7c8e49e59 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -101,6 +101,14 @@ enum M2K_RANGE sr_libm2k_analog_range_get(struct M2k *m2k, unsigned int channel) void sr_libm2k_analog_range_set(struct M2k *m2k, unsigned int channel, enum M2K_RANGE range); +void sr_libm2k_analog_acquisition_start(struct M2k *m2k, unsigned int buffer_size); + +float **sr_libm2k_analog_samples_get(struct M2k *m2k, uint64_t nb_samples); + +void sr_libm2k_analog_acquisition_cancel(struct M2k *m2k); + +void sr_libm2k_analog_acquisition_stop(struct M2k *m2k); + /* Analog trigger */ enum ANALOG_TRIGGER_SOURCE sr_libm2k_analog_trigger_source_get(struct M2k *m2k); From e2fee6f42241c4cf16901eff2b029c050f8b7a28 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:21:42 +0300 Subject: [PATCH 19/24] adalm2000: Wrap to C code the digital acquisition functionality of libm2k. Add functions for creating the internal buffers, populating them, canceling any operation performed on them and destroying them. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/libm2k.cpp | 24 ++++++++++++++++++++++++ src/hardware/adalm2000/libm2k.h | 8 ++++++++ 2 files changed, 32 insertions(+) diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 0f290596a..73a077dd2 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -243,6 +243,30 @@ double sr_libm2k_digital_samplerate_set(struct M2k *m2k, double samplerate) return digital->setSampleRateIn(samplerate); } +void sr_libm2k_digital_acquisition_start(struct M2k *m2k, unsigned int buffer_size) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + digital->startAcquisition(buffer_size); +} + +uint32_t *sr_libm2k_digital_samples_get(struct M2k *m2k, uint64_t nb_samples) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + return (uint32_t *) digital->getSamplesP(nb_samples); +} + +void sr_libm2k_digital_acquisition_cancel(struct M2k *m2k) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + digital->cancelAcquisition(); +} + +void sr_libm2k_digital_acquisition_stop(struct M2k *m2k) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + digital->stopAcquisition(); +} + /* Digital trigger */ void sr_libm2k_digital_trigger_source_set(struct M2k *m2k, enum DIGITAL_TRIGGER_SOURCE source) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 7c8e49e59..c1ea589bd 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -137,6 +137,14 @@ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); double sr_libm2k_digital_samplerate_set(struct M2k *m2k, double samplerate); +void sr_libm2k_digital_acquisition_start(struct M2k *m2k, unsigned int buffer_size); + +uint32_t *sr_libm2k_digital_samples_get(struct M2k *m2k, uint64_t nb_samples); + +void sr_libm2k_digital_acquisition_cancel(struct M2k *m2k); + +void sr_libm2k_digital_acquisition_stop(struct M2k *m2k); + /* Digital trigger*/ void sr_libm2k_digital_trigger_source_set(struct M2k *m2k, enum DIGITAL_TRIGGER_SOURCE source); From ab79f99cfdf6e07679f7140c3ecc059fe30574c7 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Mon, 2 Nov 2020 10:15:44 +0200 Subject: [PATCH 20/24] adalm2000: Wrap to C code the mixed signal acquisition functionality of libm2k. Add functions for creating the internal buffers and destroying them in the mixed signal mode. Add function to check if the mixed signal is available. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/libm2k.cpp | 18 ++++++++++++++++++ src/hardware/adalm2000/libm2k.h | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 73a077dd2..1a7ccf24b 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -95,6 +95,24 @@ int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info) return ctxs.size(); } +int sr_libm2k_has_mixed_signal(struct M2k *m2k) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + return ctx->hasMixedSignal(); +} + +void sr_libm2k_mixed_signal_acquisition_start(struct M2k *m2k, unsigned int nb_samples) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + ctx->startMixedSignalAcquisition(nb_samples); +} + +void sr_libm2k_mixed_signal_acquisition_stop(struct M2k *m2k) +{ + libm2k::context::M2k *ctx = (libm2k::context::M2k *) m2k; + ctx->stopMixedSignalAcquisition(); +} + /* Analog */ double sr_libm2k_analog_samplerate_get(struct M2k *m2k) { diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index c1ea589bd..34a15ac0f 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -87,6 +87,12 @@ void sr_libm2k_context_adc_calibrate(struct M2k *m2k); int sr_libm2k_context_get_all(struct CONTEXT_INFO ***info); +int sr_libm2k_has_mixed_signal(struct M2k *m2k); + +void sr_libm2k_mixed_signal_acquisition_start(struct M2k *m2k, unsigned int nb_samples); + +void sr_libm2k_mixed_signal_acquisition_stop(struct M2k *m2k); + /* Analog */ double sr_libm2k_analog_samplerate_get(struct M2k *m2k); From 51f9226ce6d40bfff29220a730d1a85fc9c30aa0 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:22:15 +0300 Subject: [PATCH 21/24] adalm2000: Add utility functions. Add functions for enabling the analogical channels, setting the number of kernel buffers, and enabling the streaming mode. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/libm2k.cpp | 30 ++++++++++++++++++++++++++++++ src/hardware/adalm2000/libm2k.h | 14 ++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/hardware/adalm2000/libm2k.cpp b/src/hardware/adalm2000/libm2k.cpp index 1a7ccf24b..224e0dbaf 100644 --- a/src/hardware/adalm2000/libm2k.cpp +++ b/src/hardware/adalm2000/libm2k.cpp @@ -114,6 +114,12 @@ void sr_libm2k_mixed_signal_acquisition_stop(struct M2k *m2k) } /* Analog */ +void sr_libm2k_analog_channel_enable(struct M2k *m2k, unsigned int chnIdx, int enable) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->enableChannel(chnIdx, static_cast(enable)); +} + double sr_libm2k_analog_samplerate_get(struct M2k *m2k) { libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); @@ -185,6 +191,12 @@ void sr_libm2k_analog_acquisition_stop(struct M2k *m2k) analogIn->stopAcquisition(); } +void sr_libm2k_analog_kernel_buffers_count_set(struct M2k *m2k, unsigned int count) +{ + libm2k::analog::M2kAnalogIn *analogIn = getAnalogIn(m2k); + analogIn->setKernelBuffersCount(count); +} + /* Analog trigger */ enum ANALOG_TRIGGER_SOURCE sr_libm2k_analog_trigger_source_get(struct M2k *m2k) { @@ -248,6 +260,12 @@ void sr_libm2k_analog_trigger_delay_set(struct M2k *m2k, int delay) trigger->setAnalogDelay(delay); } +void sr_libm2k_analog_streaming_flag_set(struct M2k *m2k, int flag) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setAnalogStreamingFlag(static_cast(flag)); +} + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k) { @@ -285,6 +303,12 @@ void sr_libm2k_digital_acquisition_stop(struct M2k *m2k) digital->stopAcquisition(); } +void sr_libm2k_digital_kernel_buffers_count_set(struct M2k *m2k, unsigned int count) +{ + libm2k::digital::M2kDigital *digital = getDigital(m2k); + digital->setKernelBuffersCountIn(count); +} + /* Digital trigger */ void sr_libm2k_digital_trigger_source_set(struct M2k *m2k, enum DIGITAL_TRIGGER_SOURCE source) { @@ -339,4 +363,10 @@ void sr_libm2k_digital_trigger_delay_set(struct M2k *m2k, int delay) trigger->setDigitalDelay(delay); } +void sr_libm2k_digital_streaming_flag_set(struct M2k *m2k, int flag) +{ + libm2k::M2kHardwareTrigger *trigger = getTrigger(m2k); + trigger->setDigitalStreamingFlag(flag); +} + } diff --git a/src/hardware/adalm2000/libm2k.h b/src/hardware/adalm2000/libm2k.h index 34a15ac0f..a340f76f4 100644 --- a/src/hardware/adalm2000/libm2k.h +++ b/src/hardware/adalm2000/libm2k.h @@ -95,6 +95,8 @@ void sr_libm2k_mixed_signal_acquisition_stop(struct M2k *m2k); /* Analog */ +void sr_libm2k_analog_channel_enable(struct M2k *m2k, unsigned int chnIdx, int enable); + double sr_libm2k_analog_samplerate_get(struct M2k *m2k); double sr_libm2k_analog_samplerate_set(struct M2k *m2k, double samplerate); @@ -115,6 +117,9 @@ void sr_libm2k_analog_acquisition_cancel(struct M2k *m2k); void sr_libm2k_analog_acquisition_stop(struct M2k *m2k); +void sr_libm2k_analog_kernel_buffers_count_set(struct M2k *m2k, unsigned int count); + + /* Analog trigger */ enum ANALOG_TRIGGER_SOURCE sr_libm2k_analog_trigger_source_get(struct M2k *m2k); @@ -138,6 +143,9 @@ int sr_libm2k_analog_trigger_delay_get(struct M2k *m2k); void sr_libm2k_analog_trigger_delay_set(struct M2k *m2k, int delay); +void sr_libm2k_analog_streaming_flag_set(struct M2k *m2k, int flag); + + /* Digital */ double sr_libm2k_digital_samplerate_get(struct M2k *m2k); @@ -151,6 +159,9 @@ void sr_libm2k_digital_acquisition_cancel(struct M2k *m2k); void sr_libm2k_digital_acquisition_stop(struct M2k *m2k); +void sr_libm2k_digital_kernel_buffers_count_set(struct M2k *m2k, unsigned int count); + + /* Digital trigger*/ void sr_libm2k_digital_trigger_source_set(struct M2k *m2k, enum DIGITAL_TRIGGER_SOURCE source); @@ -162,6 +173,9 @@ int sr_libm2k_digital_trigger_delay_get(struct M2k *m2k); void sr_libm2k_digital_trigger_delay_set(struct M2k *m2k, int delay); +void sr_libm2k_digital_streaming_flag_set(struct M2k *m2k, int flag); + + #ifdef __cplusplus } #endif From b4f1739e3ee371f51265abeaa5a1b658f17ce748 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:22:38 +0300 Subject: [PATCH 22/24] adalm2000: Add functionality for stopping the acquisition. Destroy all buffers and stop the streaming mode. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index 2d162a2f3..bb7ecf192 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -545,9 +545,30 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) static int dev_acquisition_stop(struct sr_dev_inst *sdi) { - /* TODO: stop acquisition. */ + struct dev_context *devc; + gboolean analog_enabled, digital_enabled; - (void)sdi; + devc = sdi->priv; + + sr_libm2k_analog_acquisition_cancel(devc->m2k); + sr_libm2k_digital_acquisition_cancel(devc->m2k); + + analog_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_ANALOG) > 0) ? TRUE : FALSE; + digital_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_LOGIC) > 0) ? TRUE : FALSE; + + if (sr_libm2k_has_mixed_signal(devc->m2k)) { + sr_libm2k_mixed_signal_acquisition_stop(devc->m2k); + } else { + if (digital_enabled) { + sr_libm2k_digital_acquisition_stop(devc->m2k); + } + if (analog_enabled) { + sr_libm2k_analog_acquisition_stop(devc->m2k); + } + } + + sr_session_source_remove(sdi->session, -1); + std_session_send_df_end(sdi); return SR_OK; } From a012857ffb24e4dba4b959568b37adbba5436be2 Mon Sep 17 00:00:00 2001 From: Teo Perisanu Date: Sun, 26 Apr 2020 20:23:06 +0300 Subject: [PATCH 23/24] adalm2000: Add functionality for starting the acquisition. Configure the digital trigger. Set the oversampling ratio. Synchronize the OSC with the LA. Start the acquisition in the streaming mode. Acquire the exact number of samples to fit in the given boundaries. Signed-off-by: Teo Perisanu --- src/hardware/adalm2000/api.c | 53 +++++++++++++- src/hardware/adalm2000/protocol.c | 112 ++++++++++++++++++++++++++++-- 2 files changed, 155 insertions(+), 10 deletions(-) diff --git a/src/hardware/adalm2000/api.c b/src/hardware/adalm2000/api.c index bb7ecf192..ac9a80400 100644 --- a/src/hardware/adalm2000/api.c +++ b/src/hardware/adalm2000/api.c @@ -535,10 +535,57 @@ static int config_list(uint32_t key, GVariant **data, static int dev_acquisition_start(const struct sr_dev_inst *sdi) { - /* TODO: configure hardware, reset acquisition state, set up - * callbacks and send header packet. */ + struct dev_context *devc; + GSList *l; + gboolean analog_enabled, digital_enabled; + struct sr_channel *ch; + + devc = sdi->priv; + devc->sent_samples = 0; + analog_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_ANALOG) > 0) ? TRUE : FALSE; + digital_enabled = (adalm2000_nb_enabled_channels(sdi, SR_CHANNEL_LOGIC) > 0) ? TRUE : FALSE; + + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + if (ch->type == SR_CHANNEL_ANALOG) { + sr_libm2k_analog_channel_enable(devc->m2k, ch->index, 1); + } + } + + if (adalm2000_convert_trigger(sdi) != SR_OK) { + sr_err("Failed to configure triggers."); + return SR_ERR; + } + + if (analog_enabled) { + if (devc->avg) { + sr_libm2k_analog_oversampling_ratio_set(devc->m2k, devc->avg_samples); + } + sr_libm2k_analog_kernel_buffers_count_set(devc->m2k, 64); + sr_libm2k_analog_streaming_flag_set(devc->m2k, 0); + } + if (digital_enabled) { + sr_libm2k_digital_kernel_buffers_count_set(devc->m2k, 64); + sr_libm2k_digital_streaming_flag_set(devc->m2k, 0); + } + + if (sr_libm2k_has_mixed_signal(devc->m2k)) { + sr_libm2k_mixed_signal_acquisition_start(devc->m2k, devc->buffersize); + } else { + if (analog_enabled) { + sr_libm2k_analog_acquisition_start(devc->m2k, devc->buffersize); + } + if (digital_enabled) { + sr_libm2k_digital_acquisition_start(devc->m2k, devc->buffersize); + } + } + + std_session_send_df_header(sdi); + sr_session_source_add(sdi->session, -1, G_IO_IN, 0, adalm2000_receive_data, + (struct sr_dev_inst *) sdi); - (void)sdi; + devc->start_time = g_get_monotonic_time(); + devc->spent_us = 0; return SR_OK; } diff --git a/src/hardware/adalm2000/protocol.c b/src/hardware/adalm2000/protocol.c index 2bd12210a..6c159503b 100644 --- a/src/hardware/adalm2000/protocol.c +++ b/src/hardware/adalm2000/protocol.c @@ -81,22 +81,120 @@ SR_PRIV int adalm2000_convert_trigger(const struct sr_dev_inst *sdi) return SR_OK; } +static void send_analog_packet(struct sr_dev_inst *sdi, float *data, int index, uint64_t sending_now) +{ + struct dev_context *devc; + struct sr_channel *ch; + struct sr_datafeed_packet packet; + + if (!(devc = sdi->priv)) { + return; + } + + ch = g_slist_nth_data(sdi->channels, DEFAULT_NUM_LOGIC_CHANNELS + index); + devc->meaning.channels = g_slist_append(NULL, ch); + + devc->packet.data = data; + devc->packet.num_samples = sending_now; + + packet.payload = &devc->packet; + packet.type = SR_DF_ANALOG; + + sr_session_send(sdi, &packet); +} + SR_PRIV int adalm2000_receive_data(int fd, int revents, void *cb_data) { - const struct sr_dev_inst *sdi; + struct sr_dev_inst *sdi; struct dev_context *devc; + struct sr_channel *ch; + struct sr_datafeed_packet packet; + struct sr_datafeed_logic logic; + uint64_t samples_todo, logic_done, analog_done, sending_now, analog_sent; + int64_t elapsed_us, limit_us, todo_us; + uint32_t *logic_data; + float **analog_data; + GSList *l; - (void)fd; + (void) fd; + (void) revents; - if (!(sdi = cb_data)) + if (!(sdi = cb_data)) { return TRUE; + } - if (!(devc = sdi->priv)) + if (!(devc = sdi->priv)) { return TRUE; + } + + elapsed_us = g_get_monotonic_time() - devc->start_time; + limit_us = 1000 * devc->limit_msec; + + if (limit_us > 0 && limit_us < elapsed_us) { + todo_us = MAX(0, limit_us - devc->spent_us); + } else { + todo_us = MAX(0, elapsed_us - devc->spent_us); + } + + samples_todo = (todo_us * sr_libm2k_digital_samplerate_get(devc->m2k) + G_USEC_PER_SEC - 1) + / G_USEC_PER_SEC; + + if (devc->limit_samples > 0) { + if (devc->limit_samples < devc->sent_samples) { + samples_todo = 0; + } else if (devc->limit_samples - devc->sent_samples < samples_todo) { + samples_todo = devc->limit_samples - devc->sent_samples; + } + } + + if (samples_todo == 0) { + return G_SOURCE_CONTINUE; + } + + todo_us = samples_todo * G_USEC_PER_SEC / sr_libm2k_digital_samplerate_get(devc->m2k); + + logic_done = 0; + analog_done = 0; + + while (logic_done < samples_todo || analog_done < samples_todo) { + if (analog_done < samples_todo) { + analog_sent = MIN(samples_todo - analog_done, devc->buffersize); + + analog_data = sr_libm2k_analog_samples_get(devc->m2k, devc->buffersize); + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + if (ch->type == SR_CHANNEL_ANALOG) { + if (ch->enabled) { + send_analog_packet(sdi, analog_data[ch->index], + ch->index, analog_sent); + } + } + } + analog_done += analog_sent; + } + if (logic_done < samples_todo) { + logic_data = sr_libm2k_digital_samples_get(devc->m2k, devc->buffersize); + + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + logic.unitsize = devc->logic_unitsize; + + sending_now = MIN(samples_todo - logic_done, devc->buffersize); + + logic.length = sending_now * devc->logic_unitsize; + logic.data = logic_data; + sr_session_send(sdi, &packet); + logic_done += sending_now; + } + + } - if (revents == G_IO_IN) { - /* TODO */ + devc->sent_samples += logic_done; + devc->spent_us += todo_us; + if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples) + || (limit_us > 0 && devc->spent_us >= limit_us)) { + sr_dev_acquisition_stop(sdi); } - return TRUE; + return G_SOURCE_CONTINUE; } From e6b987cff2203c2b5625b4cddf9cc59ab0ab1b14 Mon Sep 17 00:00:00 2001 From: Adrian Suciu Date: Fri, 2 Jul 2021 11:42:58 +0300 Subject: [PATCH 24/24] wip --- configure.ac | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d762ae24e..92e02eb06 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,9 @@ SR_EXTRA_CXX_LIBS= SR_ARG_OPT_PKG([libserialport], [LIBSERIALPORT], , [libserialport >= 0.1.1]) +SR_ARG_OPT_PKG([libm2k], [LIBM2K], , + [libm2k]) + SR_ARG_OPT_PKG([libftdi], [LIBFTDI], , [libftdi1 >= 1.0]) # pkg-config file names: MinGW/MacOSX: hidapi; Linux: hidapi-hidraw/-libusb @@ -141,8 +144,9 @@ AS_IF([test "x$sr_have_libieee1284" = xyes], SR_ARG_OPT_PKG([libgio], [LIBGIO], , [gio-2.0 >= 2.24.0]) AC_LANG_PUSH([C++]) -PKG_CHECK_MODULES(LIBM2K, libm2k) +PKG_CHECK_MODULES(LIBM2K, [libm2k] ) AC_DEFINE([HAVE_LIBM2K], [1], [Have libm2k dep.]) +#SR_APPEND([SR_PKGLIBS], ['libm2k']) SR_APPEND([sr_deps_avail], [libm2k]) AM_CONDITIONAL([NEED_LIBM2K], [test "x$sr_have_libm2k" = xyes]) AC_LANG_POP([C++]) @@ -659,6 +663,7 @@ $sr_driver_summary Enabled serial communication transports: - serial comm ................... $sr_have_serial_comm - libserialport ................. $sr_have_libserialport + - libm2k ........................ $sr_have_libm2k - hidapi ........................ $sr_have_libhidapi - bluetooth ..................... $sr_have_bluetooth - bluez ......................... $sr_have_libbluez