From: Paul Kasemir Date: Fri, 4 Dec 2020 04:45:37 +0000 (-0700) Subject: link-mso19: Fixup code to get basic analog and digital data working X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=6e183da9ee9a01bb5b45c565e5500d0d6ac088f2;p=libsigrok.git link-mso19: Fixup code to get basic analog and digital data working --- diff --git a/src/hardware/link-mso19/api.c b/src/hardware/link-mso19/api.c index c240c649..0c5f466f 100644 --- a/src/hardware/link-mso19/api.c +++ b/src/hardware/link-mso19/api.c @@ -33,7 +33,7 @@ static const uint32_t drvopts[] = { }; static const uint32_t devopts[] = { - SR_CONF_LIMIT_SAMPLES | SR_CONF_SET, + SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET, SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_TRIGGER_SLOPE | SR_CONF_SET, SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_SET, @@ -41,16 +41,6 @@ static const uint32_t devopts[] = { SR_CONF_RLE | SR_CONF_SET, }; -/* - * Channels are numbered 0 to 7. - * - * See also: http://www.linkinstruments.com/images/mso19_1113.gif - */ -static const char *channel_names[] = { - /* Note: DSO needs to be first. */ - "DSO", "0", "1", "2", "3", "4", "5", "6", "7", -}; - static const uint64_t samplerates[] = { SR_HZ(100), SR_MHZ(200), @@ -71,6 +61,7 @@ static GSList* scan_handle_port(GSList *devices, struct sp_port *port) int chtype; unsigned int i; char hwrev[32]; + struct sr_channel_group *cg; if (sp_get_port_transport(port) != SP_TRANSPORT_USB) { return devices; @@ -98,9 +89,10 @@ static GSList* scan_handle_port(GSList *devices, struct sp_port *port) return devices; } sprintf(hwrev, "r%d", devc->hwrev); - devc->ctlbase1 = 0; + devc->ctlbase1 = BIT_CTL1_ADC_ENABLE | BIT_CTL1_DC_COUPLING; devc->cur_rate = SR_KHZ(10); devc->dso_probe_attn = 10; + devc->limit_samples = MSO_NUM_SAMPLES; devc->protocol_trigger.spimode = 0; for (i = 0; i < ARRAY_SIZE(devc->protocol_trigger.word); i++) { @@ -120,10 +112,20 @@ static GSList* scan_handle_port(GSList *devices, struct sp_port *port) sdi->conn = devc->serial; sdi->priv = devc; - for (i = 0; i < ARRAY_SIZE(channel_names); i++) { - chtype = (i == 0) ? SR_CHANNEL_ANALOG : SR_CHANNEL_LOGIC; - sr_channel_new(sdi, i, chtype, TRUE, channel_names[i]); + cg = g_malloc0(sizeof(struct sr_channel_group)); + cg->name = g_strdup("DSO"); + cg->channels = g_slist_append(cg->channels, + sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE, "DSO")); + sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); + + cg = g_malloc0(sizeof(struct sr_channel_group)); + cg->name = g_strdup("LA"); + for (i = 0; i < MSO_NUM_LOGIC_CHANNELS; i++) { + char channel_name[2] = {'0' + i, '\0'}; + cg->channels = g_slist_append(cg->channels, + sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name)); } + sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); devices = g_slist_append(devices, sdi); @@ -173,26 +175,31 @@ static int dev_open(struct sr_dev_inst *sdi) devc = sdi->priv; - if (serial_open(devc->serial, SERIAL_RDWR) != SR_OK) + if (std_serial_dev_open(sdi) != SR_OK) return SR_ERR; - /* FIXME: discard serial buffer */ - mso_check_trigger(devc->serial, &devc->trigger_state); - sr_dbg("Trigger state: 0x%x.", devc->trigger_state); + serial_flush(devc->serial); ret = mso_reset_adc(sdi); if (ret != SR_OK) - return ret; + goto error_close; - mso_check_trigger(devc->serial, &devc->trigger_state); - sr_dbg("Trigger state: 0x%x.", devc->trigger_state); + serial_flush(devc->serial); + + ret = mso_read_status(devc->serial, &devc->status); + if (ret != SR_OK) { + goto error_close; + } - // ret = mso_reset_fsm(sdi); - // if (ret != SR_OK) - // return ret; - // return SR_ERR; + ret = mso_reset_fsm(sdi); + if (ret != SR_OK) { + goto error_close; + } return SR_OK; +error_close: + serial_close(devc->serial); + return ret; } static int config_get(uint32_t key, GVariant **data, @@ -211,6 +218,9 @@ static int config_get(uint32_t key, GVariant **data, case SR_CONF_SAMPLERATE: *data = g_variant_new_uint64(devc->cur_rate); break; + case SR_CONF_LIMIT_SAMPLES: + *data = g_variant_new_uint64(devc->limit_samples); + break; default: return SR_ERR_NA; } @@ -238,8 +248,8 @@ static int config_set(uint32_t key, GVariant *data, return mso_configure_rate(sdi, g_variant_get_uint64(data)); case SR_CONF_LIMIT_SAMPLES: num_samples = g_variant_get_uint64(data); - if (num_samples != 1024) { - sr_err("Only 1024 samples are supported."); + if (num_samples != MSO_NUM_SAMPLES) { + sr_err("Only %d samples are supported.", MSO_NUM_SAMPLES); return SR_ERR_ARG; } devc->limit_samples = num_samples; @@ -298,13 +308,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) return SR_ERR; } - /* FIXME: No need to do full reconfigure every time */ -// ret = mso_reset_fsm(sdi); -// if (ret != SR_OK) -// return ret; + ret = mso_reset_fsm(sdi); + if (ret != SR_OK) { + return ret; + } /* FIXME: ACDC Mode */ - devc->ctlbase1 &= 0x7f; // devc->ctlbase1 |= devc->acdcmode; ret = mso_configure_rate(sdi, devc->cur_rate); @@ -330,13 +339,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) return ret; /* Start acquisition on the device. */ - mso_check_trigger(devc->serial, &devc->trigger_state); - ret = mso_check_trigger(devc->serial, NULL); + ret = mso_read_status(devc->serial, &devc->status); + if (ret != SR_OK) + return ret; + ret = mso_read_status(devc->serial, NULL); if (ret != SR_OK) return ret; - - /* Reset trigger state. */ - devc->trigger_state = 0x00; std_session_send_df_header(sdi); @@ -344,7 +352,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) /* TODO. */ serial_source_add(sdi->session, devc->serial, G_IO_IN, -1, - mso_receive_data, sdi); + mso_receive_data, (void *)sdi); return SR_OK; } diff --git a/src/hardware/link-mso19/protocol.c b/src/hardware/link-mso19/protocol.c index ec88f097..867a8bb9 100644 --- a/src/hardware/link-mso19/protocol.c +++ b/src/hardware/link-mso19/protocol.c @@ -31,8 +31,8 @@ static const char mso_head[] = { 0x40, 0x4c, 0x44, 0x53, 0x7e }; static const char mso_foot[] = { 0x7e }; -SR_PRIV int mso_send_control_message(struct sr_serial_dev_inst *serial, - uint16_t payload[], int n) +static int mso_send_control_message(struct sr_serial_dev_inst *serial, + uint16_t payload[], int n) { int i, w, ret, s = n * 2 + sizeof(mso_head) + sizeof(mso_foot); char *p, *buf; @@ -66,12 +66,21 @@ free: return ret; } +static uint16_t mso_bank_select(const struct dev_context *devc, int bank) +{ + if (bank > 2) { + sr_err("Unsupported bank %d", bank); + } + return mso_trans(REG_CTL2, devc->ctlbase2 | BITS_CTL2_BANK(bank)); +} + SR_PRIV int mso_configure_trigger(const struct sr_dev_inst *sdi) { struct dev_context *devc = sdi->priv; uint16_t threshold_value = mso_calc_raw_from_mv(devc); - threshold_value = 0x153C; + // Use 0x200 temporary value till we can properly calculate it. + threshold_value = 0x200; uint8_t trigger_config = 0; if (devc->trigger_slope) @@ -123,7 +132,7 @@ SR_PRIV int mso_configure_trigger(const struct sr_dev_inst *sdi) SR_HZ_TO_NS(devc->cur_rate)); /* Select the SPI/I2C trigger config bank */ - ops[7] = mso_trans(REG_CTL2, (devc->ctlbase2 | BITS_CTL2_BANK(2))); + ops[7] = mso_bank_select(devc, 2); /* Configure the SPI/I2C protocol trigger */ ops[8] = mso_trans(REG_PT_WORD(0), devc->protocol_trigger.word[0]); ops[9] = mso_trans(REG_PT_WORD(1), devc->protocol_trigger.word[1]); @@ -135,7 +144,7 @@ SR_PRIV int mso_configure_trigger(const struct sr_dev_inst *sdi) ops[15] = mso_trans(REG_PT_MASK(3), devc->protocol_trigger.mask[3]); ops[16] = mso_trans(REG_PT_SPIMODE, devc->protocol_trigger.spimode); /* Select the default config bank */ - ops[17] = mso_trans(REG_CTL2, devc->ctlbase2); + ops[17] = mso_bank_select(devc, 0); return mso_send_control_message(devc->serial, ARRAY_AND_SIZE(ops)); } @@ -187,7 +196,7 @@ SR_PRIV int mso_dac_out(const struct sr_dev_inst *sdi, uint16_t val) uint16_t ops[] = { mso_trans(REG_DAC1, (val >> 8) & 0xff), mso_trans(REG_DAC2, val & 0xff), - mso_trans(REG_CTL1, devc->ctlbase1 | BIT_CTL1_RESETADC), + mso_trans(REG_CTL1, devc->ctlbase1 | BIT_CTL1_LOAD_DAC), }; sr_dbg("Setting dac word to 0x%x.", val); @@ -219,17 +228,17 @@ SR_PRIV int mso_parse_serial(const char *iSerial, const char *iProduct, if (iSerial[0] != '4' || sscanf(iSerial, "%5u%3u%3u%1u%1u%6u", &u1, &u2, &u3, &u4, &u5, &u6) != 6) return SR_ERR; - devc->hwmodel = u4; - devc->hwrev = u5; - devc->vbit = u1 / 10000; - if (devc->vbit == 0) - devc->vbit = 4.19195; + if (u1 == 0) + u1 = 42874; + if (u2 == 0) + u2 = 343; + if (u3 == 0) + u3 = 500; + devc->vbit = ((double)u1) / 10000.0 / 1000.0; devc->dac_offset = u2; - if (devc->dac_offset == 0) - devc->dac_offset = 0x1ff; devc->offset_range = u3; - if (devc->offset_range == 0) - devc->offset_range = 0x17d; + devc->hwmodel = u4; + devc->hwrev = u5; /* * FIXME: There is more code on the original software to handle @@ -240,28 +249,27 @@ SR_PRIV int mso_parse_serial(const char *iSerial, const char *iProduct, return SR_OK; } -SR_PRIV int mso_reset_adc(struct sr_dev_inst *sdi) +SR_PRIV int mso_reset_adc(const struct sr_dev_inst *sdi) { struct dev_context *devc = sdi->priv; - uint16_t ops[2]; + uint16_t ops[3]; - ops[0] = mso_trans(REG_CTL1, (devc->ctlbase1 | BIT_CTL1_RESETADC)); - ops[1] = mso_trans(REG_CTL1, devc->ctlbase1); - devc->ctlbase1 |= BIT_CTL1_ADC_UNKNOWN4; + ops[0] = mso_bank_select(devc, 0); + ops[1] = mso_trans(REG_CTL1, BIT_CTL1_RESETADC); + ops[2] = mso_trans(REG_CTL1, 0); sr_dbg("Requesting ADC reset."); return mso_send_control_message(devc->serial, ARRAY_AND_SIZE(ops)); } -SR_PRIV int mso_reset_fsm(struct sr_dev_inst *sdi) +SR_PRIV int mso_reset_fsm(const struct sr_dev_inst *sdi) { struct dev_context *devc = sdi->priv; uint16_t ops[1]; - devc->ctlbase1 |= BIT_CTL1_RESETFSM; - ops[0] = mso_trans(REG_CTL1, devc->ctlbase1); + ops[0] = mso_trans(REG_CTL1, devc->ctlbase1 | BIT_CTL1_RESETFSM); - sr_dbg("Requesting ADC reset."); + sr_dbg("Requesting FSM reset."); return mso_send_control_message(devc->serial, ARRAY_AND_SIZE(ops)); } @@ -308,23 +316,39 @@ SR_PRIV int mso_configure_rate(const struct sr_dev_inst *sdi, uint32_t rate) return ret; } -SR_PRIV int mso_check_trigger(struct sr_serial_dev_inst *serial, uint8_t *info) +static int mso_validate_status(uint8_t val) { + uint8_t action = BITS_STATUS_ACTION(val); + if (action == 0 || action > STATUS_DATA_READY + || val & 0xC0) { + sr_err("Invalid status byte %.2x", val); + return SR_ERR; + } + + return SR_OK; +} + +SR_PRIV int mso_read_status(struct sr_serial_dev_inst *serial, uint8_t *status) { - uint16_t ops[] = { mso_trans(REG_TRIGGER, 0) }; + uint16_t ops[] = { mso_trans(REG_STATUS, 0) }; + uint8_t buf = 0; int ret; - sr_dbg("Requesting trigger state."); + sr_dbg("Requesting status."); ret = mso_send_control_message(serial, ARRAY_AND_SIZE(ops)); - if (!info || ret != SR_OK) + if (!status || ret != SR_OK) { return ret; + } - uint8_t buf = 0; - if (serial_read_blocking(serial, &buf, 1, 10) != 1) - ret = SR_ERR; - if (!info) - *info = buf; + if (serial_read_blocking(serial, &buf, 1, 10) != 1) { + sr_err("Reading status failed"); + return SR_ERR; + } + ret = mso_validate_status(buf); + if (ret == SR_OK) { + *status = buf; + sr_dbg("Status is: 0x%x.", *status); + } - sr_dbg("Trigger state is: 0x%x.", *info); return ret; } @@ -332,11 +356,16 @@ SR_PRIV int mso_receive_data(int fd, int revents, void *cb_data) { struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; + struct sr_datafeed_analog analog; + struct sr_analog_encoding encoding; + struct sr_analog_meaning meaning; + struct sr_analog_spec spec; + struct sr_dev_inst *sdi; struct dev_context *devc; int i; - uint8_t in[1024]; + uint8_t in[MSO_NUM_SAMPLES]; size_t s; (void)fd; @@ -356,45 +385,61 @@ SR_PRIV int mso_receive_data(int fd, int revents, void *cb_data) /* Check if we triggered, then send a command that we are ready * to read the data */ - if (devc->trigger_state != MSO_TRIGGER_DATAREADY) { - devc->trigger_state = in[0]; - if (devc->trigger_state == MSO_TRIGGER_DATAREADY) { + if (BITS_STATUS_ACTION(devc->status) != STATUS_DATA_READY) { + if (mso_validate_status(in[0]) != SR_OK) { + return FALSE; + } + devc->status = in[0]; + if (BITS_STATUS_ACTION(devc->status) == STATUS_DATA_READY) { mso_read_buffer(sdi); devc->buffer_n = 0; } else { - mso_check_trigger(devc->serial, NULL); + mso_read_status(devc->serial, NULL); } return TRUE; } /* the hardware always dumps 1024 samples, 24bits each */ - if (devc->buffer_n < 3072) { + if (devc->buffer_n < (MSO_NUM_SAMPLES * 3)) { memcpy(devc->buffer + devc->buffer_n, in, s); devc->buffer_n += s; } - if (devc->buffer_n < 3072) + if (devc->buffer_n < (MSO_NUM_SAMPLES * 3)) return TRUE; /* do the conversion */ - uint8_t logic_out[1024]; - double analog_out[1024]; - for (i = 0; i < 1024; i++) { - /* FIXME: Need to do conversion to mV */ + uint8_t logic_out[MSO_NUM_SAMPLES]; + float analog_out[MSO_NUM_SAMPLES]; + for (i = 0; i < MSO_NUM_SAMPLES; i++) { analog_out[i] = (devc->buffer[i * 3] & 0x3f) | ((devc->buffer[i * 3 + 1] & 0xf) << 6); - (void)analog_out; + analog_out[i] = (512.0 - analog_out[i]) * devc->vbit + * devc->dso_probe_attn; logic_out[i] = ((devc->buffer[i * 3 + 1] & 0x30) >> 4) | ((devc->buffer[i * 3 + 2] & 0x3f) << 2); } packet.type = SR_DF_LOGIC; packet.payload = &logic; - logic.length = 1024; + logic.length = MSO_NUM_SAMPLES; logic.unitsize = 1; logic.data = logic_out; sr_session_send(sdi, &packet); - devc->num_samples += 1024; + 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); + g_slist_free(analog.meaning->channels); + + devc->num_samples += MSO_NUM_SAMPLES; if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { sr_info("Requested number of samples reached."); @@ -418,7 +463,8 @@ SR_PRIV int mso_configure_channels(const struct sr_dev_inst *sdi) devc->dso_trigger_voltage = 3; devc->dso_probe_attn = 1; devc->trigger_outsrc = 0; - devc->trigger_chan = 3; //LA combination trigger + //devc->trigger_chan = 3; //LA combination trigger + devc->trigger_chan = 0; // DSO trigger devc->use_trigger = FALSE; /* diff --git a/src/hardware/link-mso19/protocol.h b/src/hardware/link-mso19/protocol.h index 6dc26ac3..6dbb54fd 100644 --- a/src/hardware/link-mso19/protocol.h +++ b/src/hardware/link-mso19/protocol.h @@ -34,19 +34,9 @@ #define USB_VENDOR 0x3195 #define USB_PRODUCT 0xf190 -#define NUM_TRIGGER_STAGES 4 #define SERIALCOMM "460800/8n1/flow=2" -#define SERIALCONN "/dev/ttyUSB0" -#define CLOCK_RATE SR_MHZ(100) -#define MIN_NUM_SAMPLES 4 - -#define MSO_TRIGGER_UNKNOWN '!' -#define MSO_TRIGGER_UNKNOWN1 '1' -#define MSO_TRIGGER_UNKNOWN2 '2' -#define MSO_TRIGGER_UNKNOWN3 '3' -#define MSO_TRIGGER_WAIT '4' -#define MSO_TRIGGER_FIRED '5' -#define MSO_TRIGGER_DATAREADY '6' +#define MSO_NUM_SAMPLES 1024 +#define MSO_NUM_LOGIC_CHANNELS 8 enum trigger_slopes { SLOPE_POSITIVE = 0, @@ -64,9 +54,9 @@ struct mso_patgen { /* Pattern generator config */ uint8_t config; /* Samples buffer */ - uint8_t buffer[1024]; + uint8_t buffer[MSO_NUM_SAMPLES]; /* Input/output configuration for the samples buffer (?) */ - uint8_t io[1024]; + uint8_t io[MSO_NUM_SAMPLES]; /* Number of loops for the pattern generator */ uint8_t loops; /* Bit enable mask for the I/O lines */ @@ -99,6 +89,7 @@ struct dev_context { /* register cache */ uint8_t ctlbase1; uint8_t ctlbase2; + uint8_t status; uint8_t la_threshold; uint64_t cur_rate; @@ -107,7 +98,6 @@ struct dev_context { uint8_t trigger_chan; uint8_t trigger_slope; uint8_t trigger_outsrc; - uint8_t trigger_state; uint8_t trigger_holdoff[2]; uint8_t la_trigger; uint8_t la_trigger_mask; @@ -120,9 +110,9 @@ struct dev_context { SR_PRIV int mso_parse_serial(const char *iSerial, const char *iProduct, struct dev_context *ctx); -SR_PRIV int mso_check_trigger(struct sr_serial_dev_inst *serial, - uint8_t * info); -SR_PRIV int mso_reset_adc(struct sr_dev_inst *sdi); +SR_PRIV int mso_read_status(struct sr_serial_dev_inst *serial, + uint8_t *status); +SR_PRIV int mso_reset_adc(const struct sr_dev_inst *sdi); SR_PRIV int mso_clkrate_out(struct sr_serial_dev_inst *serial, uint16_t val); SR_PRIV int mso_configure_rate(const struct sr_dev_inst *sdi, uint32_t rate); SR_PRIV int mso_receive_data(int fd, int revents, void *cb_data); @@ -133,7 +123,7 @@ SR_PRIV int mso_arm(const struct sr_dev_inst *sdi); SR_PRIV int mso_force_capture(struct sr_dev_inst *sdi); SR_PRIV int mso_dac_out(const struct sr_dev_inst *sdi, uint16_t val); SR_PRIV uint16_t mso_calc_raw_from_mv(struct dev_context *devc); -SR_PRIV int mso_reset_fsm(struct sr_dev_inst *sdi); +SR_PRIV int mso_reset_fsm(const struct sr_dev_inst *sdi); SR_PRIV int mso_configure_channels(const struct sr_dev_inst *sdi); SR_PRIV void stop_acquisition(const struct sr_dev_inst *sdi); @@ -143,7 +133,7 @@ SR_PRIV void stop_acquisition(const struct sr_dev_inst *sdi); /* bank 0 registers */ #define REG_BUFFER 1 -#define REG_TRIGGER 2 +#define REG_STATUS 2 #define REG_CLKRATE1 9 #define REG_CLKRATE2 10 #define REG_DAC1 12 @@ -156,12 +146,27 @@ SR_PRIV void stop_acquisition(const struct sr_dev_inst *sdi); #define REG_PT_MASK(x) (x + 4) #define REG_PT_SPIMODE 8 +/* bits - REG_STATUS */ +#define BITS_STATUS_ACTION(x) (x & STATUS_MASK) +enum { + STATUS_MASK = 0x7, + STATUS_NOT_RUNNING = 1, + STATUS_TRIGGER_PRE_FILL = 3, + STATUS_TRIGGER_WAIT = 4, + STATUS_TRIGGER_POST_FILL = 5, + STATUS_DATA_READY = 6, + BIT_STATUS_ARMED = 1 << 4, + BIT_STATUS_OK = 1 << 5, +}; + /* bits - REG_CTL1 */ -#define BIT_CTL1_RESETFSM (1 << 0) -#define BIT_CTL1_ARM (1 << 1) -#define BIT_CTL1_ADC_UNKNOWN4 (1 << 4) /* adc enable? */ -#define BIT_CTL1_RESETADC (1 << 6) -#define BIT_CTL1_LED (1 << 7) +#define BIT_CTL1_RESETFSM (1 << 0) +#define BIT_CTL1_ARM (1 << 1) +#define BIT_CTL1_FORCE_TRIGGER (1 << 3) +#define BIT_CTL1_ADC_ENABLE (1 << 4) +#define BIT_CTL1_LOAD_DAC (1 << 5) +#define BIT_CTL1_RESETADC (1 << 6) +#define BIT_CTL1_DC_COUPLING (1 << 7) /* bits - REG_CTL2 */ #define BITS_CTL2_BANK(x) (x & 0x3)