Rohde&Schwarz SME-0x is a family of RF signal generators.
This patch adds basic device feature support. Frequency and output
power can be read and written. Parameter limits depend on the
specific device model and installed options.
Device list:
SME-02
SME-03
SME-03A
SME-03E
SME-06
From bad87a512be4ed3147580932d42f5834696e8d15 Mon Sep 17 00:00:00 2001
From: Vlad Ivanov <[email protected]>
Date: Thu, 27 Oct 2016 09:22:55 -0400
Subject: [PATCH] rohde-schwarz-sme-0x: Initial device support
Signed-off-by: Vlad Ivanov <[email protected]>
---
Makefile.am | 6 +
configure.ac | 1 +
src/hardware/rohde-schwarz-sme-0x/api.c | 296 +++++++++++++++++++++++++++
src/hardware/rohde-schwarz-sme-0x/protocol.c | 88 ++++++++
src/hardware/rohde-schwarz-sme-0x/protocol.h | 58 ++++++
5 files changed, 449 insertions(+)
create mode 100644 src/hardware/rohde-schwarz-sme-0x/api.c
create mode 100644 src/hardware/rohde-schwarz-sme-0x/protocol.c
create mode 100644 src/hardware/rohde-schwarz-sme-0x/protocol.h
diff --git a/Makefile.am b/Makefile.am
index 7d22a60..e0dd304 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -433,6 +433,12 @@ src_libdrivers_la_SOURCES += \
src/hardware/rigol-ds/protocol.c \
src/hardware/rigol-ds/api.c
endif
+if HW_ROHDE_SCHWARZ_SME_0X
+src_libdrivers_la_SOURCES += \
+ src/hardware/rohde-schwarz-sme-0x/protocol.h \
+ src/hardware/rohde-schwarz-sme-0x/protocol.c \
+ src/hardware/rohde-schwarz-sme-0x/api.c
+endif
if HW_SALEAE_LOGIC16
src_libdrivers_la_SOURCES += \
src/hardware/saleae-logic16/protocol.h \
diff --git a/configure.ac b/configure.ac
index 94e5457..1cb3fd8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -260,6 +260,7 @@ SR_DRIVER([OpenBench Logic Sniffer], [openbench-logic-sniffer], [libserialport])
SR_DRIVER([PCE PCE-322A], [pce-322a], [libserialport])
SR_DRIVER([Pipistrello-OLS], [pipistrello-ols], [libftdi])
SR_DRIVER([Rigol DS], [rigol-ds])
+SR_DRIVER([Rohde&Schwarz SME-0x], [rohde-schwarz-sme-0x], [libserialport])
SR_DRIVER([Saleae Logic16], [saleae-logic16], [libusb])
SR_DRIVER([SCPI PPS], [scpi-pps])
SR_DRIVER([serial DMM], [serial-dmm], [libserialport])
diff --git a/src/hardware/rohde-schwarz-sme-0x/api.c b/src/hardware/rohde-schwarz-sme-0x/api.c
new file mode 100644
index 0000000..59675c0
--- /dev/null
+++ b/src/hardware/rohde-schwarz-sme-0x/api.c
@@ -0,0 +1,296 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2016 Vlad Ivanov <[email protected]>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <libserialport.h>
+#include <scpi.h>
+#include <string.h>
+
+#include "protocol.h"
+
+SR_PRIV struct sr_dev_driver rohde_schwarz_sme_0x_driver_info;
+
+static const char * manufacturer = "Rohde&Schwarz";
+
+static const struct rs_device_model device_models[] = {{
+ .model_str = "SME02",
+ .freq_max = SR_GHZ(1.5),
+ .freq_min = SR_KHZ(5),
+ .power_max = 16,
+ .power_min = -144
+}, {
+ .model_str = "SME03E",
+ .freq_max = SR_GHZ(2.2),
+ .freq_min = SR_KHZ(5),
+ .power_max = 16,
+ .power_min = -144
+}, {
+ .model_str = "SME03A",
+ .freq_max = SR_GHZ(3),
+ .freq_min = SR_KHZ(5),
+ .power_max = 16,
+ .power_min = -144
+}, {
+ .model_str = "SME03",
+ .freq_max = SR_GHZ(3),
+ .freq_min = SR_KHZ(5),
+ .power_max = 16,
+ .power_min = -144
+}, {
+ .model_str = "SME06",
+ .freq_max = SR_GHZ(1.5),
+ .freq_min = SR_KHZ(5),
+ .power_max = 16,
+ .power_min = -144
+}};
+
+static const uint32_t scanopts[] = {
+ SR_CONF_CONN,
+ SR_CONF_SERIALCOMM,
+};
+
+static const uint32_t devopts[] = {
+ SR_CONF_OUTPUT_FREQUENCY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+ SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+};
+
+static int check_manufacturer(const char *str)
+{
+ if (!strcmp(str, manufacturer)) {
+ return SR_OK;
+ }
+
+ return SR_ERR;
+}
+
+static int rs_init_device(struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ uint8_t model_found;
+
+ devc = sdi->priv;
+ model_found = 0;
+
+ for (size_t i = 0; i < ARRAY_SIZE(device_models); i++) {
+ if (!strcmp(device_models[i].model_str, sdi->model)) {
+ model_found = 1;
+ devc->model_config = &device_models[i];
+ break;
+ }
+ }
+
+ if (!model_found) {
+ sr_dbg("Device %s %s is not supported by this driver", manufacturer, sdi->model);
+ return SR_ERR_NA;
+ }
+
+ return SR_OK;
+}
+
+static struct sr_dev_inst *rs_probe_serial_device(struct sr_scpi_dev_inst *scpi)
+{
+ struct sr_dev_inst *sdi;
+ struct dev_context *devc;
+ struct sr_scpi_hw_info *hw_info;
+
+ sdi = NULL;
+ devc = NULL;
+ hw_info = NULL;
+
+ rs_sme0x_mode_remote(scpi);
+
+ if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
+ goto fail;
+ }
+
+ if (check_manufacturer(hw_info->manufacturer) != SR_OK) {
+ goto fail;
+ }
+
+ sdi = g_malloc0(sizeof(struct sr_dev_inst));
+ sdi->vendor = g_strdup(hw_info->manufacturer);
+ sdi->model = g_strdup(hw_info->model);
+ sdi->version = g_strdup(hw_info->firmware_version);
+ sdi->serial_num = g_strdup(hw_info->serial_number);
+ sdi->driver = &rohde_schwarz_sme_0x_driver_info;
+ sdi->inst_type = SR_INST_SCPI;
+ sdi->conn = scpi;
+
+ sr_scpi_hw_info_free(hw_info);
+ hw_info = NULL;
+
+ devc = g_malloc0(sizeof(struct dev_context));
+ sdi->priv = devc;
+
+ if (rs_init_device(sdi) != SR_OK) {
+ goto fail;
+ }
+
+ return sdi;
+
+fail:
+ if (hw_info) {
+ sr_scpi_hw_info_free(hw_info);
+ }
+
+ if (sdi) {
+ sr_dev_inst_free(sdi);
+ }
+
+ g_free(devc);
+ return NULL;
+}
+
+static GSList *scan(struct sr_dev_driver *di, GSList *options)
+{
+ return sr_scpi_scan(di->context, options, rs_probe_serial_device);
+}
+
+static int dev_clear(const struct sr_dev_driver *di)
+{
+ return std_dev_clear(di, NULL);
+}
+
+static int dev_open(struct sr_dev_inst *sdi)
+{
+ if (sdi->status != SR_ST_ACTIVE && sr_scpi_open(sdi->conn) != SR_OK) {
+ return SR_ERR;
+ }
+
+ sdi->status = SR_ST_ACTIVE;
+
+ return SR_OK;
+}
+
+static int dev_close(struct sr_dev_inst *sdi)
+{
+ if (sdi->status == SR_ST_INACTIVE) {
+ return SR_OK;
+ }
+
+ sr_scpi_close(sdi->conn);
+
+ sdi->status = SR_ST_INACTIVE;
+
+ return SR_OK;
+}
+
+static int config_get(uint32_t key, GVariant **data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+ double value_f;
+
+ (void) cg;
+
+ switch (key) {
+ case SR_CONF_OUTPUT_FREQUENCY:
+ rs_sme0x_get_freq(sdi, &value_f);
+ *data = g_variant_new_double(value_f);
+ break;
+ case SR_CONF_AMPLITUDE:
+ rs_sme0x_get_power(sdi, &value_f);
+ *data = g_variant_new_double(value_f);
+ break;
+ default:
+ return SR_ERR_NA;
+ }
+
+ return SR_OK;
+}
+
+static int config_set(uint32_t key, GVariant *data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+ double value_f;
+
+ (void)cg;
+
+ if (!sdi) {
+ return SR_ERR_ARG;
+ }
+
+ if (sdi->status != SR_ST_ACTIVE) {
+ return SR_ERR_DEV_CLOSED;
+ }
+
+ switch (key) {
+ case SR_CONF_OUTPUT_FREQUENCY:
+ value_f = g_variant_get_double(data);
+ rs_sme0x_set_freq(sdi, value_f);
+ break;
+ case SR_CONF_AMPLITUDE:
+ value_f = g_variant_get_double(data);
+ rs_sme0x_set_power(sdi, value_f);
+ break;
+ default:
+ return SR_ERR_NA;
+ }
+
+ return SR_OK;
+}
+
+static int config_list(uint32_t key, GVariant **data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+ (void)sdi;
+ (void)cg;
+
+ switch (key) {
+ case SR_CONF_SCAN_OPTIONS:
+ *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
+ break;
+ case SR_CONF_DEVICE_OPTIONS:
+ *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
+ break;
+ default:
+ return SR_ERR_NA;
+ }
+
+ return SR_OK;
+}
+
+static int dev_acquisition_start(const struct sr_dev_inst *sdi)
+{
+ if (sdi->status != SR_ST_ACTIVE) {
+ return SR_ERR_DEV_CLOSED;
+ }
+
+ return SR_OK;
+}
+
+SR_PRIV struct sr_dev_driver rohde_schwarz_sme_0x_driver_info = {
+ .name = "rohde-schwarz-sme-0x",
+ .longname = "Rohde&Schwarz SME-0x",
+ .api_version = 1,
+ .init = std_init,
+ .cleanup = std_cleanup,
+ .scan = scan,
+ .dev_list = std_dev_list,
+ .dev_clear = 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 = std_serial_dev_acquisition_stop,
+ .context = NULL,
+};
+
+SR_REGISTER_DEV_DRIVER(rohde_schwarz_sme_0x_driver_info);
diff --git a/src/hardware/rohde-schwarz-sme-0x/protocol.c b/src/hardware/rohde-schwarz-sme-0x/protocol.c
new file mode 100644
index 0000000..8a4a9b7
--- /dev/null
+++ b/src/hardware/rohde-schwarz-sme-0x/protocol.c
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2016 Vlad Ivanov <[email protected]>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <scpi.h>
+
+#include "protocol.h"
+
+enum {
+ RS_CMD_CONTROL_REMOTE,
+ RS_CMD_SET_FREQ,
+ RS_CMD_SET_POWER,
+ RS_CMD_GET_FREQ,
+ RS_CMD_GET_POWER
+};
+
+static char * commands[] = {
+ [RS_CMD_CONTROL_REMOTE] = "\n",
+ [RS_CMD_SET_FREQ] = "FREQ %.1fHz",
+ [RS_CMD_SET_POWER] = "POW %.1fdBm",
+ [RS_CMD_GET_FREQ] = "FREQ?",
+ [RS_CMD_GET_POWER] = "POW?"
+};
+
+SR_PRIV int rs_sme0x_mode_remote(struct sr_scpi_dev_inst *scpi) {
+ return sr_scpi_send(scpi, commands[RS_CMD_CONTROL_REMOTE]);
+}
+
+SR_PRIV int rs_sme0x_get_freq(const struct sr_dev_inst *sdi, double * freq) {
+ if (sr_scpi_get_double(sdi->conn, commands[RS_CMD_GET_FREQ], freq) != SR_OK) {
+ return SR_ERR;
+ }
+
+ return SR_OK;
+}
+
+SR_PRIV int rs_sme0x_get_power(const struct sr_dev_inst *sdi, double * power) {
+ if (sr_scpi_get_double(sdi->conn, commands[RS_CMD_GET_POWER], power) != SR_OK) {
+ return SR_ERR;
+ }
+
+ return SR_OK;
+}
+
+SR_PRIV int rs_sme0x_set_freq(const struct sr_dev_inst *sdi, double freq) {
+ struct dev_context *devc;
+ const struct rs_device_model *config;
+
+ devc = sdi->priv;
+ config = devc->model_config;
+
+ if (freq > config->freq_max || freq < config->freq_min) {
+ return SR_ERR_ARG;
+ }
+
+ return sr_scpi_send(sdi->conn, commands[RS_CMD_SET_FREQ], freq);
+}
+
+SR_PRIV int rs_sme0x_set_power(const struct sr_dev_inst *sdi, double power) {
+ struct dev_context *devc;
+ const struct rs_device_model *config;
+
+ devc = sdi->priv;
+ config = devc->model_config;
+
+ if (power > config->power_max || power < config->power_min) {
+ return SR_ERR_ARG;
+ }
+
+ return sr_scpi_send(sdi->conn, commands[RS_CMD_SET_POWER], power);
+}
diff --git a/src/hardware/rohde-schwarz-sme-0x/protocol.h b/src/hardware/rohde-schwarz-sme-0x/protocol.h
new file mode 100644
index 0000000..f3f4fb5
--- /dev/null
+++ b/src/hardware/rohde-schwarz-sme-0x/protocol.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2016 Vlad Ivanov <[email protected]>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBSIGROK_HARDWARE_ROHDE_SCHWARZ_SME_0X_PROTOCOL_H
+#define LIBSIGROK_HARDWARE_ROHDE_SCHWARZ_SME_0X_PROTOCOL_H
+
+#include <stdint.h>
+#include <glib.h>
+#include <libsigrok/libsigrok.h>
+#include "libsigrok-internal.h"
+
+#define LOG_PREFIX "rohde-schwarz-sme-0x"
+
+struct rs_sme0x_info {
+ struct sr_dev_driver di;
+ char *vendor;
+ char *device;
+};
+
+struct rs_device_model {
+ const char * model_str;
+ double freq_max;
+ double freq_min;
+ double power_max;
+ double power_min;
+};
+
+/** Private, per-device-instance driver context. */
+struct dev_context {
+ /* Model-specific information */
+ const struct rs_device_model * model_config;
+};
+
+SR_PRIV int rs_sme0x_receive_data(int fd, int revents, void *cb_data);
+SR_PRIV int rs_sme0x_mode_remote(struct sr_scpi_dev_inst *scpi);
+SR_PRIV int rs_sme0x_close(struct sr_dev_inst *sdi);
+SR_PRIV int rs_sme0x_get_freq(const struct sr_dev_inst *sdi, double * freq);
+SR_PRIV int rs_sme0x_get_power(const struct sr_dev_inst *sdi, double * power);
+SR_PRIV int rs_sme0x_set_freq(const struct sr_dev_inst *sdi, double freq);
+SR_PRIV int rs_sme0x_set_power(const struct sr_dev_inst *sdi, double power);
+
+#endif
--
2.7.4
------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi
_______________________________________________
sigrok-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sigrok-devel