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