http://sigrok.org/wiki/BG7TBL

This device isn't really a proper function generator but you could say it implements a subset of one so I added a function generator entry for it. Comments on how to continue forward are welcome.

MvH
Benjamin Larsson


>From 3862b16e3757bc0729a7c8ba87e4461a2c89bfd6 Mon Sep 17 00:00:00 2001
From: Benjamin Larsson <benja...@southpole.se>
Date: Mon, 19 Oct 2015 00:39:02 +0200
Subject: [PATCH] Initial BG7TBL function generator support

---
 Makefile.am                    |   6 +
 configure.ac                   |   1 +
 include/libsigrok/libsigrok.h  |   3 +
 src/drivers.c                  |   6 +
 src/hardware/bg7tbl/api.c      | 313 +++++++++++++++++++++++++++++++++++++++++
 src/hardware/bg7tbl/protocol.c |  57 ++++++++
 src/hardware/bg7tbl/protocol.h |  62 ++++++++
 src/hwdriver.c                 |   1 +
 8 files changed, 449 insertions(+)
 create mode 100644 src/hardware/bg7tbl/api.c
 create mode 100644 src/hardware/bg7tbl/protocol.c
 create mode 100644 src/hardware/bg7tbl/protocol.h

diff --git a/Makefile.am b/Makefile.am
index ab93285..0b7af34 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -198,6 +198,12 @@ libsigrok_la_SOURCES += \
 	src/hardware/beaglelogic/protocol.c \
 	src/hardware/beaglelogic/api.c
 endif
+if HW_BG7TBL
+libsigrok_la_SOURCES += \
+	src/hardware/bg7tbl/protocol.h \
+	src/hardware/bg7tbl/protocol.c \
+	src/hardware/bg7tbl/api.c
+endif
 if HW_BRYMEN_BM86X
 libsigrok_la_SOURCES += \
 	src/hardware/brymen-bm86x/protocol.h \
diff --git a/configure.ac b/configure.ac
index 0ffb23c..0e88810 100644
--- a/configure.ac
+++ b/configure.ac
@@ -219,6 +219,7 @@ SR_DRIVER([ASIX SIGMA/SIGMA2], [asix-sigma], [libftdi])
 SR_DRIVER([Atten PPS3xxx], [atten-pps3xxx], [libserialport])
 SR_DRIVER([BayLibre ACME], [baylibre-acme], [sys_timerfd_h])
 SR_DRIVER([BeagleLogic], [beaglelogic], [sys_mman_h sys_ioctl_h])
+SR_DRIVER([Bg7tbl], [bg7tbl], [libserialport])
 SR_DRIVER([Brymen BM86x], [brymen-bm86x], [libusb])
 SR_DRIVER([Brymen DMM], [brymen-dmm], [libserialport])
 SR_DRIVER([CEM DT-885x], [cem-dt-885x], [libserialport])
diff --git a/include/libsigrok/libsigrok.h b/include/libsigrok/libsigrok.h
index 6c67f57..ce8141a 100644
--- a/include/libsigrok/libsigrok.h
+++ b/include/libsigrok/libsigrok.h
@@ -700,6 +700,9 @@ enum sr_configkey {
 	/** The device can act as a scale. */
 	SR_CONF_SCALE,
 
+	/** The device can act as a function generator. */
+	SR_CONF_FUNCTION_GENERATOR,
+
 	/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 
 	/*--- Driver scan options -------------------------------------------*/
diff --git a/src/drivers.c b/src/drivers.c
index d83d955..7bcbbf2 100644
--- a/src/drivers.c
+++ b/src/drivers.c
@@ -40,6 +40,9 @@ extern SR_PRIV struct sr_dev_driver baylibre_acme_driver_info;
 #ifdef HAVE_HW_BEAGLELOGIC
 extern SR_PRIV struct sr_dev_driver beaglelogic_driver_info;
 #endif
+#ifdef HAVE_HW_BG7TBL
+extern SR_PRIV struct sr_dev_driver bg7tbl_driver_info;
+#endif
 #ifdef HAVE_HW_BRYMEN_BM86X
 extern SR_PRIV struct sr_dev_driver brymen_bm86x_driver_info;
 #endif
@@ -192,6 +195,9 @@ SR_PRIV struct sr_dev_driver **drivers_lists[] = {
 #ifdef HAVE_HW_BEAGLELOGIC
 	(DRVS) {&beaglelogic_driver_info, NULL},
 #endif
+#ifdef HAVE_HW_BG7TBL
+	(DRVS) {&bg7tbl_driver_info, NULL},
+#endif
 #ifdef HAVE_HW_BRYMEN_BM86X
 	(DRVS) {&brymen_bm86x_driver_info, NULL},
 #endif
diff --git a/src/hardware/bg7tbl/api.c b/src/hardware/bg7tbl/api.c
new file mode 100644
index 0000000..a25d565
--- /dev/null
+++ b/src/hardware/bg7tbl/api.c
@@ -0,0 +1,313 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2015 Benjamin Larsson <benja...@southpole.se>
+ *
+ * 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/>.
+ */
+
+/**
+ * Test command
+ * sigrok-cli -d bg7tbl:conn=/dev/ttyUSB0 --continuous --config output_frequency_target=200000000 -l 5
+ */
+
+#include <config.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <glib.h>
+#include <libsigrok/libsigrok.h>
+#include "libsigrok-internal.h"
+#include "protocol.h"
+
+
+#define SERIALCOMM "57600/8n1"
+#define PACKET_SIZE 2
+
+static const uint32_t scanopts[] = {
+	SR_CONF_CONN,
+	SR_CONF_SERIALCOMM,
+};
+
+static const uint32_t drvopts[] = {
+	SR_CONF_FUNCTION_GENERATOR,
+};
+
+static const uint32_t devopts[] = {
+	/* Device configuration */
+	SR_CONF_CONTINUOUS,
+	SR_CONF_OUTPUT_FREQUENCY_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+};
+
+static int dev_clear(const struct sr_dev_driver *di)
+{
+	return std_dev_clear(di, NULL);
+}
+
+static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
+{
+	return std_init(sr_ctx, di, LOG_PREFIX);
+}
+
+static GSList *scan(struct sr_dev_driver *di, GSList *options)
+{
+	struct sr_config *src;
+	GSList *l, *devices;
+	const char *conn, *serialcomm;
+	struct sr_dev_inst *sdi;
+	struct drv_context *drvc;
+	struct dev_context *devc;
+	struct sr_channel *ch;
+	struct sr_channel_group *cg;
+	struct sr_serial_dev_inst *serial;
+	uint8_t packet[PACKET_SIZE];
+	int delay_ms, ret;
+	char channel[10];
+
+	conn = serialcomm = NULL;
+	drvc = di->context;
+	devices = NULL;
+
+	for (l = options; l; l = l->next) {
+		src = l->data;
+		switch (src->key) {
+		case SR_CONF_CONN:
+			conn = g_variant_get_string(src->data, NULL);
+			break;
+		case SR_CONF_SERIALCOMM:
+			serialcomm = g_variant_get_string(src->data, NULL);
+			break;
+		}
+	}
+
+	if (!conn)
+		return NULL;
+
+	if (!serialcomm)
+		serialcomm = SERIALCOMM;
+
+	serial = sr_serial_dev_inst_new(conn, serialcomm);
+
+	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
+		return NULL;
+
+	serial_flush(serial);
+
+	/* Issue the firmware version command. */
+	memset(packet, 0, PACKET_SIZE);
+	packet[0] = 0x8f;
+	packet[1] = 'v';
+	delay_ms = serial_timeout(serial, PACKET_SIZE);
+	if (serial_write_blocking(serial, packet, PACKET_SIZE, delay_ms) < PACKET_SIZE) {
+		sr_err("Unable to write while probing for hardware.");
+		return NULL;
+	}
+
+	g_usleep(300 * 1000);
+	memset(packet, 0, PACKET_SIZE);
+	if ((ret = serial_read_nonblocking(serial, packet, 1)) < 0) {
+		sr_err("Unable to read while probing for hardware: %s",
+				sr_strerror(ret));
+		return NULL;
+	}
+	if (ret != 1 || packet[0] != 0x77) {
+		/* Doesn't look like an bg7tbl device. */
+		sr_info("Doesn't look like an bg7tbl device %x.", packet[0]);
+		return NULL;
+	}
+	
+	sr_info("Found device on port %s. FW version: 0x%x", conn, packet[0]);
+
+	sdi = g_malloc0(sizeof(struct sr_dev_inst));
+	sdi->status = SR_ST_INACTIVE;
+	sdi->vendor =  g_strdup("BG7TBL");
+	devc = g_malloc0(sizeof(struct dev_context));
+	devc->firmware_version = packet[0];
+	devc->frequency = 0;
+	devc->frequency_range_start =  138000000;
+	devc->frequency_range_stop  = 4400000000;
+	sdi->inst_type = SR_INST_SERIAL;
+	sdi->conn = serial;
+	sdi->priv = devc;
+	sdi->driver = di;
+
+	snprintf(channel, 10, "CH1");
+	ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, channel);
+	cg = g_malloc(sizeof(struct sr_channel_group));
+	cg->name = g_strdup(channel);
+	cg->channels = g_slist_append(NULL, ch);
+	cg->priv = NULL;
+	sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
+
+	drvc->instances = g_slist_append(drvc->instances, sdi);
+	devices = g_slist_append(devices, sdi);
+
+	serial_close(serial);
+
+	return devices;
+}
+
+static GSList *dev_list(const struct sr_dev_driver *di)
+{
+	return ((struct drv_context *)(di->context))->instances;
+}
+
+static int cleanup(const struct sr_dev_driver *di)
+{
+	return dev_clear(di);
+}
+
+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)
+{
+	struct dev_context *devc;
+
+	(void)cg;
+
+	if (sdi->status != SR_ST_ACTIVE)
+		return SR_ERR_DEV_CLOSED;
+
+	if (!(devc = sdi->priv)) {
+		sr_err("sdi->priv was NULL.");
+		return SR_ERR_BUG;
+	}
+
+	switch (key) {
+	case SR_CONF_OUTPUT_FREQUENCY_TARGET:
+		devc->frequency = g_variant_get_double(data);
+		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)
+{
+	struct dev_context *devc;
+	GVariant *grange[2];
+
+	(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:
+		if (!sdi)
+			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+					drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
+		else
+			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
+		break;
+	case SR_CONF_OUTPUT_FREQUENCY_TARGET:
+		devc = sdi->priv;
+		grange[0] = g_variant_new_uint64(devc->frequency_range_start);
+		grange[1] = g_variant_new_uint64(devc->frequency_range_stop);
+		*data = g_variant_new_tuple(grange, 2);
+		break;
+	default:
+		return SR_ERR_NA;
+	}
+
+		return SR_OK;
+}
+
+static int dev_close(struct sr_dev_inst *sdi)
+{
+	return std_serial_dev_close(sdi);
+}
+
+static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
+{
+        (void)cb_data;
+
+		if (sdi->status != SR_ST_ACTIVE)
+			return SR_ERR_DEV_CLOSED;
+
+		/* TODO: configure hardware, reset acquisition state, set up
+		* callbacks and send header packet. */
+		set_output_frequency(sdi);
+
+		return SR_OK;
+}
+
+static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
+{
+		(void)cb_data;
+		struct dev_context *devc;
+
+
+		if (sdi->status != SR_ST_ACTIVE)
+			return SR_ERR_DEV_CLOSED;
+
+		devc = sdi->priv;
+
+		/* TODO: stop acquisition. */
+
+		/** There is not really any good way to stop this device,
+		 *  this will emulate the original software. But significant
+		 *  signals and harminics will be there.
+		 */
+		devc->frequency = 10000000.0;
+		set_output_frequency(sdi);
+		devc->frequency = 0.0;
+		set_output_frequency(sdi);
+
+		return SR_OK;
+}
+
+
+SR_PRIV struct sr_dev_driver bg7tbl_driver_info = {
+	.name = "bg7tbl",
+	.longname = "BG7TBL USB RF Signal Generator",
+	.api_version = 1,
+	.init = init,
+	.cleanup = cleanup,
+	.scan = scan,
+	.dev_list = dev_list,
+	.dev_clear = NULL,
+	.config_get = config_get,
+	.config_set = config_set,
+	.config_list = config_list,
+	.dev_open = std_serial_dev_open,
+	.dev_close = dev_close,
+	.dev_acquisition_start = dev_acquisition_start,
+	.dev_acquisition_stop = dev_acquisition_stop,
+	.context = NULL,
+};
diff --git a/src/hardware/bg7tbl/protocol.c b/src/hardware/bg7tbl/protocol.c
new file mode 100644
index 0000000..3d413e6
--- /dev/null
+++ b/src/hardware/bg7tbl/protocol.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2015 Benjamin Larsson <benja...@southpole.se>
+ *
+ * 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 <string.h>
+#include "protocol.h"
+
+#define FSET_PSIZE 11
+
+static void dump_packet(char *msg, char *packet)
+{
+	int i;
+	char str[128];
+
+	str[0] = 0;
+	for (i = 0; i < FSET_PSIZE; i++)
+		sprintf(str + strlen(str), "%02x ", (unsigned char)packet[i]);
+	sr_dbg("%s: %s : %s", msg, str, &packet[1]);
+
+}
+
+SR_PRIV void set_output_frequency(const struct sr_dev_inst *sdi)
+{
+	struct dev_context *devc;
+	struct sr_serial_dev_inst *serial;
+	char packet[FSET_PSIZE+1] = {0};
+	int delay_ms;
+
+	devc = sdi->priv;
+	serial = sdi->conn;
+
+	packet[0] = 0x8f;
+	sprintf(&packet[1], "f%09d",(int)(devc->frequency/10.0));
+
+	delay_ms = serial_timeout(serial, FSET_PSIZE);
+	if (serial_write_blocking(serial, packet, FSET_PSIZE, delay_ms) < FSET_PSIZE) {
+		sr_err("Failed to send packet.");
+	}
+
+	dump_packet("sent", packet);
+}
\ No newline at end of file
diff --git a/src/hardware/bg7tbl/protocol.h b/src/hardware/bg7tbl/protocol.h
new file mode 100644
index 0000000..eaf916e
--- /dev/null
+++ b/src/hardware/bg7tbl/protocol.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2015 Benjamin Larsson <benja...@southpole.se>
+ *
+ * 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_BG7TBL_PROTOCOL_H
+#define LIBSIGROK_HARDWARE_BG7TBL_PROTOCOL_H
+
+#include <stdint.h>
+#include <glib.h>
+#include <libsigrok/libsigrok.h>
+#include "libsigrok-internal.h"
+
+#define LOG_PREFIX "serial-bg7tbl"
+
+struct bg7tbl_info {
+	/** libsigrok driver info struct. */
+	struct sr_dev_driver di;
+	/** Manufacturer/brand. */
+	char *vendor;
+	/** Model. */
+	char *device;
+	/** serialconn string. */
+	char *conn;
+	/** Baud rate. */
+	uint32_t baudrate;
+	/** Size of chipset info struct. */
+	gsize info_size;
+};
+
+/** Private, per-device-instance driver context. */
+struct dev_context {
+	/** The current transmitted frequency. */
+	double frequency;
+
+	/** Firmware version from the device. */
+	int firmware_version;
+
+	/** Frequency range start */
+	uint64_t frequency_range_start;
+
+	/** Frequency range stop */
+	uint64_t frequency_range_stop;
+};
+
+SR_PRIV void set_output_frequency(const struct sr_dev_inst *sdi);
+
+#endif
diff --git a/src/hwdriver.c b/src/hwdriver.c
index c5d4bf2..44142b7 100644
--- a/src/hwdriver.c
+++ b/src/hwdriver.c
@@ -61,6 +61,7 @@ static struct sr_key_info sr_key_info_config[] = {
 	{SR_CONF_LCRMETER, SR_T_STRING, NULL, "LCR meter", NULL},
 	{SR_CONF_ELECTRONIC_LOAD, SR_T_STRING, NULL, "Electronic load", NULL},
 	{SR_CONF_SCALE, SR_T_STRING, NULL, "Scale", NULL},
+	{SR_CONF_FUNCTION_GENERATOR, SR_T_STRING, NULL, "Function Generator", NULL},
 
 	/* Driver scan options */
 	{SR_CONF_CONN, SR_T_STRING, "conn",
-- 
2.1.4


------------------------------------------------------------------------------
_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to