@@ -47,6 +47,14 @@ static uint64_t g_sample_bytes = 0;
4747static int g_unitsize = 2 ; /* bytes per sample, set from channel count */
4848static int g_dev_mode = 0 ; /* LOGIC=0, DSO=1, ANALOG=2 */
4949static uint64_t g_limit_samples = 0 ; /* requested sample count for DSO stop */
50+ static int g_hw_nch = 0 ; /* hw mode channel count (FPGA data packing) */
51+
52+ /* Leftover buffer for cross-to-parallel conversion.
53+ * USB transfers and receive_transfer() truncation can deliver data
54+ * that is not a whole multiple of nch*8 bytes (one cross-format group).
55+ * We buffer partial groups here and prepend them to the next callback. */
56+ static uint8_t g_cross_leftover [MAX_CH * 8 ]; /* max group = 16 * 8 = 128 */
57+ static size_t g_cross_leftover_len = 0 ;
5058
5159/* -------------------------------------------------------------------------
5260 * Channel / trigger config (filled by argument parsing)
@@ -95,50 +103,91 @@ static void event_callback(int event)
95103}
96104
97105/*
98- * Convert cross-format logic data to parallel format.
106+ * Convert one complete cross-format group to parallel format and write it .
99107 *
108+ * One group = nch * 8 input bytes -> 64 parallel samples of unitsize bytes.
100109 * The DSLogic FPGA sends LA_CROSS_DATA: data interleaved at 8-byte (64-bit)
101- * boundaries per enabled channel. With N enabled channels, the byte stream
102- * is: [ch0 uint64][ch1 uint64]...[chN-1 uint64] repeated.
110+ * boundaries per enabled channel. With N enabled channels, each group is:
111+ * [ch0 uint64][ch1 uint64]...[chN-1 uint64]
103112 * Each uint64 holds 64 consecutive sample bits for that one channel.
104113 *
105114 * Parallel format (what sigrok / our Python layer expects):
106- * Each sample is g_unitsize bytes, with bit K = channel K value.
107- * So 64 cross-format samples (N*8 input bytes) become 64 parallel samples
108- * of g_unitsize bytes each (64 * g_unitsize output bytes).
115+ * Each sample is unitsize bytes, with bit K = channel K value.
116+ */
117+ static void convert_one_group (const uint8_t * gp , int nch , int unitsize ,
118+ FILE * fp , uint64_t * written )
119+ {
120+ uint8_t out [64 * 2 ]; /* max unitsize=2, 64 samples per group */
121+
122+ memset (out , 0 , (size_t )(64 * unitsize ));
123+
124+ for (int ch = 0 ; ch < nch ; ch ++ ) {
125+ /* 8 bytes (64 bits) for this channel in this group */
126+ const uint8_t * ch_bytes = gp + ch * 8 ;
127+ int bit = ch ; /* bit position in the output sample */
128+
129+ for (int b = 0 ; b < 64 ; b ++ ) {
130+ int byte_idx = b / 8 ;
131+ int bit_idx = b % 8 ;
132+ if (ch_bytes [byte_idx ] & (1 << bit_idx )) {
133+ out [b * unitsize + bit / 8 ]
134+ |= (uint8_t )(1 << (bit % 8 ));
135+ }
136+ }
137+ }
138+ fwrite (out , (size_t )unitsize , 64 , fp );
139+ * written += (uint64_t )(64 * unitsize );
140+ }
141+
142+ /*
143+ * Convert cross-format logic data to parallel format, handling partial
144+ * groups across callbacks.
109145 *
110- * We convert in-place in the callback and write parallel-format data to
111- * the output file.
146+ * USB transfers and receive_transfer() truncation (dsl.c:2403) can
147+ * deliver data that is not a whole multiple of nch*8 bytes. We buffer
148+ * leftover bytes in g_cross_leftover[] and prepend them to the next
149+ * callback's data before processing complete groups.
112150 */
113151static void cross_to_parallel (const uint8_t * src , size_t src_len ,
114152 int nch , int unitsize , FILE * fp ,
115153 uint64_t * written )
116154{
117- /* Each group: nch * 8 input bytes -> 64 parallel samples */
118155 size_t grp_in = (size_t )nch * 8 ;
119- size_t n_groups = src_len / grp_in ;
120- uint8_t out [64 * 2 ]; /* max unitsize=2, 64 samples per group */
121-
122- for (size_t g = 0 ; g < n_groups ; g ++ ) {
123- const uint8_t * gp = src + g * grp_in ;
124- memset (out , 0 , (size_t )(64 * unitsize ));
125-
126- for (int ch = 0 ; ch < nch ; ch ++ ) {
127- /* 8 bytes (64 bits) for this channel in this group */
128- const uint8_t * ch_bytes = gp + ch * 8 ;
129- int bit = ch ; /* bit position in the output sample */
130-
131- for (int b = 0 ; b < 64 ; b ++ ) {
132- int byte_idx = b / 8 ;
133- int bit_idx = b % 8 ;
134- if (ch_bytes [byte_idx ] & (1 << bit_idx )) {
135- out [b * unitsize + bit / 8 ]
136- |= (uint8_t )(1 << (bit % 8 ));
137- }
138- }
156+ const uint8_t * p = src ;
157+ size_t remain = src_len ;
158+
159+ /* If we have leftover bytes from the previous callback, try to
160+ * complete the partial group by appending from the new data. */
161+ if (g_cross_leftover_len > 0 ) {
162+ size_t need = grp_in - g_cross_leftover_len ;
163+ if (remain >= need ) {
164+ memcpy (g_cross_leftover + g_cross_leftover_len ,
165+ p , need );
166+ convert_one_group (g_cross_leftover , nch , unitsize ,
167+ fp , written );
168+ p += need ;
169+ remain -= need ;
170+ g_cross_leftover_len = 0 ;
171+ } else {
172+ /* Still not enough for a full group -- accumulate */
173+ memcpy (g_cross_leftover + g_cross_leftover_len ,
174+ p , remain );
175+ g_cross_leftover_len += remain ;
176+ return ;
139177 }
140- fwrite (out , (size_t )unitsize , 64 , fp );
141- * written += (uint64_t )(64 * unitsize );
178+ }
179+
180+ /* Process all complete groups in the current buffer */
181+ while (remain >= grp_in ) {
182+ convert_one_group (p , nch , unitsize , fp , written );
183+ p += grp_in ;
184+ remain -= grp_in ;
185+ }
186+
187+ /* Save any remaining bytes for the next callback */
188+ if (remain > 0 ) {
189+ memcpy (g_cross_leftover , p , remain );
190+ g_cross_leftover_len = remain ;
142191 }
143192}
144193
@@ -151,11 +200,11 @@ static void datafeed_callback(const struct sr_dev_inst *sdi,
151200 (const struct sr_datafeed_logic * )packet -> payload ;
152201 if (logic && logic -> data && logic -> length > 0 ) {
153202 if (logic -> format == LA_CROSS_DATA &&
154- g_n_enabled_chs > 0 ) {
203+ g_hw_nch > 0 ) {
155204 cross_to_parallel (
156205 (const uint8_t * )logic -> data ,
157206 (size_t )logic -> length ,
158- g_n_enabled_chs ,
207+ g_hw_nch ,
159208 g_unitsize ,
160209 g_capture_file ,
161210 & g_sample_bytes );
@@ -444,19 +493,27 @@ static void apply_trigger(void)
444493
445494static int setup_channels (int total_ch )
446495{
447- /* Enable only the requested physical channels; name them if provided */
496+ /* Enable ALL channels within the hardware mode range, matching
497+ * the DSView GUI behaviour. The FPGA packs cross-format data
498+ * for every enabled channel. Disabling a subset within the mode
499+ * causes the FPGA packing to differ from what cross_to_parallel()
500+ * expects (nch = g_hw_nch = mode channel count).
501+ *
502+ * Channels beyond the mode range are disabled.
503+ * User-requested channels get their names set. */
448504 for (int ch = 0 ; ch < total_ch ; ch ++ ) {
449- gboolean en = FALSE;
505+ gboolean en = (ch < g_hw_nch ) ? TRUE : FALSE;
506+ ds_enable_device_channel_index (ch , en );
507+
508+ /* Set name for user-requested channels */
450509 int name_idx = -1 ;
451510 for (int j = 0 ; j < g_n_enabled_chs ; j ++ ) {
452511 if (g_enabled_chs [j ] == ch ) {
453- en = TRUE;
454512 name_idx = j ;
455513 break ;
456514 }
457515 }
458- ds_enable_device_channel_index (ch , en );
459- if (en && name_idx >= 0 && g_ch_names [name_idx ][0 ])
516+ if (name_idx >= 0 && g_ch_names [name_idx ][0 ])
460517 ds_set_device_channel_name (ch , g_ch_names [name_idx ]);
461518 }
462519 return SR_OK ;
@@ -667,6 +724,8 @@ static int cmd_capture(int dev_index, uint64_t samplerate, uint64_t limit_sample
667724{
668725 g_capture_done = g_capture_error = 0 ;
669726 g_sample_bytes = 0 ;
727+ g_cross_leftover_len = 0 ;
728+ g_hw_nch = 0 ;
670729 memset (g_ch_vdiv , 0 , sizeof (g_ch_vdiv ));
671730 memset (g_ch_vfactor , 0 , sizeof (g_ch_vfactor ));
672731 memset (g_ch_coupling , 0 , sizeof (g_ch_coupling ));
@@ -740,6 +799,21 @@ static int cmd_capture(int dev_index, uint64_t samplerate, uint64_t limit_sample
740799 (struct sr_list_item * )(uintptr_t ) g_variant_get_uint64 (cm_data );
741800 g_variant_unref (cm_data );
742801
802+ /* The hw mode must cover ALL requested channel indices.
803+ * For contiguous channels 0-6 (count=7), max index is 6,
804+ * so min_hw_channels = 7. For non-contiguous channels
805+ * like 0,3,7 (count=3), max index is 7, so
806+ * min_hw_channels = 8. The mode must have >= this many
807+ * channels because the FPGA addresses channels by index. */
808+ int max_ch_idx = 0 ;
809+ for (int i = 0 ; i < g_n_enabled_chs ; i ++ ) {
810+ if (g_enabled_chs [i ] > max_ch_idx )
811+ max_ch_idx = g_enabled_chs [i ];
812+ }
813+ int min_hw_chs = max_ch_idx + 1 ;
814+ if (min_hw_chs < g_n_enabled_chs )
815+ min_hw_chs = g_n_enabled_chs ;
816+
743817 /* Find the mode with the smallest channel count
744818 * that can still accommodate all requested channels.
745819 * Parse channel count from desc: "Use N Channels ..." */
@@ -760,7 +834,7 @@ static int cmd_capture(int dev_index, uint64_t samplerate, uint64_t limit_sample
760834 nch = atoi (t + 2 ) + 1 ;
761835 }
762836 }
763- if (nch >= g_n_enabled_chs && nch < best_nch ) {
837+ if (nch >= min_hw_chs && nch < best_nch ) {
764838 best_nch = nch ;
765839 best_id = modes [i ].id ;
766840 }
@@ -778,17 +852,18 @@ static int cmd_capture(int dev_index, uint64_t samplerate, uint64_t limit_sample
778852 }
779853 }
780854
855+ /* Store the hw channel mode count globally. The FPGA packs cross-
856+ * format data for ALL enabled channels. Like the DSView GUI, we
857+ * keep all channels in the mode enabled (not just user-requested
858+ * ones) so the FPGA packing matches our expectation exactly. */
859+ g_hw_nch = ch_mode_num > 0 ? ch_mode_num : g_n_enabled_chs ;
860+
781861 /* bytes-per-sample: DSO = 1 byte per channel (8-bit ADC),
782862 * LOGIC = use the hw channel mode's channel count for unitsize */
783863 if (is_dso )
784864 g_unitsize = 1 ; /* 8-bit ADC, 1 byte per channel per sample */
785- else {
786- /* The FPGA always packs data based on the hardware channel
787- * mode, not the number of user-enabled channels. Use the
788- * actual hw mode channel count for unitsize calculation. */
789- int hw_nch = ch_mode_num > 0 ? ch_mode_num : g_n_enabled_chs ;
790- g_unitsize = (hw_nch <= 8 ) ? 1 : 2 ;
791- }
865+ else
866+ g_unitsize = (g_hw_nch <= 8 ) ? 1 : 2 ;
792867
793868 /* Samplerate -- sr_config_set() takes ownership of the GVariant
794869 * (ref_sink + unref), so we must NOT unref after the call. */
@@ -847,11 +922,13 @@ static int cmd_capture(int dev_index, uint64_t samplerate, uint64_t limit_sample
847922 /* Channel enable / name.
848923 *
849924 * After the channel mode change, dsl_adjust_probes() may have
850- * resized the probe list (e.g. 16 -> 8 for 3-channel mode).
851- * Re-query the channel count and enable only the user-requested
852- * channels. The FPGA packs data in "cross" format: cycling
853- * through enabled channels, 8 sample-bits per byte per channel.
854- * dsl_en_ch_num() must match what the FPGA was told via ch_en. */
925+ * resized the probe list (e.g. 16 -> 8 for "Use 8 Channels").
926+ * Re-query the channel count and enable ALL channels within the
927+ * hw mode range (matching DSView GUI behaviour). The FPGA packs
928+ * cross-format data for every enabled channel -- selectively
929+ * disabling channels within the mode causes the data packing to
930+ * differ from what cross_to_parallel() expects.
931+ * dsl_en_ch_num() will return g_hw_nch after setup_channels(). */
855932 struct ds_device_full_info finfo ;
856933 memset (& finfo , 0 , sizeof (finfo ));
857934 ds_get_actived_device_info (& finfo );
@@ -941,7 +1018,10 @@ static int cmd_capture(int dev_index, uint64_t samplerate, uint64_t limit_sample
9411018 return 1 ;
9421019 }
9431020 uint64_t hdr_sr = samplerate ;
944- uint32_t hdr_ch = (uint32_t ) g_n_enabled_chs ;
1021+ /* Write the hw mode channel count so the Python layer computes
1022+ * the correct unitsize for the parallel-format data we produce. */
1023+ uint32_t hdr_ch = is_dso ? (uint32_t )g_n_enabled_chs
1024+ : (uint32_t )g_hw_nch ;
9451025 fwrite (& hdr_sr , sizeof (hdr_sr ), 1 , g_capture_file );
9461026 fwrite (& hdr_ch , sizeof (hdr_ch ), 1 , g_capture_file );
9471027
0 commit comments