/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_usb_dev_inst *usb; struct sr_datafeed_packet packet; packet.type = SR_DF_END; sr_session_send(cb_data, &packet); if (!(devc = sdi->priv)) { sr_err("%s: sdi->priv was NULL", __func__); return SR_ERR_BUG; } usb = sdi->conn; analyzer_reset(usb->devhdl); /* TODO: Need to cancel and free any queued up transfers. */ return SR_OK; }
static int handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, int idx) { struct sr_datafeed_packet packet; struct sr_datafeed_analog_old analog; struct dev_context *devc; struct center_info info; GSList *l; int i, ret; devc = sdi->priv; memset(&analog, 0, sizeof(struct sr_datafeed_analog_old)); memset(&info, 0, sizeof(struct center_info)); ret = packet_parse(buf, idx, &info); if (ret < 0) { sr_err("Failed to parse packet."); return SR_ERR; } /* Common values for all 4 channels. */ packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; analog.mq = SR_MQ_TEMPERATURE; analog.unit = (info.celsius) ? SR_UNIT_CELSIUS : SR_UNIT_FAHRENHEIT; analog.num_samples = 1; /* Send the values for T1 - T4. */ for (i = 0; i < NUM_CHANNELS; i++) { l = NULL; l = g_slist_append(l, g_slist_nth_data(sdi->channels, i)); analog.channels = l; analog.data = &(info.temp[i]); sr_session_send(sdi, &packet); g_slist_free(l); } devc->num_samples++; return SR_OK; }
static int send_samples(const struct sr_dev_inst *sdi, uint8_t *buffer, gsize buffer_size, gsize count) { int res; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; gsize i; packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.unitsize = buffer_size; logic.length = buffer_size; logic.data = buffer; for (i = 0; i < count; i++) { if ((res = sr_session_send(sdi, &packet)) != SR_OK) return res; } 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); }
/** * Standard API helper for sending an SR_DF_END packet. * * @param sdi The device instance to use. Must not be NULL. * * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or * SR_ERR upon other errors. */ SR_PRIV int std_session_send_df_end(const struct sr_dev_inst *sdi) { const char *prefix = (sdi->driver) ? sdi->driver->name : "unknown"; int ret; struct sr_datafeed_packet packet; if (!sdi) return SR_ERR_ARG; sr_dbg("%s: Sending SR_DF_END packet.", prefix); packet.type = SR_DF_END; packet.payload = NULL; if ((ret = sr_session_send(sdi, &packet)) < 0) { sr_err("%s: Failed to send SR_DF_END packet: %d.", prefix, ret); return ret; } return SR_OK; }
static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_datafeed_packet packet; (void)cb_data; devc = sdi->priv; sr_dbg("Stopping acquisition."); sr_session_source_remove_channel(devc->channel); g_io_channel_shutdown(devc->channel, FALSE, NULL); g_io_channel_unref(devc->channel); devc->channel = NULL; /* Send last packet. */ packet.type = SR_DF_END; sr_session_send(sdi, &packet); return SR_OK; }
/** * Standard sr_session_stop() API helper. * * This function can be used to simplify most (serial port based) driver's * dev_acquisition_stop() API callback. * * @param sdi The device instance for which acquisition should stop. * Must not be NULL. * @param cb_data Opaque 'cb_data' pointer. Must not be NULL. * @param dev_close_fn Function pointer to the driver's dev_close(). * Must not be NULL. * @param serial The serial device instance (struct serial_dev_inst *). * Must not be NULL. * @param[in] prefix A driver-specific prefix string used for log messages. * Must not be NULL. An empty string is allowed. * * @retval SR_OK Success. * @retval SR_ERR_ARG Invalid arguments. * @retval SR_ERR_DEV_CLOSED Device is closed. * @retval SR_ERR Other errors. */ SR_PRIV int std_serial_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data, dev_close_callback dev_close_fn, struct sr_serial_dev_inst *serial, const char *prefix) { int ret; struct sr_datafeed_packet packet; if (!prefix) { sr_err("Invalid prefix."); return SR_ERR_ARG; } if (sdi->status != SR_ST_ACTIVE) { sr_err("%s: Device inactive, can't stop acquisition.", prefix); return SR_ERR_DEV_CLOSED; } sr_dbg("%s: Stopping acquisition.", prefix); if ((ret = serial_source_remove(sdi->session, serial)) < 0) { sr_err("%s: Failed to remove source: %d.", prefix, ret); return ret; } if ((ret = dev_close_fn(sdi)) < 0) { sr_err("%s: Failed to close device: %d.", prefix, ret); return ret; } /* Send SR_DF_END packet to the session bus. */ sr_dbg("%s: Sending SR_DF_END packet.", prefix); packet.type = SR_DF_END; packet.payload = NULL; if ((ret = sr_session_send(cb_data, &packet)) < 0) { sr_err("%s: Failed to send SR_DF_END packet: %d.", prefix, ret); return ret; } return SR_OK; }
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); } }
/** * Standard API helper for sending an SR_DF_HEADER packet. * * This function can be used to simplify most driver's * dev_acquisition_start() API callback. * * @param sdi The device instance to use. * * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or * SR_ERR upon other errors. */ SR_PRIV int std_session_send_df_header(const struct sr_dev_inst *sdi) { const char *prefix = (sdi->driver) ? sdi->driver->name : "unknown"; int ret; struct sr_datafeed_packet packet; struct sr_datafeed_header header; sr_dbg("%s: Starting acquisition.", prefix); /* Send header packet to the session bus. */ sr_dbg("%s: Sending SR_DF_HEADER packet.", prefix); packet.type = SR_DF_HEADER; packet.payload = (uint8_t *)&header; header.feed_version = 1; gettimeofday(&header.starttime, NULL); if ((ret = sr_session_send(sdi, &packet)) < 0) { sr_err("%s: Failed to send header packet: %d.", prefix, ret); return ret; } return SR_OK; }
static void appa_55ii_live_data(struct sr_dev_inst *sdi, const uint8_t *buf) { struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; struct sr_channel *ch; float values[APPA_55II_NUM_CHANNELS], *val_ptr; int i; devc = sdi->priv; if (devc->data_source != DATA_SOURCE_LIVE) return; val_ptr = values; memset(&analog, 0, sizeof(analog)); analog.num_samples = 1; analog.mq = SR_MQ_TEMPERATURE; analog.unit = SR_UNIT_CELSIUS; analog.mqflags = appa_55ii_flags(buf); analog.data = values; for (i = 0; i < APPA_55II_NUM_CHANNELS; i++) { ch = g_slist_nth_data(sdi->channels, i); if (!ch->enabled) continue; analog.channels = g_slist_append(analog.channels, ch); *val_ptr++ = appa_55ii_temp(buf, i); } packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(devc->session_cb_data, &packet); g_slist_free(analog.channels); devc->num_samples++; }
static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_datafeed_packet packet; (void)cb_data; packet.type = SR_DF_END; packet.payload = NULL; sr_session_send(sdi, &packet); if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; devc = sdi->priv; devc->num_frames = 0; g_slist_free(devc->enabled_channels); devc->enabled_channels = NULL; sr_scpi_source_remove(sdi->session, sdi->conn); return SR_OK; }
/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */ static int hw_dev_acquisition_stop(int dev_index, void *cb_data) { struct sr_datafeed_packet packet; struct sr_dev_inst *sdi; struct context *ctx; packet.type = SR_DF_END; sr_session_send(cb_data, &packet); if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) { sr_err("zp: %s: sdi was NULL", __func__); return SR_ERR_BUG; } if (!(ctx = sdi->priv)) { sr_err("zp: %s: sdi->priv was NULL", __func__); return SR_ERR_BUG; } analyzer_reset(ctx->usb->devhdl); /* TODO: Need to cancel and free any queued up transfers. */ return SR_OK; }
static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct sr_datafeed_packet *packet; struct sr_datafeed_header *header; struct dev_context *devc; int ret = SR_ERR; devc = sdi->priv; if (sdi->status != SR_ST_ACTIVE) return SR_ERR; if (mso_configure_probes(sdi) != SR_OK) { sr_err("Failed to configure probes."); return SR_ERR; } /* FIXME: No need to do full reconfigure every time */ // 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); if (ret != SR_OK) return ret; /* set dac offset */ ret = mso_dac_out(sdi, devc->dac_offset); if (ret != SR_OK) return ret; ret = mso_configure_threshold_level(sdi); if (ret != SR_OK) return ret; ret = mso_configure_trigger(sdi); if (ret != SR_OK) return ret; /* END of config hardware part */ ret = mso_arm(sdi); if (ret != SR_OK) return ret; /* Start acquisition on the device. */ mso_check_trigger(devc->serial, &devc->trigger_state); ret = mso_check_trigger(devc->serial, NULL); if (ret != SR_OK) return ret; sr_source_add(devc->serial->fd, G_IO_IN, -1, mso_receive_data, cb_data); if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) { sr_err("Datafeed packet malloc failed."); return SR_ERR_MALLOC; } if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) { sr_err("Datafeed header malloc failed."); g_free(packet); return SR_ERR_MALLOC; } packet->type = SR_DF_HEADER; packet->payload = (unsigned char *)header; header->feed_version = 1; gettimeofday(&header->starttime, NULL); sr_session_send(cb_data, packet); g_free(header); g_free(packet); return SR_OK; }
static int receive_data(int fd, int revents, const struct sr_dev_inst *cb_sdi) { struct sr_dev_inst *sdi; struct session_vdev *vdev; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; struct sr_datafeed_dso dso; struct sr_datafeed_analog analog; GSList *l; int ret, got_data; (void)fd; (void)revents; sr_dbg("Feed chunk."); got_data = FALSE; for (l = dev_insts; l; l = l->next) { sdi = l->data; vdev = sdi->priv; if (!vdev) /* already done with this instance */ continue; ret = zip_fread(vdev->capfile, vdev->buf, CHUNKSIZE); if (ret > 0) { got_data = TRUE; if (sdi->mode == DSO) { packet.type = SR_DF_DSO; packet.payload = &dso; dso.num_samples = ret / vdev->unitsize; dso.data = vdev->buf; dso.probes = sdi->channels; dso.mq = SR_MQ_VOLTAGE; dso.unit = SR_UNIT_VOLT; dso.mqflags = SR_MQFLAG_AC; } else if (sdi->mode == ANALOG){ packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.probes = sdi->channels; analog.num_samples = ret / vdev->unitsize; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = SR_MQFLAG_AC; analog.data = vdev->buf; } else { packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = ret; logic.unitsize = vdev->unitsize; logic.data = vdev->buf; } vdev->bytes_read += ret; sr_session_send(cb_sdi, &packet); } else { /* done with this capture file */ zip_fclose(vdev->capfile); //g_free(vdev->capturefile); //g_free(vdev); //sdi->priv = NULL; } } if (!got_data) { packet.type = SR_DF_END; sr_session_send(cb_sdi, &packet); sr_session_source_remove(-1); } return TRUE; }
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_old analog; 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(cb_data, &packet); sdi->driver->dev_acquisition_stop(sdi, cb_data); 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(cb_data, &packet); sdi->driver->dev_acquisition_stop(sdi, cb_data); 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; analog.channels = g_slist_append(NULL, ch); analog.num_samples = len; analog.data = devc->data; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = 0; packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; sr_session_send(cb_data, &packet); g_slist_free(analog.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(cb_data, &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(cb_data, &packet); sdi->driver->dev_acquisition_stop(sdi, cb_data); 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(cb_data, &packet); if (++devc->num_frames == devc->limit_frames) { /* Last frame, stop capture. */ sdi->driver->dev_acquisition_stop(sdi, cb_data); } 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(cb_data, &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_old analog; 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); /* Convert data. */ for (i = 0; i < num_samples; i++) samples[i] = ((float) ((int16_t) (RB16(&devc->rcv_buffer[i*2])))) / 256. * VERTICAL_DIVISIONS * volts_per_division; /* Fill frame. */ analog.channels = g_slist_append(NULL, g_slist_nth_data(sdi->channels, devc->cur_acq_channel)); analog.num_samples = num_samples; analog.data = samples; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = 0; packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; sr_session_send(sdi, &packet); g_slist_free(analog.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; }
SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) { struct sr_channel *ch; struct sr_dev_inst *sdi; struct dev_context *devc; struct sr_datafeed_packet packet; GArray *data; struct sr_datafeed_analog analog; struct sr_datafeed_logic logic; (void)fd; data = NULL; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; if (revents != G_IO_IN) return TRUE; ch = devc->current_channel->data; switch (ch->type) { case SR_CHANNEL_ANALOG: if (sr_scpi_get_floatv(sdi->conn, NULL, &data) != SR_OK) { if (data) g_array_free(data, TRUE); return TRUE; } packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); analog.channels = g_slist_append(NULL, ch); analog.num_samples = data->len; analog.data = (float *) data->data; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = 0; packet.type = SR_DF_ANALOG; packet.payload = &analog; sr_session_send(cb_data, &packet); g_slist_free(analog.channels); g_array_free(data, TRUE); data = NULL; break; case SR_CHANNEL_LOGIC: if (sr_scpi_get_uint8v(sdi->conn, NULL, &data) != SR_OK) { g_free(data); return TRUE; } packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); logic.length = data->len; logic.unitsize = 1; logic.data = data->data; packet.type = SR_DF_LOGIC; packet.payload = &logic; sr_session_send(cb_data, &packet); g_array_free(data, TRUE); data = NULL; break; default: sr_err("Invalid channel type."); break; } packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); if (devc->current_channel->next) { devc->current_channel = devc->current_channel->next; hmo_request_data(sdi); } else if (++devc->num_frames == devc->frame_limit) { sdi->driver->dev_acquisition_stop(sdi, cb_data); } else { devc->current_channel = devc->enabled_channels; hmo_request_data(sdi); } return TRUE; }
static int handle_event(int fd, int revents, void *cb_data) { const struct sr_dev_inst *sdi; struct sr_datafeed_packet packet; struct timeval tv; struct dev_context *devc; struct drv_context *drvc = di->priv; int num_probes; uint32_t trigger_offset; uint8_t capturestate; (void)fd; (void)revents; sdi = cb_data; devc = sdi->priv; if (devc->dev_state == STOPPING) { /* We've been told to wind up the acquisition. */ sr_dbg("Stopping acquisition."); /* * TODO: Doesn't really cancel pending transfers so they might * come in after SR_DF_END is sent. */ usb_source_remove(drvc->sr_ctx); packet.type = SR_DF_END; sr_session_send(sdi, &packet); devc->dev_state = IDLE; return TRUE; } /* Always handle pending libusb events. */ tv.tv_sec = tv.tv_usec = 0; libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv); /* TODO: ugh */ if (devc->dev_state == NEW_CAPTURE) { if (dso_capture_start(sdi) != SR_OK) return TRUE; if (dso_enable_trigger(sdi) != SR_OK) return TRUE; // if (dso_force_trigger(sdi) != SR_OK) // return TRUE; sr_dbg("Successfully requested next chunk."); devc->dev_state = CAPTURE; return TRUE; } if (devc->dev_state != CAPTURE) return TRUE; if ((dso_get_capturestate(sdi, &capturestate, &trigger_offset)) != SR_OK) return TRUE; sr_dbg("Capturestate %d.", capturestate); sr_dbg("Trigger offset 0x%.6x.", trigger_offset); switch (capturestate) { case CAPTURE_EMPTY: if (++devc->capture_empty_count >= MAX_CAPTURE_EMPTY) { devc->capture_empty_count = 0; if (dso_capture_start(sdi) != SR_OK) break; if (dso_enable_trigger(sdi) != SR_OK) break; // if (dso_force_trigger(sdi) != SR_OK) // break; sr_dbg("Successfully requested next chunk."); } break; case CAPTURE_FILLING: /* No data yet. */ break; case CAPTURE_READY_8BIT: /* Remember where in the captured frame the trigger is. */ devc->trigger_offset = trigger_offset; num_probes = (devc->ch1_enabled && devc->ch2_enabled) ? 2 : 1; /* TODO: Check malloc return value. */ devc->framebuf = g_try_malloc(devc->framesize * num_probes * 2); devc->samp_buffered = devc->samp_received = 0; /* Tell the scope to send us the first frame. */ if (dso_get_channeldata(sdi, receive_transfer) != SR_OK) break; /* * Don't hit the state machine again until we're done fetching * the data we just told the scope to send. */ devc->dev_state = FETCH_DATA; /* Tell the frontend a new frame is on the way. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); break; case CAPTURE_READY_9BIT: /* TODO */ sr_err("Not yet supported."); break; case CAPTURE_TIMEOUT: /* Doesn't matter, we'll try again next time. */ break; default: sr_dbg("Unknown capture state: %d.", capturestate); break; } return TRUE; }
/* Callback handling data */ static int prepare_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; struct sr_channel_group *cg; struct analog_gen *ag; GSList *l; uint64_t logic_todo, analog_todo, expected_samplenum, analog_samples, sending_now; int64_t time, elapsed; (void)fd; (void)revents; sdi = cb_data; devc = sdi->priv; /* How many "virtual" samples should we have collected by now? */ time = g_get_monotonic_time(); elapsed = time - devc->starttime; expected_samplenum = elapsed * devc->cur_samplerate / 1000000; /* Of those, how many do we still have to send? */ logic_todo = MIN(expected_samplenum, devc->limit_samples) - devc->logic_counter; analog_todo = MIN(expected_samplenum, devc->limit_samples) - devc->analog_counter; while (logic_todo || analog_todo) { /* Logic */ if (devc->num_logic_channels > 0 && logic_todo > 0) { sending_now = MIN(logic_todo, LOGIC_BUFSIZE / devc->logic_unitsize); logic_generator(sdi, sending_now * devc->logic_unitsize); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = sending_now * devc->logic_unitsize; logic.unitsize = devc->logic_unitsize; logic.data = devc->logic_data; sr_session_send(sdi, &packet); logic_todo -= sending_now; devc->logic_counter += sending_now; } /* Analog, one channel at a time */ if (devc->num_analog_channels > 0 && analog_todo > 0) { sending_now = 0; for (l = devc->analog_channel_groups; l; l = l->next) { cg = l->data; ag = cg->priv; packet.type = SR_DF_ANALOG; packet.payload = &ag->packet; /* FIXME we should make sure we output a whole * period of data before we send out again the * beginning of our buffer. A ring buffer would * help here as well */ analog_samples = MIN(analog_todo, ag->num_samples); /* Whichever channel group gets there first. */ sending_now = MAX(sending_now, analog_samples); ag->packet.num_samples = analog_samples; sr_session_send(sdi, &packet); } analog_todo -= sending_now; devc->analog_counter += sending_now; } } if (devc->logic_counter >= devc->limit_samples && devc->analog_counter >= devc->limit_samples) { sr_dbg("Requested number of samples reached."); dev_acquisition_stop(sdi, cb_data); return TRUE; } return TRUE; }
SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data) { uint32_t cur_time, elapsed_time; uint64_t nrexpiration; struct sr_datafeed_packet packet, framep; struct sr_datafeed_analog analog; struct sr_dev_inst *sdi; struct sr_channel *ch; struct channel_priv *chp; struct dev_context *devc; GSList *chl, chonly; unsigned i; (void)fd; (void)revents; sdi = cb_data; if (!sdi) return TRUE; devc = sdi->priv; if (!devc) return TRUE; packet.type = SR_DF_ANALOG; packet.payload = &analog; memset(&analog, 0, sizeof(struct sr_datafeed_analog)); if (read(devc->timer_fd, &nrexpiration, sizeof(nrexpiration)) < 0) { sr_warn("Failed to read timer information"); return TRUE; } /* * We were not able to process the previous timer expiration, we are * overloaded. */ if (nrexpiration > 1) devc->samples_missed += nrexpiration - 1; /* * XXX This is a nasty workaround... * * At high sampling rates and maximum channels we are not able to * acquire samples fast enough, even though frontends still think * that samples arrive on time. This causes shifts in frontend * plots. * * To compensate for the delay we check if any clock events were * missed and - if so - don't really read the next value, but send * the same sample as fast as possible. We do it until we are back * on schedule. * * At high sampling rate this doesn't seem to visibly reduce the * accuracy. */ for (i = 0; i < nrexpiration; i++) { framep.type = SR_DF_FRAME_BEGIN; sr_session_send(cb_data, &framep); /* * Due to different units used in each channel we're sending * samples one-by-one. */ for (chl = sdi->channels; chl; chl = chl->next) { ch = chl->data; chp = ch->priv; if (!ch->enabled) continue; chonly.next = NULL; chonly.data = ch; analog.channels = &chonly; analog.num_samples = 1; analog.mq = channel_to_mq(chl->data); analog.unit = channel_to_unit(ch); if (i < 1) chp->val = read_sample(ch); analog.data = &chp->val; sr_session_send(cb_data, &packet); } framep.type = SR_DF_FRAME_END; sr_session_send(cb_data, &framep); } devc->samples_read++; if (devc->limit_samples > 0 && devc->samples_read >= devc->limit_samples) { sr_info("Requested number of samples reached."); sdi->driver->dev_acquisition_stop(sdi, cb_data); devc->last_sample_fin = g_get_monotonic_time(); return TRUE; } else if (devc->limit_msec > 0) { cur_time = g_get_monotonic_time(); elapsed_time = cur_time - devc->start_time; if (elapsed_time >= devc->limit_msec) { sr_info("Sampling time limit reached."); sdi->driver->dev_acquisition_stop(sdi, cb_data); devc->last_sample_fin = g_get_monotonic_time(); return TRUE; } } devc->last_sample_fin = g_get_monotonic_time(); return TRUE; }
/* * Called by libusb (as triggered by handle_event()) when a transfer comes in. * Only channel data comes in asynchronously, and all transfers for this are * queued up beforehand, so this just needs to chuck the incoming data onto * the libsigrok session bus. */ static void receive_transfer(struct libusb_transfer *transfer) { struct sr_datafeed_packet packet; struct sr_dev_inst *sdi; struct dev_context *devc; int num_samples, pre; sdi = transfer->user_data; devc = sdi->priv; sr_spew("receive_transfer(): status %d received %d bytes.", transfer->status, transfer->actual_length); if (transfer->actual_length == 0) /* Nothing to send to the bus. */ return; num_samples = transfer->actual_length / 2; sr_spew("Got %d-%d/%d samples in frame.", devc->samp_received + 1, devc->samp_received + num_samples, devc->framesize); /* * The device always sends a full frame, but the beginning of the frame * doesn't represent the trigger point. The offset at which the trigger * happened came in with the capture state, so we need to start sending * from there up the session bus. The samples in the frame buffer * before that trigger point came after the end of the device's frame * buffer was reached, and it wrapped around to overwrite up until the * trigger point. */ if (devc->samp_received < devc->trigger_offset) { /* Trigger point not yet reached. */ if (devc->samp_received + num_samples < devc->trigger_offset) { /* The entire chunk is before the trigger point. */ memcpy(devc->framebuf + devc->samp_buffered * 2, transfer->buffer, num_samples * 2); devc->samp_buffered += num_samples; } else { /* * This chunk hits or overruns the trigger point. * Store the part before the trigger fired, and * send the rest up to the session bus. */ pre = devc->trigger_offset - devc->samp_received; memcpy(devc->framebuf + devc->samp_buffered * 2, transfer->buffer, pre * 2); devc->samp_buffered += pre; /* The rest of this chunk starts with the trigger point. */ sr_dbg("Reached trigger point, %d samples buffered.", devc->samp_buffered); /* Avoid the corner case where the chunk ended at * exactly the trigger point. */ if (num_samples > pre) send_chunk(sdi, transfer->buffer + pre * 2, num_samples - pre); } } else { /* Already past the trigger point, just send it all out. */ send_chunk(sdi, transfer->buffer, num_samples); } devc->samp_received += num_samples; /* Everything in this transfer was either copied to the buffer or * sent to the session bus. */ g_free(transfer->buffer); libusb_free_transfer(transfer); if (devc->samp_received >= devc->framesize) { /* That was the last chunk in this frame. Send the buffered * pre-trigger samples out now, in one big chunk. */ sr_dbg("End of frame, sending %d pre-trigger buffered samples.", devc->samp_buffered); send_chunk(sdi, devc->framebuf, devc->samp_buffered); /* Mark the end of this frame. */ packet.type = SR_DF_FRAME_END; sr_session_send(devc->cb_data, &packet); if (devc->limit_frames && ++devc->num_frames == devc->limit_frames) { /* Terminate session */ devc->dev_state = STOPPING; } else { devc->dev_state = NEW_CAPTURE; } } }
SR_PRIV void send_block_to_session_bus(struct dev_context *devc, int block) { int i; uint8_t sample, expected_sample; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; int trigger_point; /* Relative trigger point (in this block). */ /* Note: No sanity checks on devc/block, caller is responsible. */ /* Check if we can find the trigger condition in this block. */ trigger_point = -1; expected_sample = devc->trigger_pattern & devc->trigger_mask; for (i = 0; i < BS; i++) { /* Don't continue if the trigger was found previously. */ if (devc->trigger_found) break; /* * Also, don't continue if triggers are "don't care", i.e. if * no trigger conditions were specified by the user. In that * case we don't want to send an SR_DF_TRIGGER packet at all. */ if (devc->trigger_mask == 0x00) break; sample = *(devc->final_buf + (block * BS) + i); if ((sample & devc->trigger_mask) == expected_sample) { trigger_point = i; devc->trigger_found = 1; break; } } /* If no trigger was found, send one SR_DF_LOGIC packet. */ if (trigger_point == -1) { /* Send an SR_DF_LOGIC packet to the session bus. */ sr_spew("Sending SR_DF_LOGIC packet (%d bytes) for " "block %d.", BS, block); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = BS; logic.unitsize = 1; logic.data = devc->final_buf + (block * BS); sr_session_send(devc->session_dev_id, &packet); return; } /* * We found the trigger, so some special handling is needed. We have * to send an SR_DF_LOGIC packet with the samples before the trigger * (if any), then the SD_DF_TRIGGER packet itself, then another * SR_DF_LOGIC packet with the samples after the trigger (if any). */ /* TODO: Send SR_DF_TRIGGER packet before or after the actual sample? */ /* If at least one sample is located before the trigger... */ if (trigger_point > 0) { /* Send pre-trigger SR_DF_LOGIC packet to the session bus. */ sr_spew("Sending pre-trigger SR_DF_LOGIC packet, " "start = %d, length = %d.", block * BS, trigger_point); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = trigger_point; logic.unitsize = 1; logic.data = devc->final_buf + (block * BS); sr_session_send(devc->session_dev_id, &packet); } /* Send the SR_DF_TRIGGER packet to the session bus. */ sr_spew("Sending SR_DF_TRIGGER packet, sample = %d.", (block * BS) + trigger_point); packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(devc->session_dev_id, &packet); /* If at least one sample is located after the trigger... */ if (trigger_point < (BS - 1)) { /* Send post-trigger SR_DF_LOGIC packet to the session bus. */ sr_spew("Sending post-trigger SR_DF_LOGIC packet, " "start = %d, length = %d.", (block * BS) + trigger_point, BS - trigger_point); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = BS - trigger_point; logic.unitsize = 1; logic.data = devc->final_buf + (block * BS) + trigger_point; sr_session_send(devc->session_dev_id, &packet); } }
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; }
static int receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct session_vdev *vdev; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; struct zip_stat zs; GSList *l; int ret, got_data; char capturefile[16]; void *buf; (void)fd; (void)revents; got_data = FALSE; for (l = dev_insts; l; l = l->next) { sdi = l->data; if (!(vdev = sdi->priv)) /* Already done with this instance. */ continue; if (!(buf = g_try_malloc(CHUNKSIZE))) { sr_err("%s: buf malloc failed", __func__); return FALSE; } if (!vdev->capfile) { /* No capture file opened yet, or finished with the last * chunked one. */ if (vdev->cur_chunk == 0) { /* capturefile is always the unchunked base name. */ if (zip_stat(vdev->archive, vdev->capturefile, 0, &zs) != -1) { /* No chunks, just a single capture file. */ vdev->cur_chunk = 0; if (!(vdev->capfile = zip_fopen(vdev->archive, vdev->capturefile, 0))) return FALSE; sr_dbg("Opened %s.", vdev->capturefile); } else { /* Try as first chunk filename. */ snprintf(capturefile, 15, "%s-1", vdev->capturefile); if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { vdev->cur_chunk = 1; if (!(vdev->capfile = zip_fopen(vdev->archive, capturefile, 0))) return FALSE; sr_dbg("Opened %s.", capturefile); } else { sr_err("No capture file '%s' in " "session file '%s'.", vdev->capturefile, vdev->sessionfile); return FALSE; } } } else { /* Capture data is chunked, advance to the next chunk. */ vdev->cur_chunk++; snprintf(capturefile, 15, "%s-%d", vdev->capturefile, vdev->cur_chunk); if (zip_stat(vdev->archive, capturefile, 0, &zs) != -1) { if (!(vdev->capfile = zip_fopen(vdev->archive, capturefile, 0))) return FALSE; sr_dbg("Opened %s.", capturefile); } else { /* We got all the chunks, finish up. */ g_free(vdev->capturefile); g_free(vdev); sdi->priv = NULL; continue; } } } ret = zip_fread(vdev->capfile, buf, CHUNKSIZE); if (ret > 0) { got_data = TRUE; packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = ret; logic.unitsize = vdev->unitsize; logic.data = buf; vdev->bytes_read += ret; sr_session_send(cb_data, &packet); } else { /* done with this capture file */ zip_fclose(vdev->capfile); vdev->capfile = NULL; if (vdev->cur_chunk == 0) { /* It was the only file. */ g_free(vdev->capturefile); g_free(vdev); sdi->priv = NULL; } else { /* There might be more chunks, so don't fall through * to the SR_DF_END here. */ return TRUE; } } } if (!got_data) { packet.type = SR_DF_END; sr_session_send(cb_data, &packet); sr_session_source_remove(-1); } return TRUE; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_channel *ch; struct sr_datafeed_packet packet; gboolean some_digital; GSList *l; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; scpi = sdi->conn; devc = sdi->priv; devc->num_frames = 0; some_digital = FALSE; for (l = sdi->channels; l; l = l->next) { ch = l->data; sr_dbg("handling channel %s", ch->name); if (ch->type == SR_CHANNEL_ANALOG) { if (ch->enabled) devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); if (ch->enabled != devc->analog_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->analog_channels[ch->index] = ch->enabled; } } else if (ch->type == SR_CHANNEL_LOGIC) { /* Only one list entry for DS1000D series. All channels are retrieved * together when this entry is processed. */ if (ch->enabled && ( devc->model->series->protocol > PROTOCOL_V2 || !some_digital)) devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); if (ch->enabled) { some_digital = TRUE; /* Turn on LA module if currently off. */ if (!devc->la_enabled) { if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:STAT ON" : ":LA:DISP ON") != SR_OK) return SR_ERR; devc->la_enabled = TRUE; } } if (ch->enabled != devc->digital_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:DIG%d:DISP %s" : ":DIG%d:TURN %s", ch->index, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->digital_channels[ch->index] = ch->enabled; } } } if (!devc->enabled_channels) return SR_ERR; /* Turn off LA module if on and no digital channels selected. */ if (devc->la_enabled && !some_digital) if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK) return SR_ERR; /* Set memory mode. */ if (devc->data_source == DATA_SOURCE_SEGMENTED) { sr_err("Data source 'Segmented' not yet supported"); return SR_ERR; } devc->analog_frame_size = analog_frame_size(sdi); devc->digital_frame_size = digital_frame_size(sdi); switch (devc->model->series->protocol) { case PROTOCOL_V2: if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK) return SR_ERR; break; case PROTOCOL_V3: /* Apparently for the DS2000 the memory * depth can only be set in Running state - * this matches the behaviour of the UI. */ if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d", devc->analog_frame_size) != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":STOP") != SR_OK) return SR_ERR; break; default: break; } if (devc->data_source == DATA_SOURCE_LIVE) if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi); std_session_send_df_header(sdi); devc->channel_entry = devc->enabled_channels; if (rigol_ds_capture_start(sdi) != SR_OK) return SR_ERR; /* Start of first frame. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; struct sr_usb_dev_inst *usb; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; unsigned int samples_read; int res; unsigned int packet_num, n; unsigned char *buf; unsigned int status; unsigned int stop_address; unsigned int now_address; unsigned int trigger_address; unsigned int trigger_offset; unsigned int triggerbar; unsigned int ramsize_trigger; unsigned int memory_size; unsigned int valid_samples; unsigned int discard; int trigger_now; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; if (!(devc = sdi->priv)) { sr_err("%s: sdi->priv was NULL", __func__); return SR_ERR_ARG; } if (configure_channels(sdi) != SR_OK) { sr_err("Failed to configure channels."); return SR_ERR; } usb = sdi->conn; set_triggerbar(devc); /* Push configured settings to device. */ analyzer_configure(usb->devhdl); analyzer_start(usb->devhdl); sr_info("Waiting for data."); analyzer_wait_data(usb->devhdl); status = analyzer_read_status(usb->devhdl); stop_address = analyzer_get_stop_address(usb->devhdl); now_address = analyzer_get_now_address(usb->devhdl); trigger_address = analyzer_get_trigger_address(usb->devhdl); triggerbar = analyzer_get_triggerbar_address(); ramsize_trigger = analyzer_get_ramsize_trigger_address(); n = get_memory_size(devc->memory_size); memory_size = n / 4; sr_info("Status = 0x%x.", status); sr_info("Stop address = 0x%x.", stop_address); sr_info("Now address = 0x%x.", now_address); sr_info("Trigger address = 0x%x.", trigger_address); sr_info("Triggerbar address = 0x%x.", triggerbar); sr_info("Ramsize trigger = 0x%x.", ramsize_trigger); sr_info("Memory size = 0x%x.", memory_size); /* Send header packet to the session bus. */ std_session_send_df_header(cb_data, LOG_PREFIX); /* Check for empty capture */ if ((status & STATUS_READY) && !stop_address) { packet.type = SR_DF_END; sr_session_send(cb_data, &packet); return SR_OK; } if (!(buf = g_try_malloc(PACKET_SIZE))) { sr_err("Packet buffer malloc failed."); return SR_ERR_MALLOC; } /* Check if the trigger is in the samples we are throwing away */ trigger_now = now_address == trigger_address || ((now_address + 1) % memory_size) == trigger_address; /* * STATUS_READY doesn't clear until now_address advances past * addr 0, but for our logic, clear it in that case */ if (!now_address) status &= ~STATUS_READY; analyzer_read_start(usb->devhdl); /* Calculate how much data to discard */ discard = 0; if (status & STATUS_READY) { /* * We haven't wrapped around, we need to throw away data from * our current position to the end of the buffer. * Additionally, the first two samples captured are always * bogus. */ discard += memory_size - now_address + 2; now_address = 2; } /* If we have more samples than we need, discard them */ valid_samples = (stop_address - now_address) % memory_size; if (valid_samples > ramsize_trigger + triggerbar) { discard += valid_samples - (ramsize_trigger + triggerbar); now_address += valid_samples - (ramsize_trigger + triggerbar); } sr_info("Need to discard %d samples.", discard); /* Calculate how far in the trigger is */ if (trigger_now) trigger_offset = 0; else trigger_offset = (trigger_address - now_address) % memory_size; /* Recalculate the number of samples available */ valid_samples = (stop_address - now_address) % memory_size; /* Send the incoming transfer to the session bus. */ samples_read = 0; for (packet_num = 0; packet_num < n / PACKET_SIZE; packet_num++) { unsigned int len; unsigned int buf_offset; res = analyzer_read_data(usb->devhdl, buf, PACKET_SIZE); sr_info("Tried to read %d bytes, actually read %d bytes.", PACKET_SIZE, res); if (discard >= PACKET_SIZE / 4) { discard -= PACKET_SIZE / 4; continue; } len = PACKET_SIZE - discard * 4; buf_offset = discard * 4; discard = 0; /* Check if we've read all the samples */ if (samples_read + len / 4 >= valid_samples) len = (valid_samples - samples_read) * 4; if (!len) break; if (samples_read < trigger_offset && samples_read + len / 4 > trigger_offset) { /* Send out samples remaining before trigger */ packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = (trigger_offset - samples_read) * 4; logic.unitsize = 4; logic.data = buf + buf_offset; sr_session_send(cb_data, &packet); len -= logic.length; samples_read += logic.length / 4; buf_offset += logic.length; } if (samples_read == trigger_offset) { /* Send out trigger */ packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(cb_data, &packet); } /* Send out data (or data after trigger) */ packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = len; logic.unitsize = 4; logic.data = buf + buf_offset; sr_session_send(cb_data, &packet); samples_read += len / 4; } analyzer_read_stop(usb->devhdl); g_free(buf); packet.type = SR_DF_END; sr_session_send(cb_data, &packet); return SR_OK; }
static int loadfile(struct sr_input *in, const char *filename) { int res; struct context *ctx; struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *cfg; GIOStatus status; gboolean read_new_line; gsize term_pos; char **columns; gsize num_columns; int max_columns; (void)filename; ctx = in->internal; /* Send header packet to the session bus. */ std_session_send_df_header(in->sdi, LOG_PREFIX); if (ctx->samplerate) { packet.type = SR_DF_META; packet.payload = &meta; cfg = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(ctx->samplerate)); meta.config = g_slist_append(NULL, cfg); sr_session_send(in->sdi, &packet); sr_config_free(cfg); } read_new_line = FALSE; /* Limit the number of columns to parse. */ if (ctx->multi_column_mode) max_columns = ctx->num_probes; else max_columns = 1; while (TRUE) { /* * Skip reading a new line for the first time if the last read * line was not a header because the sample data is not parsed * yet. */ if (read_new_line || ctx->header) { ctx->line_number++; status = g_io_channel_read_line_string(ctx->channel, ctx->buffer, &term_pos, NULL); if (status == G_IO_STATUS_EOF) break; if (status != G_IO_STATUS_NORMAL) { sr_err("Error while reading line %zu.", ctx->line_number); free_context(ctx); return SR_ERR; } /* Remove line termination character(s). */ g_string_truncate(ctx->buffer, term_pos); } read_new_line = TRUE; if (!ctx->buffer->len) { sr_spew("Blank line %zu skipped.", ctx->line_number); continue; } /* Remove trailing comment. */ strip_comment(ctx->buffer, ctx->comment); if (!ctx->buffer->len) { sr_spew("Comment-only line %zu skipped.", ctx->line_number); continue; } if (!(columns = parse_line(ctx, max_columns))) { sr_err("Error while parsing line %zu.", ctx->line_number); free_context(ctx); return SR_ERR; } num_columns = g_strv_length(columns); /* Ensure that the first column is not out of bounds. */ if (!num_columns) { sr_err("Column %zu in line %zu is out of bounds.", ctx->first_column, ctx->line_number); g_strfreev(columns); free_context(ctx); return SR_ERR; } /* * Ensure that the number of probes does not exceed the number * of columns in multi column mode. */ if (ctx->multi_column_mode && num_columns < ctx->num_probes) { sr_err("Not enough columns for desired number of probes in line %zu.", ctx->line_number); g_strfreev(columns); free_context(ctx); return SR_ERR; } if (ctx->multi_column_mode) res = parse_multi_columns(columns, ctx); else res = parse_single_column(columns[0], ctx); if (res != SR_OK) { g_strfreev(columns); free_context(ctx); return SR_ERR; } g_strfreev(columns); /* * TODO: Parse sample numbers / timestamps and use it for * decompression. */ /* Send sample data to the session bus. */ res = send_samples(in->sdi, ctx->sample_buffer, ctx->sample_buffer_size, 1); if (res != SR_OK) { sr_err("Sending samples failed."); free_context(ctx); return SR_ERR; } } /* Send end packet to the session bus. */ packet.type = SR_DF_END; sr_session_send(in->sdi, &packet); free_context(ctx); return SR_OK; }
static int process_buffer(struct sr_input *in) { struct context *inc; struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *src; int offset, chunk_samples, total_samples, processed, max_chunk_samples; int num_samples, i; char channelname[8]; inc = in->priv; if (!inc->started) { for (i = 0; i < inc->num_channels; i++) { snprintf(channelname, 8, "CH%d", i + 1); sr_channel_new(in->sdi, i, SR_CHANNEL_ANALOG, TRUE, channelname); } std_session_send_df_header(in->sdi, LOG_PREFIX); packet.type = SR_DF_META; packet.payload = &meta; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(inc->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); sr_config_free(src); inc->started = TRUE; } if (!inc->found_data) { /* Skip past size of 'fmt ' chunk. */ i = 20 + RL32(in->buf->str + 16); offset = find_data_chunk(in->buf, i); if (offset < 0) { if (in->buf->len > MAX_DATA_CHUNK_OFFSET) { sr_err("Couldn't find data chunk."); return SR_ERR; } } inc->found_data = TRUE; } else offset = 0; /* Round off up to the last channels * unitsize boundary. */ chunk_samples = (in->buf->len - offset) / inc->num_channels / inc->unitsize; max_chunk_samples = CHUNK_SIZE / inc->num_channels / inc->unitsize; processed = 0; total_samples = chunk_samples; while (processed < total_samples) { if (chunk_samples > max_chunk_samples) num_samples = max_chunk_samples; else num_samples = chunk_samples; send_chunk(in, offset, num_samples); offset += num_samples * inc->unitsize; chunk_samples -= num_samples; processed += num_samples; } if ((unsigned int)offset < in->buf->len) { /* * The incoming buffer wasn't processed completely. Stash * the leftover data for next time. */ g_string_erase(in->buf, 0, offset); } else g_string_truncate(in->buf, 0); return SR_OK; }
SR_PRIV void cv_send_block_to_session_bus(struct dev_context *devc, int block) { int i, idx; uint8_t sample, expected_sample, tmp8; struct sr_datafeed_packet packet; struct sr_datafeed_logic logic; int trigger_point; /* Relative trigger point (in this block). */ /* Note: Caller ensures devc/devc->ftdic != NULL and block > 0. */ /* TODO: Implement/test proper trigger support for the LA16. */ /* Check if we can find the trigger condition in this block. */ trigger_point = -1; expected_sample = devc->trigger_pattern & devc->trigger_mask; for (i = 0; i < BS; i++) { /* Don't continue if the trigger was found previously. */ if (devc->trigger_found) break; /* * Also, don't continue if triggers are "don't care", i.e. if * no trigger conditions were specified by the user. In that * case we don't want to send an SR_DF_TRIGGER packet at all. */ if (devc->trigger_mask == 0x0000) break; sample = *(devc->final_buf + (block * BS) + i); if ((sample & devc->trigger_mask) == expected_sample) { trigger_point = i; devc->trigger_found = 1; break; } } /* Swap low and high bytes of the 16-bit LA16 samples. */ if (devc->prof->model == CHRONOVU_LA16) { for (i = 0; i < BS; i += 2) { idx = (block * BS) + i; tmp8 = devc->final_buf[idx]; devc->final_buf[idx] = devc->final_buf[idx + 1]; devc->final_buf[idx + 1] = tmp8; } } /* If no trigger was found, send one SR_DF_LOGIC packet. */ if (trigger_point == -1) { /* Send an SR_DF_LOGIC packet to the session bus. */ sr_spew("Sending SR_DF_LOGIC packet (%d bytes) for " "block %d.", BS, block); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = BS; logic.unitsize = devc->prof->num_channels / 8; logic.data = devc->final_buf + (block * BS); sr_session_send(devc->cb_data, &packet); return; } /* * We found the trigger, so some special handling is needed. We have * to send an SR_DF_LOGIC packet with the samples before the trigger * (if any), then the SD_DF_TRIGGER packet itself, then another * SR_DF_LOGIC packet with the samples after the trigger (if any). */ /* TODO: Send SR_DF_TRIGGER packet before or after the actual sample? */ /* If at least one sample is located before the trigger... */ if (trigger_point > 0) { /* Send pre-trigger SR_DF_LOGIC packet to the session bus. */ sr_spew("Sending pre-trigger SR_DF_LOGIC packet, " "start = %d, length = %d.", block * BS, trigger_point); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = trigger_point; logic.unitsize = devc->prof->num_channels / 8; logic.data = devc->final_buf + (block * BS); sr_session_send(devc->cb_data, &packet); } /* Send the SR_DF_TRIGGER packet to the session bus. */ sr_spew("Sending SR_DF_TRIGGER packet, sample = %d.", (block * BS) + trigger_point); packet.type = SR_DF_TRIGGER; packet.payload = NULL; sr_session_send(devc->cb_data, &packet); /* If at least one sample is located after the trigger... */ if (trigger_point < (BS - 1)) { /* Send post-trigger SR_DF_LOGIC packet to the session bus. */ sr_spew("Sending post-trigger SR_DF_LOGIC packet, " "start = %d, length = %d.", (block * BS) + trigger_point, BS - trigger_point); packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.length = BS - trigger_point; logic.unitsize = devc->prof->num_channels / 8; logic.data = devc->final_buf + (block * BS) + trigger_point; sr_session_send(devc->cb_data, &packet); } }