};
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,
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),
int chtype;
unsigned int i;
char hwrev[32];
+ struct sr_channel_group *cg;
if (sp_get_port_transport(port) != SP_TRANSPORT_USB) {
return devices;
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++) {
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);
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,
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;
}
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;
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);
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);
/* TODO. */
serial_source_add(sdi->session, devc->serial, G_IO_IN, -1,
- mso_receive_data, sdi);
+ mso_receive_data, (void *)sdi);
return SR_OK;
}
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;
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)
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]);
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));
}
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);
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
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));
}
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;
}
{
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;
/* 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.");
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;
/*
#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,
/* 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 */
/* register cache */
uint8_t ctlbase1;
uint8_t ctlbase2;
+ uint8_t status;
uint8_t la_threshold;
uint64_t cur_rate;
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;
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);
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);
/* 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
#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)