]> sigrok.org Git - libsigrok.git/commitdiff
nexus-osciprime: basic scanning functionality
authorBert Vermeulen <redacted>
Tue, 25 Dec 2012 18:09:12 +0000 (19:09 +0100)
committerBert Vermeulen <redacted>
Tue, 25 Dec 2012 18:09:12 +0000 (19:09 +0100)
Unfortunately the device doesn't have an EEPROM on board at all, and so
initially enumerates with the default Cypress FX2 VID:PID (04b4:8613).
Since we already support using plain FX2* as basic logic analyzers using
the fx2lafw firmware, we cannot support that same VID:PID for the
OsciPrime. Therefore a USB conn is required for the initial scan.

However, once the firmware is uploaded the device re-enumerates as
04b4:1004, which we do detect for scanning automatically.

Thus, the OsciPrime driver requires one scan with conn parameter to get
the firmware uploaded, but it will then keep working until powered off.

hardware/nexus-osciprime/Makefile.am
hardware/nexus-osciprime/api.c
hardware/nexus-osciprime/protocol.h

index a8d74c5eca00b91aeafc556fb4cd265088019815..01f313e2612d1f329d069aa4a127fb3547f6c8e2 100644 (file)
@@ -19,6 +19,8 @@
 
 if HW_NEXUS_OSCIPRIME
 
+AM_CPPFLAGS = -DFIRMWARE_DIR='"$(FIRMWARE_DIR)"'
+
 # Local lib, this is NOT meant to be installed!
 noinst_LTLIBRARIES = libsigrok_hw_nexus_osciprime.la
 
index 4c9a1da6ac6eeb3374af9cf281ce145a48f04bd8..100fb3ba158176c15df991ddf9942127660d832e 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <string.h>
 #include <glib.h>
 #include "libsigrok.h"
 #include "libsigrok-internal.h"
 #include "protocol.h"
 
+#define OSCI_VENDOR "Nexus Computing"
+#define OSCI_MODEL "OsciPrime"
+#define OSCI_VERSION "1.0"
+#define OSCI_FIRMWARE FIRMWARE_DIR "/nexus-osciprime.fw"
+#define OSCI_VIDPID "04b4.1004"
+
+static const int hwopts[] = {
+       SR_HWOPT_CONN,
+       SR_HWOPT_SERIALCOMM,
+       0,
+};
+
+static const int hwcaps[] = {
+       SR_HWCAP_OSCILLOSCOPE,
+       SR_HWCAP_LIMIT_SAMPLES,
+       SR_HWCAP_CONTINUOUS,
+       SR_HWCAP_TIMEBASE,
+       SR_HWCAP_VDIV,
+       0,
+};
+
+static const struct sr_rational timebases[] = {
+       /* 24 MHz */
+       { 42, 1e9 },
+       /* 12 MHz */
+       { 83, 1e9 },
+       /* 6 MHz */
+       { 167, 1e9 },
+       /* 3 MHz */
+       { 333, 1e9 },
+       /* 1.5 MHz */
+       { 667, 1e9 },
+       /* 750 kHz */
+       { 1333, 1e9 },
+       /* 375 kHz */
+       { 2667, 1e9 },
+       /* 187.5 kHz */
+       { 5333, 1e9 },
+       /* 93.25 kHz */
+       { 10724, 1e9 },
+       /* 46.875 kHz */
+       { 21333, 1e9 },
+       /* 23.4375 kHz */
+       { 42666, 1e9 },
+       /* 11.718 kHz */
+       { 85339, 1e9 },
+       /* 5.859 kHz */
+       { 170678, 1e9 },
+       /* 2.929 kHz */
+       { 341413, 1e9 },
+       /* 1.465 kHz */
+       { 682594, 1e9 },
+       /* 732 Hz */
+       { 1366, 1e6 },
+       /* 366 Hz */
+       { 2732, 1e6 },
+       /* 183 Hz */
+       { 5464, 1e6 },
+       /* 91 Hz */
+       { 10989, 1e6 },
+       /* 46 Hz */
+       { 21739, 1e6 },
+       /* 23 Hz */
+       { 43478, 1e6 },
+       /* 12 Hz */
+       { 83333, 1e6 },
+};
+
+static const char *probe_names[] = {
+       "CHA",
+       "CHB",
+       NULL,
+};
+
+static const struct sr_rational vdivs[] = {
+       { 1, 1 },
+       { 2, 1 },
+       { 5, 2 },
+       { 5, 1 },
+       { 10, 1 },
+};
+
+
 SR_PRIV struct sr_dev_driver nexus_osciprime_driver_info;
 static struct sr_dev_driver *di = &nexus_osciprime_driver_info;
+static int hw_dev_close(struct sr_dev_inst *sdi);
 
 /* Properly close and free all devices. */
 static int clear_instances(void)
@@ -42,8 +127,8 @@ static int clear_instances(void)
                if (!(devc = sdi->priv))
                        continue;
 
-               /* TODO */
-
+               hw_dev_close(sdi);
+               sr_usb_dev_inst_free(devc->usb);
                sr_dev_inst_free(sdi);
        }
 
@@ -53,7 +138,7 @@ static int clear_instances(void)
        return SR_OK;
 }
 
-static int hw_init(void)
+static int hw_init(struct sr_context *sr_ctx)
 {
        struct drv_context *drvc;
 
@@ -62,8 +147,7 @@ static int hw_init(void)
                return SR_ERR_MALLOC;
        }
 
-       /* TODO */
-
+       drvc->sr_ctx = sr_ctx;
        di->priv = drvc;
 
        return SR_OK;
@@ -72,15 +156,76 @@ static int hw_init(void)
 static GSList *hw_scan(GSList *options)
 {
        struct drv_context *drvc;
-       GSList *devices;
+       struct dev_context *devc;
+       struct sr_dev_inst *sdi;
+       struct sr_usb_dev_inst *usb;
+       struct sr_hwopt *opt;
+       struct sr_probe *probe;
+       libusb_device *dev;
+       GSList *usb_devices, *devices, *l;
+       int i;
+       const char *conn;
 
        (void)options;
 
-       devices = NULL;
-       drvc = di->priv;
-       drvc->instances = NULL;
+       if (!(drvc = di->priv)) {
+               sr_err("Driver was not initialized.");
+               return NULL;
+       }
 
-       /* TODO */
+       /* USB scan is always authoritative. */
+       clear_instances();
+
+       conn = NULL;
+       for (l = options; l; l = l->next) {
+               opt = l->data;
+               switch (opt->hwopt) {
+               case SR_HWOPT_CONN:
+                       conn = opt->value;
+                       break;
+               }
+       }
+       if (!conn)
+               conn = OSCI_VIDPID;
+
+       devices = NULL;
+       if ((usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn))) {
+               for (l = usb_devices; l; l = l->next) {
+                       usb = l->data;
+                       if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE,
+                                       OSCI_VENDOR, OSCI_MODEL, OSCI_VERSION)))
+                               return NULL;
+                       sdi->driver = di;
+                       for (i = 0; probe_names[i]; i++) {
+                               if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
+                                               probe_names[i])))
+                                       return NULL;
+                               sdi->probes = g_slist_append(sdi->probes, probe);
+                       }
+
+                       if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
+                               return NULL;
+                       sdi->priv = devc;
+                       devc->usb = usb;
+
+                       if (strcmp(conn, OSCI_VIDPID)) {
+                               if (sr_usb_open(drvc->sr_ctx->libusb_ctx, usb) != SR_OK)
+                                       break;
+                               dev = libusb_get_device(usb->devhdl);
+                               if (ezusb_upload_firmware(dev, 0, OSCI_FIRMWARE) == SR_OK)
+                                       /* Remember when the firmware on this device was updated */
+                                       devc->fw_updated = g_get_monotonic_time();
+                               else
+                                       sr_err("Firmware upload failed for device "
+                                                       "at bus %d address %d.", usb->bus, usb->address);
+                       }
+
+                       drvc->instances = g_slist_append(drvc->instances, sdi);
+                       devices = g_slist_append(devices, sdi);
+               }
+               g_slist_free(usb_devices);
+       } else
+               g_slist_free_full(usb_devices, g_free);
 
        return devices;
 }
@@ -175,7 +320,7 @@ static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
 
 SR_PRIV struct sr_dev_driver nexus_osciprime_driver_info = {
        .name = "nexus-osciprime",
-       .longname = "Nexus Osciprime",
+       .longname = "Nexus OsciPrime",
        .api_version = 1,
        .init = hw_init,
        .cleanup = hw_cleanup,
index 539924c3cf0c707ef6ed220574f6e1b45151c88a..f7cec237a3076771b2e90ae8800d154d0ce9a58a 100644 (file)
@@ -46,6 +46,9 @@ struct dev_context {
 
        /** The current number of already received samples. */
        uint64_t num_samples;
+       struct sr_usb_dev_inst *usb;
+       int usbfd[10];
+       int64_t fw_updated;
 };
 
 SR_PRIV int nexus_osciprime_receive_data(int fd, int revents, void *cb_data);