demo: Mask out logic data for disabled channels in datafeed packets

The previous implementation used to provide datafeed packets which
contain logic data in positions that correspond to disabled channels.

Do mask out logic data of disabled channels in the memory image before
it is sent to the session's datafeed. This implementation works fine for
those situations where either all logic channels are enabled (default
configuration) or when only the upper channels get disabled (which can
be considered a typical use case).

For those configurations where enabled channels follow disabled channels
(i.e. setups with gaps in the sequence of enabled channels) behaviour
will be unexpected: Neither is the mask adjusted to contain gaps, nor
will enabled channels get mapped to result in a dense representation.
The respective code paths are marked with TODO comments.

Add a comment to discuss a non-obvious generator call for analog data in
the acquisition start routine, while we are here.
This commit is contained in:
Gerhard Sittig 2017-06-20 21:04:37 +02:00 committed by Uwe Hermann
parent 1b7b72d49e
commit 4a465510fb
3 changed files with 63 additions and 3 deletions

View File

@ -459,6 +459,8 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
struct dev_context *devc;
GSList *l;
struct sr_channel *ch;
int bitpos;
uint8_t mask;
GHashTableIter iter;
void *value;
@ -468,6 +470,11 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
devc = sdi->priv;
devc->sent_samples = 0;
/*
* Determine the numbers of logic and analog channels that are
* involved in the acquisition. Determine an offset and a mask to
* remove excess logic data content before datafeed submission.
*/
devc->enabled_logic_channels = 0;
devc->enabled_analog_channels = 0;
for (l = sdi->channels; l; l = l->next) {
@ -478,12 +485,34 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
devc->enabled_analog_channels++;
continue;
}
if (ch->type == SR_CHANNEL_LOGIC) {
devc->enabled_logic_channels++;
if (ch->type != SR_CHANNEL_LOGIC)
continue;
}
/*
* TODO: Need we create a channel map here, such that the
* session datafeed packets will have a dense representation
* of the enabled channels' data? For example store channels
* D3 and D5 in bit positions 0 and 1 respectively, when all
* other channels are disabled? The current implementation
* generates a sparse layout, might provide data for logic
* channels that are disabled while it might suppress data
* from enabled channels at the same time.
*/
devc->enabled_logic_channels++;
}
devc->first_partial_logic_index = devc->enabled_logic_channels / 8;
bitpos = devc->enabled_logic_channels % 8;
mask = (1 << bitpos) - 1;
devc->first_partial_logic_mask = mask;
sr_dbg("DBG: %s(), num logic %zu, partial off %zu, mask 0x%02x",
__func__, devc->enabled_logic_channels,
devc->first_partial_logic_index,
devc->first_partial_logic_mask);
/*
* Have the waveform for analog patterns pre-generated. It's
* supposed to be periodic, so the generator just needs to
* access the prepared sample data (DDS style).
*/
g_hash_table_iter_init(&iter, devc->ch_ag);
while (g_hash_table_iter_next(&iter, NULL, &value))
demo_generate_analog_pattern(value, devc->cur_samplerate);

View File

@ -333,6 +333,34 @@ static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
}
}
/*
* Fixup a memory image of generated logic data before it gets sent to
* the session's datafeed. Mask out content from disabled channels.
*
* TODO: Need we apply a channel map, and enforce a dense representation
* of the enabled channels' data?
*/
static void logic_fixup_feed(struct dev_context *devc,
struct sr_datafeed_logic *logic)
{
size_t fp_off;
uint8_t fp_mask;
size_t off, idx;
uint8_t *sample;
fp_off = devc->first_partial_logic_index;
fp_mask = devc->first_partial_logic_mask;
if (fp_off == logic->unitsize)
return;
for (off = 0; off < logic->length; off += logic->unitsize) {
sample = logic->data + off;
sample[fp_off] &= fp_mask;
for (idx = fp_off + 1; idx < logic->unitsize; idx++)
sample[idx] = 0x00;
}
}
static void send_analog_packet(struct analog_gen *ag,
struct sr_dev_inst *sdi, uint64_t *analog_sent,
uint64_t analog_pos, uint64_t analog_todo)
@ -465,6 +493,7 @@ SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data)
logic.length = sending_now * devc->logic_unitsize;
logic.unitsize = devc->logic_unitsize;
logic.data = devc->logic_data;
logic_fixup_feed(devc, &logic);
sr_session_send(sdi, &packet);
logic_done += sending_now;
}

View File

@ -56,6 +56,8 @@ struct dev_context {
uint64_t avg_samples;
size_t enabled_logic_channels;
size_t enabled_analog_channels;
size_t first_partial_logic_index;
uint8_t first_partial_logic_mask;
};
/* Logic patterns we can generate. */