Skip to content

Commit 70c9a25

Browse files
committed
greatfet: support capture of the upper pin bank (first pin 8)
Present all 16 channels to users. By default lower channels are enabled and upper channels are disabled. Support the configuration where users capture upper channels after disabling lower channels. Device firmware provides the "first pin" feature and only communicates pin states for the upper bank to the host. This mode of operation can be useful to inspect different signal sets without physically moving probes. Upper bank capture combines well with higher rates at lower pin counts. This implementation in theory also covers 16 channel captures, though the firmware does not officially support multi-bank captures. Emit a warning when this setup gets detected, but don't refuse operation and attempt a best effort capture. This commit also improves reliability in paths where failed acquisition starts shutdown the operation, before another request gets serviced.
1 parent 2c3fadf commit 70c9a25

File tree

3 files changed

+103
-22
lines changed

3 files changed

+103
-22
lines changed

src/hardware/greatfet/api.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
#define DEFAULT_SAMPLERATE SR_KHZ(34000)
3636
#define BANDWIDTH_THRESHOLD (SR_MHZ(42) * 8)
3737

38-
#define WITH_16CHAN_SUPPORT 0
39-
4038
static const uint32_t scanopts[] = {
4139
SR_CONF_CONN,
4240
SR_CONF_PROBE_NAMES,
@@ -61,10 +59,8 @@ static const uint32_t devopts_cg[] = {
6159
static const char *channel_names[] = {
6260
"SGPIO0", "SGPIO1", "SGPIO2", "SGPIO3",
6361
"SGPIO4", "SGPIO5", "SGPIO6", "SGPIO7",
64-
#if WITH_16CHAN_SUPPORT
6562
"SGPIO8", "SGPIO9", "SGPIO10", "SGPIO11",
6663
"SGPIO12", "SGPIO13", "SGPIO14", "SGPIO15",
67-
#endif
6864
};
6965

7066
/*

src/hardware/greatfet/protocol.c

Lines changed: 102 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@
121121

122122
#define GREATFET_CLASS_LA 0x10d
123123
#define LA_VERB_CONFIGURE 0x0
124+
#define LA_VERB_FIRST_PIN 0x1
125+
#define LA_VERB_ALT_PIN_MAP 0x2
124126
#define LA_VERB_START_CAPTURE 0x3
125127
#define LA_VERB_STOP_CAPTURE 0x4
126128

@@ -488,6 +490,42 @@ static int greatfet_logic_config(const struct sr_dev_inst *sdi)
488490
if (ret != SR_OK)
489491
return ret;
490492

493+
/*
494+
* Optionally request to capture the upper pin bank. The device
495+
* can sample from pins starting at number 8. We use the feature
496+
* transparently when the first 8 channels are disabled.
497+
*
498+
* Values different from 0 or 8 are not used here. The details
499+
* of the SGPIO hardware implementation degrade performance in
500+
* this case. Its use is not desirable for users.
501+
*/
502+
sr_dbg("about to config first pin, upper %d", acq->use_upper_pins);
503+
wrptr = req;
504+
write_u32le_inc(&wrptr, GREATFET_CLASS_LA);
505+
write_u32le_inc(&wrptr, LA_VERB_FIRST_PIN);
506+
write_u8_inc(&wrptr, acq->use_upper_pins ? 8 : 0);
507+
wrlen = wrptr - req;
508+
ret = greatfet_ctrl_out_in(sdi, req, wrlen,
509+
NULL, 0, LOGIC_DEFAULT_TIMEOUT);
510+
if (ret < 0) {
511+
sr_err("Cannot configure first capture pin.");
512+
return ret;
513+
}
514+
515+
/* Disable alt pin mapping, just for good measure. */
516+
sr_dbg("about to config alt pin mapping");
517+
wrptr = req;
518+
write_u32le_inc(&wrptr, GREATFET_CLASS_LA);
519+
write_u32le_inc(&wrptr, LA_VERB_ALT_PIN_MAP);
520+
write_u8_inc(&wrptr, 0);
521+
wrlen = wrptr - req;
522+
ret = greatfet_ctrl_out_in(sdi, req, wrlen,
523+
NULL, 0, LOGIC_DEFAULT_TIMEOUT);
524+
if (ret < 0) {
525+
sr_err("Cannot configure alt pin mapping.");
526+
return ret;
527+
}
528+
491529
/*
492530
* Prepare to get a specific amount of receive data. The logic
493531
* analyzer configure response is strictly binary, in contrast
@@ -549,6 +587,8 @@ static int greatfet_logic_config(const struct sr_dev_inst *sdi)
549587
acq->capture_channels, print_bw);
550588
g_free(print_bw);
551589
bw = acq->capture_samplerate * 8 / acq->points_per_byte;
590+
if (!acq->use_upper_pins)
591+
bw *= acq->unit_size;
552592
print_bw = sr_si_string_u64(bw, "bps");
553593
sr_info("Resulting USB bandwidth: %s.", print_bw);
554594
g_free(print_bw);
@@ -618,7 +658,9 @@ static int greatfet_calc_capture_chans(const struct sr_dev_inst *sdi)
618658
GSList *l;
619659
struct sr_channel *ch;
620660
int last_used_idx;
661+
uint16_t pin_map;
621662
size_t logic_ch_count, en_ch_count, fw_ch_count;
663+
gboolean have_upper, have_lower, use_upper_pins;
622664
int ret;
623665

624666
if (!sdi)
@@ -630,6 +672,7 @@ static int greatfet_calc_capture_chans(const struct sr_dev_inst *sdi)
630672

631673
last_used_idx = -1;
632674
logic_ch_count = 0;
675+
pin_map = 0;
633676
for (l = sdi->channels; l; l = l->next) {
634677
ch = l->data;
635678
if (ch->type != SR_CHANNEL_LOGIC)
@@ -639,14 +682,26 @@ static int greatfet_calc_capture_chans(const struct sr_dev_inst *sdi)
639682
continue;
640683
if (last_used_idx < ch->index)
641684
last_used_idx = ch->index;
685+
pin_map |= 1UL << ch->index;
642686
}
643687
en_ch_count = last_used_idx + 1;
644688
sr_dbg("channel count, logic %zu, highest enabled idx %d -> count %zu",
645689
logic_ch_count, last_used_idx, en_ch_count);
646690
if (!en_ch_count)
647691
return SR_ERR_ARG;
692+
have_upper = pin_map & 0xff00;
693+
have_lower = pin_map & 0x00ff;
694+
use_upper_pins = have_upper && !have_lower;
695+
if (use_upper_pins) {
696+
sr_dbg("ch mask 0x%04x -> using upper pins", pin_map);
697+
last_used_idx -= 8;
698+
en_ch_count -= 8;
699+
}
700+
if (have_upper && !use_upper_pins)
701+
sr_warn("Multi-bank capture, check firmware support!");
648702

649703
acq->capture_channels = en_ch_count;
704+
acq->use_upper_pins = use_upper_pins;
650705
ret = sr_next_power_of_two(last_used_idx, NULL, &fw_ch_count);
651706
if (ret != SR_OK)
652707
return ret;
@@ -657,6 +712,8 @@ static int greatfet_calc_capture_chans(const struct sr_dev_inst *sdi)
657712
acq->points_per_byte = 1;
658713
} else {
659714
acq->unit_size = sizeof(uint8_t);
715+
if (acq->use_upper_pins)
716+
acq->unit_size = sizeof(uint16_t);
660717
acq->points_per_byte = 8 / fw_ch_count;
661718
}
662719
acq->channel_shift = fw_ch_count % 8;
@@ -732,7 +789,8 @@ static void greatfet_abort_acquisition_quick(const struct sr_dev_inst *sdi)
732789
(void)greatfet_logic_stop(sdi);
733790
greatfet_cancel_transfers(sdi);
734791

735-
feed_queue_logic_flush(acq->feed_queue);
792+
if (acq->feed_queue)
793+
feed_queue_logic_flush(acq->feed_queue);
736794
}
737795

738796
/* Allocate USB transfers and associated receive buffers. */
@@ -847,6 +905,8 @@ static int greatfet_cancel_transfers(const struct sr_dev_inst *sdi)
847905
if (!devc)
848906
return SR_ERR_ARG;
849907
dxfer = &devc->transfers;
908+
if (!dxfer->transfers)
909+
return SR_OK;
850910

851911
for (idx = 0; idx < dxfer->transfers_count; idx++) {
852912
xfer = dxfer->transfers[idx];
@@ -1204,11 +1264,12 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi,
12041264
struct feed_queue_logic *q;
12051265
uint64_t samples_remain;
12061266
gboolean exceeded;
1267+
gboolean full_bytes, lower_empty;
12071268
size_t samples_rcvd;
12081269
uint8_t raw_mask;
12091270
size_t points_per_byte, points_count;
1210-
uint8_t raw_data;
1211-
uint8_t accum[8];
1271+
uint8_t raw_data, wr_data;
1272+
uint8_t accum[16];
12121273
const uint8_t *rdptr;
12131274
uint8_t *wrptr;
12141275
int ret;
@@ -1237,9 +1298,21 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi,
12371298
/*
12381299
* Check for the simple case first. Where bytes carry samples
12391300
* of exactly one sample point. Pass memory in verbatim form.
1240-
* Notice that 16bit sample quantities happen to work here too.
1301+
*
1302+
* This approach applies to two cases: Captures of the first 8
1303+
* channels, and captures for 16 channels where both banks are
1304+
* involved (the device firmware provides all 16 bits of data
1305+
* for any given sample point). The 16bit case happens to work
1306+
* because sample data received from the device and logic data
1307+
* in sigrok sessions both use the little endian format.
1308+
*
1309+
* The "upper pins" case must be handled below because the
1310+
* device will not provide data for the lower pin bank, but the
1311+
* samples (all-zero values) must be sent to the sigrok session.
12411312
*/
1242-
if (!acq->channel_shift) {
1313+
full_bytes = !acq->channel_shift;
1314+
lower_empty = acq->use_upper_pins;
1315+
if (full_bytes && !lower_empty) {
12431316
samples_rcvd = dlen / acq->unit_size;
12441317
if (samples_remain && samples_rcvd > samples_remain)
12451318
samples_rcvd = samples_remain;
@@ -1251,22 +1324,29 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi,
12511324
}
12521325

12531326
/*
1254-
* Handle the complex case by means of some naive logic. To
1255-
* simplify the implementation for now and see if the approach
1256-
* works out. It helps that the firmware provides sample data
1257-
* in units of power-of-two bit counts per sample point. This
1258-
* eliminates fragments which could span several transfers.
1327+
* Handle the complex cases where one byte carries values that
1328+
* were taken at multiple sample points, or where the firmware
1329+
* does not communicate the lower pin bank's data (upper pins).
1330+
* This involves manipulation between reception and forwarding.
1331+
* It helps that the firmware provides sample data in units of
1332+
* power-of-two bit counts per sample point. This eliminates
1333+
* fragments which could span several transfers.
12591334
*
1260-
* Notice that dense sample memory only happens for channel
1261-
* counts under 8. That's why we read bytes here and need not
1262-
* dispatch based on unit size.
1335+
* Notice that "upper pins" and "multiple samples per byte" can
1336+
* happen in combination. The implementation transparently deals
1337+
* with upper pin use where bytes carry exactly one value.
12631338
*/
1264-
raw_mask = (1UL << acq->channel_shift) - 1;
1265-
points_per_byte = 8 / acq->channel_shift;
1339+
if (acq->channel_shift) {
1340+
raw_mask = (1UL << acq->channel_shift) - 1;
1341+
points_per_byte = 8 / acq->channel_shift;
1342+
} else {
1343+
raw_mask = (1UL << 8) - 1;
1344+
points_per_byte = 1;
1345+
}
12661346
if (!diag_shown++) {
1267-
sr_dbg("sample memory: ch count %zu, ch shift %zu, mask 0x%x, points %zu",
1347+
sr_dbg("sample mem: ch count %zu, ch shift %zu, mask 0x%x, points %zu, upper %d",
12681348
acq->capture_channels, acq->channel_shift,
1269-
raw_mask, points_per_byte);
1349+
raw_mask, points_per_byte, acq->use_upper_pins);
12701350
}
12711351
samples_rcvd = dlen * points_per_byte;
12721352
if (samples_remain && samples_rcvd > samples_remain) {
@@ -1281,7 +1361,11 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi,
12811361
wrptr = accum;
12821362
points_count = points_per_byte;
12831363
while (points_count--) {
1284-
write_u8_inc(&wrptr, raw_data & raw_mask);
1364+
wr_data = raw_data & raw_mask;
1365+
if (acq->use_upper_pins)
1366+
write_u16le_inc(&wrptr, wr_data << 8);
1367+
else
1368+
write_u8_inc(&wrptr, wr_data);
12851369
raw_data >>= acq->channel_shift;
12861370
}
12871371
points_count = points_per_byte;

src/hardware/greatfet/protocol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct dev_context {
4444
size_t unit_size;
4545
struct feed_queue_logic *feed_queue;
4646
size_t capture_channels;
47+
gboolean use_upper_pins;
4748
size_t channel_shift;
4849
size_t points_per_byte;
4950
uint64_t capture_samplerate;

0 commit comments

Comments
 (0)