]> sigrok.org Git - libsigrok.git/commitdiff
link-mso19: Fixup horiz_triggerpos and add trigger location
authorPaul Kasemir <redacted>
Fri, 18 Dec 2020 07:42:07 +0000 (00:42 -0700)
committerSoeren Apel <redacted>
Wed, 16 Oct 2024 22:08:34 +0000 (00:08 +0200)
src/hardware/link-mso19/api.c
src/hardware/link-mso19/protocol.c
src/hardware/link-mso19/protocol.h

index ffcc44968f723d5338620192a6f18d9b10383e9b..9636aea4c985c14cc8e90a43c84243babf657499 100644 (file)
@@ -37,8 +37,7 @@ static const uint32_t devopts[] = {
        SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
        SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
        SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
-       SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_SET,
-       SR_CONF_CAPTURE_RATIO | SR_CONF_SET,
+       SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
 };
 
 static const uint32_t devopts_cg_analog[] = {
@@ -134,6 +133,30 @@ static void mso_limit_trigger_level(struct dev_context *devc)
        sr_info("Adjusted dso trigger level to %f", devc->dso_trigger_adjusted);
 }
 
+static void mso_update_trigger_pos(struct dev_context *devc)
+{
+       int pos = (devc->horiz_triggerpos * MSO_NUM_SAMPLES) + 0.5;
+       uint16_t sign_bit = TRIG_POS_IS_POSITIVE;
+       if (pos < 0) {
+               pos = -pos;
+               sign_bit = TRIG_POS_IS_NEGATIVE;
+               if (pos < (MSO_NUM_SAMPLES + 10)) {
+                       // Program doesn't allow these holdoff values, but they
+                       // sometimes work, so just warn about stability.
+                       sr_warn("Trigger holdoff > -1.011 may be unstable %f", devc->horiz_triggerpos);
+               }
+       } else if (pos >= MSO_NUM_SAMPLES) {
+               pos = MSO_NUM_SAMPLES - 1;
+       } else if (pos < 10) {
+               // Program never runs trigger less than 10. It sometimes fails
+               // to trigger properly if less than 10.
+               sr_warn("Trigger position < .01 may be unstable %f", devc->horiz_triggerpos);
+       }
+       devc->ctltrig_pos = pos & TRIG_POS_VALUE_MASK;
+       if (devc->ctltrig_pos)
+               devc->ctltrig_pos |= sign_bit;
+}
+
 static GSList* scan_handle_port(GSList *devices, struct sp_port *port)
 {
        int usb_vid, usb_pid;
@@ -175,6 +198,8 @@ static GSList* scan_handle_port(GSList *devices, struct sp_port *port)
        TRIG_UPDATE_OUT(devc->ctltrig, TRIG_OUT_TRIGGER);
        TRIG_UPDATE_SRC(devc->ctltrig, TRIG_SRC_DSO);
        mso_update_trigger_slope(devc);
+       devc->horiz_triggerpos = 0.5;
+       mso_update_trigger_pos(devc);
        devc->coupling = coupling[0];
        devc->cur_rate = SR_KHZ(10);
        devc->dso_probe_factor = 10;
@@ -331,6 +356,9 @@ static int config_get(uint32_t key, GVariant **data,
                        return SR_ERR_ARG;
                *data = g_variant_new_double(devc->dso_trigger_level);
                break;
+       case SR_CONF_HORIZ_TRIGGERPOS:
+               *data = g_variant_new_double(devc->horiz_triggerpos);
+               break;
        default:
                return SR_ERR_NA;
        }
@@ -343,7 +371,6 @@ static int config_set(uint32_t key, GVariant *data,
 {
        struct dev_context *devc;
        uint64_t tmp_u64;
-       int trigger_pos;
        double pos;
        int idx;
 
@@ -361,8 +388,6 @@ static int config_set(uint32_t key, GVariant *data,
                }
                devc->limit_samples = tmp_u64;
                break;
-       case SR_CONF_CAPTURE_RATIO:
-               break;
        case SR_CONF_TRIGGER_SOURCE:
                idx = std_str_idx(data, ARRAY_AND_SIZE(trigger_sources));
                if (idx < 0)
@@ -402,12 +427,13 @@ static int config_set(uint32_t key, GVariant *data,
                break;
        case SR_CONF_HORIZ_TRIGGERPOS:
                pos = g_variant_get_double(data);
-               if (pos < 0 || pos > 255) {
-                       sr_err("Trigger position (%f) should be between 0 and 255.", pos);
+               // Negative position equates to trigger holdoff in the program
+               if (pos < -10.0 || pos > 1.0) {
+                       sr_err("Trigger position (%f) should be between -10.0 and 1.0", pos);
                        return SR_ERR_ARG;
                }
-               trigger_pos = (int)pos;
-               devc->trigger_holdoff[0] = trigger_pos & 0xff;
+               devc->horiz_triggerpos = pos;
+               mso_update_trigger_pos(devc);
                break;
        case SR_CONF_COUPLING:
                if (!cg_is_analog(cg))
index 27186655f43eea6dcbbd43b171d9a0377deda79b..c2fdf5c549eebec61600aa58165712c7a646146e 100644 (file)
@@ -86,10 +86,10 @@ SR_PRIV int mso_configure_trigger(const struct sr_dev_inst *sdi)
                mso_trans(REG_TRIG, devc->ctltrig),
                mso_trans(REG_TRIG_LA_VAL, devc->la_trigger),
                mso_trans(REG_TRIG_LA_MASK, devc->la_trigger_mask),
-               mso_trans(7, devc->trigger_holdoff[0]),
-               mso_trans(8, devc->trigger_holdoff[1]),
+               mso_trans(REG_TRIG_POS_LSB, devc->ctltrig_pos & 0xff),
+               mso_trans(REG_TRIG_POS_MSB, (devc->ctltrig_pos >> 8) & 0xff),
 
-               mso_trans(11,
+               mso_trans(REG_TRIG_WIDTH,
                          devc->dso_trigger_width /
                          SR_HZ_TO_NS(devc->cur_rate)),
 
@@ -327,6 +327,8 @@ SR_PRIV int mso_receive_data(int fd, int revents, void *cb_data)
        struct sr_dev_inst *sdi;
        struct dev_context *devc;
        int i;
+       int trigger_sample;
+       int pre_samples, post_samples;
 
        uint8_t in[MSO_NUM_SAMPLES];
        size_t s;
@@ -382,24 +384,55 @@ SR_PRIV int mso_receive_data(int fd, int revents, void *cb_data)
                    ((devc->buffer[i * 3 + 2] & 0x3f) << 2);
        }
 
-       packet.type = SR_DF_LOGIC;
-       packet.payload = &logic;
-       logic.length = MSO_NUM_SAMPLES;
-       logic.unitsize = 1;
-       logic.data = logic_out;
-       sr_session_send(sdi, &packet);
+       if (devc->ctltrig_pos & TRIG_POS_IS_NEGATIVE) {
+               trigger_sample = -1;
+               pre_samples = MSO_NUM_SAMPLES;
+       } else {
+               trigger_sample = devc->ctltrig_pos & TRIG_POS_VALUE_MASK;
+               pre_samples = MIN(trigger_sample, MSO_NUM_SAMPLES);
+       }
+
+       logic.unitsize = sizeof(*logic_out);
 
        sr_analog_init(&analog, &encoding, &meaning, &spec, 3);
        analog.meaning->channels = g_slist_append(NULL, g_slist_nth_data(sdi->channels, 0));
-       analog.num_samples = MSO_NUM_SAMPLES;
-       analog.data = analog_out;
        analog.meaning->mq = SR_MQ_VOLTAGE;
        analog.meaning->unit = SR_UNIT_VOLT;
        analog.meaning->mqflags = SR_MQFLAG_DC;
 
-       packet.type = SR_DF_ANALOG;
-       packet.payload = &analog;
-       sr_session_send(sdi, &packet);
+       if (pre_samples > 0) {
+               packet.type = SR_DF_LOGIC;
+               packet.payload = &logic;
+               logic.length = pre_samples * sizeof(*logic_out);
+               logic.data = logic_out;
+               sr_session_send(sdi, &packet);
+
+               packet.type = SR_DF_ANALOG;
+               packet.payload = &analog;
+               analog.num_samples = pre_samples;
+               analog.data = analog_out;
+               sr_session_send(sdi, &packet);
+       }
+
+       if (pre_samples == trigger_sample) {
+               std_session_send_df_trigger(sdi);
+       }
+
+       post_samples = MSO_NUM_SAMPLES - pre_samples;
+
+       if (post_samples > 0) {
+               packet.type = SR_DF_LOGIC;
+               packet.payload = &logic;
+               logic.length = post_samples * sizeof(*logic_out);
+               logic.data = logic_out + pre_samples;
+               sr_session_send(sdi, &packet);
+
+               packet.type = SR_DF_ANALOG;
+               packet.payload = &analog;
+               analog.num_samples = post_samples;
+               analog.data = analog_out + pre_samples;
+               sr_session_send(sdi, &packet);
+       }
        g_slist_free(analog.meaning->channels);
 
        devc->num_samples += MSO_NUM_SAMPLES;
index f6d714d5e060dd17824c7953fe246e376bbf65ec..0c50ab85eada3afdf97d184634612bd358a1c2ef 100644 (file)
@@ -88,6 +88,7 @@ struct dev_context {
        uint8_t ctlbase1;
        uint8_t ctlbase2;
        uint8_t ctltrig;
+       uint16_t ctltrig_pos;
        uint8_t status;
 
        uint8_t la_threshold;
@@ -97,10 +98,10 @@ struct dev_context {
        uint8_t trigger_source;
        uint8_t dso_trigger_slope;
        uint8_t trigger_outsrc;
-       uint8_t trigger_holdoff[2];
        uint8_t la_trigger_slope;
        uint8_t la_trigger;
        uint8_t la_trigger_mask;
+       double horiz_triggerpos;
        double dso_trigger_level;
        double dso_trigger_adjusted;
        uint16_t dso_trigger_width;
@@ -139,8 +140,11 @@ SR_PRIV void stop_acquisition(const struct sr_dev_inst *sdi);
 #define REG_TRIG               4
 #define REG_TRIG_LA_VAL                5
 #define REG_TRIG_LA_MASK       6
+#define REG_TRIG_POS_LSB       7
+#define REG_TRIG_POS_MSB       8
 #define REG_CLKRATE1           9
 #define REG_CLKRATE2           10
+#define REG_TRIG_WIDTH         11
 #define REG_DAC1               12
 #define REG_DAC2               13
 /* possibly bank agnostic: */
@@ -193,6 +197,13 @@ enum {
 #define TRIG_UPDATE_OUT(reg, val)      TRIG_UPDATE_MASK((reg), (val), TRIG_OUT_MASK)
 #define TRIG_UPDATE_SRC(reg, val)      TRIG_UPDATE_MASK((reg), (val), TRIG_SRC_MASK)
 
+/* bits - REG_TRIG_POS_MSB */
+enum {
+       TRIG_POS_VALUE_MASK =   0x7fff,
+       TRIG_POS_IS_POSITIVE =  0 << 15,
+       TRIG_POS_IS_NEGATIVE =  1 << 15,
+};
+
 /* bits - REG_CTL1 */
 #define BIT_CTL1_RESETFSM              (1 << 0)
 #define BIT_CTL1_ARM                   (1 << 1)