Add initial Sysclk SLA5032 driver.
This commit is contained in:
parent
ddbe6880a0
commit
8da8c8265f
|
@ -554,6 +554,14 @@ src_libdrivers_la_SOURCES += \
|
|||
src/hardware/sysclk-lwla/protocol.c \
|
||||
src/hardware/sysclk-lwla/api.c
|
||||
endif
|
||||
if HW_SYSCLK_SLA5032
|
||||
src_libdrivers_la_SOURCES += \
|
||||
src/hardware/sysclk-sla5032/sla5032.h \
|
||||
src/hardware/sysclk-sla5032/sla5032.c \
|
||||
src/hardware/sysclk-sla5032/protocol.h \
|
||||
src/hardware/sysclk-sla5032/protocol.c \
|
||||
src/hardware/sysclk-sla5032/api.c
|
||||
endif
|
||||
if HW_TELEINFO
|
||||
src_libdrivers_la_SOURCES += \
|
||||
src/hardware/teleinfo/protocol.h \
|
||||
|
|
|
@ -277,6 +277,7 @@ SR_DRIVER([serial DMM], [serial-dmm], [libserialport])
|
|||
SR_DRIVER([serial LCR], [serial-lcr], [libserialport])
|
||||
SR_DRIVER([Siglent SDS], [siglent-sds])
|
||||
SR_DRIVER([Sysclk LWLA], [sysclk-lwla], [libusb])
|
||||
SR_DRIVER([Sysclk SLA5032], [sysclk-sla5032], [libusb])
|
||||
SR_DRIVER([Teleinfo], [teleinfo], [libserialport])
|
||||
SR_DRIVER([Testo], [testo], [libusb])
|
||||
SR_DRIVER([Tondaj SL-814], [tondaj-sl-814], [libserialport])
|
||||
|
|
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2014 Daniel Elstner <daniel.kitta@gmail.com>
|
||||
* Copyright (C) 2019 Vitaliy Vorobyov
|
||||
*
|
||||
* 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 <libusb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libsigrok/libsigrok.h>
|
||||
#include <libsigrok-internal.h>
|
||||
#include "protocol.h"
|
||||
#include "sla5032.h"
|
||||
|
||||
/* Number of logic channels. */
|
||||
#define NUM_CHANNELS 32
|
||||
|
||||
static const uint32_t scanopts[] = {
|
||||
SR_CONF_CONN,
|
||||
};
|
||||
|
||||
static const uint32_t drvopts[] = {
|
||||
SR_CONF_LOGIC_ANALYZER,
|
||||
};
|
||||
|
||||
static const int32_t trigger_matches[] = {
|
||||
SR_TRIGGER_ZERO,
|
||||
SR_TRIGGER_ONE,
|
||||
SR_TRIGGER_RISING,
|
||||
SR_TRIGGER_FALLING,
|
||||
};
|
||||
|
||||
static const uint64_t capture_ratios[] = {
|
||||
0, 10, 20, 30, 50, 70, 90, 100,
|
||||
};
|
||||
|
||||
static const uint32_t devopts[] = {
|
||||
SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
|
||||
SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
|
||||
SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
|
||||
SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
|
||||
SR_CONF_RLE | SR_CONF_GET,
|
||||
};
|
||||
|
||||
static const uint64_t samplerates[] = {
|
||||
SR_MHZ(500), SR_MHZ(400), SR_MHZ(250), SR_MHZ(200), SR_MHZ(100),
|
||||
SR_MHZ(50), SR_MHZ(25), SR_MHZ(20), SR_MHZ(10), SR_MHZ(5), SR_MHZ(2),
|
||||
SR_MHZ(1), SR_KHZ(500), SR_KHZ(200), SR_KHZ(100), SR_KHZ(50),
|
||||
SR_KHZ(20), SR_KHZ(10), SR_KHZ(5), SR_KHZ(2),
|
||||
};
|
||||
|
||||
static struct sr_dev_inst *dev_inst_new(void)
|
||||
{
|
||||
struct sr_dev_inst *sdi;
|
||||
struct dev_context *devc;
|
||||
int i;
|
||||
char name[8];
|
||||
|
||||
devc = g_malloc0(sizeof(struct dev_context));
|
||||
devc->active_fpga_config = FPGA_NOCONF;
|
||||
devc->samplerate = samplerates[0];
|
||||
devc->limit_samples = MAX_LIMIT_SAMPLES;
|
||||
devc->capture_ratio = capture_ratios[4];
|
||||
devc->channel_mask = (UINT64_C(1) << NUM_CHANNELS) - 1;
|
||||
|
||||
sdi = g_malloc0(sizeof(struct sr_dev_inst));
|
||||
sdi->status = SR_ST_INACTIVE;
|
||||
sdi->vendor = g_strdup("Sysclk");
|
||||
sdi->model = g_strdup("SLA5032");
|
||||
sdi->priv = devc;
|
||||
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
g_snprintf(name, sizeof(name), "CH%d", i);
|
||||
sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, name);
|
||||
}
|
||||
|
||||
return sdi;
|
||||
}
|
||||
|
||||
/* Create a new device instance for a libusb device if it is a Sysclk SLA5032
|
||||
* device and also matches the connection specification.
|
||||
*/
|
||||
static struct sr_dev_inst *dev_inst_new_matching(GSList *conn_matches,
|
||||
libusb_device *dev)
|
||||
{
|
||||
GSList *node;
|
||||
struct sr_usb_dev_inst *usb;
|
||||
struct sr_dev_inst *sdi;
|
||||
struct libusb_device_descriptor des;
|
||||
int bus, address, ret;
|
||||
unsigned int vid, pid;
|
||||
|
||||
bus = libusb_get_bus_number(dev);
|
||||
address = libusb_get_device_address(dev);
|
||||
|
||||
for (node = conn_matches; node != NULL; node = node->next) {
|
||||
usb = node->data;
|
||||
if (usb && usb->bus == bus && usb->address == address)
|
||||
break; /* found */
|
||||
}
|
||||
if (conn_matches && !node)
|
||||
return NULL; /* no match */
|
||||
|
||||
ret = libusb_get_device_descriptor(dev, &des);
|
||||
if (ret != 0) {
|
||||
sr_err("Failed to get USB device descriptor: %s.",
|
||||
libusb_error_name(ret));
|
||||
return NULL;
|
||||
}
|
||||
vid = des.idVendor;
|
||||
pid = des.idProduct;
|
||||
|
||||
/* Create sigrok device instance. */
|
||||
if (vid == USB_VID_SYSCLK && pid == USB_PID_SLA5032) {
|
||||
} else {
|
||||
if (conn_matches)
|
||||
sr_warn("USB device %d.%d (%04x:%04x) is not a"
|
||||
" Sysclk SLA5032.", bus, address, vid, pid);
|
||||
return NULL;
|
||||
}
|
||||
sdi = dev_inst_new();
|
||||
|
||||
sdi->inst_type = SR_INST_USB;
|
||||
sdi->conn = sr_usb_dev_inst_new(bus, address, NULL);
|
||||
|
||||
return sdi;
|
||||
}
|
||||
|
||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
|
||||
{
|
||||
GSList *conn_devices, *devices, *node;
|
||||
struct drv_context *drvc;
|
||||
struct sr_dev_inst *sdi;
|
||||
struct sr_config *src;
|
||||
const char *conn;
|
||||
libusb_device **devlist;
|
||||
ssize_t num_devs, i;
|
||||
|
||||
drvc = di->context;
|
||||
conn = NULL;
|
||||
conn_devices = NULL;
|
||||
devices = NULL;
|
||||
|
||||
for (node = options; node != NULL; node = node->next) {
|
||||
src = node->data;
|
||||
if (src->key == SR_CONF_CONN) {
|
||||
conn = g_variant_get_string(src->data, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (conn) {
|
||||
/* Find devices matching the connection specification. */
|
||||
conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
|
||||
}
|
||||
|
||||
/* List all libusb devices. */
|
||||
num_devs = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
|
||||
if (num_devs < 0) {
|
||||
sr_err("Failed to list USB devices: %s.",
|
||||
libusb_error_name(num_devs));
|
||||
g_slist_free_full(conn_devices,
|
||||
(GDestroyNotify)&sr_usb_dev_inst_free);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Scan the USB device list for matching devices. */
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
sdi = dev_inst_new_matching(conn_devices, devlist[i]);
|
||||
if (!sdi)
|
||||
continue; /* no match */
|
||||
|
||||
/* Register device instance with driver. */
|
||||
devices = g_slist_append(devices, sdi);
|
||||
}
|
||||
|
||||
libusb_free_device_list(devlist, 1);
|
||||
g_slist_free_full(conn_devices, (GDestroyNotify)&sr_usb_dev_inst_free);
|
||||
|
||||
return std_scan_complete(di, devices);
|
||||
}
|
||||
|
||||
static int dev_open(struct sr_dev_inst *sdi)
|
||||
{
|
||||
struct drv_context *drvc;
|
||||
struct dev_context *devc;
|
||||
struct sr_usb_dev_inst *usb;
|
||||
int ret;
|
||||
|
||||
drvc = sdi->driver->context;
|
||||
devc = sdi->priv;
|
||||
usb = sdi->conn;
|
||||
|
||||
ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = libusb_set_configuration(usb->devhdl, USB_CONFIG);
|
||||
if (ret != LIBUSB_SUCCESS) {
|
||||
sr_err("Failed to set USB configuration: %s.",
|
||||
libusb_error_name(ret));
|
||||
sr_usb_close(usb);
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE);
|
||||
if (ret != LIBUSB_SUCCESS) {
|
||||
sr_err("Failed to claim interface: %s.",
|
||||
libusb_error_name(ret));
|
||||
sr_usb_close(usb);
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
sdi->status = SR_ST_ACTIVE;
|
||||
|
||||
devc->active_fpga_config = FPGA_NOCONF;
|
||||
devc->state = STATE_IDLE;
|
||||
|
||||
ret = sla5032_apply_fpga_config(sdi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dev_close(struct sr_dev_inst *sdi)
|
||||
{
|
||||
struct sr_usb_dev_inst *usb;
|
||||
|
||||
usb = sdi->conn;
|
||||
|
||||
if (usb->devhdl)
|
||||
libusb_release_interface(usb->devhdl, USB_INTERFACE);
|
||||
|
||||
sr_usb_close(usb);
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
/* Check whether the device options contain a specific key.
|
||||
* Also match against get/set/list bits if specified.
|
||||
*/
|
||||
static int has_devopt(uint32_t key)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(devopts); i++) {
|
||||
if ((devopts[i] & (SR_CONF_MASK | key)) == key)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int config_get(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)
|
||||
return SR_ERR_ARG;
|
||||
|
||||
devc = sdi->priv;
|
||||
|
||||
if (!has_devopt(key | SR_CONF_GET))
|
||||
return SR_ERR_NA;
|
||||
|
||||
switch (key) {
|
||||
case SR_CONF_SAMPLERATE:
|
||||
*data = g_variant_new_uint64(devc->samplerate);
|
||||
break;
|
||||
case SR_CONF_LIMIT_SAMPLES:
|
||||
*data = g_variant_new_uint64(devc->limit_samples);
|
||||
break;
|
||||
case SR_CONF_CAPTURE_RATIO:
|
||||
*data = g_variant_new_uint64(devc->capture_ratio);
|
||||
break;
|
||||
case SR_CONF_RLE:
|
||||
*data = g_variant_new_boolean(TRUE);
|
||||
break;
|
||||
default:
|
||||
/* Must not happen for a key listed in devopts. */
|
||||
return SR_ERR_BUG;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static int config_set(uint32_t key, GVariant *data,
|
||||
const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
|
||||
{
|
||||
uint64_t value;
|
||||
struct dev_context *devc;
|
||||
int idx;
|
||||
|
||||
(void)cg;
|
||||
|
||||
if (!sdi)
|
||||
return SR_ERR_ARG;
|
||||
|
||||
devc = sdi->priv;
|
||||
|
||||
if (!has_devopt(key | SR_CONF_SET))
|
||||
return SR_ERR_NA;
|
||||
|
||||
switch (key) {
|
||||
case SR_CONF_SAMPLERATE:
|
||||
value = g_variant_get_uint64(data);
|
||||
if ((idx = std_u64_idx(data, ARRAY_AND_SIZE(samplerates))) < 0)
|
||||
return SR_ERR_ARG;
|
||||
devc->samplerate = samplerates[idx];
|
||||
break;
|
||||
case SR_CONF_LIMIT_SAMPLES:
|
||||
value = g_variant_get_uint64(data);
|
||||
if (value > MAX_LIMIT_SAMPLES || value < MIN_LIMIT_SAMPLES)
|
||||
return SR_ERR_ARG;
|
||||
devc->limit_samples = value;
|
||||
break;
|
||||
case SR_CONF_CAPTURE_RATIO:
|
||||
value = g_variant_get_uint64(data);
|
||||
devc->capture_ratio = value;
|
||||
break;
|
||||
default:
|
||||
/* Must not happen for a key listed in devopts. */
|
||||
return SR_ERR_BUG;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static int config_channel_set(const struct sr_dev_inst *sdi,
|
||||
struct sr_channel *ch, unsigned int changes)
|
||||
{
|
||||
uint64_t channel_bit;
|
||||
struct dev_context *devc;
|
||||
|
||||
if (!sdi)
|
||||
return SR_ERR_ARG;
|
||||
|
||||
devc = sdi->priv;
|
||||
|
||||
if (ch->index < 0 || ch->index >= NUM_CHANNELS) {
|
||||
sr_err("Channel index %d out of range.", ch->index);
|
||||
return SR_ERR_BUG;
|
||||
}
|
||||
|
||||
if ((changes & SR_CHANNEL_SET_ENABLED) != 0) {
|
||||
channel_bit = UINT64_C(1) << ch->index;
|
||||
|
||||
/* Enable or disable logic input for this channel. */
|
||||
if (ch->enabled)
|
||||
devc->channel_mask |= channel_bit;
|
||||
else
|
||||
devc->channel_mask &= ~channel_bit;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
/* Derive trigger masks from the session's trigger configuration. */
|
||||
static int prepare_trigger_masks(const struct sr_dev_inst* sdi)
|
||||
{
|
||||
uint32_t trigger_mask, trigger_values, trigger_edge_mask;
|
||||
uint32_t level_bit, type_bit;
|
||||
struct dev_context* devc;
|
||||
struct sr_trigger* trigger;
|
||||
struct sr_trigger_stage* stage;
|
||||
struct sr_trigger_match* match;
|
||||
const GSList* node;
|
||||
int idx;
|
||||
enum sr_trigger_matches trg;
|
||||
|
||||
devc = sdi->priv;
|
||||
|
||||
trigger_mask = 0;
|
||||
trigger_values = 0;
|
||||
trigger_edge_mask = 0;
|
||||
|
||||
trigger = sr_session_trigger_get(sdi->session);
|
||||
if (!trigger || !trigger->stages) {
|
||||
goto no_triggers;
|
||||
}
|
||||
|
||||
if (trigger->stages->next) {
|
||||
sr_err("This device only supports 1 trigger stage.");
|
||||
return SR_ERR_ARG;
|
||||
}
|
||||
stage = trigger->stages->data;
|
||||
|
||||
for (node = stage->matches; node; node = node->next) {
|
||||
match = node->data;
|
||||
|
||||
if (!match->channel->enabled)
|
||||
continue; /* Ignore disabled channel. */
|
||||
|
||||
idx = match->channel->index;
|
||||
trg = match->match;
|
||||
|
||||
if (idx < 0 || idx >= NUM_CHANNELS) {
|
||||
sr_err("Channel index %d out of range.", idx);
|
||||
return SR_ERR_BUG; /* Should not happen. */
|
||||
}
|
||||
if (trg != SR_TRIGGER_ZERO
|
||||
&& trg != SR_TRIGGER_ONE
|
||||
&& trg != SR_TRIGGER_RISING
|
||||
&& trg != SR_TRIGGER_FALLING) {
|
||||
sr_err("Unsupported trigger match for CH%d.", idx);
|
||||
return SR_ERR_ARG;
|
||||
}
|
||||
level_bit = (trg == SR_TRIGGER_ONE
|
||||
|| trg == SR_TRIGGER_RISING) ? 1 : 0;
|
||||
type_bit = (trg == SR_TRIGGER_RISING
|
||||
|| trg == SR_TRIGGER_FALLING) ? 1 : 0; /* 1 if edge triggered, 0 if level triggered */
|
||||
|
||||
trigger_mask |= UINT32_C(1) << idx;
|
||||
trigger_values |= level_bit << idx;
|
||||
trigger_edge_mask |= type_bit << idx;
|
||||
}
|
||||
|
||||
no_triggers:
|
||||
devc->trigger_mask = trigger_mask;
|
||||
devc->trigger_values = trigger_values;
|
||||
devc->trigger_edge_mask = trigger_edge_mask;
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static int config_commit(const struct sr_dev_inst *sdi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = prepare_trigger_masks(sdi);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = sla5032_apply_fpga_config(sdi);
|
||||
if (ret != SR_OK) {
|
||||
sr_err("Failed to apply FPGA configuration.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
devc = (sdi) ? sdi->priv : NULL;
|
||||
|
||||
switch (key) {
|
||||
case SR_CONF_SCAN_OPTIONS:
|
||||
case SR_CONF_DEVICE_OPTIONS:
|
||||
return std_opts_config_list(key, data, sdi, cg,
|
||||
ARRAY_AND_SIZE(scanopts), ARRAY_AND_SIZE(drvopts),
|
||||
(devc) ? devopts : NULL,
|
||||
(devc) ? ARRAY_SIZE(devopts) : 0);
|
||||
}
|
||||
|
||||
if (!devc)
|
||||
return SR_ERR_ARG;
|
||||
if (!has_devopt(key | SR_CONF_LIST))
|
||||
return SR_ERR_NA;
|
||||
|
||||
switch (key) {
|
||||
case SR_CONF_SAMPLERATE:
|
||||
*data = std_gvar_samplerates(ARRAY_AND_SIZE(samplerates));
|
||||
break;
|
||||
case SR_CONF_LIMIT_SAMPLES:
|
||||
*data = std_gvar_tuple_u64(MIN_LIMIT_SAMPLES, MAX_LIMIT_SAMPLES);
|
||||
break;
|
||||
case SR_CONF_CAPTURE_RATIO:
|
||||
*data = std_gvar_array_u64(ARRAY_AND_SIZE(capture_ratios));
|
||||
break;
|
||||
case SR_CONF_TRIGGER_MATCH:
|
||||
*data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
|
||||
break;
|
||||
default:
|
||||
/* Must not happen for a key listed in devopts. */
|
||||
return SR_ERR_BUG;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
/* Set up the device hardware to begin capturing samples as soon as the
|
||||
* configured trigger conditions are met, or immediately if no triggers
|
||||
* are configured.
|
||||
*/
|
||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
|
||||
{
|
||||
return la_start_acquisition(sdi);
|
||||
}
|
||||
|
||||
static int dev_acquisition_stop(struct sr_dev_inst *sdi)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
|
||||
devc = sdi->priv;
|
||||
|
||||
sr_session_source_remove(sdi->session, -1);
|
||||
|
||||
std_session_send_df_end(sdi);
|
||||
|
||||
devc->state = STATE_IDLE;
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static struct sr_dev_driver sysclk_sla5032_driver_info = {
|
||||
.name = "sysclk-sla5032",
|
||||
.longname = "Sysclk SLA5032",
|
||||
.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_channel_set = config_channel_set,
|
||||
.config_commit = config_commit,
|
||||
.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(sysclk_sla5032_driver_info);
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2019 Vitaliy Vorobyov
|
||||
*
|
||||
* 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"
|
||||
#include "sla5032.h"
|
||||
|
||||
/* Callback handling data */
|
||||
static int la_prepare_data(int fd, int revents, void *cb_data)
|
||||
{
|
||||
struct sr_dev_inst *sdi;
|
||||
struct dev_context *devc;
|
||||
struct sr_usb_dev_inst *usb;
|
||||
int i, j, ret, xfer_len;
|
||||
uint8_t *rle_buf, *samples;
|
||||
const uint8_t *p, *q;
|
||||
uint16_t rle_count;
|
||||
int samples_count, rle_samples_count;
|
||||
uint32_t status[3];
|
||||
struct sr_datafeed_packet packet;
|
||||
struct sr_datafeed_logic logic;
|
||||
uint32_t value;
|
||||
int trigger_offset;
|
||||
|
||||
enum {
|
||||
RLE_SAMPLE_SIZE = sizeof(uint32_t) + sizeof(uint16_t),
|
||||
RLE_SAMPLES_COUNT = 0x100000,
|
||||
RLE_BUF_SIZE = RLE_SAMPLES_COUNT * RLE_SAMPLE_SIZE,
|
||||
RLE_END_MARKER = 0xFFFF,
|
||||
};
|
||||
|
||||
(void)fd;
|
||||
(void)revents;
|
||||
|
||||
sdi = cb_data;
|
||||
devc = sdi->priv;
|
||||
usb = sdi->conn;
|
||||
|
||||
memset(status, 0, sizeof(status));
|
||||
ret = sla5032_get_status(usb, status);
|
||||
if (ret != SR_OK) {
|
||||
sla5032_write_reg14_zero(usb);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
/* data not ready (acquision in progress) */
|
||||
if (status[1] != 3)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
sr_dbg("acquision done, status: %u.", (unsigned int)status[2]);
|
||||
|
||||
/* data ready (download, decode and send to sigrok) */
|
||||
ret = sla5032_set_read_back(usb);
|
||||
if (ret != SR_OK) {
|
||||
sla5032_write_reg14_zero(usb);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
rle_buf = g_try_malloc(RLE_BUF_SIZE);
|
||||
if (rle_buf == NULL) {
|
||||
sla5032_write_reg14_zero(usb);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
do {
|
||||
xfer_len = 0;
|
||||
ret = sla5032_read_data_chunk(usb, rle_buf, RLE_BUF_SIZE, &xfer_len);
|
||||
if (ret != SR_OK) {
|
||||
sla5032_write_reg14_zero(usb);
|
||||
g_free(rle_buf);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
|
||||
sr_dbg("acquision done, ret: %d.", ret);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
sr_dbg("acquision done, xfer_len: %d.", xfer_len);
|
||||
|
||||
if (xfer_len == 0) {
|
||||
sla5032_write_reg14_zero(usb);
|
||||
g_free(rle_buf);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
p = rle_buf;
|
||||
samples_count = 0;
|
||||
rle_samples_count = xfer_len / RLE_SAMPLE_SIZE;
|
||||
|
||||
sr_dbg("acquision done, rle_samples_count: %d.", rle_samples_count);
|
||||
|
||||
for (i = 0; i < rle_samples_count; i++) {
|
||||
p += sizeof(uint32_t); /* skip sample value */
|
||||
|
||||
rle_count = RL16(p); /* read RLE counter */
|
||||
p += sizeof(uint16_t);
|
||||
if (rle_count == RLE_END_MARKER) {
|
||||
rle_samples_count = i;
|
||||
break;
|
||||
}
|
||||
samples_count += rle_count + 1;
|
||||
}
|
||||
sr_dbg("acquision done, samples_count: %d.", samples_count);
|
||||
|
||||
if (samples_count == 0) {
|
||||
sr_dbg("acquision done, no samples.");
|
||||
sla5032_write_reg14_zero(usb);
|
||||
g_free(rle_buf);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
/* Decode RLE */
|
||||
samples = g_try_malloc(samples_count * sizeof(uint32_t));
|
||||
if (!samples) {
|
||||
sr_dbg("memory allocation error.");
|
||||
sla5032_write_reg14_zero(usb);
|
||||
g_free(rle_buf);
|
||||
sr_dev_acquisition_stop(sdi);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
p = rle_buf;
|
||||
q = samples;
|
||||
for (i = 0; i < rle_samples_count; i++) {
|
||||
value = RL32(p);
|
||||
p += sizeof(uint32_t); /* read sample value */
|
||||
|
||||
rle_count = RL16(p); /* read RLE counter */
|
||||
p += sizeof(uint16_t);
|
||||
|
||||
if (rle_count == RLE_END_MARKER) {
|
||||
sr_dbg("RLE end marker found.");
|
||||
break;
|
||||
}
|
||||
|
||||
for (j = 0; j <= rle_count; j++) {
|
||||
WL32(q, value);
|
||||
q += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
if (devc->trigger_fired) {
|
||||
/* Send the incoming transfer to the session bus. */
|
||||
packet.type = SR_DF_LOGIC;
|
||||
packet.payload = &logic;
|
||||
|
||||
logic.length = samples_count * sizeof(uint32_t);
|
||||
logic.unitsize = sizeof(uint32_t);
|
||||
logic.data = samples;
|
||||
sr_session_send(sdi, &packet);
|
||||
} else {
|
||||
trigger_offset = soft_trigger_logic_check(devc->stl,
|
||||
samples, samples_count * sizeof(uint32_t), NULL);
|
||||
if (trigger_offset > -1) {
|
||||
packet.type = SR_DF_LOGIC;
|
||||
packet.payload = &logic;
|
||||
int num_samples = samples_count - trigger_offset;
|
||||
|
||||
logic.length = num_samples * sizeof(uint32_t);
|
||||
logic.unitsize = sizeof(uint32_t);
|
||||
logic.data = samples + trigger_offset * sizeof(uint32_t);
|
||||
sr_session_send(sdi, &packet);
|
||||
|
||||
devc->trigger_fired = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(samples);
|
||||
} while (rle_samples_count == RLE_SAMPLES_COUNT);
|
||||
|
||||
sr_dbg("acquision stop, rle_samples_count < RLE_SAMPLES_COUNT.");
|
||||
|
||||
sla5032_write_reg14_zero(usb);
|
||||
|
||||
sr_dev_acquisition_stop(sdi); /* if all data transfered */
|
||||
|
||||
g_free(rle_buf);
|
||||
|
||||
if (devc->stl) {
|
||||
soft_trigger_logic_free(devc->stl);
|
||||
devc->stl = NULL;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
SR_PRIV int la_start_acquisition(const struct sr_dev_inst *sdi)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
struct sr_usb_dev_inst *usb;
|
||||
struct sr_trigger* trigger;
|
||||
int ret;
|
||||
enum { poll_interval_ms = 100 };
|
||||
uint64_t pre, post;
|
||||
|
||||
devc = sdi->priv;
|
||||
usb = sdi->conn;
|
||||
|
||||
if (devc->state != STATE_IDLE) {
|
||||
sr_err("Not in idle state, cannot start acquisition.");
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
pre = (devc->limit_samples * devc->capture_ratio) / 100;
|
||||
post = devc->limit_samples - pre;
|
||||
|
||||
if ((trigger = sr_session_trigger_get(sdi->session))) {
|
||||
devc->stl = soft_trigger_logic_new(sdi, trigger, pre);
|
||||
if (!devc->stl) {
|
||||
sr_err("stl alloc error.");
|
||||
return SR_ERR_MALLOC;
|
||||
}
|
||||
devc->trigger_fired = FALSE;
|
||||
}
|
||||
else
|
||||
devc->trigger_fired = TRUE;
|
||||
|
||||
sr_dbg("start acquision, smp lim: %" PRIu64 ", cap ratio: %" PRIu64
|
||||
".", devc->limit_samples, devc->capture_ratio);
|
||||
|
||||
sr_dbg("start acquision, pre: %" PRIu64 ", post: %" PRIu64 ".", pre, post);
|
||||
pre /= 256;
|
||||
pre = max(pre, 2);
|
||||
pre--;
|
||||
|
||||
post /= 256;
|
||||
post = max(post, 2);
|
||||
post--;
|
||||
|
||||
sr_dbg("start acquision, pre: %" PRIx64 ", post: %" PRIx64 ".", pre, post);
|
||||
|
||||
/* (x + 1) * 256 (samples) pre, post */
|
||||
ret = sla5032_set_depth(usb, pre, post);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = sla5032_set_triggers(usb, devc->trigger_values, devc->trigger_edge_mask, devc->trigger_mask);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = sla5032_set_samplerate(usb, devc->samplerate);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
/* TODO: make PWM generator as separate configurable subdevice */
|
||||
enum {
|
||||
pwm1_hi = 20000000 - 1,
|
||||
pwm1_lo = 200000 - 1,
|
||||
pwm2_hi = 15 - 1,
|
||||
pwm2_lo = 5 - 1,
|
||||
};
|
||||
|
||||
ret = sla5032_set_pwm1(usb, pwm1_hi, pwm1_lo);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = sla5032_set_pwm2(usb, pwm2_hi, pwm2_lo);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = sla5032_start_sample(usb);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
sr_session_source_add(sdi->session, -1, 0, poll_interval_ms,
|
||||
la_prepare_data, (struct sr_dev_inst *)sdi);
|
||||
|
||||
std_session_send_df_header(sdi);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2019 Vitaliy Vorobyov
|
||||
*
|
||||
* 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_SYSCLK_SLA5032_PROTOCOL_H
|
||||
#define LIBSIGROK_HARDWARE_SYSCLK_SLA5032_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <libusb.h>
|
||||
#include <glib.h>
|
||||
#include <libsigrok/libsigrok.h>
|
||||
#include <libsigrok-internal.h>
|
||||
|
||||
#define LOG_PREFIX "sysclk-sla5032"
|
||||
|
||||
/* Maximum configurable sample count limit. */
|
||||
#define MAX_LIMIT_SAMPLES (64 * 1024 * 1024)
|
||||
#define MIN_LIMIT_SAMPLES 512
|
||||
|
||||
/* USB vendor and product IDs. */
|
||||
enum {
|
||||
USB_VID_SYSCLK = 0x2961,
|
||||
USB_PID_SLA5032 = 0x66B0,
|
||||
};
|
||||
|
||||
/* USB device characteristics. */
|
||||
enum {
|
||||
USB_CONFIG = 1,
|
||||
USB_INTERFACE = 0,
|
||||
USB_CMD_TIMEOUT_MS = 5000,
|
||||
USB_REPLY_TIMEOUT_MS = 500000,
|
||||
USB_DATA_TIMEOUT_MS = 2000,
|
||||
};
|
||||
|
||||
/* USB device end points. */
|
||||
enum usb_endpoint {
|
||||
EP_COMMAND = 4 | LIBUSB_ENDPOINT_OUT,
|
||||
EP_REPLY = 8 | LIBUSB_ENDPOINT_IN,
|
||||
EP_DATA = 6 | LIBUSB_ENDPOINT_IN,
|
||||
};
|
||||
|
||||
|
||||
/* Common indicator for no or unknown FPGA config. */
|
||||
enum {
|
||||
FPGA_NOCONF = -1,
|
||||
FPGA_CONF,
|
||||
};
|
||||
|
||||
/** Acquisition protocol states. */
|
||||
enum protocol_state {
|
||||
/* idle states */
|
||||
STATE_IDLE = 0,
|
||||
STATE_STATUS_WAIT,
|
||||
/* device command states */
|
||||
STATE_START_CAPTURE,
|
||||
STATE_STOP_CAPTURE,
|
||||
STATE_READ_PREPARE,
|
||||
STATE_READ_FINISH,
|
||||
/* command followed by response */
|
||||
STATE_EXPECT_RESPONSE = 1 << 3,
|
||||
STATE_STATUS_REQUEST = STATE_EXPECT_RESPONSE,
|
||||
STATE_LENGTH_REQUEST,
|
||||
STATE_READ_REQUEST,
|
||||
};
|
||||
|
||||
struct dev_context {
|
||||
uint64_t samplerate; /* requested samplerate */
|
||||
uint64_t limit_samples; /* requested capture length (samples) */
|
||||
uint64_t capture_ratio;
|
||||
|
||||
uint64_t channel_mask; /* bit mask of enabled channels */
|
||||
uint64_t trigger_mask; /* trigger enable mask */
|
||||
uint64_t trigger_edge_mask; /* trigger type mask */
|
||||
uint64_t trigger_values; /* trigger level/slope bits */
|
||||
|
||||
struct soft_trigger_logic *stl;
|
||||
gboolean trigger_fired;
|
||||
|
||||
int active_fpga_config; /* FPGA configuration index */
|
||||
|
||||
enum protocol_state state; /* async protocol state */
|
||||
};
|
||||
|
||||
SR_PRIV int la_start_acquisition(const struct sr_dev_inst *sdi);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,742 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2019 Vitaliy Vorobyov
|
||||
*
|
||||
* 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 "sla5032.h"
|
||||
#include "protocol.h"
|
||||
|
||||
/*
|
||||
* Register description (all registers are 32bit):
|
||||
*
|
||||
* Rx - means register with index x (register address is x*4)
|
||||
*
|
||||
* R0(wr): trigger sel0 (low/high)
|
||||
* R0(rd): n*256 samples (post trigger) captured
|
||||
*
|
||||
* R1(wr): trigger sel1 (level/edge)
|
||||
* R1(rd): current sampled value
|
||||
*
|
||||
* R2(wr): trigger enable mask
|
||||
*
|
||||
* R2(rd): (status register)
|
||||
* b0: 1 - keys entered
|
||||
* b1: 1 - triggered
|
||||
* b3: 1 - capture done
|
||||
*
|
||||
* not configured: B6FF9C97, 12FF9C97, 92FF9C97, 16FF9C97, ...
|
||||
* configured: A5A5A5A0, after enter keys A5A5A5A1
|
||||
*
|
||||
* sel1 (one bit per channel):
|
||||
* 0 - level triggered
|
||||
* 1 - edge triggered
|
||||
*
|
||||
* sel0 (one bit per channel):
|
||||
* 0 - (low level trigger, sel1=0), (falling edge, sel1=1)
|
||||
* 1 - (high level trigger, sel1=0), (raising edge, sel1=1)
|
||||
*
|
||||
* mask (one bit per channel):
|
||||
* 0 - disable trigger on channel n
|
||||
* 1 - enable trigger on channel n
|
||||
*
|
||||
* R3: upload base address or num samples (0x300000)
|
||||
*
|
||||
* R4: pll divisor - 1
|
||||
* 0 - div 1 (no division)
|
||||
* 1 - div 2
|
||||
* 2 - div 3
|
||||
* ...
|
||||
* n-1 - div n
|
||||
*
|
||||
* R5(rd/wr):
|
||||
* b0: 1 - enable pll mul 2, 0 - disable pll mul 2
|
||||
* b1: ??
|
||||
* b2: ??
|
||||
* b3: ??
|
||||
* b4:
|
||||
* b5: ->0->1 upload next data chunk (to pc)
|
||||
* b6: ??
|
||||
* b7: 0 - enable pll mul 1.25, 1 - disable pll mul 1.25
|
||||
* b8: ??
|
||||
*
|
||||
* R6: post trigger depth, value x means (x+1)*256 (samples), min value is 1
|
||||
* R7: pre trigger depth, value y means (y+1)*256 (samples), min value is 1
|
||||
* (x+1)*256 + (y+1)*256 <= 64M
|
||||
*
|
||||
* R9: PWM1 HI (1 width-1)
|
||||
* R10: PWM1 LO (0 width-1)
|
||||
*
|
||||
* R11: PWM2 HI (1 width-1)
|
||||
* R12: PWM2 LO (0 width-1)
|
||||
*
|
||||
* R14:
|
||||
* 1 - start sample?
|
||||
* 0 - upload done?
|
||||
*
|
||||
* R16: rom key 0
|
||||
* R17: rom key 1
|
||||
*
|
||||
* key0 is F6 81 13 64
|
||||
* key1 is 00 00 00 00
|
||||
*
|
||||
* start sample:
|
||||
* r5 <= b2 <= 0
|
||||
* r5 <= b3 <= 0
|
||||
* r5 <= b5 <= 0
|
||||
*
|
||||
* r5 <= b6 <= 1
|
||||
* r5 <= b1 <= 1
|
||||
* r5 <= b1 <= 0
|
||||
*
|
||||
* r5 <= b8 <= 1
|
||||
* r5 <= b8 <= 0
|
||||
*
|
||||
* r5 <= b6 <= 1
|
||||
* r5 <= b2 <= 1
|
||||
*
|
||||
* read back:
|
||||
* r5 <= 0x08 (b3)
|
||||
* r5 <= 0x28 (b5,b3)
|
||||
*/
|
||||
|
||||
#define BITSTREAM_NAME "sysclk-sla5032.bit"
|
||||
#define BITSTREAM_MAX_SIZE (512 * 1024) /* Bitstream size limit for safety */
|
||||
#define BITSTREAM_HEADER_SIZE 0x69
|
||||
#define FW_CHUNK_SIZE 250
|
||||
#define XILINX_SYNC_WORD 0xAA995566
|
||||
|
||||
static int la_write_cmd_buf(const struct sr_usb_dev_inst *usb, uint8_t cmd,
|
||||
unsigned int addr, unsigned int len, const void *data)
|
||||
{
|
||||
uint8_t *cmd_pkt;
|
||||
int ret, xfer_len;
|
||||
int cmd_len;
|
||||
|
||||
cmd_pkt = g_try_malloc(len + 10);
|
||||
if (!cmd_pkt) {
|
||||
ret = SR_ERR_MALLOC;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cmd_pkt[0] = cmd;
|
||||
cmd_len = 1;
|
||||
xfer_len = 0;
|
||||
|
||||
switch(cmd) {
|
||||
case CMD_INIT_FW_UPLOAD: /* init firmware upload */
|
||||
break;
|
||||
case CMD_UPLOAD_FW_CHUNK:
|
||||
cmd_pkt[1] = len;
|
||||
cmd_len += 1 + len;
|
||||
memcpy(&cmd_pkt[2], data, len);
|
||||
break;
|
||||
case CMD_READ_REG: /* read register */
|
||||
cmd_pkt[1] = addr;
|
||||
cmd_pkt[2] = len;
|
||||
cmd_len += 2;
|
||||
break;
|
||||
case CMD_WRITE_REG: /* write register */
|
||||
cmd_pkt[1] = addr;
|
||||
cmd_pkt[2] = len;
|
||||
cmd_len += 2 + len;
|
||||
memcpy(&cmd_pkt[3], data, len);
|
||||
break;
|
||||
case CMD_READ_MEM: /* read mem */
|
||||
cmd_pkt[1] = (addr >> 8) & 0xFF;
|
||||
cmd_pkt[2] = addr & 0xFF;
|
||||
cmd_pkt[3] = len;
|
||||
cmd_len += 3;
|
||||
break;
|
||||
case CMD_READ_DATA: /* read samples */
|
||||
cmd_pkt[1] = addr;
|
||||
cmd_len += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = libusb_bulk_transfer(usb->devhdl, EP_COMMAND, cmd_pkt, cmd_len,
|
||||
&xfer_len, USB_CMD_TIMEOUT_MS);
|
||||
if (ret != 0) {
|
||||
sr_dbg("Failed to send command %d: %s.",
|
||||
cmd, libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
if (xfer_len != cmd_len) {
|
||||
sr_dbg("Invalid send command response of length %d.", xfer_len);
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
exit:
|
||||
g_free(cmd_pkt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_read_reg(const struct sr_usb_dev_inst *usb, unsigned int reg, uint32_t *val)
|
||||
{
|
||||
int ret, xfer_len;
|
||||
uint32_t reply;
|
||||
|
||||
ret = la_write_cmd_buf(usb, CMD_READ_REG, reg * sizeof(uint32_t),
|
||||
sizeof(reply), NULL); /* rd reg */
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = libusb_bulk_transfer(usb->devhdl, EP_REPLY, (uint8_t *)&reply,
|
||||
sizeof(reply), &xfer_len, USB_REPLY_TIMEOUT_MS);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
if (xfer_len != sizeof(uint32_t)) {
|
||||
sr_dbg("Invalid register read response of length %d.", xfer_len);
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
*val = GUINT32_FROM_BE(reply);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_write_reg(const struct sr_usb_dev_inst *usb, unsigned int reg, uint32_t val)
|
||||
{
|
||||
int ret;
|
||||
uint32_t val_be;
|
||||
|
||||
val_be = GUINT32_TO_BE(val);
|
||||
|
||||
ret = la_write_cmd_buf(usb, CMD_WRITE_REG, reg * sizeof(uint32_t),
|
||||
sizeof(val_be), &val_be); /* wr reg */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_read_mem(const struct sr_usb_dev_inst *usb, unsigned int addr, unsigned int len, void *data)
|
||||
{
|
||||
int ret, xfer_len;
|
||||
|
||||
ret = la_write_cmd_buf(usb, CMD_READ_MEM, addr, len, NULL); /* rd mem */
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
xfer_len = 0;
|
||||
ret = libusb_bulk_transfer(usb->devhdl, EP_REPLY, (uint8_t *)data,
|
||||
len, &xfer_len, USB_REPLY_TIMEOUT_MS);
|
||||
if (xfer_len != (int)len) {
|
||||
sr_dbg("Invalid memory read response of length %d.", xfer_len);
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_read_samples(const struct sr_usb_dev_inst *usb, unsigned int addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_write_cmd_buf(usb, CMD_READ_DATA, addr, 0, NULL); /* rd samples */
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_set_depth(const struct sr_usb_dev_inst *usb, uint32_t pre, uint32_t post)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* (pre + 1)*256 + (post + 1)*256 <= 64*1024*1024 */
|
||||
ret = la_write_reg(usb, 7, pre);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 6, post);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_set_triggers(const struct sr_usb_dev_inst *usb,
|
||||
uint32_t trg_value, uint32_t trg_edge_mask, uint32_t trg_mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
sr_dbg("set trigger: val: %08X, e_mask: %08X, mask: %08X.", trg_value,
|
||||
trg_edge_mask, trg_mask);
|
||||
|
||||
ret = la_write_reg(usb, 0, trg_value);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 1, trg_edge_mask);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 2, trg_mask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_set_res_reg_bit(const struct sr_usb_dev_inst *usb,
|
||||
unsigned int reg, unsigned int bit, unsigned int set_bit)
|
||||
{
|
||||
int ret;
|
||||
uint32_t v;
|
||||
|
||||
v = 0;
|
||||
ret = la_read_reg(usb, reg, &v);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
if (set_bit)
|
||||
v |= (1u << bit);
|
||||
else
|
||||
v &= ~(1u << bit);
|
||||
|
||||
ret = la_write_reg(usb, reg, v);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pll_tbl_entry_t
|
||||
{
|
||||
unsigned int sr;
|
||||
uint32_t pll_div_minus_1;
|
||||
unsigned int pll_mul_flags;
|
||||
};
|
||||
|
||||
enum {
|
||||
PLL_MUL2 = 1, /* x2 */
|
||||
PLL_MUL1_25 = 2, /* x1.25 */
|
||||
};
|
||||
|
||||
static const struct pll_tbl_entry_t pll_tbl[] = {
|
||||
{ 500000000, 0, PLL_MUL2 | PLL_MUL1_25 }, /* 500M = f*2*1.25/1 */
|
||||
{ 400000000, 0, PLL_MUL2 }, /* 400M = f*2/1 */
|
||||
{ 250000000, 0, PLL_MUL1_25 }, /* 250M = f*1.25/1 */
|
||||
{ 200000000, 0, 0 }, /* 200M = f/1 */
|
||||
{ 100000000, 1, 0 }, /* 100M = f/2 */
|
||||
{ 50000000, 3, 0 }, /* 50M = f/4 */
|
||||
{ 25000000, 7, 0 }, /* 25M = f/8 */
|
||||
{ 20000000, 9, 0 }, /* 20M = f/10 */
|
||||
{ 10000000, 19, 0 }, /* 10M = f/20 */
|
||||
{ 5000000, 39, 0 }, /* 5M = f/40 */
|
||||
{ 2000000, 99, 0 }, /* 2M = f/100 */
|
||||
{ 1000000, 199, 0 }, /* 1M = f/200 */
|
||||
{ 500000, 399, 0 }, /* 500k = f/400 */
|
||||
{ 200000, 999, 0 }, /* 200k = f/1000 */
|
||||
{ 100000, 1999, 0 }, /* 100k = f/2000 */
|
||||
{ 50000, 3999, 0 }, /* 50k = f/4000 */
|
||||
{ 20000, 9999, 0 }, /* 20k = f/10000 */
|
||||
{ 10000, 19999, 0 }, /* 10k = f/20000 */
|
||||
{ 5000, 39999, 0 }, /* 5k = f/40000 */
|
||||
{ 2000, 99999, 0 }, /* 2k = f/100000 */
|
||||
};
|
||||
|
||||
SR_PRIV int sla5032_set_samplerate(const struct sr_usb_dev_inst *usb, unsigned int sr)
|
||||
{
|
||||
int i, ret;
|
||||
const struct pll_tbl_entry_t *e;
|
||||
|
||||
e = NULL;
|
||||
for (i = 0; i < (int)ARRAY_SIZE(pll_tbl); i++) {
|
||||
if (sr == pll_tbl[i].sr) {
|
||||
e = &pll_tbl[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!e)
|
||||
return SR_ERR_SAMPLERATE;
|
||||
|
||||
sr_dbg("set sample rate: %u.", e->sr);
|
||||
|
||||
ret = la_write_reg(usb, 4, e->pll_div_minus_1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 0,
|
||||
(e->pll_mul_flags & PLL_MUL2) ? 1 : 0); /* bit0 (1=en_mul2) */
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 7,
|
||||
(e->pll_mul_flags & PLL_MUL1_25) ? 0 : 1); /* bit7 (0=en_mul_1.25) */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_start_sample(const struct sr_usb_dev_inst *usb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_write_reg(usb, 14, 1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 2, 0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 3, 0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 5, 0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 6, 1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 1, 1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 1, 0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 8, 1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 8, 0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 6, 1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 2, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_get_status(const struct sr_usb_dev_inst *usb, uint32_t status[3])
|
||||
{
|
||||
int ret;
|
||||
uint32_t v;
|
||||
|
||||
ret = la_read_reg(usb, 1, &status[0]);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
status[1] = 1; /* wait trigger */
|
||||
|
||||
ret = la_read_reg(usb, 0, &status[2]);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
v = 0;
|
||||
ret = la_read_reg(usb, 2, &v);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
if (v & 8) {
|
||||
status[1] = 3; /* sample done */
|
||||
sr_dbg("get status, reg2: %08X.", v);
|
||||
} else if (v & 2) {
|
||||
status[1] = 2; /* triggered */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_read_samples_data(const struct sr_usb_dev_inst *usb, void *buf,
|
||||
unsigned int len, int *xfer_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libusb_bulk_transfer(usb->devhdl, EP_DATA, (uint8_t *)buf, len,
|
||||
xfer_len, USB_DATA_TIMEOUT_MS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_read_data_chunk(const struct sr_usb_dev_inst *usb,
|
||||
void *buf, unsigned int len, int *xfer_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_read_samples(usb, 3);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 3, 0x300000);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 4, 0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_set_res_reg_bit(usb, 5, 4, 1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_read_samples_data(usb, buf, len, xfer_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_set_read_back(const struct sr_usb_dev_inst *usb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_write_reg(usb, 5, 0x08);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 5, 0x28);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_set_pwm1(const struct sr_usb_dev_inst* usb, uint32_t hi, uint32_t lo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_write_reg(usb, 9, hi);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 10, lo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_set_pwm2(const struct sr_usb_dev_inst* usb, uint32_t hi, uint32_t lo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_write_reg(usb, 11, hi);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 12, lo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int sla5032_write_reg14_zero(const struct sr_usb_dev_inst* usb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = la_write_reg(usb, 14, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int la_cfg_fpga_done(const struct sr_usb_dev_inst *usb, unsigned int addr)
|
||||
{
|
||||
uint8_t done_key[8];
|
||||
uint32_t k0, k1;
|
||||
unsigned int reg2;
|
||||
int ret;
|
||||
|
||||
memset(done_key, 0, sizeof(done_key));
|
||||
|
||||
ret = la_read_mem(usb, addr, sizeof(done_key), done_key); /* read key from eeprom */
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
k0 = RL32(done_key); /* 0x641381F6 */
|
||||
k1 = RL32(done_key + 4); /* 0x00000000 */
|
||||
|
||||
sr_dbg("cfg fpga done, k0: %08X, k1: %08X.", k0, k1);
|
||||
|
||||
ret = la_write_reg(usb, 16, k0);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
ret = la_write_reg(usb, 17, k1);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
reg2 = 0;
|
||||
ret = la_read_reg(usb, 2, ®2);
|
||||
|
||||
sr_dbg("cfg fpga done, reg2: %08X.", reg2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a bitstream file into memory. Returns a newly allocated array
|
||||
* consisting of a 32-bit length field followed by the bitstream data.
|
||||
*/
|
||||
static unsigned char *load_bitstream(struct sr_context *ctx,
|
||||
const char *name, int *length_p)
|
||||
{
|
||||
struct sr_resource fw;
|
||||
unsigned char *stream, *fw_data;
|
||||
ssize_t length, count;
|
||||
|
||||
if (sr_resource_open(ctx, &fw, SR_RESOURCE_FIRMWARE, name) != SR_OK)
|
||||
return NULL;
|
||||
|
||||
if (fw.size <= BITSTREAM_HEADER_SIZE || fw.size > BITSTREAM_MAX_SIZE) {
|
||||
sr_err("Refusing to load bitstream of unreasonable size "
|
||||
"(%" PRIu64 " bytes).", fw.size);
|
||||
sr_resource_close(ctx, &fw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream = g_try_malloc(fw.size);
|
||||
if (!stream) {
|
||||
sr_err("Failed to allocate bitstream buffer.");
|
||||
sr_resource_close(ctx, &fw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
count = sr_resource_read(ctx, &fw, stream, fw.size);
|
||||
sr_resource_close(ctx, &fw);
|
||||
|
||||
if (count != (ssize_t)fw.size) {
|
||||
sr_err("Failed to read bitstream '%s'.", name);
|
||||
g_free(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (RB32(stream + BITSTREAM_HEADER_SIZE) != XILINX_SYNC_WORD) {
|
||||
sr_err("Invalid bitstream signature.");
|
||||
g_free(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = fw.size - BITSTREAM_HEADER_SIZE + 0x100;
|
||||
fw_data = g_try_malloc(length);
|
||||
if (!fw_data) {
|
||||
sr_err("Failed to allocate bitstream aligned buffer.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(fw_data, 0xFF, 0x100);
|
||||
memcpy(fw_data + 0x100, stream + BITSTREAM_HEADER_SIZE,
|
||||
fw.size - BITSTREAM_HEADER_SIZE);
|
||||
g_free(stream);
|
||||
|
||||
*length_p = length;
|
||||
|
||||
return fw_data;
|
||||
}
|
||||
|
||||
static int sla5032_is_configured(const struct sr_usb_dev_inst* usb, gboolean *is_configured)
|
||||
{
|
||||
int ret;
|
||||
uint32_t reg2;
|
||||
|
||||
reg2 = 0;
|
||||
ret = la_read_reg(usb, 2, ®2);
|
||||
if (ret == SR_OK)
|
||||
*is_configured = (reg2 & 0xFFFFFFF1) == 0xA5A5A5A1 ? TRUE : FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Load a Binary File from the firmware directory, transfer it to the device. */
|
||||
static int sla5032_send_bitstream(struct sr_context *ctx,
|
||||
const struct sr_usb_dev_inst *usb, const char *name)
|
||||
{
|
||||
unsigned char *stream;
|
||||
int ret, length, i, n, m;
|
||||
uint32_t reg2;
|
||||
|
||||
if (!ctx || !usb || !name)
|
||||
return SR_ERR_BUG;
|
||||
|
||||
stream = load_bitstream(ctx, name, &length);
|
||||
if (!stream)
|
||||
return SR_ERR;
|
||||
|
||||
sr_dbg("Downloading FPGA bitstream '%s'.", name);
|
||||
|
||||
reg2 = 0;
|
||||
ret = la_read_reg(usb, 2, ®2);
|
||||
sr_dbg("send bitstream, reg2: %08X.", reg2);
|
||||
|
||||
/* Transfer the entire bitstream in one URB. */
|
||||
ret = la_write_cmd_buf(usb, CMD_INIT_FW_UPLOAD, 0, 0, NULL); /* init firmware upload */
|
||||
if (ret != SR_OK) {
|
||||
g_free(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
n = length / FW_CHUNK_SIZE;
|
||||
m = length % FW_CHUNK_SIZE;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
/* upload firmware chunk */
|
||||
ret = la_write_cmd_buf(usb, CMD_UPLOAD_FW_CHUNK, 0,
|
||||
FW_CHUNK_SIZE, &stream[i * FW_CHUNK_SIZE]);
|
||||
|
||||
if (ret != SR_OK) {
|
||||
g_free(stream);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (m != 0) {
|
||||
/* upload firmware last chunk */
|
||||
ret = la_write_cmd_buf(usb, CMD_UPLOAD_FW_CHUNK, 0, m,
|
||||
&stream[n * FW_CHUNK_SIZE]);
|
||||
|
||||
if (ret != SR_OK) {
|
||||
g_free(stream);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(stream);
|
||||
|
||||
la_cfg_fpga_done(usb, 4000);
|
||||
|
||||
sla5032_write_reg14_zero(usb);
|
||||
|
||||
sr_dbg("FPGA bitstream download of %d bytes done.", length);
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
/* Select and transfer FPGA bitstream for the current configuration. */
|
||||
SR_PRIV int sla5032_apply_fpga_config(const struct sr_dev_inst *sdi)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
struct drv_context *drvc;
|
||||
int ret;
|
||||
gboolean is_configured;
|
||||
|
||||
devc = sdi->priv;
|
||||
drvc = sdi->driver->context;
|
||||
|
||||
if (FPGA_NOCONF != devc->active_fpga_config)
|
||||
return SR_OK; /* No change. */
|
||||
|
||||
is_configured = FALSE;
|
||||
ret = sla5032_is_configured(sdi->conn, &is_configured);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
if (is_configured) {
|
||||
devc->active_fpga_config = FPGA_CONF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sr_dbg("FPGA not configured, send bitstream.");
|
||||
ret = sla5032_send_bitstream(drvc->sr_ctx, sdi->conn, BITSTREAM_NAME);
|
||||
devc->active_fpga_config = (ret == SR_OK) ? FPGA_CONF : FPGA_NOCONF;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2019 Vitaliy Vorobyov
|
||||
*
|
||||
* 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_SYSCLK_SLA5032_SLA5032_H
|
||||
#define LIBSIGROK_HARDWARE_SYSCLK_SLA5032_SLA5032_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <libusb.h>
|
||||
#include <glib.h>
|
||||
#include <libsigrok/libsigrok.h>
|
||||
|
||||
/** SLA5032 protocol command ID codes. */
|
||||
enum command_id {
|
||||
CMD_INIT_FW_UPLOAD = 1,
|
||||
CMD_UPLOAD_FW_CHUNK = 2,
|
||||
CMD_READ_REG = 3,
|
||||
CMD_WRITE_REG = 4,
|
||||
CMD_READ_MEM = 5,
|
||||
CMD_READ_DATA = 7,
|
||||
};
|
||||
|
||||
struct sr_usb_dev_inst;
|
||||
|
||||
SR_PRIV int sla5032_apply_fpga_config(const struct sr_dev_inst* sdi);
|
||||
SR_PRIV int sla5032_start_sample(const struct sr_usb_dev_inst *usb);
|
||||
SR_PRIV int sla5032_get_status(const struct sr_usb_dev_inst *usb, uint32_t status[3]);
|
||||
SR_PRIV int sla5032_set_read_back(const struct sr_usb_dev_inst *usb);
|
||||
SR_PRIV int sla5032_read_data_chunk(const struct sr_usb_dev_inst *usb, void *buf, unsigned int len, int *xfer_len);
|
||||
SR_PRIV int sla5032_set_depth(const struct sr_usb_dev_inst *usb, uint32_t pre, uint32_t post);
|
||||
SR_PRIV int sla5032_set_triggers(const struct sr_usb_dev_inst *usb, uint32_t trg_value, uint32_t trg_edge_mask, uint32_t trg_mask);
|
||||
SR_PRIV int sla5032_set_samplerate(const struct sr_usb_dev_inst *usb, unsigned int sr);
|
||||
SR_PRIV int sla5032_set_pwm1(const struct sr_usb_dev_inst *usb, uint32_t hi, uint32_t lo);
|
||||
SR_PRIV int sla5032_set_pwm2(const struct sr_usb_dev_inst* usb, uint32_t hi, uint32_t lo);
|
||||
SR_PRIV int sla5032_write_reg14_zero(const struct sr_usb_dev_inst* usb);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue