From 6239c175c1b967b577f760032d326322dd4c4576 Mon Sep 17 00:00:00 2001 From: Uwe Hermann Date: Thu, 6 Jan 2011 19:16:47 +0100 Subject: [PATCH] Initial, unfinished demo/simulation hardware driver. --- Makefile.am | 1 + hardware/demo/demo.c | 332 +++++++++++++++++++++++++++++++++++++++++++ hwplugin.c | 2 + 3 files changed, 335 insertions(+) create mode 100644 hardware/demo/demo.c diff --git a/Makefile.am b/Makefile.am index f5fb2b30..85dfe41c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ libsigrok_la_SOURCES = \ hardware/common/ezusb.c \ hardware/common/misc.c \ hardware/common/serial.c \ + hardware/demo/demo.c \ input/input_binary.c \ input/input.c \ output/output_binary.c \ diff --git a/hardware/demo/demo.c b/hardware/demo/demo.c new file mode 100644 index 00000000..b8f36fbf --- /dev/null +++ b/hardware/demo/demo.c @@ -0,0 +1,332 @@ +/* + * This file is part of the sigrok project. + * + * Copyright (C) 2010 Uwe Hermann + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "config.h" + +#define NUM_PROBES 8 +#define NUM_TRIGGER_STAGES 4 +#define TRIGGER_TYPES "01" + +/* Software trigger implementation: positive values indicate trigger stage. */ +#define TRIGGER_FIRED -1 + +static int capabilities[] = { + HWCAP_LOGIC_ANALYZER, + HWCAP_SAMPLERATE, + HWCAP_LIMIT_SAMPLES, +}; + +/* Random selection of samplerates this "device" shall support. */ +static uint64_t supported_samplerates[] = { + KHZ(100), + KHZ(500), + MHZ(1), + MHZ(2), + MHZ(12), + MHZ(24), + 0, +}; + +static struct samplerates samplerates = { + KHZ(100), + MHZ(24), + 0, + supported_samplerates, +}; + +/* TODO: All of these should go in a device-specific struct. */ +static uint64_t cur_samplerate = 0; +static uint64_t limit_samples = 0; +// static uint8_t probe_mask = 0; +// static uint8_t trigger_mask[NUM_TRIGGER_STAGES] = { 0 }; +// static uint8_t trigger_value[NUM_TRIGGER_STAGES] = { 0 }; +// static uint8_t trigger_buffer[NUM_TRIGGER_STAGES] = { 0 }; + +// static int trigger_stage = TRIGGER_FIRED; + +static int hw_set_configuration(int device_index, int capability, void *value); +static void hw_stop_acquisition(int device_index, gpointer session_device_id); + +#if 0 +static int configure_probes(GSList *probes) +{ + struct probe *probe; + GSList *l; + int probe_bit, stage, i; + char *tc; + + probe_mask = 0; + for (i = 0; i < NUM_TRIGGER_STAGES; i++) { + trigger_mask[i] = 0; + trigger_value[i] = 0; + } + + stage = -1; + for (l = probes; l; l = l->next) { + probe = (struct probe *)l->data; + if (!(probe->enabled)) + continue; + probe_bit = 1 << (probe->index - 1); + probe_mask |= probe_bit; + if (!(probe->trigger)) + continue; + + stage = 0; + for (tc = probe->trigger; *tc; tc++) { + trigger_mask[stage] |= probe_bit; + if (*tc == '1') + trigger_value[stage] |= probe_bit; + stage++; + if (stage > NUM_TRIGGER_STAGES) + return SIGROK_ERR; + } + } + + if (stage == -1) + /* + * We didn't configure any triggers, make sure acquisition + * doesn't wait for any. + */ + trigger_stage = TRIGGER_FIRED; + else + trigger_stage = 0; + + return SIGROK_OK; +} +#endif + +static int hw_init(char *deviceinfo) +{ + /* Avoid compiler warning. */ + deviceinfo = deviceinfo; + + /* Nothing needed so far. */ + return 1; /* FIXME? */ +} + +static int hw_opendev(int device_index) +{ + /* Avoid compiler warning. */ + device_index = device_index; + + /* Nothing needed so far. */ + return SIGROK_OK; +} + +static void hw_closedev(int device_index) +{ + /* Avoid compiler warning. */ + device_index = device_index; + + /* Nothing needed so far. */ +} + +static void hw_cleanup(void) +{ + /* Nothing needed so far. */ +} + +static void *hw_get_device_info(int device_index, int device_info_id) +{ + void *info = NULL; + + /* Avoid compiler warning. */ + device_index = device_index; + + switch (device_info_id) { + case DI_INSTANCE: + /// info = sdi; + /* TODO */ + break; + case DI_NUM_PROBES: + info = GINT_TO_POINTER(NUM_PROBES); + break; + case DI_SAMPLERATES: + info = &samplerates; + break; + case DI_TRIGGER_TYPES: + info = TRIGGER_TYPES; + break; + case DI_CUR_SAMPLERATE: + info = &cur_samplerate; + break; + } + + return info; +} + +static int hw_get_status(int device_index) +{ + /* Avoid compiler warning. */ + device_index = device_index; + + return 0; /* FIXME */ +} + +static int *hw_get_capabilities(void) +{ + return capabilities; +} + +static int hw_set_configuration(int device_index, int capability, void *value) +{ + int ret; + + /* Avoid compiler warning. */ + device_index = device_index; + + if (capability == HWCAP_SAMPLERATE) { + cur_samplerate = *(uint64_t *)value; + ret = SIGROK_OK; + } else if (capability == HWCAP_PROBECONFIG) { + // ret = configure_probes((GSList *) value); + ret = SIGROK_ERR; + } else if (capability == HWCAP_LIMIT_SAMPLES) { + limit_samples = strtoull(value, NULL, 10); + ret = SIGROK_OK; + } else { + ret = SIGROK_ERR; + } + + return ret; +} + +static int hw_start_acquisition(int device_index, gpointer session_device_id) +{ + struct datafeed_packet *packet; + struct datafeed_header *header; + unsigned char *buf; + + /* Avoid compiler warning. */ + device_index = device_index; + + packet = malloc(sizeof(struct datafeed_packet)); + header = malloc(sizeof(struct datafeed_header)); + buf = malloc(2048); + if (!packet || !header || !buf) + return SIGROK_ERR_MALLOC; + + /* FIXME */ + memset(buf, 0x55, 2048); + + packet->type = DF_HEADER; + packet->length = sizeof(struct datafeed_header); + packet->payload = (unsigned char *)header; + header->feed_version = 1; + gettimeofday(&header->starttime, NULL); + header->samplerate = cur_samplerate; + header->protocol_id = PROTO_RAW; + header->num_probes = NUM_PROBES; + session_bus(session_device_id, packet); + free(header); + free(packet); + + return SIGROK_OK; +} + +#if 0 +void receive_transfer(struct libusb_transfer *transfer) +{ + static int num_samples = 0; + static int empty_transfer_count = 0; + struct datafeed_packet packet; + void *user_data; + int cur_buflen, trigger_offset, i; + unsigned char *cur_buf, *new_buf; + + g_message("receive_transfer(): status %d received %d bytes", + transfer->status, transfer->actual_length); + + /* Save incoming transfer before reusing the transfer struct. */ + cur_buf = transfer->buffer; + cur_buflen = transfer->actual_length; + user_data = transfer->user_data; + + /* Fire off a new request. */ + new_buf = g_malloc(4096); + transfer->buffer = new_buf; + transfer->length = 4096; + if (libusb_submit_transfer(transfer) != 0) { + /* TODO: Stop session? */ + g_warning("eek"); + } + + trigger_offset = 0; + if (trigger_stage >= 0) { + for (i = 0; i < cur_buflen; i++) { + trigger_helper(i, cur_buf, &packet, user_data, + &trigger_offset); + } + } + + if (trigger_stage == TRIGGER_FIRED) { + /* Send the incoming transfer to the session bus. */ + packet.type = DF_LOGIC8; + packet.length = cur_buflen - trigger_offset; + packet.payload = cur_buf + trigger_offset; + session_bus(user_data, &packet); + free(cur_buf); + + num_samples += cur_buflen; + if ((unsigned int)num_samples > limit_samples) { + hw_stop_acquisition(-1, user_data); + } + } else { + /* + * TODO: Buffer pre-trigger data in capture + * ratio-sized buffer. + */ + } +} +#endif + +/* This stops acquisition on ALL devices, ignoring device_index. */ +static void hw_stop_acquisition(int device_index, gpointer session_device_id) +{ + struct datafeed_packet packet; + + /* QUICK HACK */ + device_index = device_index; + + packet.type = DF_END; + session_bus(session_device_id, &packet); + + /// receive_transfer(NULL); + + /* TODO: Need to cancel and free any queued up transfers. */ +} + +struct device_plugin demo_plugin_info = { + "demo", + 1, + hw_init, + hw_cleanup, + hw_opendev, + hw_closedev, + hw_get_device_info, + hw_get_status, + hw_get_capabilities, + hw_set_configuration, + hw_start_acquisition, + hw_stop_acquisition, +}; diff --git a/hwplugin.c b/hwplugin.c index 1fd95214..4ae0088e 100644 --- a/hwplugin.c +++ b/hwplugin.c @@ -42,6 +42,7 @@ struct hwcap_option hwcap_options[] = { {0, 0, NULL, NULL}, }; +extern struct device_plugin demo_plugin_info; #ifdef HAVE_LA_SALEAE_LOGIC extern struct device_plugin saleae_logic_plugin_info; #endif @@ -58,6 +59,7 @@ extern struct device_plugin asix_sigma_plugin_info; /* TODO: No linked list needed, this can be a simple array. */ int load_hwplugins(void) { + plugins = g_slist_append(plugins, (gpointer *)&demo_plugin_info); #ifdef HAVE_LA_SALEAE_LOGIC plugins = g_slist_append(plugins, (gpointer *)&saleae_logic_plugin_info);