From: Gerhard Sittig Date: Tue, 20 Jun 2017 19:04:37 +0000 (+0200) Subject: demo: Mask out logic data for disabled channels in datafeed packets X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=4a465510fb2a427089f3460da599a4dda6e4a146;p=libsigrok.git 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. --- diff --git a/src/hardware/demo/api.c b/src/hardware/demo/api.c index 92b59fe3..f1a97eb4 100644 --- a/src/hardware/demo/api.c +++ b/src/hardware/demo/api.c @@ -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); diff --git a/src/hardware/demo/protocol.c b/src/hardware/demo/protocol.c index 1c1ec607..47000302 100644 --- a/src/hardware/demo/protocol.c +++ b/src/hardware/demo/protocol.c @@ -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; } diff --git a/src/hardware/demo/protocol.h b/src/hardware/demo/protocol.h index 79e5d886..7930624d 100644 --- a/src/hardware/demo/protocol.h +++ b/src/hardware/demo/protocol.h @@ -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. */