asix-sigma: Rework decode_chunk_ts()
This function could have never returned correct data. Rework the decoding logic according to the Sigma documentation. This patch also fixes the handling of partial DRAM lines and partial DRAM clusters. While at it, do not allocate megabytes of data on stack, just allocate 2KiB which is plenty for all the work this function needs to do. Signed-off-by: Marek Vasut <marex@denx.de>
This commit is contained in:
parent
46641facd4
commit
5fc01191eb
|
@ -829,7 +829,7 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
|
||||||
{
|
{
|
||||||
struct dev_context *devc;
|
struct dev_context *devc;
|
||||||
uint64_t num_samples;
|
uint64_t num_samples;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
(void)cg;
|
(void)cg;
|
||||||
|
|
||||||
|
@ -899,27 +899,29 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Software trigger to determine exact trigger position. */
|
/* Software trigger to determine exact trigger position. */
|
||||||
static int get_trigger_offset(uint16_t *samples, uint16_t last_sample,
|
static int get_trigger_offset(uint8_t *samples, uint16_t last_sample,
|
||||||
struct sigma_trigger *t)
|
struct sigma_trigger *t)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
uint16_t sample = 0;
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) {
|
for (i = 0; i < 8; ++i) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
last_sample = samples[i-1];
|
last_sample = sample;
|
||||||
|
sample = samples[2 * i] | (samples[2 * i + 1] << 8);
|
||||||
|
|
||||||
/* Simple triggers. */
|
/* Simple triggers. */
|
||||||
if ((samples[i] & t->simplemask) != t->simplevalue)
|
if ((sample & t->simplemask) != t->simplevalue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Rising edge. */
|
/* Rising edge. */
|
||||||
if ((last_sample & t->risingmask) != 0 || (samples[i] &
|
if (((last_sample & t->risingmask) != 0) ||
|
||||||
t->risingmask) != t->risingmask)
|
((sample & t->risingmask) != t->risingmask))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Falling edge. */
|
/* Falling edge. */
|
||||||
if ((last_sample & t->fallingmask) != t->fallingmask ||
|
if ((last_sample & t->fallingmask) != t->fallingmask ||
|
||||||
(samples[i] & t->fallingmask) != 0)
|
(sample & t->fallingmask) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -951,20 +953,18 @@ static int decode_chunk_ts(struct sigma_dram_line *dram_line, uint16_t *lastts,
|
||||||
uint16_t *lastsample, int triggerpos,
|
uint16_t *lastsample, int triggerpos,
|
||||||
uint16_t events_in_line, void *cb_data)
|
uint16_t events_in_line, void *cb_data)
|
||||||
{
|
{
|
||||||
uint8_t *buf = (uint8_t *)dram_line;
|
|
||||||
struct sigma_dram_cluster *dram_cluster;
|
struct sigma_dram_cluster *dram_cluster;
|
||||||
struct sr_dev_inst *sdi = cb_data;
|
struct sr_dev_inst *sdi = cb_data;
|
||||||
struct dev_context *devc = sdi->priv;
|
struct dev_context *devc = sdi->priv;
|
||||||
uint16_t tsdiff, ts;
|
uint16_t tsdiff, ts;
|
||||||
uint16_t samples[65536 * devc->samples_per_event];
|
uint8_t samples[2048];
|
||||||
struct sr_datafeed_packet packet;
|
struct sr_datafeed_packet packet;
|
||||||
struct sr_datafeed_logic logic;
|
struct sr_datafeed_logic logic;
|
||||||
int i, j, k, l, numpad, tosend;
|
unsigned int i, j;
|
||||||
size_t n = 0, sent = 0;
|
|
||||||
int clustersize = EVENTS_PER_CLUSTER * devc->samples_per_event;
|
|
||||||
uint16_t *event;
|
|
||||||
uint16_t cur_sample;
|
|
||||||
int triggerts = -1;
|
int triggerts = -1;
|
||||||
|
unsigned int clusters_in_line =
|
||||||
|
(events_in_line + (EVENTS_PER_CLUSTER - 1)) / EVENTS_PER_CLUSTER;
|
||||||
|
unsigned int events_in_cluster;
|
||||||
|
|
||||||
/* Check if trigger is in this chunk. */
|
/* Check if trigger is in this chunk. */
|
||||||
if (triggerpos != -1) {
|
if (triggerpos != -1) {
|
||||||
|
@ -975,81 +975,83 @@ static int decode_chunk_ts(struct sigma_dram_line *dram_line, uint16_t *lastts,
|
||||||
triggerpos = 0;
|
triggerpos = 0;
|
||||||
|
|
||||||
/* Find in which cluster the trigger occured. */
|
/* Find in which cluster the trigger occured. */
|
||||||
triggerts = triggerpos / 7;
|
triggerts = triggerpos / EVENTS_PER_CLUSTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For each ts. */
|
packet.type = SR_DF_LOGIC;
|
||||||
for (i = 0; i < (events_in_line / 7); i++) {
|
packet.payload = &logic;
|
||||||
|
logic.unitsize = 2;
|
||||||
|
logic.data = samples;
|
||||||
|
|
||||||
|
/* For each full DRAM cluster. */
|
||||||
|
for (i = 0; i < clusters_in_line; i++) {
|
||||||
dram_cluster = &dram_line->cluster[i];
|
dram_cluster = &dram_line->cluster[i];
|
||||||
|
|
||||||
ts = sigma_dram_cluster_ts(dram_cluster);
|
ts = sigma_dram_cluster_ts(dram_cluster);
|
||||||
tsdiff = ts - *lastts;
|
tsdiff = ts - *lastts;
|
||||||
*lastts = ts;
|
*lastts = ts;
|
||||||
|
|
||||||
/* Pad last sample up to current point. */
|
logic.data = samples;
|
||||||
numpad = tsdiff * devc->samples_per_event - clustersize;
|
|
||||||
if (numpad > 0) {
|
|
||||||
for (j = 0; j < numpad; ++j)
|
|
||||||
samples[j] = *lastsample;
|
|
||||||
|
|
||||||
n = numpad;
|
/*
|
||||||
}
|
* First of all, send Sigrok a copy of the last sample from
|
||||||
|
* previous cluster as many times as needed to make up for
|
||||||
|
* the differential characteristics of data we get from the
|
||||||
|
* Sigma. Sigrok needs one sample of data per period.
|
||||||
|
*
|
||||||
|
* One DRAM cluster contains a timestamp and seven samples,
|
||||||
|
* the units of timestamp are "devc->period_ps" , the first
|
||||||
|
* sample in the cluster happens at the time of the timestamp
|
||||||
|
* and the remaining samples happen at timestamp +1...+6 .
|
||||||
|
*/
|
||||||
|
for (ts = 0; ts < tsdiff - (EVENTS_PER_CLUSTER - 1); ts++) {
|
||||||
|
j = ts % 1024;
|
||||||
|
samples[2 * j + 0] = *lastsample & 0xff;
|
||||||
|
samples[2 * j + 1] = *lastsample >> 8;
|
||||||
|
|
||||||
/* Send samples between previous and this timestamp to sigrok. */
|
/*
|
||||||
sent = 0;
|
* If we have 1024 samples ready or we're at the
|
||||||
while (sent < n) {
|
* end of submitting the padding samples, submit
|
||||||
tosend = MIN(2048, n - sent);
|
* the packet to Sigrok.
|
||||||
|
*/
|
||||||
packet.type = SR_DF_LOGIC;
|
if ((j == 1023) || (ts == (tsdiff - EVENTS_PER_CLUSTER))) {
|
||||||
packet.payload = &logic;
|
logic.length = (j + 1) * logic.unitsize;
|
||||||
logic.length = tosend * sizeof(uint16_t);
|
|
||||||
logic.unitsize = 2;
|
|
||||||
logic.data = samples + sent;
|
|
||||||
sr_session_send(devc->cb_data, &packet);
|
sr_session_send(devc->cb_data, &packet);
|
||||||
|
|
||||||
sent += tosend;
|
|
||||||
}
|
}
|
||||||
n = 0;
|
|
||||||
|
|
||||||
event = (uint16_t *) &buf[i * 16 + 2];
|
|
||||||
cur_sample = 0;
|
|
||||||
|
|
||||||
/* For each event in cluster. */
|
|
||||||
for (j = 0; j < 7; ++j) {
|
|
||||||
|
|
||||||
/* For each sample in event. */
|
|
||||||
for (k = 0; k < devc->samples_per_event; ++k) {
|
|
||||||
cur_sample = 0;
|
|
||||||
|
|
||||||
/* For each channel. */
|
|
||||||
for (l = 0; l < devc->num_channels; ++l)
|
|
||||||
cur_sample |= (!!(event[j] & (1 << (l *
|
|
||||||
devc->samples_per_event + k)))) << l;
|
|
||||||
|
|
||||||
samples[n++] = cur_sample;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The last cluster might not be full. */
|
||||||
|
if ((i == clusters_in_line - 1) && (events_in_line % EVENTS_PER_CLUSTER))
|
||||||
|
events_in_cluster = events_in_line % EVENTS_PER_CLUSTER;
|
||||||
|
else
|
||||||
|
events_in_cluster = EVENTS_PER_CLUSTER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the samples in current cluster and prepare them
|
||||||
|
* to be submitted to Sigrok.
|
||||||
|
*/
|
||||||
|
for (j = 0; j < events_in_cluster; j++) {
|
||||||
|
samples[2 * j + 1] = dram_cluster->samples[j].sample_lo;
|
||||||
|
samples[2 * j + 0] = dram_cluster->samples[j].sample_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send data up to trigger point (if triggered). */
|
/* Send data up to trigger point (if triggered). */
|
||||||
sent = 0;
|
int trigger_offset = 0;
|
||||||
if (i == triggerts) {
|
if ((int)i == triggerts) {
|
||||||
/*
|
/*
|
||||||
* Trigger is not always accurate to sample because of
|
* Trigger is not always accurate to sample because of
|
||||||
* pipeline delay. However, it always triggers before
|
* pipeline delay. However, it always triggers before
|
||||||
* the actual event. We therefore look at the next
|
* the actual event. We therefore look at the next
|
||||||
* samples to pinpoint the exact position of the trigger.
|
* samples to pinpoint the exact position of the trigger.
|
||||||
*/
|
*/
|
||||||
tosend = get_trigger_offset(samples, *lastsample,
|
trigger_offset = get_trigger_offset(samples,
|
||||||
&devc->trigger);
|
*lastsample, &devc->trigger);
|
||||||
|
|
||||||
if (tosend > 0) {
|
if (trigger_offset > 0) {
|
||||||
packet.type = SR_DF_LOGIC;
|
packet.type = SR_DF_LOGIC;
|
||||||
packet.payload = &logic;
|
logic.length = trigger_offset * logic.unitsize;
|
||||||
logic.length = tosend * sizeof(uint16_t);
|
|
||||||
logic.unitsize = 2;
|
|
||||||
logic.data = samples;
|
|
||||||
sr_session_send(devc->cb_data, &packet);
|
sr_session_send(devc->cb_data, &packet);
|
||||||
|
events_in_cluster -= trigger_offset;
|
||||||
sent += tosend;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only send trigger if explicitly enabled. */
|
/* Only send trigger if explicitly enabled. */
|
||||||
|
@ -1059,19 +1061,16 @@ static int decode_chunk_ts(struct sigma_dram_line *dram_line, uint16_t *lastts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send rest of the chunk to sigrok. */
|
if (events_in_cluster > 0) {
|
||||||
tosend = n - sent;
|
|
||||||
|
|
||||||
if (tosend > 0) {
|
|
||||||
packet.type = SR_DF_LOGIC;
|
packet.type = SR_DF_LOGIC;
|
||||||
packet.payload = &logic;
|
logic.length = events_in_cluster * logic.unitsize;
|
||||||
logic.length = tosend * sizeof(uint16_t);
|
logic.data = samples +
|
||||||
logic.unitsize = 2;
|
(trigger_offset * logic.unitsize);
|
||||||
logic.data = samples + sent;
|
|
||||||
sr_session_send(devc->cb_data, &packet);
|
sr_session_send(devc->cb_data, &packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
*lastsample = samples[n - 1];
|
*lastsample = samples[2 * (events_in_cluster - 1)] |
|
||||||
|
(samples[2 * (events_in_cluster - 1) + 1] << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
|
|
|
@ -199,6 +199,7 @@ struct dev_context {
|
||||||
struct timeval start_tv;
|
struct timeval start_tv;
|
||||||
int cur_firmware;
|
int cur_firmware;
|
||||||
int num_channels;
|
int num_channels;
|
||||||
|
int cur_channels;
|
||||||
int samples_per_event;
|
int samples_per_event;
|
||||||
int capture_ratio;
|
int capture_ratio;
|
||||||
struct sigma_trigger trigger;
|
struct sigma_trigger trigger;
|
||||||
|
|
Loading…
Reference in New Issue