Example #1
0
/* 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;
}
Example #2
0
/* 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 analog_gen *ag;
	GHashTableIter iter;
	void *value;
	uint64_t samples_todo, logic_done, analog_done, analog_sent, sending_now;
	int64_t elapsed_us, limit_us, todo_us;

	(void)fd;
	(void)revents;

	sdi = cb_data;
	devc = sdi->priv;

	/* Just in case. */
	if (devc->cur_samplerate <= 0
			|| (devc->num_logic_channels <= 0
			&& devc->num_analog_channels <= 0)) {
		dev_acquisition_stop(sdi);
		return G_SOURCE_CONTINUE;
	}

	/* What time span should we send samples for? */
	elapsed_us = g_get_monotonic_time() - devc->start_us;
	limit_us = 1000 * devc->limit_msec;
	if (limit_us > 0 && limit_us < elapsed_us)
		todo_us = MAX(0, limit_us - devc->spent_us);
	else
		todo_us = MAX(0, elapsed_us - devc->spent_us);

	/* How many samples are outstanding since the last round? */
	samples_todo = (todo_us * devc->cur_samplerate + G_USEC_PER_SEC - 1)
			/ G_USEC_PER_SEC;
	if (devc->limit_samples > 0) {
		if (devc->limit_samples < devc->sent_samples)
			samples_todo = 0;
		else if (devc->limit_samples - devc->sent_samples < samples_todo)
			samples_todo = devc->limit_samples - devc->sent_samples;
	}
	/* Calculate the actual time covered by this run back from the sample
	 * count, rounded towards zero. This avoids getting stuck on a too-low
	 * time delta with no samples being sent due to round-off.
	 */
	todo_us = samples_todo * G_USEC_PER_SEC / devc->cur_samplerate;

	logic_done  = devc->num_logic_channels  > 0 ? 0 : samples_todo;
	analog_done = devc->num_analog_channels > 0 ? 0 : samples_todo;

	while (logic_done < samples_todo || analog_done < samples_todo) {
		/* Logic */
		if (logic_done < samples_todo) {
			sending_now = MIN(samples_todo - logic_done,
					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_done += sending_now;
		}

		/* Analog, one channel at a time */
		if (analog_done < samples_todo) {
			analog_sent = 0;

			g_hash_table_iter_init(&iter, devc->ch_ag);
			while (g_hash_table_iter_next(&iter, NULL, &value)) {
				send_analog_packet(value, sdi, &analog_sent,
						devc->sent_samples + analog_done,
						samples_todo - analog_done);
			}
			analog_done += analog_sent;
		}
	}
	/* At this point, both logic_done and analog_done should be
	 * exactly equal to samples_todo, or else.
	 */
	if (logic_done != samples_todo || analog_done != samples_todo) {
		sr_err("BUG: Sample count mismatch.");
		return G_SOURCE_REMOVE;
	}
	devc->sent_samples += samples_todo;
	devc->spent_us += todo_us;

	if ((devc->limit_samples > 0 && devc->sent_samples >= devc->limit_samples)
			|| (limit_us > 0 && devc->spent_us >= limit_us)) {

		/* If we're averaging everything - now is the time to send data */
		if (devc->avg_samples == 0) {
			g_hash_table_iter_init(&iter, devc->ch_ag);
			while (g_hash_table_iter_next(&iter, NULL, &value)) {
				ag = value;
				packet.type = SR_DF_ANALOG;
				packet.payload = &ag->packet;
				ag->packet.data = &ag->avg_val;
				ag->packet.num_samples = 1;
				sr_session_send(sdi, &packet);
			}
		}
		sr_dbg("Requested number of samples reached.");
		dev_acquisition_stop(sdi);
	}

	return G_SOURCE_CONTINUE;
}