]> sigrok.org Git - libsigrok.git/blobdiff - hardware/zeroplus-logic-cube/analyzer.c
Revise session API to allow for multiple sessions in future.
[libsigrok.git] / hardware / zeroplus-logic-cube / analyzer.c
index 283820b2dbc1e15306757ddbe52c8179b5a40ec9..c404a66b73b04a47324f5c5c539c866fe8a0300e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * This file is part of the sigrok project.
+ * This file is part of the libsigrok project.
  *
  * Copyright (C) 2010 Sven Peter <sven@fail0verflow.com>
  * Copyright (C) 2010 Haxx Enterprises <bushing@gmail.com>
  */
 
 #include <assert.h>
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
 #include "analyzer.h"
 #include "gl_usb.h"
+#include "protocol.h"
 
 enum {
        HARD_DATA_CHECK_SUM             = 0x00,
        PASS_WORD,
 
-       DEVICE_ID0                      = 0x10,
-       DEVICE_ID1,
+       DEV_ID0                         = 0x10,
+       DEV_ID1,
 
        START_STATUS                    = 0x20,
-       DEVICE_STATUS                   = 0x21,
+       DEV_STATUS                      = 0x21,
        FREQUENCY_REG0                  = 0x30,
        FREQUENCY_REG1,
        FREQUENCY_REG2,
@@ -109,12 +112,13 @@ static int g_trigger_count = 1;
 static int g_filter_status[8] = { 0 };
 static int g_filter_enable = 0;
 
-static int g_freq_value = 100;
+static int g_freq_value = 1;
 static int g_freq_scale = FREQ_SCALE_MHZ;
-static int g_memory_size = MEMORY_SIZE_512K;
-static int g_ramsize_triggerbar_addr = 0x80000 >> 2;
-static int g_triggerbar_addr = 0x3fe;
+static int g_memory_size = MEMORY_SIZE_8K;
+static int g_ramsize_triggerbar_addr = 2 * 1024;
+static int g_triggerbar_addr = 0;
 static int g_compression = COMPRESSION_NONE;
+static int g_thresh = 0x31; /* 1.5V */
 
 /* Maybe unk specifies an "endpoint" or "register" of sorts. */
 static int analyzer_write_status(libusb_device_handle *devh, unsigned char unk,
@@ -124,6 +128,7 @@ static int analyzer_write_status(libusb_device_handle *devh, unsigned char unk,
        return gl_reg_write(devh, START_STATUS, unk << 6 | flags);
 }
 
+#if 0
 static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale)
 {
        int reg0 = 0, divisor = 0, reg2 = 0;
@@ -241,6 +246,11 @@ static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale)
                reg2 = 64;
                break;
        }
+
+       sr_dbg("Setting samplerate regs (freq=%d, scale=%d): "
+              "reg0: %d, reg1: %d, reg2: %d, reg3: %d.",
+              freq, scale, divisor, reg0, 0x02, reg2);
+
        if (gl_reg_write(devh, FREQUENCY_REG0, divisor) < 0)
                return -1; /* Divisor maybe? */
 
@@ -255,6 +265,80 @@ static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale)
 
        return 0;
 }
+#endif
+
+/*
+ * It seems that ...
+ *     FREQUENCT_REG0 - division factor (?)
+ *     FREQUENCT_REG1 - multiplication factor (?)
+ *     FREQUENCT_REG4 - clock selection (?)
+ *
+ *     clock selection
+ *     0  10MHz  16   1MHz  32 100kHz  48  10kHz  64   1kHz
+ *     1   5MHz  17 500kHz  33  50kHz  49   5kHz  65  500Hz
+ *     2 2.5MHz   .          .         50 2.5kHz  66  250Hz
+ *     .          .          .          .         67  125Hz
+ *     .          .          .          .         68 62.5Hz
+ */
+static int __analyzer_set_freq(libusb_device_handle *devh, int freq, int scale)
+{
+       struct freq_factor {
+               int freq;
+               int scale;
+               int sel;
+               int div;
+               int mul;
+       };
+
+       static const struct freq_factor f[] = {
+               { 200, FREQ_SCALE_MHZ,  0,  1, 20 },
+               { 150, FREQ_SCALE_MHZ,  0,  1, 15 },
+               { 100, FREQ_SCALE_MHZ,  0,  1, 10 },
+               {  80, FREQ_SCALE_MHZ,  0,  2, 16 },
+               {  50, FREQ_SCALE_MHZ,  0,  2, 10 },
+               {  25, FREQ_SCALE_MHZ,  1,  5, 25 },
+               {  10, FREQ_SCALE_MHZ,  1,  5, 10 },
+               {   1, FREQ_SCALE_MHZ, 16,  5,  5 },
+               { 800, FREQ_SCALE_KHZ, 17,  5,  8 },
+               { 400, FREQ_SCALE_KHZ, 32,  5, 20 },
+               { 200, FREQ_SCALE_KHZ, 32,  5, 10 },
+               { 100, FREQ_SCALE_KHZ, 32,  5,  5 },
+               {  50, FREQ_SCALE_KHZ, 33,  5,  5 },
+               {  25, FREQ_SCALE_KHZ, 49,  5, 25 },
+               {   5, FREQ_SCALE_KHZ, 50,  5, 10 },
+               {   1, FREQ_SCALE_KHZ, 64,  5,  5 },
+               { 500, FREQ_SCALE_HZ,  64, 10,  5 },
+               { 100, FREQ_SCALE_HZ,  68,  5,  8 },
+               {   0, 0,              0,   0,  0 }
+       };
+
+       int i;
+
+       for (i = 0; f[i].freq; i++) {
+               if (scale == f[i].scale && freq == f[i].freq)
+                       break;
+       }
+       if (!f[i].freq)
+               return -1;
+
+       sr_dbg("Setting samplerate regs (freq=%d, scale=%d): "
+              "reg0: %d, reg1: %d, reg2: %d, reg3: %d.",
+              freq, scale, f[i].div, f[i].mul, 0x02, f[i].sel);
+
+       if (gl_reg_write(devh, FREQUENCY_REG0, f[i].div) < 0)
+               return -1;
+
+       if (gl_reg_write(devh, FREQUENCY_REG1, f[i].mul) < 0)
+               return -1;
+
+       if (gl_reg_write(devh, FREQUENCY_REG2, 0x02) < 0)
+               return -1;
+
+       if (gl_reg_write(devh, FREQUENCY_REG4, f[i].sel) < 0)
+               return -1;
+
+       return 0;
+}
 
 static void __analyzer_set_ramsize_trigger_address(libusb_device_handle *devh,
                                                   unsigned int address)
@@ -302,52 +386,51 @@ static void analyzer_set_filter(libusb_device_handle *devh)
                gl_reg_write(devh, FILTER_STATUS + i, g_filter_status[i]);
 }
 
-void analyzer_reset(libusb_device_handle *devh)
+SR_PRIV void analyzer_reset(libusb_device_handle *devh)
 {
        analyzer_write_status(devh, 3, STATUS_FLAG_NONE);       // reset device
        analyzer_write_status(devh, 3, STATUS_FLAG_RESET);      // reset device
 }
 
-void analyzer_initialize(libusb_device_handle *devh)
+SR_PRIV void analyzer_initialize(libusb_device_handle *devh)
 {
        analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
        analyzer_write_status(devh, 1, STATUS_FLAG_INIT);
        analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
 }
 
-void analyzer_wait(libusb_device_handle *devh, int set, int unset)
+SR_PRIV void analyzer_wait(libusb_device_handle *devh, int set, int unset)
 {
        int status;
+
        while (1) {
-               status = gl_reg_read(devh, DEVICE_STATUS);
-               if ((status & set) && ((status & unset) == 0))
+               status = gl_reg_read(devh, DEV_STATUS);
+               if ((!set || (status & set)) && ((status & unset) == 0))
                        return;
        }
 }
 
-void analyzer_read_start(libusb_device_handle *devh)
+SR_PRIV void analyzer_read_start(libusb_device_handle *devh)
 {
-       int i;
-
        analyzer_write_status(devh, 3, STATUS_FLAG_20 | STATUS_FLAG_READ);
 
-       for (i = 0; i < 8; i++)
-               (void)gl_reg_read(devh, READ_RAM_STATUS);
+       /* Prep for bulk reads */
+       gl_reg_read_buf(devh, READ_RAM_STATUS, NULL, 0);
 }
 
-int analyzer_read_data(libusb_device_handle *devh, void *buffer,
+SR_PRIV int analyzer_read_data(libusb_device_handle *devh, void *buffer,
                       unsigned int size)
 {
        return gl_read_bulk(devh, buffer, size);
 }
 
-void analyzer_read_stop(libusb_device_handle *devh)
+SR_PRIV void analyzer_read_stop(libusb_device_handle *devh)
 {
        analyzer_write_status(devh, 3, STATUS_FLAG_20);
        analyzer_write_status(devh, 3, STATUS_FLAG_NONE);
 }
 
-void analyzer_start(libusb_device_handle *devh)
+SR_PRIV void analyzer_start(libusb_device_handle *devh)
 {
        analyzer_write_status(devh, 1, STATUS_FLAG_NONE);
        analyzer_write_status(devh, 1, STATUS_FLAG_INIT);
@@ -355,7 +438,7 @@ void analyzer_start(libusb_device_handle *devh)
        analyzer_write_status(devh, 1, STATUS_FLAG_GO);
 }
 
-void analyzer_configure(libusb_device_handle *devh)
+SR_PRIV void analyzer_configure(libusb_device_handle *devh)
 {
        int i;
 
@@ -383,10 +466,10 @@ void analyzer_configure(libusb_device_handle *devh)
        __analyzer_set_trigger_count(devh, g_trigger_count);
 
        /* Set_Trigger_Level */
-       gl_reg_write(devh, TRIGGER_LEVEL0, 0x31);
-       gl_reg_write(devh, TRIGGER_LEVEL1, 0x31);
-       gl_reg_write(devh, TRIGGER_LEVEL2, 0x31);
-       gl_reg_write(devh, TRIGGER_LEVEL3, 0x31);
+       gl_reg_write(devh, TRIGGER_LEVEL0, g_thresh);
+       gl_reg_write(devh, TRIGGER_LEVEL1, g_thresh);
+       gl_reg_write(devh, TRIGGER_LEVEL2, g_thresh);
+       gl_reg_write(devh, TRIGGER_LEVEL3, g_thresh);
 
        /* Size of actual memory >> 2 */
        __analyzer_set_ramsize_trigger_address(devh, g_ramsize_triggerbar_addr);
@@ -405,50 +488,46 @@ void analyzer_configure(libusb_device_handle *devh)
        __analyzer_set_compression(devh, g_compression);
 }
 
-void analyzer_add_trigger(int channel, int type)
+SR_PRIV int analyzer_add_triggers(const struct sr_dev_inst *sdi)
 {
-       int i;
-
-       if ((channel & 0xf) >= 8)
-               return;
-
-       if (type == TRIGGER_HIGH || type == TRIGGER_LOW) {
-               if (channel & CHANNEL_A)
-                       i = 0;
-               else if (channel & CHANNEL_B)
-                       i = 2;
-               else if (channel & CHANNEL_C)
-                       i = 4;
-               else if (channel & CHANNEL_D)
-                       i = 6;
-               else
-                       return;
-               if ((channel & 0xf) >= 4) {
-                       i++;
-                       channel -= 4;
+       struct dev_context *devc;
+       struct sr_trigger *trigger;
+       struct sr_trigger_stage *stage;
+       struct sr_trigger_match *match;
+       GSList *l, *m;
+       int channel;
+
+       devc = sdi->priv;
+
+       if (!(trigger = sr_session_trigger_get(sdi->session)))
+               return SR_OK;
+
+       for (l = trigger->stages; l; l = l->next) {
+               stage = l->data;
+               for (m = stage->matches; m; m = m->next) {
+                       match = m->data;
+                       devc->trigger = 1;
+                       if (!match->channel->enabled)
+                               /* Ignore disabled channels with a trigger. */
+                               continue;
+                       channel = match->channel->index;
+                       switch (match->match) {
+                       case SR_TRIGGER_ZERO:
+                               g_trigger_status[channel / 4] |= 2 << (channel % 4 * 2);
+                       case SR_TRIGGER_ONE:
+                               g_trigger_status[channel / 4] |= 1 << (channel % 4 * 2);
+                               break;
+                       default:
+                               sr_err("Unsupported match %d", match->match);
+                               return SR_ERR;
+                       }
                }
-               g_trigger_status[i] |=
-                   1 << ((2 * channel) + (type == TRIGGER_LOW ? 1 : 0));
-       } else {
-               if (type == TRIGGER_POSEDGE)
-                       g_trigger_status[8] = 0x40;
-               else if (type == TRIGGER_NEGEDGE)
-                       g_trigger_status[8] = 0x80;
-               else
-                       g_trigger_status[8] = 0xc0;
-
-               /* FIXME: Just guessed the index; need to verify. */
-               if (channel & CHANNEL_B)
-                       g_trigger_status[8] += 8;
-               else if (channel & CHANNEL_C)
-                       g_trigger_status[8] += 16;
-               else if (channel & CHANNEL_D)
-                       g_trigger_status[8] += 24;
-               g_trigger_status[8] += channel % 8;
        }
+
+       return SR_OK;
 }
 
-void analyzer_add_filter(int channel, int type)
+SR_PRIV void analyzer_add_filter(int channel, int type)
 {
        int i;
 
@@ -479,73 +558,92 @@ void analyzer_add_filter(int channel, int type)
        g_filter_enable = 1;
 }
 
-void analyzer_set_trigger_count(int count)
+SR_PRIV void analyzer_set_trigger_count(int count)
 {
        g_trigger_count = count;
 }
 
-void analyzer_set_freq(int freq, int scale)
+SR_PRIV void analyzer_set_freq(int freq, int scale)
 {
        g_freq_value = freq;
        g_freq_scale = scale;
 }
 
-void analyzer_set_memory_size(unsigned int size)
+SR_PRIV void analyzer_set_memory_size(unsigned int size)
 {
        g_memory_size = size;
 }
 
-void analyzer_set_ramsize_trigger_address(unsigned int address)
+SR_PRIV void analyzer_set_ramsize_trigger_address(unsigned int address)
 {
        g_ramsize_triggerbar_addr = address;
 }
 
-void analyzer_set_triggerbar_address(unsigned int address)
+SR_PRIV unsigned int analyzer_get_ramsize_trigger_address(void)
+{
+       return g_ramsize_triggerbar_addr;
+}
+
+SR_PRIV void analyzer_set_triggerbar_address(unsigned int address)
 {
        g_triggerbar_addr = address;
 }
 
-unsigned int analyzer_read_id(libusb_device_handle *devh)
+SR_PRIV unsigned int analyzer_get_triggerbar_address(void)
+{
+       return g_triggerbar_addr;
+}
+
+SR_PRIV unsigned int analyzer_read_status(libusb_device_handle *devh)
 {
-       return gl_reg_read(devh, DEVICE_ID1) << 8 | gl_reg_read(devh,
-                                                               DEVICE_ID0);
+       return gl_reg_read(devh, DEV_STATUS);
 }
 
-unsigned int analyzer_get_stop_address(libusb_device_handle *devh)
+SR_PRIV unsigned int analyzer_read_id(libusb_device_handle *devh)
+{
+       return gl_reg_read(devh, DEV_ID1) << 8 | gl_reg_read(devh, DEV_ID0);
+}
+
+SR_PRIV unsigned int analyzer_get_stop_address(libusb_device_handle *devh)
 {
        return gl_reg_read(devh, STOP_ADDRESS2) << 16 | gl_reg_read(devh,
                        STOP_ADDRESS1) << 8 | gl_reg_read(devh, STOP_ADDRESS0);
 }
 
-unsigned int analyzer_get_now_address(libusb_device_handle *devh)
+SR_PRIV unsigned int analyzer_get_now_address(libusb_device_handle *devh)
 {
        return gl_reg_read(devh, NOW_ADDRESS2) << 16 | gl_reg_read(devh,
                        NOW_ADDRESS1) << 8 | gl_reg_read(devh, NOW_ADDRESS0);
 }
 
-unsigned int analyzer_get_trigger_address(libusb_device_handle *devh)
+SR_PRIV unsigned int analyzer_get_trigger_address(libusb_device_handle *devh)
 {
        return gl_reg_read(devh, TRIGGER_ADDRESS2) << 16 | gl_reg_read(devh,
                TRIGGER_ADDRESS1) << 8 | gl_reg_read(devh, TRIGGER_ADDRESS0);
 }
 
-void analyzer_set_compression(unsigned int type)
+SR_PRIV void analyzer_set_compression(unsigned int type)
 {
        g_compression = type;
 }
 
-void analyzer_wait_button(libusb_device_handle *devh)
+SR_PRIV void analyzer_set_voltage_threshold(int thresh)
+{
+       g_thresh = thresh;
+}
+
+SR_PRIV void analyzer_wait_button(libusb_device_handle *devh)
 {
        analyzer_wait(devh, STATUS_BUTTON_PRESSED, 0);
 }
 
-void analyzer_wait_data(libusb_device_handle *devh)
+SR_PRIV void analyzer_wait_data(libusb_device_handle *devh)
 {
-       analyzer_wait(devh, STATUS_READY | 8, STATUS_BUSY);
+       analyzer_wait(devh, 0, STATUS_BUSY);
 }
 
-int analyzer_decompress(void *input, unsigned int input_len, void *output,
-                       unsigned int output_len)
+SR_PRIV int analyzer_decompress(void *input, unsigned int input_len,
+                               void *output, unsigned int output_len)
 {
        unsigned char *in = input;
        unsigned char *out = output;