static void brymen_bm86x_handle_packet(const struct sr_dev_inst *sdi, unsigned char *buf) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog[2]; struct sr_analog_encoding encoding[2]; struct sr_analog_meaning meaning[2]; struct sr_analog_spec spec[2]; float floatval[2]; devc = sdi->priv; sr_analog_init(&analog[0], &encoding[0], &meaning[0], &spec[0], 0); sr_analog_init(&analog[1], &encoding[1], &meaning[1], &spec[1], 0); analog[0].meaning->mq = 0; analog[0].meaning->mqflags = 0; analog[1].meaning->mq = 0; analog[1].meaning->mqflags = 0; brymen_bm86x_parse(buf, floatval, analog); if (analog[0].meaning->mq != 0) { /* Got a measurement. */ analog[0].num_samples = 1; analog[0].data = &floatval[0]; analog[0].meaning->channels = g_slist_append(NULL, sdi->channels->data); packet.type = SR_DF_ANALOG; packet.payload = &analog[0]; sr_session_send(sdi, &packet); g_slist_free(analog[0].meaning->channels); } if (analog[1].meaning->mq != 0) { /* Got a measurement. */ analog[1].num_samples = 1; analog[1].data = &floatval[1]; analog[1].meaning->channels = g_slist_append(NULL, sdi->channels->next->data); packet.type = SR_DF_ANALOG; packet.payload = &analog[1]; sr_session_send(sdi, &packet); g_slist_free(analog[1].meaning->channels); } if (analog[0].meaning->mq != 0 || analog[1].meaning->mq != 0) sr_sw_limits_update_samples_read(&devc->sw_limits, 1); }
static void send_sample(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; devc = sdi->priv; sr_analog_init(&analog, &encoding, &meaning, &spec, 2); packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = SR_MQFLAG_DC; analog.data = &devc->voltage; sr_session_send(sdi, &packet); analog.meaning->mq = SR_MQ_CURRENT; analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags = 0; analog.data = &devc->current; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi) { float floatval; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; devc = sdi->priv; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.num_samples = 1; analog.meaning->mq = 0; if (brymen_parse(buf, &floatval, &analog, NULL) != SR_OK) return; analog.data = &floatval; analog.meaning->channels = sdi->channels; if (analog.meaning->mq != 0) { /* Got a measurement. */ packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->sw_limits, 1); } }
static void send_data(const struct sr_dev_inst *sdi, float sample) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; devc = sdi->priv; sr_analog_init(&analog, &encoding, &meaning, &spec, 1); meaning.mq = SR_MQ_SOUND_PRESSURE_LEVEL; meaning.mqflags = devc->cur_mqflags; meaning.unit = SR_UNIT_DECIBEL_SPL; meaning.channels = sdi->channels; analog.num_samples = 1; analog.data = &sample; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); devc->num_samples++; if (devc->limit_samples && devc->num_samples >= devc->limit_samples) sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi); }
static void teleinfo_send_value(struct sr_dev_inst *sdi, const char *channel_name, float value, enum sr_mq mq, enum sr_unit unit) { struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_channel *ch; ch = teleinfo_find_channel(sdi, channel_name); if (!ch || !ch->enabled) return; /* Note: digits/spec_digits is actually really 0 for this device! */ sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = g_slist_append(analog.meaning->channels, ch); analog.num_samples = 1; analog.meaning->mq = mq; analog.meaning->unit = unit; analog.data = &value; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); }
static void push_samples(const struct sr_dev_inst *sdi, uint8_t *buf, size_t num) { struct dev_context *devc = sdi->priv; float *data = devc->samples; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_datafeed_packet packet = { .type = SR_DF_ANALOG, .payload = &analog, }; float factor = devc->factor; while (num--) data[num] = (buf[num] - 0x80) * factor; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = devc->enabled_channel; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0; analog.num_samples = num; analog.data = data; sr_session_send(sdi, &packet); }
static int handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, int idx) { float temperature, humidity; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc; GSList *l; int ret; (void)idx; devc = sdi->priv; ret = packet_parse((const char *)buf, idx, &temperature, &humidity); if (ret < 0) { sr_err("Failed to parse packet."); return SR_ERR; } sr_analog_init(&analog, &encoding, &meaning, &spec, 3); /* Common values for both channels. */ packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.num_samples = 1; /* Temperature. */ l = g_slist_copy(sdi->channels); l = g_slist_remove_link(l, g_slist_nth(l, 1)); meaning.channels = l; meaning.mq = SR_MQ_TEMPERATURE; meaning.unit = SR_UNIT_CELSIUS; /* TODO: Use C/F correctly. */ analog.data = &temperature; sr_session_send(sdi, &packet); g_slist_free(l); /* Humidity. */ if (mic_devs[idx].has_humidity) { l = g_slist_copy(sdi->channels); l = g_slist_remove_link(l, g_slist_nth(l, 0)); meaning.channels = l; meaning.mq = SR_MQ_RELATIVE_HUMIDITY; meaning.unit = SR_UNIT_PERCENTAGE; analog.data = &humidity; sr_session_send(sdi, &packet); g_slist_free(l); } devc->num_samples++; return SR_OK; }
static void maynuo_m97_session_send_value(const struct sr_dev_inst *sdi, struct sr_channel *ch, float value, enum sr_mq mq, enum sr_unit unit) { struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = g_slist_append(NULL, ch); analog.num_samples = 1; analog.data = &value; analog.meaning->mq = mq; analog.meaning->unit = unit; 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); }
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, void *info) { struct dmm_info *dmm; float floatval; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc; dmm = (struct dmm_info *)sdi->driver; log_dmm_packet(buf); devc = sdi->priv; /* Note: digits/spec_digits will be overridden by the DMM parsers. */ sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.meaning->mq = 0; dmm->packet_parse(buf, &floatval, &analog, info); analog.data = &floatval; /* If this DMM needs additional handling, call the resp. function. */ if (dmm->dmm_details) dmm->dmm_details(&analog, info); if (analog.meaning->mq != 0) { /* Got a measurement. */ packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); } }
/** Send data packets for current measurements. */ static void send_data(struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; int i; float data[MAX_CHANNELS]; devc = sdi->priv; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = SR_MQFLAG_DC; analog.data = data; for (i = 0; i < devc->model->num_channels; i++) ((float *)analog.data)[i] = devc->channel_status[i].output_voltage_last; /* Value always 3.3 or 5 for channel 3, if present! */ sr_session_send(sdi, &packet); analog.meaning->mq = SR_MQ_CURRENT; analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags = 0; analog.data = data; for (i = 0; i < devc->model->num_channels; i++) ((float *)analog.data)[i] = devc->channel_status[i].output_current_last; /* Value always 0 for channel 3, if present! */ sr_session_send(sdi, &packet); sr_sw_limits_update_samples_read(&devc->limits, 1); }
SR_PRIV void mso_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, size_t length, size_t sample_width) { size_t i; struct dev_context *devc; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; (void)sample_width; devc = sdi->priv; length /= 2; /* Send the logic */ for (i = 0; i < length; i++) { devc->logic_buffer[i] = data[i * 2]; /* Rescale to -10V - +10V from 0-255. */ devc->analog_buffer[i] = (data[i * 2 + 1] - 128.0f) / 12.8f; }; const struct sr_datafeed_logic logic = { .length = length, .unitsize = 1, .data = devc->logic_buffer }; const struct sr_datafeed_packet logic_packet = { .type = SR_DF_LOGIC, .payload = &logic }; sr_session_send(sdi, &logic_packet); sr_analog_init(&analog, &encoding, &meaning, &spec, 2); analog.meaning->channels = devc->enabled_analog_channels; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0 /* SR_MQFLAG_DC */; analog.num_samples = length; analog.data = devc->analog_buffer; const struct sr_datafeed_packet analog_packet = { .type = SR_DF_ANALOG, .payload = &analog }; sr_session_send(sdi, &analog_packet); } SR_PRIV void la_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, size_t length, size_t sample_width) { const struct sr_datafeed_logic logic = { .length = length, .unitsize = sample_width, .data = data }; const struct sr_datafeed_packet packet = { .type = SR_DF_LOGIC, .payload = &logic }; sr_session_send(sdi, &packet); } SR_PRIV void LIBUSB_CALL fx2lafw_receive_transfer(struct libusb_transfer *transfer) { struct sr_dev_inst *sdi; struct dev_context *devc; gboolean packet_has_error = FALSE; struct sr_datafeed_packet packet; unsigned int num_samples; int trigger_offset, cur_sample_count, unitsize; int pre_trigger_samples; sdi = transfer->user_data; devc = sdi->priv; /* * If acquisition has already ended, just free any queued up * transfer that come in. */ if (devc->acq_aborted) { free_transfer(transfer); return; } sr_dbg("receive_transfer(): status %s received %d bytes.", libusb_error_name(transfer->status), transfer->actual_length); /* Save incoming transfer before reusing the transfer struct. */ unitsize = devc->sample_wide ? 2 : 1; cur_sample_count = transfer->actual_length / unitsize; switch (transfer->status) { case LIBUSB_TRANSFER_NO_DEVICE: fx2lafw_abort_acquisition(devc); free_transfer(transfer); return; case LIBUSB_TRANSFER_COMPLETED: case LIBUSB_TRANSFER_TIMED_OUT: /* We may have received some data though. */ break; default: packet_has_error = TRUE; break; } if (transfer->actual_length == 0 || packet_has_error) { devc->empty_transfer_count++; if (devc->empty_transfer_count > MAX_EMPTY_TRANSFERS) { /* * The FX2 gave up. End the acquisition, the frontend * will work out that the samplecount is short. */ fx2lafw_abort_acquisition(devc); free_transfer(transfer); } else { resubmit_transfer(transfer); } return; } else { devc->empty_transfer_count = 0; } if (devc->trigger_fired) { if (!devc->limit_samples || devc->sent_samples < devc->limit_samples) { /* Send the incoming transfer to the session bus. */ if (devc->limit_samples && devc->sent_samples + cur_sample_count > devc->limit_samples) num_samples = devc->limit_samples - devc->sent_samples; else num_samples = cur_sample_count; if (devc->dslogic && devc->trigger_pos > devc->sent_samples && devc->trigger_pos <= devc->sent_samples + num_samples) { /* DSLogic trigger in this block. Send trigger position. */ trigger_offset = devc->trigger_pos - devc->sent_samples; /* Pre-trigger samples. */ devc->send_data_proc(sdi, (uint8_t *)transfer->buffer, trigger_offset * unitsize, unitsize); devc->sent_samples += trigger_offset; /* Trigger position. */ devc->trigger_pos = 0; packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(sdi, &packet); /* Post trigger samples. */ num_samples -= trigger_offset; devc->send_data_proc(sdi, (uint8_t *)transfer->buffer + trigger_offset * unitsize, num_samples * unitsize, unitsize); devc->sent_samples += num_samples; } else { devc->send_data_proc(sdi, (uint8_t *)transfer->buffer, num_samples * unitsize, unitsize); devc->sent_samples += num_samples; } } } else { trigger_offset = soft_trigger_logic_check(devc->stl, transfer->buffer, transfer->actual_length, &pre_trigger_samples); if (trigger_offset > -1) { devc->sent_samples += pre_trigger_samples; num_samples = cur_sample_count - trigger_offset; if (devc->limit_samples && num_samples > devc->limit_samples - devc->sent_samples) num_samples = devc->limit_samples - devc->sent_samples; devc->send_data_proc(sdi, (uint8_t *)transfer->buffer + trigger_offset * unitsize, num_samples * unitsize, unitsize); devc->sent_samples += num_samples; devc->trigger_fired = TRUE; } } if (devc->limit_samples && devc->sent_samples >= devc->limit_samples) { fx2lafw_abort_acquisition(devc); free_transfer(transfer); } else resubmit_transfer(transfer); } static unsigned int to_bytes_per_ms(unsigned int samplerate) { return samplerate / 1000; } SR_PRIV size_t fx2lafw_get_buffer_size(struct dev_context *devc) { size_t s; /* * The buffer should be large enough to hold 10ms of data and * a multiple of 512. */ s = 10 * to_bytes_per_ms(devc->cur_samplerate); return (s + 511) & ~511; }
/** * Process received line. It consists of 20 hex digits + \\r\\n, * e.g. '08100400018100400000'. */ static void nma_process_line(const struct sr_dev_inst *sdi) { struct dev_context *devc; int pos, flags; int vt, range; /* Measurement value type, range in device format */ int mmode, devstat; /* Measuring mode, device status */ float value; /* Measured value */ float scale; /* Scaling factor depending on range and function */ struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_datafeed_packet packet; devc = sdi->priv; devc->buf[LINE_LENGTH] = '\0'; sr_spew("Received line '%s'.", devc->buf); /* Check line. */ if (strlen((const char *)devc->buf) != LINE_LENGTH) { sr_err("line: Invalid status '%s', must be 20 hex digits.", devc->buf); devc->buflen = 0; return; } for (pos = 0; pos < LINE_LENGTH; pos++) { if (!isxdigit(devc->buf[pos])) { sr_err("line: Expected hex digit in '%s' at pos %d!", devc->buf, pos); devc->buflen = 0; return; } } /* Start decoding. */ value = 0.0; scale = 1.0; /* TODO: Use proper 'digits' value for this device (and its modes). */ sr_analog_init(&analog, &encoding, &meaning, &spec, 2); /* * The numbers are hex digits, starting from 0. * 0: Keyboard status, currently not interesting. * 1: Central switch status, currently not interesting. * 2: Type of measured value. */ vt = xgittoint(devc->buf[2]); switch (vt) { case 0: analog.meaning->mq = SR_MQ_VOLTAGE; break; case 1: analog.meaning->mq = SR_MQ_CURRENT; /* 2A */ break; case 2: analog.meaning->mq = SR_MQ_RESISTANCE; break; case 3: analog.meaning->mq = SR_MQ_CAPACITANCE; break; case 4: analog.meaning->mq = SR_MQ_TEMPERATURE; break; case 5: analog.meaning->mq = SR_MQ_FREQUENCY; break; case 6: analog.meaning->mq = SR_MQ_CURRENT; /* 10A */ break; case 7: analog.meaning->mq = SR_MQ_GAIN; /* TODO: Scale factor */ break; case 8: analog.meaning->mq = SR_MQ_GAIN; /* Percentage */ scale /= 100.0; break; case 9: analog.meaning->mq = SR_MQ_GAIN; /* dB */ scale /= 100.0; break; default: sr_err("Unknown value type: 0x%02x.", vt); break; } /* 3: Measurement range for measured value */ range = xgittoint(devc->buf[3]); switch (vt) { case 0: /* V */ scale *= pow(10.0, range - 5); break; case 1: /* A */ scale *= pow(10.0, range - 7); break; case 2: /* Ω */ scale *= pow(10.0, range - 2); break; case 3: /* F */ scale *= pow(10.0, range - 12); break; case 4: /* °C */ scale *= pow(10.0, range - 1); break; case 5: /* Hz */ scale *= pow(10.0, range - 2); break; // No default, other value types have fixed display format. } /* 5: Sign and 1st digit */ flags = xgittoint(devc->buf[5]); value = (flags & 0x03); if (flags & 0x04) scale *= -1; /* 6-9: 2nd-4th digit */ for (pos = 6; pos < 10; pos++) value = value * 10 + xgittoint(devc->buf[pos]); value *= scale; /* 10: Display counter */ mmode = xgittoint(devc->buf[10]); switch (mmode) { case 0: /* Frequency */ analog.meaning->unit = SR_UNIT_HERTZ; break; case 1: /* V TRMS, only type 5 */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 2: /* V AC */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= SR_MQFLAG_AC; if (devc->type >= 3) analog.meaning->mqflags |= SR_MQFLAG_RMS; break; case 3: /* V DC */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= SR_MQFLAG_DC; break; case 4: /* Ohm */ analog.meaning->unit = SR_UNIT_OHM; break; case 5: /* Continuity */ analog.meaning->unit = SR_UNIT_BOOLEAN; analog.meaning->mq = SR_MQ_CONTINUITY; /* TODO: Continuity handling is a bit odd in libsigrok. */ break; case 6: /* Degree Celsius */ analog.meaning->unit = SR_UNIT_CELSIUS; break; case 7: /* Capacity */ analog.meaning->unit = SR_UNIT_FARAD; break; case 8: /* Current DC */ analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags |= SR_MQFLAG_DC; break; case 9: /* Current AC */ analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags |= SR_MQFLAG_AC; if (devc->type >= 3) analog.meaning->mqflags |= SR_MQFLAG_RMS; break; case 0xa: /* Current TRMS, only type 5 */ analog.meaning->unit = SR_UNIT_AMPERE; analog.meaning->mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS); break; case 0xb: /* Diode */ analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags |= (SR_MQFLAG_DIODE | SR_MQFLAG_DC); break; default: sr_err("Unknown mmode: 0x%02x.", mmode); break; } /* 11: Device status */ devstat = xgittoint(devc->buf[11]); switch (devstat) { case 1: /* Normal measurement */ break; case 2: /* Input loop (limit, reference values) */ break; case 3: /* TRANS/SENS */ break; case 4: /* Error */ sr_err("Device error. Fuse?"); /* TODO: Really abort? */ devc->buflen = 0; return; /* Cannot continue. */ default: sr_err("Unknown device status: 0x%02x", devstat); break; } /* 12-19: Flags and display symbols */ /* 12, 13 */ flags = (xgittoint(devc->buf[12]) << 8) | xgittoint(devc->buf[13]); /* 0x80: PRINT TODO: Stop polling when discovered? */ /* 0x40: EXTR */ if (analog.meaning->mq == SR_MQ_CONTINUITY) { if (flags & 0x20) value = 1.0; /* Beep */ else value = 0.0; } /* 0x10: AVG */ /* 0x08: Diode */ if (flags & 0x04) /* REL */ analog.meaning->mqflags |= SR_MQFLAG_RELATIVE; /* 0x02: SHIFT */ if (flags & 0x01) /* % */ analog.meaning->unit = SR_UNIT_PERCENTAGE; /* 14, 15 */ flags = (xgittoint(devc->buf[14]) << 8) | xgittoint(devc->buf[15]); if (!(flags & 0x80)) /* MAN: Manual range */ analog.meaning->mqflags |= SR_MQFLAG_AUTORANGE; if (flags & 0x40) /* LOBATT1: Low battery, measurement still within specs */ devc->lowbatt = 1; /* 0x20: PEAK */ /* 0x10: COUNT */ if (flags & 0x08) /* HOLD */ analog.meaning->mqflags |= SR_MQFLAG_HOLD; /* 0x04: LIMIT */ if (flags & 0x02) /* MAX */ analog.meaning->mqflags |= SR_MQFLAG_MAX; if (flags & 0x01) /* MIN */ analog.meaning->mqflags |= SR_MQFLAG_MIN; /* 16, 17 */ flags = (xgittoint(devc->buf[16]) << 8) | xgittoint(devc->buf[17]); /* 0xe0: undefined */ if (flags & 0x10) { /* LOBATT2: Low battery, measurement inaccurate */ devc->lowbatt = 2; sr_warn("Low battery, measurement quality degraded!"); } /* 0x08: SCALED */ /* 0x04: RATE (=lower resolution, allows higher data rate up to 10/s. */ /* 0x02: Current clamp */ if (flags & 0x01) { /* dB */ /* * TODO: The Norma has an adjustable dB reference value. If * changed from default, this is not correct. */ if (analog.meaning->unit == SR_UNIT_VOLT) analog.meaning->unit = SR_UNIT_DECIBEL_VOLT; else analog.meaning->unit = SR_UNIT_UNITLESS; } /* 18, 19 */ /* flags = (xgittoint(devc->buf[18]) << 8) | xgittoint(devc->buf[19]); */ /* 0x80: Undefined. */ /* 0x40: Remote mode, keyboard locked */ /* 0x38: Undefined. */ /* 0x04: MIN > MAX */ /* 0x02: Measured value < Min */ /* 0x01: Measured value > Max */ /* 4: Flags. Evaluating this after setting value! */ flags = xgittoint(devc->buf[4]); if (flags & 0x04) /* Invalid value */ value = NAN; else if (flags & 0x01) /* Overload */ value = INFINITY; if (flags & 0x02) { /* Duplicate value, has been sent before. */ sr_spew("Duplicate value, dismissing!"); devc->buflen = 0; return; } sr_spew("range=%d/scale=%f/value=%f", range, (double)scale, (double)value); /* Finish and send packet. */ analog.meaning->channels = sdi->channels; analog.num_samples = 1; analog.data = &value; memset(&packet, 0, sizeof(struct sr_datafeed_packet)); packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); /* Finish processing. */ sr_sw_limits_update_samples_read(&devc->limits, 1); devc->buflen = 0; }
SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_datafeed_logic logic; double vdiv, offset; int len, i, vref; struct sr_channel *ch; gsize expected_data_bytes; (void)fd; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; if (!(revents == G_IO_IN || revents == 0)) return TRUE; switch (devc->wait_event) { case WAIT_NONE: break; case WAIT_TRIGGER: if (rigol_ds_trigger_wait(sdi) != SR_OK) return TRUE; if (rigol_ds_channel_start(sdi) != SR_OK) return TRUE; return TRUE; case WAIT_BLOCK: if (rigol_ds_block_wait(sdi) != SR_OK) return TRUE; break; case WAIT_STOP: if (rigol_ds_stop_wait(sdi) != SR_OK) return TRUE; if (rigol_ds_check_stop(sdi) != SR_OK) return TRUE; if (rigol_ds_channel_start(sdi) != SR_OK) return TRUE; return TRUE; default: sr_err("BUG: Unknown event target encountered"); break; } ch = devc->channel_entry->data; expected_data_bytes = ch->type == SR_CHANNEL_ANALOG ? devc->analog_frame_size : devc->digital_frame_size; if (devc->num_block_bytes == 0) { if (devc->model->series->protocol >= PROTOCOL_V4) { if (sr_scpi_send(sdi->conn, ":WAV:START %d", devc->num_channel_bytes + 1) != SR_OK) return TRUE; if (sr_scpi_send(sdi->conn, ":WAV:STOP %d", MIN(devc->num_channel_bytes + ACQ_BLOCK_SIZE, devc->analog_frame_size)) != SR_OK) return TRUE; } if (devc->model->series->protocol >= PROTOCOL_V3) if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK) return TRUE; if (sr_scpi_read_begin(scpi) != SR_OK) return TRUE; if (devc->format == FORMAT_IEEE488_2) { sr_dbg("New block header expected"); len = rigol_ds_read_header(sdi); if (len == 0) /* Still reading the header. */ return TRUE; if (len == -1) { sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } /* At slow timebases in live capture the DS2072 * sometimes returns "short" data blocks, with * apparently no way to get the rest of the data. * Discard these, the complete data block will * appear eventually. */ if (devc->data_source == DATA_SOURCE_LIVE && (unsigned)len < expected_data_bytes) { sr_dbg("Discarding short data block"); sr_scpi_read_data(scpi, (char *)devc->buffer, len + 1); return TRUE; } devc->num_block_bytes = len; } else { devc->num_block_bytes = expected_data_bytes; } devc->num_block_read = 0; } len = devc->num_block_bytes - devc->num_block_read; if (len > ACQ_BUFFER_SIZE) len = ACQ_BUFFER_SIZE; sr_dbg("Requesting read of %d bytes", len); len = sr_scpi_read_data(scpi, (char *)devc->buffer, len); if (len == -1) { sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } sr_dbg("Received %d bytes.", len); devc->num_block_read += len; if (ch->type == SR_CHANNEL_ANALOG) { vref = devc->vert_reference[ch->index]; vdiv = devc->vdiv[ch->index] / 25.6; offset = devc->vert_offset[ch->index]; if (devc->model->series->protocol >= PROTOCOL_V3) for (i = 0; i < len; i++) devc->data[i] = ((int)devc->buffer[i] - vref) * vdiv - offset; else for (i = 0; i < len; i++) devc->data[i] = (128 - devc->buffer[i]) * vdiv - offset; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = g_slist_append(NULL, ch); analog.num_samples = len; analog.data = devc->data; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); } else { logic.length = len; // TODO: For the MSO1000Z series, we need a way to express that // this data is in fact just for a single channel, with the valid // data for that channel in the LSB of each byte. logic.unitsize = devc->model->series->protocol == PROTOCOL_V4 ? 1 : 2; logic.data = devc->buffer; packet.type = SR_DF_LOGIC; packet.payload = &logic; sr_session_send(sdi, &packet); } if (devc->num_block_read == devc->num_block_bytes) { sr_dbg("Block has been completed"); if (devc->model->series->protocol >= PROTOCOL_V3) { /* Discard the terminating linefeed */ sr_scpi_read_data(scpi, (char *)devc->buffer, 1); } if (devc->format == FORMAT_IEEE488_2) { /* Prepare for possible next block */ devc->num_header_bytes = 0; devc->num_block_bytes = 0; if (devc->data_source != DATA_SOURCE_LIVE) rigol_ds_set_wait_event(devc, WAIT_BLOCK); } if (!sr_scpi_read_complete(scpi)) { sr_err("Read should have been completed"); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } devc->num_block_read = 0; } else { sr_dbg("%" PRIu64 " of %" PRIu64 " block bytes read", devc->num_block_read, devc->num_block_bytes); } devc->num_channel_bytes += len; if (devc->num_channel_bytes < expected_data_bytes) /* Don't have the full data for this channel yet, re-run. */ return TRUE; /* End of data for this channel. */ if (devc->model->series->protocol == PROTOCOL_V3) { /* Signal end of data download to scope */ if (devc->data_source != DATA_SOURCE_LIVE) /* * This causes a query error, without it switching * to the next channel causes an error. Fun with * firmware... */ rigol_ds_config_set(sdi, ":WAV:END"); } if (devc->channel_entry->next) { /* We got the frame for this channel, now get the next channel. */ devc->channel_entry = devc->channel_entry->next; rigol_ds_channel_start(sdi); } else { /* Done with this frame. */ packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); if (++devc->num_frames == devc->limit_frames) { /* Last frame, stop capture. */ sdi->driver->dev_acquisition_stop(sdi); } else { /* Get the next frame, starting with the first channel. */ devc->channel_entry = devc->enabled_channels; rigol_ds_capture_start(sdi); /* Start of next frame. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); } } return TRUE; }
SR_PRIV int gwinstek_gds_800_receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; char command[32]; char *response; float volts_per_division; int num_samples, i; float samples[MAX_SAMPLES]; uint32_t sample_rate; char *end_ptr; (void)fd; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; if (!(revents == G_IO_IN || revents == 0)) return TRUE; switch (devc->state) { case START_ACQUISITION: if (sr_scpi_send(scpi, ":TRIG:MOD 3") != SR_OK) { sr_err("Failed to set trigger mode to SINGLE."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } if (sr_scpi_send(scpi, ":STOP") != SR_OK) { sr_err("Failed to put the trigger system into STOP state."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } if (sr_scpi_send(scpi, ":RUN") != SR_OK) { sr_err("Failed to put the trigger system into RUN state."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } devc->cur_acq_channel = 0; devc->state = START_TRANSFER_OF_CHANNEL_DATA; break; case START_TRANSFER_OF_CHANNEL_DATA: if (((struct sr_channel *)g_slist_nth_data(sdi->channels, devc->cur_acq_channel))->enabled) { if (sr_scpi_send(scpi, ":ACQ%d:MEM?", devc->cur_acq_channel+1) != SR_OK) { sr_err("Failed to acquire memory."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } if (sr_scpi_read_begin(scpi) != SR_OK) { sr_err("Could not begin reading SCPI response."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } devc->state = WAIT_FOR_TRANSFER_OF_BEGIN_TRANSMISSION_COMPLETE; devc->cur_rcv_buffer_position = 0; } else { /* All channels acquired. */ if (devc->cur_acq_channel == ANALOG_CHANNELS - 1) { sr_spew("All channels acquired."); if (devc->cur_acq_frame == devc->frame_limit - 1) { /* All frames accquired. */ sr_spew("All frames acquired."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } else { /* Start acquiring next frame. */ if (devc->df_started) { packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); } devc->cur_acq_frame++; devc->state = START_ACQUISITION; } } else { /* Start acquiring next channel. */ devc->cur_acq_channel++; } } break; case WAIT_FOR_TRANSFER_OF_BEGIN_TRANSMISSION_COMPLETE: if (read_data(sdi, scpi, devc, 1) == SR_OK) { if (devc->rcv_buffer[0] == '#') devc->state = WAIT_FOR_TRANSFER_OF_DATA_SIZE_DIGIT_COMPLETE; } break; case WAIT_FOR_TRANSFER_OF_DATA_SIZE_DIGIT_COMPLETE: if (read_data(sdi, scpi, devc, 1) == SR_OK) { if (devc->rcv_buffer[0] != '4' && devc->rcv_buffer[0] != '5' && devc->rcv_buffer[0] != '6') { sr_err("Data size digits is not 4, 5 or 6 but " "'%c'.", devc->rcv_buffer[0]); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } else { devc->data_size_digits = devc->rcv_buffer[0] - '0'; devc->state = WAIT_FOR_TRANSFER_OF_DATA_SIZE_COMPLETE; } } break; case WAIT_FOR_TRANSFER_OF_DATA_SIZE_COMPLETE: if (read_data(sdi, scpi, devc, devc->data_size_digits) == SR_OK) { devc->rcv_buffer[devc->data_size_digits] = 0; if (sr_atoi(devc->rcv_buffer, &devc->data_size) != SR_OK) { sr_err("Could not parse data size '%s'", devc->rcv_buffer); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } else devc->state = WAIT_FOR_TRANSFER_OF_SAMPLE_RATE_COMPLETE; } break; case WAIT_FOR_TRANSFER_OF_SAMPLE_RATE_COMPLETE: if (read_data(sdi, scpi, devc, sizeof(float)) == SR_OK) { /* * Contrary to the documentation, this field is * transfered with most significant byte first! */ sample_rate = RB32(devc->rcv_buffer); memcpy(&devc->sample_rate, &sample_rate, sizeof(float)); devc->state = WAIT_FOR_TRANSFER_OF_CHANNEL_INDICATOR_COMPLETE; if (!devc->df_started) { std_session_send_df_header(sdi); packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); devc->df_started = TRUE; } } break; case WAIT_FOR_TRANSFER_OF_CHANNEL_INDICATOR_COMPLETE: if (read_data(sdi, scpi, devc, 1) == SR_OK) devc->state = WAIT_FOR_TRANSFER_OF_RESERVED_DATA_COMPLETE; break; case WAIT_FOR_TRANSFER_OF_RESERVED_DATA_COMPLETE: if (read_data(sdi, scpi, devc, 3) == SR_OK) devc->state = WAIT_FOR_TRANSFER_OF_CHANNEL_DATA_COMPLETE; break; case WAIT_FOR_TRANSFER_OF_CHANNEL_DATA_COMPLETE: if (read_data(sdi, scpi, devc, devc->data_size - 8) == SR_OK) { /* Fetch data needed for conversion from device. */ snprintf(command, sizeof(command), ":CHAN%d:SCAL?", devc->cur_acq_channel + 1); if (sr_scpi_get_string(scpi, command, &response) != SR_OK) { sr_err("Failed to get volts per division."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } volts_per_division = g_ascii_strtod(response, &end_ptr); if (!strcmp(end_ptr, "mV")) volts_per_division *= 1.e-3; g_free(response); num_samples = (devc->data_size - 8) / 2; sr_spew("Received %d number of samples from channel " "%d.", num_samples, devc->cur_acq_channel + 1); float vbit = volts_per_division * VERTICAL_DIVISIONS / 256.0; float vbitlog = log10f(vbit); int digits = -(int)vbitlog + (vbitlog < 0.0); /* Convert data. */ for (i = 0; i < num_samples; i++) samples[i] = ((float) ((int16_t) (RB16(&devc->rcv_buffer[i*2])))) * vbit; /* Fill frame. */ sr_analog_init(&analog, &encoding, &meaning, &spec, digits); analog.meaning->channels = g_slist_append(NULL, g_slist_nth_data(sdi->channels, devc->cur_acq_channel)); analog.num_samples = num_samples; analog.data = samples; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); /* All channels acquired. */ if (devc->cur_acq_channel == ANALOG_CHANNELS - 1) { sr_spew("All channels acquired."); if (devc->cur_acq_frame == devc->frame_limit - 1) { /* All frames acquired. */ sr_spew("All frames acquired."); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } else { /* Start acquiring next frame. */ if (devc->df_started) { packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); } devc->cur_acq_frame++; devc->state = START_ACQUISITION; } } else { /* Start acquiring next channel. */ devc->state = START_TRANSFER_OF_CHANNEL_DATA; devc->cur_acq_channel++; return TRUE; } } break; } return TRUE; }
static int recv_log(const struct sr_dev_inst *sdi, GMatchInfo *match, const int mqs[], const int units[], const int exponents[], unsigned int num_functions) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; char *mstr; unsigned function; int value, negative, overload, exponent, alternate_unit, mq, unit; int mqflags = 0; float fvalue; sr_spew("LOG response '%s'.", g_match_info_get_string(match)); devc = sdi->priv; mstr = g_match_info_fetch(match, 2); if (sr_atoi(mstr, (int*)&function) != SR_OK || function >= num_functions) { g_free(mstr); sr_dbg("Invalid function."); return SR_ERR; } g_free(mstr); mstr = g_match_info_fetch(match, 3); if (sr_atoi(mstr, &value) != SR_OK) { g_free(mstr); sr_dbg("Invalid value."); return SR_ERR; } g_free(mstr); mstr = g_match_info_fetch(match, 1); negative = mstr[7] & 2 ? -1 : 1; overload = mstr[8] & 4; exponent = (mstr[9] & 0xF) + exponents[function]; alternate_unit = mstr[10] & 1; if (mstr[ 8] & 1) mqflags |= SR_MQFLAG_DC; if (mstr[ 8] & 2) mqflags |= SR_MQFLAG_AC; if (mstr[11] & 4) mqflags |= SR_MQFLAG_RELATIVE; if (mstr[12] & 1) mqflags |= SR_MQFLAG_AVG; if (mstr[12] & 2) mqflags |= SR_MQFLAG_MIN; if (mstr[12] & 4) mqflags |= SR_MQFLAG_MAX; if (function == 5) mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; g_free(mstr); mq = mqs[function]; unit = units[function]; if (alternate_unit) { if (mq == SR_MQ_RESISTANCE) mq = SR_MQ_CONTINUITY; if (unit == SR_UNIT_DECIBEL_MW) unit = SR_UNIT_DECIBEL_VOLT; if (unit == SR_UNIT_CELSIUS) { unit = SR_UNIT_FAHRENHEIT; if (devc->profile->model == KEYSIGHT_U1281 || devc->profile->model == KEYSIGHT_U1282) exponent--; } } if (overload) fvalue = NAN; else fvalue = negative * value * powf(10, exponent); sr_analog_init(&analog, &encoding, &meaning, &spec, -exponent); analog.meaning->mq = mq; analog.meaning->unit = unit; analog.meaning->mqflags = mqflags; analog.meaning->channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.data = &fvalue; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); sr_sw_limits_update_samples_read(&devc->limits, 1); devc->cur_sample++; return JOB_LOG; }
static void mso_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, size_t length, size_t sample_width) { size_t i; struct dev_context *devc; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; (void)sample_width; devc = sdi->priv; length /= 2; /* Send the logic */ for (i = 0; i < length; i++) { devc->logic_buffer[i] = data[i * 2]; /* Rescale to -10V - +10V from 0-255. */ devc->analog_buffer[i] = (data[i * 2 + 1] - 128.0f) / 12.8f; }; const struct sr_datafeed_logic logic = { .length = length, .unitsize = 1, .data = devc->logic_buffer }; const struct sr_datafeed_packet logic_packet = { .type = SR_DF_LOGIC, .payload = &logic }; sr_session_send(sdi, &logic_packet); sr_analog_init(&analog, &encoding, &meaning, &spec, 2); analog.meaning->channels = devc->enabled_analog_channels; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0 /* SR_MQFLAG_DC */; analog.num_samples = length; analog.data = devc->analog_buffer; const struct sr_datafeed_packet analog_packet = { .type = SR_DF_ANALOG, .payload = &analog }; sr_session_send(sdi, &analog_packet); } static void la_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, size_t length, size_t sample_width) { const struct sr_datafeed_logic logic = { .length = length, .unitsize = sample_width, .data = data }; const struct sr_datafeed_packet packet = { .type = SR_DF_LOGIC, .payload = &logic }; sr_session_send(sdi, &packet); } static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) { struct sr_dev_inst *sdi; struct dev_context *devc; gboolean packet_has_error = FALSE; unsigned int num_samples; int trigger_offset, cur_sample_count, unitsize; int pre_trigger_samples; sdi = transfer->user_data; devc = sdi->priv; /* * If acquisition has already ended, just free any queued up * transfer that come in. */ if (devc->acq_aborted) { free_transfer(transfer); return; } sr_dbg("receive_transfer(): status %s received %d bytes.", libusb_error_name(transfer->status), transfer->actual_length); /* Save incoming transfer before reusing the transfer struct. */ unitsize = devc->sample_wide ? 2 : 1; cur_sample_count = transfer->actual_length / unitsize; switch (transfer->status) { case LIBUSB_TRANSFER_NO_DEVICE: fx2lafw_abort_acquisition(devc); free_transfer(transfer); return; case LIBUSB_TRANSFER_COMPLETED: case LIBUSB_TRANSFER_TIMED_OUT: /* We may have received some data though. */ break; default: packet_has_error = TRUE; break; } if (transfer->actual_length == 0 || packet_has_error) { devc->empty_transfer_count++; if (devc->empty_transfer_count > MAX_EMPTY_TRANSFERS) { /* * The FX2 gave up. End the acquisition, the frontend * will work out that the samplecount is short. */ fx2lafw_abort_acquisition(devc); free_transfer(transfer); } else { resubmit_transfer(transfer); } return; } else { devc->empty_transfer_count = 0; } if (devc->trigger_fired) { if (!devc->limit_samples || devc->sent_samples < devc->limit_samples) { /* Send the incoming transfer to the session bus. */ if (devc->limit_samples && devc->sent_samples + cur_sample_count > devc->limit_samples) num_samples = devc->limit_samples - devc->sent_samples; else num_samples = cur_sample_count; devc->send_data_proc(sdi, (uint8_t *)transfer->buffer, num_samples * unitsize, unitsize); devc->sent_samples += num_samples; } } else { trigger_offset = soft_trigger_logic_check(devc->stl, transfer->buffer, transfer->actual_length, &pre_trigger_samples); if (trigger_offset > -1) { devc->sent_samples += pre_trigger_samples; num_samples = cur_sample_count - trigger_offset; if (devc->limit_samples && num_samples > devc->limit_samples - devc->sent_samples) num_samples = devc->limit_samples - devc->sent_samples; devc->send_data_proc(sdi, (uint8_t *)transfer->buffer + trigger_offset * unitsize, num_samples * unitsize, unitsize); devc->sent_samples += num_samples; devc->trigger_fired = TRUE; } } if (devc->limit_samples && devc->sent_samples >= devc->limit_samples) { fx2lafw_abort_acquisition(devc); free_transfer(transfer); } else resubmit_transfer(transfer); } static int configure_channels(const struct sr_dev_inst *sdi) { struct dev_context *devc; const GSList *l; int p; struct sr_channel *ch; uint32_t channel_mask = 0, num_analog = 0; devc = sdi->priv; g_slist_free(devc->enabled_analog_channels); devc->enabled_analog_channels = NULL; for (l = sdi->channels, p = 0; l; l = l->next, p++) { ch = l->data; if ((p <= NUM_CHANNELS) && (ch->type == SR_CHANNEL_ANALOG) && (ch->enabled)) { num_analog++; devc->enabled_analog_channels = g_slist_append(devc->enabled_analog_channels, ch); } else { channel_mask |= ch->enabled << p; } } /* * Use wide sampling if either any of the LA channels 8..15 is enabled, * and/or at least one analog channel is enabled. */ devc->sample_wide = channel_mask > 0xff || num_analog > 0; return SR_OK; } static unsigned int to_bytes_per_ms(unsigned int samplerate) { return samplerate / 1000; } static size_t get_buffer_size(struct dev_context *devc) { size_t s; /* * The buffer should be large enough to hold 10ms of data and * a multiple of 512. */ s = 10 * to_bytes_per_ms(devc->cur_samplerate); return (s + 511) & ~511; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct dev_context *devc; struct sr_dev_inst *sdi; struct sr_channel *ch; struct sr_channel_group *cg, *acg; struct sr_config *src; struct analog_gen *ag; GSList *l; int num_logic_channels, num_analog_channels, pattern, i; char channel_name[16]; num_logic_channels = DEFAULT_NUM_LOGIC_CHANNELS; num_analog_channels = DEFAULT_NUM_ANALOG_CHANNELS; for (l = options; l; l = l->next) { src = l->data; switch (src->key) { case SR_CONF_NUM_LOGIC_CHANNELS: num_logic_channels = g_variant_get_int32(src->data); break; case SR_CONF_NUM_ANALOG_CHANNELS: num_analog_channels = g_variant_get_int32(src->data); break; } } sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->model = g_strdup("Demo device"); devc = g_malloc0(sizeof(struct dev_context)); devc->cur_samplerate = SR_KHZ(200); devc->num_logic_channels = num_logic_channels; devc->logic_unitsize = (devc->num_logic_channels + 7) / 8; devc->logic_pattern = PATTERN_SIGROK; devc->num_analog_channels = num_analog_channels; if (num_logic_channels > 0) { /* Logic channels, all in one channel group. */ cg = g_malloc0(sizeof(struct sr_channel_group)); cg->name = g_strdup("Logic"); for (i = 0; i < num_logic_channels; i++) { sprintf(channel_name, "D%d", i); ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name); cg->channels = g_slist_append(cg->channels, ch); } sdi->channel_groups = g_slist_append(NULL, cg); } /* Analog channels, channel groups and pattern generators. */ if (num_analog_channels > 0) { pattern = 0; /* An "Analog" channel group with all analog channels in it. */ acg = g_malloc0(sizeof(struct sr_channel_group)); acg->name = g_strdup("Analog"); sdi->channel_groups = g_slist_append(sdi->channel_groups, acg); devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal); for (i = 0; i < num_analog_channels; i++) { snprintf(channel_name, 16, "A%d", i); ch = sr_channel_new(sdi, i + num_logic_channels, SR_CHANNEL_ANALOG, TRUE, channel_name); acg->channels = g_slist_append(acg->channels, ch); /* Every analog channel gets its own channel group as well. */ cg = g_malloc0(sizeof(struct sr_channel_group)); cg->name = g_strdup(channel_name); cg->channels = g_slist_append(NULL, ch); sdi->channel_groups = g_slist_append(sdi->channel_groups, cg); /* Every channel gets a generator struct. */ ag = g_malloc(sizeof(struct analog_gen)); ag->amplitude = DEFAULT_ANALOG_AMPLITUDE; sr_analog_init(&ag->packet, &ag->encoding, &ag->meaning, &ag->spec, 2); ag->packet.meaning->channels = cg->channels; ag->packet.meaning->mq = 0; ag->packet.meaning->mqflags = 0; ag->packet.meaning->unit = SR_UNIT_VOLT; ag->packet.data = ag->pattern_data; ag->pattern = pattern; ag->avg_val = 0.0f; ag->num_avgs = 0; g_hash_table_insert(devc->ch_ag, ch, ag); if (++pattern == ARRAY_SIZE(analog_pattern_str)) pattern = 0; } } sdi->priv = devc; return std_scan_complete(di, g_slist_append(NULL, sdi)); }
static void decode_buf(struct sr_dev_inst *sdi, unsigned char *data) { struct sr_datafeed_packet packet; struct sr_datafeed_analog2 analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc; long factor, ivalue; uint8_t digits[4]; gboolean is_duty, is_continuity, is_diode, is_ac, is_dc, is_auto; gboolean is_hold, is_max, is_min, is_relative, minus; float fvalue; devc = sdi->priv; digits[0] = decode_digit(data[12]); digits[1] = decode_digit(data[11]); digits[2] = decode_digit(data[10]); digits[3] = decode_digit(data[9]); if (digits[0] == 0x0f && digits[1] == 0x00 && digits[2] == 0x0a && digits[3] == 0x0f) /* The "over limit" (OL) display comes through like this */ ivalue = -1; else if (digits[0] > 9 || digits[1] > 9 || digits[2] > 9 || digits[3] > 9) /* An invalid digit in any position denotes no value. */ ivalue = -2; else { ivalue = digits[0] * 1000; ivalue += digits[1] * 100; ivalue += digits[2] * 10; ivalue += digits[3]; } /* Decimal point position */ factor = 0; switch (data[7] >> 4) { case 0x00: factor = 0; break; case 0x02: factor = 1; break; case 0x04: factor = 2; break; case 0x08: factor = 3; break; default: sr_err("Unknown decimal point byte: 0x%.2x.", data[7]); break; } /* Minus flag */ minus = data[2] & 0x01; /* Mode detail symbols on the right side of the digits */ is_duty = is_continuity = is_diode = FALSE; switch (data[4]) { case 0x00: /* None. */ break; case 0x01: /* Micro */ factor += 6; break; case 0x02: /* Milli */ factor += 3; break; case 0x04: /* Kilo */ ivalue *= 1000; break; case 0x08: /* Mega */ ivalue *= 1000000; break; case 0x10: /* Continuity shows up as Ohm + this bit */ is_continuity = TRUE; break; case 0x20: /* Diode tester is Volt + this bit */ is_diode = TRUE; break; case 0x40: is_duty = TRUE; break; case 0x80: /* Never seen */ sr_dbg("Unknown mode right detail: 0x%.2x.", data[4]); break; default: sr_dbg("Unknown/invalid mode right detail: 0x%.2x.", data[4]); break; } /* Scale flags on the right, continued */ is_max = is_min = FALSE; if (data[5] & 0x04) is_max = TRUE; if (data[5] & 0x08) is_min = TRUE; if (data[5] & 0x40) /* Nano */ factor += 9; /* Mode detail symbols on the left side of the digits */ is_auto = is_dc = is_ac = is_hold = is_relative = FALSE; if (data[6] & 0x04) is_auto = TRUE; if (data[6] & 0x08) is_dc = TRUE; if (data[6] & 0x10) is_ac = TRUE; if (data[6] & 0x20) is_relative = TRUE; if (data[6] & 0x40) is_hold = TRUE; fvalue = (float)ivalue / pow(10, factor); if (minus) fvalue = -fvalue; sr_analog_init(&analog, &encoding, &meaning, &spec, 4); /* Measurement mode */ meaning.channels = sdi->channels; meaning.mq = 0; switch (data[3]) { case 0x00: if (is_duty) { meaning.mq = SR_MQ_DUTY_CYCLE; meaning.unit = SR_UNIT_PERCENTAGE; } else sr_dbg("Unknown measurement mode: %.2x.", data[3]); break; case 0x01: if (is_diode) { meaning.mq = SR_MQ_VOLTAGE; meaning.unit = SR_UNIT_VOLT; meaning.mqflags |= SR_MQFLAG_DIODE; if (ivalue < 0) fvalue = NAN; } else { if (ivalue < 0) break; meaning.mq = SR_MQ_VOLTAGE; meaning.unit = SR_UNIT_VOLT; if (is_ac) meaning.mqflags |= SR_MQFLAG_AC; if (is_dc) meaning.mqflags |= SR_MQFLAG_DC; } break; case 0x02: meaning.mq = SR_MQ_CURRENT; meaning.unit = SR_UNIT_AMPERE; if (is_ac) meaning.mqflags |= SR_MQFLAG_AC; if (is_dc) meaning.mqflags |= SR_MQFLAG_DC; break; case 0x04: if (is_continuity) { meaning.mq = SR_MQ_CONTINUITY; meaning.unit = SR_UNIT_BOOLEAN; fvalue = ivalue < 0 ? 0.0 : 1.0; } else { meaning.mq = SR_MQ_RESISTANCE; meaning.unit = SR_UNIT_OHM; if (ivalue < 0) fvalue = INFINITY; } break; case 0x08: /* Never seen */ sr_dbg("Unknown measurement mode: 0x%.2x.", data[3]); break; case 0x10: meaning.mq = SR_MQ_FREQUENCY; meaning.unit = SR_UNIT_HERTZ; break; case 0x20: meaning.mq = SR_MQ_CAPACITANCE; meaning.unit = SR_UNIT_FARAD; break; case 0x40: meaning.mq = SR_MQ_TEMPERATURE; meaning.unit = SR_UNIT_CELSIUS; break; case 0x80: meaning.mq = SR_MQ_TEMPERATURE; meaning.unit = SR_UNIT_FAHRENHEIT; break; default: sr_dbg("Unknown/invalid measurement mode: 0x%.2x.", data[3]); break; } if (meaning.mq == 0) return; if (is_auto) meaning.mqflags |= SR_MQFLAG_AUTORANGE; if (is_hold) meaning.mqflags |= SR_MQFLAG_HOLD; if (is_max) meaning.mqflags |= SR_MQFLAG_MAX; if (is_min) meaning.mqflags |= SR_MQFLAG_MIN; if (is_relative) meaning.mqflags |= SR_MQFLAG_RELATIVE; analog.data = &fvalue; analog.num_samples = 1; packet.type = SR_DF_ANALOG2; packet.payload = &analog; sr_session_send(devc->cb_data, &packet); devc->num_samples++; }
SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; const struct sr_dev_inst *sdi; struct sr_channel *next_channel; struct sr_scpi_dev_inst *scpi; struct pps_channel *pch; const struct channel_spec *ch_spec; float f; int cmd; (void)fd; (void)revents; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; /* Retrieve requested value for this state. */ if (sr_scpi_get_float(scpi, NULL, &f) == SR_OK) { pch = devc->cur_channel->priv; ch_spec = &devc->device->channels[pch->hw_output_idx]; packet.type = SR_DF_ANALOG; packet.payload = &analog; /* Note: digits/spec_digits will be overridden later. */ sr_analog_init(&analog, &encoding, &meaning, &spec, 0); analog.meaning->channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.meaning->mq = pch->mq; if (pch->mq == SR_MQ_VOLTAGE) { analog.meaning->unit = SR_UNIT_VOLT; analog.encoding->digits = ch_spec->voltage[4]; analog.spec->spec_digits = ch_spec->voltage[3]; } else if (pch->mq == SR_MQ_CURRENT) { analog.meaning->unit = SR_UNIT_AMPERE; analog.encoding->digits = ch_spec->current[4]; analog.spec->spec_digits = ch_spec->current[3]; } else if (pch->mq == SR_MQ_POWER) { analog.meaning->unit = SR_UNIT_WATT; analog.encoding->digits = ch_spec->power[4]; analog.spec->spec_digits = ch_spec->power[3]; } analog.meaning->mqflags = SR_MQFLAG_DC; analog.data = &f; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); } if (g_slist_length(sdi->channels) > 1) { next_channel = sr_next_enabled_channel(sdi, devc->cur_channel); if (select_channel(sdi, next_channel) != SR_OK) { sr_err("Failed to select channel %s", next_channel->name); return FALSE; } } pch = devc->cur_channel->priv; if (pch->mq == SR_MQ_VOLTAGE) cmd = SCPI_CMD_GET_MEAS_VOLTAGE; else if (pch->mq == SR_MQ_FREQUENCY) cmd = SCPI_CMD_GET_MEAS_FREQUENCY; else if (pch->mq == SR_MQ_CURRENT) cmd = SCPI_CMD_GET_MEAS_CURRENT; else if (pch->mq == SR_MQ_POWER) cmd = SCPI_CMD_GET_MEAS_POWER; else return SR_ERR; scpi_cmd(sdi, devc->device->commands, cmd); return TRUE; }
static void send_chunk(struct sr_dev_inst *sdi, unsigned char *buf, int num_samples) { struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc = sdi->priv; GSList *channels = devc->enabled_channels; const float ch_bit[] = { RANGE(0) / 255, RANGE(1) / 255 }; const float ch_center[] = { RANGE(0) / 2, RANGE(1) / 2 }; sr_analog_init(&analog, &encoding, &meaning, &spec, 0); packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.num_samples = num_samples; analog.meaning->mq = SR_MQ_VOLTAGE; analog.meaning->unit = SR_UNIT_VOLT; analog.meaning->mqflags = 0; analog.data = g_try_malloc(num_samples * sizeof(float)); if (!analog.data) { sr_err("Analog data buffer malloc failed."); devc->dev_state = STOPPING; return; } for (int ch = 0; ch < 2; ch++) { if (!devc->ch_enabled[ch]) continue; float vdivlog = log10f(ch_bit[ch]); int digits = -(int)vdivlog + (vdivlog < 0.0); analog.encoding->digits = digits; analog.spec->spec_digits = digits; analog.meaning->channels = g_slist_append(NULL, channels->data); for (int i = 0; i < num_samples; i++) { /* * The device always sends data for both channels. If a channel * is disabled, it contains a copy of the enabled channel's * data. However, we only send the requested channels to * the bus. * * Voltage values are encoded as a value 0-255, where the * value is a point in the range represented by the vdiv * setting. There are 10 vertical divs, so e.g. 500mV/div * represents 5V peak-to-peak where 0 = -2.5V and 255 = +2.5V. */ ((float *)analog.data)[i] = ch_bit[ch] * *(buf + i * 2 + ch) - ch_center[ch]; } sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); channels = channels->next; } g_free(analog.data); }
static int recv_fetc(const struct sr_dev_inst *sdi, GMatchInfo *match) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_analog_encoding encoding; struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_channel *prev_chan; float fvalue; const char *s; char *mstr; int i, exp; sr_spew("FETC reply '%s'.", g_match_info_get_string(match)); devc = sdi->priv; i = devc->cur_channel->index; if (devc->cur_mq[i] == -1) /* This detects when channel P2 is reporting TEMP as an identical * copy of channel P3. In this case, we just skip P2. */ goto skip_value; s = g_match_info_get_string(match); if (!strcmp(s, "-9.90000000E+37") || !strcmp(s, "+9.90000000E+37")) { /* An invalid measurement shows up on the display as "O.L", but * comes through like this. Since comparing 38-digit floats * is rather problematic, we'll cut through this here. */ fvalue = NAN; } else { mstr = g_match_info_fetch(match, 1); if (sr_atof_ascii(mstr, &fvalue) != SR_OK) { g_free(mstr); sr_dbg("Invalid float."); return SR_ERR; } g_free(mstr); if (devc->cur_exponent[i] != 0) fvalue *= powf(10, devc->cur_exponent[i]); } if (devc->cur_unit[i] == SR_UNIT_DECIBEL_MW || devc->cur_unit[i] == SR_UNIT_DECIBEL_VOLT || devc->cur_unit[i] == SR_UNIT_PERCENTAGE) { mstr = g_match_info_fetch(match, 2); if (mstr && sr_atoi(mstr, &exp) == SR_OK) { devc->cur_digits[i] = MIN(4 - exp, devc->cur_digits[i]); devc->cur_encoding[i] = MIN(5 - exp, devc->cur_encoding[i]); } g_free(mstr); } sr_analog_init(&analog, &encoding, &meaning, &spec, devc->cur_digits[i] - devc->cur_exponent[i]); analog.meaning->mq = devc->cur_mq[i]; analog.meaning->unit = devc->cur_unit[i]; analog.meaning->mqflags = devc->cur_mqflags[i]; analog.meaning->channels = g_slist_append(NULL, devc->cur_channel); analog.num_samples = 1; analog.data = &fvalue; encoding.digits = devc->cur_encoding[i] - devc->cur_exponent[i]; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.meaning->channels); sr_sw_limits_update_samples_read(&devc->limits, 1); skip_value: prev_chan = devc->cur_channel; devc->cur_channel = sr_next_enabled_channel(sdi, devc->cur_channel); if (devc->cur_channel->index > prev_chan->index) return JOB_AGAIN; else return JOB_FETC; }