]>
Commit | Line | Data |
---|---|---|
dc90146e A |
1 | /* |
2 | * This file is part of the libsigrok project. | |
3 | * | |
bac2a8b8 | 4 | * Copyright (C) 2022 Shawn Walker <ac0bi00@gmail.com> |
dc90146e A |
5 | * |
6 | * This program is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
bac2a8b8 A |
20 | #define _GNU_SOURCE |
21 | ||
dc90146e | 22 | #include <config.h> |
bac2a8b8 A |
23 | #include <errno.h> |
24 | #include <glib.h> | |
25 | #include <math.h> | |
26 | #include <stdlib.h> | |
27 | #include <stdarg.h> | |
28 | #include <string.h> | |
29 | #include <time.h> | |
30 | #include <unistd.h> | |
31 | #include <libsigrok/libsigrok.h> | |
32 | #include "libsigrok-internal.h" | |
dc90146e A |
33 | #include "protocol.h" |
34 | ||
bac2a8b8 A |
35 | SR_PRIV int send_serial_str(struct sr_serial_dev_inst *serial, char *str){ |
36 | int len=strlen(str); | |
37 | if((len>15)||(len<1)){ //limit length to catch errant strings | |
38 | sr_err("ERROR:Serial string len %d invalid ",len); | |
39 | return SR_ERR; | |
40 | } | |
41 | //100ms timeout. With USB CDC serial we can't define the timeout | |
42 | //based on link rate, so just pick something large as we shouldn't normally see them | |
43 | if(serial_write_blocking(serial,str,len,100) != len){ | |
44 | sr_err("ERROR:Serial str write failed"); | |
45 | return SR_ERR; | |
46 | } | |
47 | ||
48 | return SR_OK; | |
49 | } | |
50 | SR_PRIV int send_serial_char(struct sr_serial_dev_inst *serial, char ch){ | |
51 | char buf[1]; | |
52 | buf[0]=ch; | |
53 | if(serial_write_blocking(serial,buf,1,100) != 1){ //100ms | |
54 | sr_err("ERROR:Serial char write failed"); | |
55 | return SR_ERR; | |
56 | } | |
57 | return SR_OK; | |
58 | } | |
59 | //Issue a command that expects a string return, return length of string | |
60 | int send_serial_w_resp(struct sr_serial_dev_inst *serial, char *str,char *resp,size_t cnt){ | |
61 | int num_read,i; | |
62 | send_serial_str(serial,str); | |
63 | //Using the serial_read_blocking function when reading a response of unknown length requires | |
64 | //a long worst case timeout to always be taken. So, instead loop waiting for a first byte, and | |
65 | //then a final small delay for the rest. | |
66 | for(i=0;i<1000;i++){ //wait up to 1 second in ms increments | |
67 | num_read = serial_read_blocking(serial, resp, cnt, 1); | |
68 | if(num_read>0) break; | |
69 | } | |
70 | //sr_spew("rwprsp1 i %d nr %d",i,num_read); | |
71 | //Since the serial port is usb CDC we can't calculate timeouts based on baud rate but | |
72 | //even if the response is split between two USB transfers 10ms should be plenty. | |
73 | num_read+= serial_read_blocking(serial, &(resp[num_read]), cnt-num_read, 10); | |
74 | //sr_spew("rwrsp2 nr %d",num_read); | |
75 | ||
76 | if ((num_read < 1)||(num_read>30)) { | |
77 | sr_err("ERROR:Serial_w_resp failed (%d).", num_read); | |
78 | return -1; | |
79 | }else{ | |
80 | return num_read; | |
81 | } | |
82 | } | |
83 | //Issue a command that expects a single char ack | |
84 | SR_PRIV int send_serial_w_ack(struct sr_serial_dev_inst *serial, char *str){ | |
85 | char buf[2]; | |
86 | int num_read; | |
87 | //In case we have left over transfer from the device, drain them | |
88 | while((num_read=serial_read_blocking(serial, buf, 2, 10))){ | |
89 | //sr_dbg("swack drops 2 previous bytes %d %d",buf[0],buf[1]); | |
90 | } | |
91 | send_serial_str(serial,str); | |
92 | //1000ms timeout | |
93 | num_read =serial_read_blocking(serial, buf, 1, 1000); | |
94 | if ((num_read == 1)&&(buf[0]=='*')) { | |
95 | return SR_OK; | |
96 | }else{ | |
97 | sr_err("ERROR:Serial_w_ack %s failed (%d).", str,num_read); | |
98 | if(num_read){ | |
99 | sr_err("ack resp char %c d %d\n\r",buf[0],buf[0]); | |
100 | } | |
101 | return SR_ERR; | |
102 | } | |
103 | } | |
104 | ||
105 | //Process incoming data stream assuming it is optimized packing of 4 channels or less | |
106 | //Each byte is 4 channels of data and a 3 bit rle value, or a larger rle value, or a control signal. | |
107 | //This also checks for aborts and ends. | |
108 | //If an end is seen we stop processing but do not check the byte_cnt | |
109 | //The output is a set of samples fed to process group to perform sw triggering and sending of data to the session | |
110 | //as well as maintenance of the serial rx byte cnt. | |
111 | //Since we can get huge rle values we chop them up for processing into smaller groups | |
112 | //In this mode we can always consume all bytes because there are no cases where the processing of one | |
113 | //byte requires the one after it. | |
114 | void process_D4(struct sr_dev_inst *sdi,struct dev_context *d){ | |
115 | int32_t j; | |
116 | uint8_t cbyte; | |
117 | uint8_t cval; | |
118 | uint32_t rlecnt=0; | |
119 | uint32_t sampcnt=0; //number of samples received with no rles | |
120 | while(d->ser_rdptr < d->bytes_avail){ | |
121 | cbyte=d->buffer[(d->ser_rdptr)]; | |
122 | //RLE only byte | |
123 | if(cbyte>=48 && cbyte<=127){ | |
124 | rlecnt+=(cbyte-47)*8; | |
125 | d->byte_cnt++; | |
126 | }else if(cbyte>=0x80){ //sample with possible rle | |
127 | rlecnt+=(cbyte&0x70)>>4; | |
128 | if(rlecnt){ | |
129 | //On a value change, duplicate the previous values first. | |
130 | //The maximum value of one rle is 640. | |
131 | //To ensure we don't overflow the sample buffer but still send it large chunks of data | |
132 | //(to make the packet sends to the session efficient) only call process group after | |
133 | //a large number of samples have been seen. | |
134 | //Likely we could use the max rle value of 640 but 2048 gives some extra room. | |
135 | if((rlecnt+d->cbuf_wrptr)>(d->sample_buf_size-2048)){ | |
136 | //process_group is sent the number of slices which is just the cbufwrptr divided by the slice size | |
137 | //This modulo check should never happen as long the calculations for dig_sample_bytes etc are | |
138 | //correct, but it's a good cross check for code development. | |
139 | if((d->cbuf_wrptr)%(d->dig_sample_bytes)){ | |
140 | sr_err("Modulo fail %d %d ",d->cbuf_wrptr,d->dig_sample_bytes); | |
141 | } | |
142 | process_group(sdi,d,(d->cbuf_wrptr/d->dig_sample_bytes)); | |
143 | } | |
144 | rle_memset(d,rlecnt); | |
145 | rlecnt=0; | |
146 | sampcnt=0; | |
147 | } | |
148 | //Finally add in the new values | |
149 | cval=cbyte&0xF; | |
150 | d->d_data_buf[d->cbuf_wrptr++]=cval; | |
151 | //pad in all other bytes since the sessions even wants disabled channels reported | |
152 | for(j=1;j<d->dig_sample_bytes;j++){ | |
153 | d->d_data_buf[d->cbuf_wrptr++]=0; | |
154 | } | |
155 | sampcnt++; | |
156 | d->byte_cnt++; | |
157 | sr_spew("Dchan4 rdptr %d wrptr %d bytein 0x%X rle %d cval 0x%X\n", | |
158 | (d->ser_rdptr)-1,d->cbuf_wrptr,cbyte,rlecnt,cval); | |
159 | rlecnt=0; | |
160 | ||
161 | d->d_last[0]=cval; | |
162 | } | |
163 | //Any other character ends parsing - it could be a frame error or a start of the final byte cnt | |
164 | else { | |
165 | if(cbyte=='$'){ | |
166 | sr_info("D4 Data stream stops with cbyte %d char %c rdidx %d cnt %llu",cbyte,cbyte,d->ser_rdptr,d->byte_cnt); | |
167 | d->rxstate=RX_STOPPED; | |
168 | }else{ | |
169 | sr_err("D4 Data stream aborts with cbyte %d char %c rdidx %d cnt %llu",cbyte,cbyte,d->ser_rdptr,d->byte_cnt); | |
170 | d->rxstate=RX_ABORT; | |
171 | } | |
172 | break; //break from while loop | |
173 | } | |
174 | (d->ser_rdptr)++; | |
175 | }//while rdptr < wrptr | |
176 | sr_spew("D4 while done rdptr %d",d->ser_rdptr); | |
177 | //If we reach the end of the serial input stream send any remaining values or rles to the session | |
178 | /*this can also be skipped now the rle_memset handles cbufwrptr | |
179 | if(sampcnt){ | |
180 | process_group(sdi,d,sampcnt); | |
181 | sampcnt=0; | |
182 | } | |
183 | */ | |
184 | if(rlecnt){ | |
185 | sr_spew("Residual D4 slice rlecnt %d",rlecnt); | |
186 | rle_memset(d,rlecnt); | |
187 | } | |
188 | if(d->cbuf_wrptr){ | |
189 | sr_spew("Residual D4 data wrptr %d",d->cbuf_wrptr); | |
190 | process_group(sdi,d,d->cbuf_wrptr/d->dig_sample_bytes); | |
191 | ||
192 | } | |
193 | ||
194 | }//Process_D4 | |
195 | ||
196 | //Process incoming data stream and forward to trigger processing with process_group | |
197 | //The final value of ser_rdptr indicates how many bytes were processed. | |
198 | //This version handles all other enabled channel configurations that Process_D4 doesn't | |
199 | void process_slice(struct sr_dev_inst *sdi,struct dev_context *devc){ | |
200 | int32_t i; | |
201 | uint32_t tmp32; | |
202 | uint8_t cbyte; | |
203 | uint32_t slices_avail=0; | |
204 | uint32_t cword; | |
205 | uint32_t slice_bytes; //number of bytes that have legal slice values | |
206 | //Only process legal data values for this mode which are >=0x80 | |
207 | for(slice_bytes=1;(slice_bytes<devc->bytes_avail)&&(devc->buffer[slice_bytes-1]>=0x80);slice_bytes++); | |
208 | if(slice_bytes!=devc->bytes_avail){ | |
209 | cbyte=devc->buffer[slice_bytes-1]; | |
210 | slice_bytes--; //Don't process the ending character | |
211 | if(cbyte=='$'){ | |
212 | sr_info("Data stream stops with cbyte %d char %c rdidx %d sbytes %d cnt %llu",cbyte,cbyte,devc->ser_rdptr,slice_bytes,devc->byte_cnt); | |
213 | devc->rxstate=RX_STOPPED; | |
214 | }else{ | |
215 | sr_err("Data stream aborts with cbyte %d char %c rdidx %d sbytes %d cnt %llu",cbyte,cbyte,devc->ser_rdptr,slice_bytes,devc->byte_cnt); | |
216 | devc->rxstate=RX_ABORT; | |
217 | } | |
218 | } | |
219 | //If the wrptr is non-zero due to a residual from the previous serial transfer don't double count it towards byte_cnt | |
220 | devc->byte_cnt+=slice_bytes-(devc->wrptr); | |
221 | sr_spew("process slice avail %d rdptr %d sb %d byte_cnt %d",devc->bytes_avail,devc->ser_rdptr,slice_bytes,devc->byte_cnt); | |
222 | //Must have a full slice | |
223 | while((devc->ser_rdptr+devc->bytes_per_slice)<=slice_bytes){ | |
224 | //The use of devc->cbuf_wrptr is different between analog and digital. | |
225 | //For analog it targets a float sized offset for that channel's buffer | |
226 | //For digital it targets a bit, so the 3 lsbs are bit offsets within a byte | |
227 | slices_avail++; | |
228 | cword=0; | |
229 | //build up a word 7 bits at a time, using only enabled channels | |
230 | for(i=0;i<devc->num_d_channels;i+=7){ | |
231 | if(((devc->d_chan_mask)>>i)&0x7F){ | |
232 | cword|=((devc->buffer[devc->ser_rdptr])&0x7F)<<i; | |
233 | (devc->ser_rdptr)++; | |
234 | } | |
235 | } | |
236 | //and then distribute 8 bits at a time to all possible channels | |
237 | for(i=0;i<devc->num_d_channels;i+=8){ | |
238 | uint32_t idx=((devc->cbuf_wrptr)*devc->dig_sample_bytes)+(i>>3); | |
239 | devc->d_data_buf[idx]=cword&0xFF; | |
240 | sr_spew("Dchan i %d wrptr %d idx %d char 0x%X cword 0x%X",i,devc->cbuf_wrptr,idx,devc->d_data_buf[idx],cword); | |
241 | cword>>=8; | |
242 | } | |
243 | //Each analog value is a 7 bit value | |
244 | for(i=0;i<devc->num_a_channels;i++){ | |
245 | if((devc->a_chan_mask>>i)&1){ | |
246 | //a_size is depracted and must always be 1B | |
247 | tmp32=devc->buffer[devc->ser_rdptr]-0x80; | |
248 | devc->a_data_bufs[i][devc->cbuf_wrptr]=((float)tmp32 * devc->a_scale[i])+devc->a_offset[i]; | |
249 | devc->a_last[i]=devc->a_data_bufs[i][devc->cbuf_wrptr]; | |
250 | sr_spew("AChan %d t32 %d value %f wrptr %d rdptr %d sc %d off %d",i,tmp32,devc->a_data_bufs[i][devc->cbuf_wrptr],devc->cbuf_wrptr,devc->ser_rdptr,devc->a_scale[i],devc->a_offset[i]); | |
251 | devc->ser_rdptr++; | |
252 | }//if channel enabled | |
253 | }//for num_a_channels | |
254 | devc->cbuf_wrptr++; | |
255 | }//While another slice available | |
256 | if(slices_avail){ | |
257 | process_group(sdi,devc,slices_avail); | |
258 | } | |
259 | ||
260 | } | |
261 | //Send the processed analog values to the session | |
262 | int send_analog(struct sr_dev_inst *sdi,struct dev_context *devc,uint32_t num_samples, uint32_t offset){ | |
263 | struct sr_datafeed_packet packet; | |
264 | struct sr_datafeed_analog analog; | |
265 | struct sr_analog_encoding encoding; | |
266 | struct sr_analog_meaning meaning; | |
267 | struct sr_analog_spec spec; | |
268 | struct sr_channel *ch; | |
269 | uint32_t i; | |
270 | float *fptr; | |
271 | ||
272 | sr_analog_init(&analog, &encoding, &meaning, &spec, ANALOG_DIGITS); | |
273 | for(i=0;i<devc->num_a_channels;i++){ | |
274 | if((devc->a_chan_mask>>i)&1){ | |
275 | ch=devc->analog_groups[i]->channels->data; | |
276 | analog.meaning->channels = g_slist_append(NULL, ch); | |
277 | analog.num_samples = num_samples; | |
278 | analog.data = (devc->a_data_bufs[i]) + offset; | |
279 | fptr=analog.data; | |
280 | sr_spew("send analog num %d offset %d first %f 2 %f",num_samples,offset,*(devc->a_data_bufs[i]),*fptr); | |
281 | analog.meaning->mq = SR_MQ_VOLTAGE; | |
282 | analog.meaning->unit = SR_UNIT_VOLT; | |
283 | analog.meaning->mqflags = 0; | |
284 | packet.type = SR_DF_ANALOG; | |
285 | packet.payload = &analog; | |
286 | sr_session_send(sdi, &packet); | |
287 | g_slist_free(analog.meaning->channels); | |
288 | } //if enabled | |
289 | }//for channels | |
290 | return 0; | |
291 | ||
292 | } | |
293 | //Send the ring buffer of pre-trigger analog samples. | |
294 | // The entire buffer is sent (as long as it filled once), but need send two payloads split at the | |
295 | // the writeptr | |
296 | int send_analog_ring(struct sr_dev_inst *sdi,struct dev_context *devc,uint32_t num_samples){ | |
297 | struct sr_datafeed_packet packet; | |
298 | struct sr_datafeed_analog analog; | |
299 | struct sr_analog_encoding encoding; | |
300 | struct sr_analog_meaning meaning; | |
301 | struct sr_analog_spec spec; | |
302 | struct sr_channel *ch; | |
303 | int i; | |
304 | uint32_t num_pre,start_pre; | |
305 | uint32_t num_post,start_post; | |
306 | num_pre=(num_samples>=devc->pretrig_wr_ptr) ? devc->pretrig_wr_ptr : num_samples; | |
307 | start_pre=devc->pretrig_wr_ptr-num_pre; | |
308 | num_post=num_samples-num_pre; | |
309 | start_post=devc->pretrig_entries-num_post; | |
310 | sr_spew("send_analog ring wrptr %u ns %d npre %u spre %u npost %u spost %u",devc->pretrig_wr_ptr,num_samples,num_pre,start_pre,num_post,start_post); | |
311 | float *fptr; | |
312 | sr_analog_init(&analog, &encoding, &meaning, &spec, ANALOG_DIGITS); | |
313 | for(i=0;i<devc->num_a_channels;i++){ | |
314 | if((devc->a_chan_mask>>i)&1){ | |
315 | ch=devc->analog_groups[i]->channels->data; | |
316 | analog.meaning->channels = g_slist_append(NULL, ch); | |
317 | analog.meaning->mq = SR_MQ_VOLTAGE; | |
318 | analog.meaning->unit = SR_UNIT_VOLT; | |
319 | analog.meaning->mqflags = 0; | |
320 | packet.type = SR_DF_ANALOG; | |
321 | packet.payload = &analog; | |
322 | //First send what is after the write pointer because it is oldest | |
323 | if(num_post){ | |
324 | analog.num_samples = num_post; | |
325 | analog.data = (devc->a_pretrig_bufs[i]) + start_post; | |
326 | //sr_spew("ring buf %d starts at %p",i,(void *) devc->a_pretrig_bufs[i]); | |
327 | //sr_spew("analog data %d starts at %p",i,(void *) analog.data); | |
328 | //sr_spew("Sending A%d ring buffer oldest ",i); | |
329 | for(uint32_t j=0;j<analog.num_samples;j++){ | |
330 | fptr=analog.data+(j*sizeof(float)); | |
331 | //sr_spew("RNGDCT%d j %d %f %p",i,j,*fptr,(void *)fptr); | |
332 | } | |
333 | sr_session_send(sdi, &packet); | |
334 | } | |
335 | if(num_pre){ | |
336 | analog.num_samples = num_pre; | |
337 | analog.data = (devc->a_pretrig_bufs[i])+start_pre; | |
338 | sr_dbg("Sending A%d ring buffer newest ",i); | |
339 | for(uint32_t j=0;j<analog.num_samples;j++){ | |
340 | fptr=analog.data+(j*sizeof(float)); | |
341 | sr_spew("RNGDCW%d j %d %f %p",i,j,*fptr,(void *)fptr); | |
342 | } | |
343 | sr_session_send(sdi, &packet); | |
344 | } | |
345 | g_slist_free(analog.meaning->channels); | |
346 | sr_dbg("Sending A%d ring buffer done ",i); | |
347 | } //if enabled | |
348 | }//for channels | |
349 | return 0; | |
350 | ||
351 | } | |
352 | ||
353 | //Given a chunk of slices forward to trigger check or session as appropriate and update state | |
354 | //these could be real slices or those generated by rles | |
355 | int process_group(struct sr_dev_inst *sdi,struct dev_context *devc,uint32_t num_slices){ | |
356 | int trigger_offset; | |
357 | int pre_trigger_samples; | |
358 | //These are samples sent to session and are less than num_slices if we reach limit_samples | |
359 | size_t num_samples; | |
360 | struct sr_datafeed_logic logic; | |
361 | struct sr_datafeed_packet packet; | |
362 | int i; | |
363 | size_t cbuf_wrptr_cpy; | |
364 | cbuf_wrptr_cpy=devc->cbuf_wrptr; | |
365 | //regardless of whether we forward samples on or not (because we aren't triggered), always reset the | |
366 | //pointer into the device data buffers | |
367 | devc->cbuf_wrptr=0; | |
368 | if(devc->trigger_fired){ //send directly to session | |
369 | if (devc->limit_samples && | |
370 | num_slices > devc->limit_samples - devc->sent_samples){ | |
371 | num_samples = devc->limit_samples - devc->sent_samples; | |
372 | }else{ | |
373 | num_samples=num_slices; | |
374 | } | |
375 | if(num_samples>0) { | |
376 | sr_spew("Process_group sending %d post trig samples dsb %d",num_samples,devc->dig_sample_bytes); | |
377 | //for(int z=0;(z<num_samples);z+=2){ | |
378 | // sr_spew("0x%X ",devc->d_data_buf[z]); | |
379 | //} | |
380 | if(devc->num_d_channels){ | |
381 | packet.type = SR_DF_LOGIC; | |
382 | packet.payload = &logic; | |
383 | //Size the number of bytes required to fit all of the channels | |
384 | logic.unitsize = devc->dig_sample_bytes; | |
385 | //The total length of the array sent | |
386 | logic.length=num_samples*logic.unitsize; | |
387 | logic.data = devc->d_data_buf; | |
388 | sr_session_send(sdi, &packet); | |
389 | } | |
390 | send_analog(sdi,devc,num_samples,0); | |
391 | }//num_sample>0 | |
392 | devc->sent_samples+=num_samples; | |
393 | return 0; | |
394 | } //trigger_fired | |
395 | else{ | |
396 | size_t num_ring_samples; | |
397 | size_t sptr; | |
398 | size_t eptr; | |
399 | size_t numtail; | |
400 | size_t numwrap; | |
401 | size_t srcptr; | |
402 | //sr_spew("Process_group check %d pre trig samples",num_slices); | |
403 | //The trigger_offset is -1 if no trigger is found, but if a trigger is found | |
404 | //then trigger_offset is the offset into the data buffer sent to it. | |
405 | //The pre_trigger_samples is the total number of samples before the trigger, but limited to | |
406 | //the size of the ring buffer set by the capture_ratio. So the pre_trigger_samples can include both the new samples | |
407 | //and the ring buffer, but trigger_offset is only in relation to the new samples | |
408 | trigger_offset = soft_trigger_logic_check(devc->stl, | |
409 | devc->d_data_buf, num_slices * devc->dig_sample_bytes, &pre_trigger_samples); | |
410 | //A trigger offset >=0 indicate a trigger was seen. The stl will isue the trigger to the session | |
411 | //and will forward all pre trigger logic samples, but we must send any post trigger logic | |
412 | //and all pre and post trigger analog signals | |
413 | // sr_dbg("trggr_off %d",trigger_offset); | |
414 | // sr_dbg("pre_samp %d",pre_trigger_samples); | |
415 | if (trigger_offset > -1) { | |
416 | devc->trigger_fired = TRUE; | |
417 | devc->sent_samples += pre_trigger_samples; | |
418 | packet.type = SR_DF_LOGIC; | |
419 | packet.payload = &logic; | |
420 | num_samples = num_slices - trigger_offset; | |
421 | //Since we are in continuous mode for SW triggers it is possible to get more samples than limit_samples, so | |
422 | //once the trigger fires make sure we don't get beyond limit samples. At this point sent_samples should | |
423 | //be equal to pre_trigger_samples (just added above) because without being triggered we'd never increment | |
424 | //sent_samples. | |
425 | //This number is the number of post trigger logic samples to send to the session, the number of floats | |
426 | //is larger because of the analog ring buffer we track. | |
427 | if (devc->limit_samples && | |
428 | num_samples > devc->limit_samples - devc->sent_samples) | |
429 | num_samples = devc->limit_samples - devc->sent_samples; | |
430 | //The soft trigger logic issues the trigger and sends packest for all logic data that was pretrigger | |
431 | //so only send what is left | |
432 | if(num_samples>0){ | |
433 | sr_dbg("Sending post trigger logical remainder of %d",num_samples); | |
434 | logic.length = num_samples * devc->dig_sample_bytes; | |
435 | logic.unitsize = devc->dig_sample_bytes; | |
436 | logic.data = devc->d_data_buf + (trigger_offset * devc->dig_sample_bytes); | |
437 | devc->sent_samples += num_samples; | |
438 | sr_session_send(sdi, &packet); | |
439 | } | |
440 | size_t new_start,new_end,new_samples,ring_samples; | |
441 | //Figure out the analog data to send. | |
442 | //We might need to send: | |
443 | //-some or all of incoming data | |
444 | //-all of incoming data and some of ring buffer | |
445 | //-all of incoming data and all of ring buffer (and still might be short) | |
446 | //We don't need to compare to limit_samples because pretrig_entries can never be more than limit_samples | |
447 | //trigger offset indicatese where in the new samples the trigger was, but we need to go back pretrig_entries before it | |
448 | new_start=(trigger_offset>(int)devc->pretrig_entries) ? trigger_offset-devc->pretrig_entries : 0; | |
449 | //Note that we might not have gotten all the pre triggerstore data we were looking for. In such a case the sw trigger | |
450 | //logic seems to fill up to the limit_samples and thus the ratio is off, but we get the full number of samples | |
451 | //The number of entries in the ring buffer is pre_trigger_samples-trigger_offset so subtract that from limit samples | |
452 | //as a threshold | |
453 | new_end=MIN(num_slices-1,devc->limit_samples-(pre_trigger_samples-trigger_offset)-1); | |
454 | //This includes pre and post trigger storage. | |
455 | new_samples=new_end-new_start+1; | |
456 | //pre_trigger_samples can never be greater than trigger_offset by more than the ring buffer depth (pretrig entries) | |
457 | ring_samples=(pre_trigger_samples>trigger_offset) ? pre_trigger_samples-trigger_offset : 0; | |
458 | sr_spew("SW trigger float info newstart %zu new_end %zu new_samp %zu ring_samp %zu",new_start,new_end,new_samples,ring_samples); | |
459 | if(ring_samples>0){ | |
460 | send_analog_ring(sdi,devc,ring_samples); | |
461 | } | |
462 | if(new_samples){ | |
463 | send_analog(sdi,devc,new_samples,new_start); | |
464 | } | |
465 | ||
466 | }//if trigger_offset | |
467 | else { //We didn't trigger but need to copy to ring buffer | |
468 | if((devc->a_chan_mask)&&(devc->pretrig_entries)){ | |
469 | //The incoming data buffer could be much larger than the ring buffer, so never copy more than | |
470 | //the size of the ring buffer | |
471 | num_ring_samples=num_slices > devc->pretrig_entries ? devc->pretrig_entries : num_slices; | |
472 | sptr=devc->pretrig_wr_ptr; //starting pointer to copy to | |
473 | //endptr can't go past the end | |
474 | eptr=(sptr+num_ring_samples)>=devc->pretrig_entries ? devc->pretrig_entries-1 : sptr+num_ring_samples-1; | |
475 | numtail=(eptr-sptr)+1; //number of samples to copy to the tail of ring buffer without wrapping | |
476 | numwrap=(num_ring_samples>numtail) ? num_ring_samples-numtail:0; | |
477 | //cbuf_wrptr points to where the next write should go, not theactual write data | |
478 | srcptr=cbuf_wrptr_cpy-num_ring_samples; | |
479 | sr_spew("RNG num %zu sptr %zu eptr %zu ",num_ring_samples,sptr,eptr); | |
480 | //sr_spew("RNG srcptr %zu nt %zu nw %zu",srcptr,numtail,numwrap); | |
481 | for(i=0;i<devc->num_a_channels;i++){ | |
482 | if((devc->a_chan_mask>>i)&1){ | |
483 | //copy tail | |
484 | for(uint32_t j=0;j<numtail;j++){ | |
485 | devc->a_pretrig_bufs[i][sptr+j]=devc->a_data_bufs[i][srcptr+j]; | |
486 | //sr_spew("RNGCpyT C%d src %zu dest %zu",i,srcptr+j,sptr+j); | |
487 | }//for j | |
488 | } //if chan_mask | |
489 | }//for channels | |
490 | //Copy wrap | |
491 | srcptr+=numtail; | |
492 | for(i=0;i<devc->num_a_channels;i++){ | |
493 | if((devc->a_chan_mask>>i)&1){ | |
494 | for(uint32_t j=0;j<numwrap;j++){ | |
495 | devc->a_pretrig_bufs[i][j]=devc->a_data_bufs[i][srcptr+j]; | |
496 | //sr_spew("RNGCpyW C%d src %zu dest %zu",i,srcptr+j,j); | |
497 | }//for j | |
498 | }//if chan_mask | |
499 | }//for channels | |
500 | devc->pretrig_wr_ptr=(numwrap) ? numwrap : (eptr+1)%devc->pretrig_entries; | |
501 | //sr_dbg("RNG pwrptr new %u",devc->pretrig_wr_ptr); | |
502 | }//if any analog channel enabled and pretrig_entries | |
503 | }//else (trigger not detected) | |
504 | }//trigger not set on function entry | |
505 | return 0; | |
506 | }//process_group | |
507 | ||
508 | ||
509 | //Duplicate previous sample values | |
510 | //This function relies on the caller to ensure d_data_buf has samples to handle the full value of the rle | |
511 | void rle_memset(struct dev_context *devc,uint32_t num_slices){ | |
512 | uint32_t j,k; | |
513 | sr_spew("rle_memset val 0x%X,slices %d dsb %ld\n",devc->d_last[0],num_slices,devc->dig_sample_bytes); | |
514 | //Even if a channel is disabled, PV expects the same location and size for the enabled | |
515 | // channels as if the channel were enabled. | |
516 | for(j=0;j<num_slices;j++){ | |
517 | for(k=0;k<devc->dig_sample_bytes;k++){ | |
518 | devc->d_data_buf[devc->cbuf_wrptr++]=devc->d_last[k]; | |
519 | //sr_spew("k %d j %d v 0x%X",k,j,devc->d_data_buf[(devc->cbuf_wrptr)-1]); | |
520 | } | |
521 | } | |
522 | } | |
523 | ||
524 | //This callback function is mapped from api.c with serial_source_add and is created after a capture | |
525 | //has been setup and is responsible for querying the device trigger status, downloading data | |
526 | //and forwarding packets | |
527 | SR_PRIV int raspberrypi_pico_receive(int fd, int revents, void *cb_data) | |
dc90146e | 528 | { |
bac2a8b8 A |
529 | struct sr_dev_inst *sdi; |
530 | struct dev_context *devc; | |
531 | struct sr_serial_dev_inst *serial; | |
532 | uint32_t i; | |
533 | int len; | |
534 | uint32_t bytes_rem; | |
535 | uint32_t residual_bytes; | |
536 | (void)fd; | |
537 | ||
538 | if (!(sdi = cb_data)) | |
539 | return TRUE; | |
540 | ||
541 | if (!(devc = sdi->priv)) | |
542 | return TRUE; | |
543 | if(devc->rxstate!=RX_ACTIVE){ | |
544 | //This condition is normal operation and expected to happen | |
545 | //but printed as information | |
546 | sr_dbg("Reached non active state in receive %d",devc->rxstate); | |
547 | //don't return - we may be waiting for a final bytecnt | |
548 | //return TRUE; | |
549 | } | |
550 | if(devc->rxstate==RX_IDLE){ | |
551 | //This is the normal end condition where we do one more receive | |
552 | //to make sure we get the full byte_cnt | |
553 | sr_dbg("Reached idle state in receive %d",devc->rxstate); | |
554 | return FALSE; | |
555 | } | |
dc90146e | 556 | |
bac2a8b8 A |
557 | serial = sdi->conn; |
558 | //return true if it is some kind of event we don't handle | |
559 | if (!(revents == G_IO_IN || revents == 0)) | |
560 | return TRUE; | |
561 | //Fill the buffer, note the end may have partial slices | |
562 | bytes_rem=devc->serial_buffer_size - devc->wrptr; | |
563 | //Read one byte less so that we can null it and print as a string | |
564 | //Do a small 10ms timeout, if we get nothing, we'll always come back again | |
565 | len=serial_read_blocking(serial, &(devc->buffer[devc->wrptr]), bytes_rem-1,10); | |
566 | sr_spew("Entry wrptr %u bytes_rem %u len %d",devc->wrptr,bytes_rem,len); | |
dc90146e | 567 | |
bac2a8b8 A |
568 | if(len>0){ |
569 | devc->buffer[devc->wrptr+len]=0; | |
570 | //Add the "#" so that spaces are clearly seen | |
571 | sr_dbg("rx string %s#",devc->buffer); | |
572 | //This is not guaranteed to be a dataloss condition, but definitely indicates we are | |
573 | //processing data right at the incoming rate. | |
574 | //With the addition of the byte_cnt sent at the end we will detect any dataloss conditions | |
575 | //and thus this is disabled | |
576 | //if(len>=(int)bytes_rem-8){ | |
577 | // sr_err("ERROR: Serial buffer near or at max depth, data from device may have been lost"); | |
578 | //} | |
579 | devc->bytes_avail=(devc->wrptr+len); | |
580 | sr_spew("rx len %d bytes_avail %ul sent_samples %ul wrptr %u",len,devc->bytes_avail,devc->sent_samples,devc->wrptr); | |
581 | //sr_err("rx len %d ",len); | |
582 | }else if (len==0){ | |
583 | return TRUE; | |
584 | }else { | |
585 | sr_err("ERROR:Negative serial read code %d",len); | |
586 | sdi->driver->dev_acquisition_stop(sdi); | |
587 | return FALSE; | |
588 | }//len>0 | |
589 | //This can be used as a bit bucket to drop all samples to see how host processing time effects | |
590 | //the devices ability to send data. Obviously no data will be forwarded to the session so it will hang | |
591 | // return TRUE; | |
dc90146e | 592 | |
bac2a8b8 A |
593 | //Process the serial read data |
594 | devc->ser_rdptr=0; | |
595 | if(devc->rxstate==RX_ACTIVE){ | |
596 | if((devc->a_chan_mask==0)&&((devc->d_chan_mask&0xFFFFFFF0)==0)){ | |
597 | process_D4(sdi,devc); | |
598 | }else{ | |
599 | process_slice(sdi,devc); | |
600 | } | |
601 | } | |
602 | //process_slice/process_D4 increment ser_rdptr as bytes of the serial buffer are used | |
603 | //But they may not use all of it, and thus the residual unused bytes are shifted to the start of the buffer | |
604 | //for the next call. | |
605 | residual_bytes=devc->bytes_avail - devc->ser_rdptr; | |
606 | //sr_spew("Residuals resid %d avail %d rdptr %d wrptr %d\n",residual_bytes,devc->bytes_avail,devc->ser_rdptr,devc->wrptr); | |
607 | if(residual_bytes){ | |
608 | for(i=0;i<residual_bytes;i++){ | |
609 | devc->buffer[i]=devc->buffer[i+devc->ser_rdptr]; | |
610 | } | |
611 | devc->ser_rdptr=0; | |
612 | devc->wrptr=residual_bytes; | |
613 | sr_spew("Residual shift rdptr %u wrptr %u",devc->ser_rdptr,devc->wrptr); | |
614 | }else{ | |
615 | //If there are no residuals shifted then zero the wrptr since all data is used | |
616 | devc->wrptr=0; | |
617 | } | |
618 | //ABORT ends immediately | |
619 | if(devc->rxstate==RX_ABORT){ | |
620 | sr_err("Ending receive on abort"); | |
621 | sdi->driver->dev_acquisition_stop(sdi); | |
622 | return FALSE;// | |
623 | } | |
624 | //if stopped look for final '+' indicating the full byte_cnt is received | |
625 | if(devc->rxstate==RX_STOPPED){ | |
626 | sr_dbg("Stopped, checking byte_cnt"); | |
627 | if(devc->buffer[0]!='$'){ | |
628 | //If this happens it means that we got a set of data that was not processed as | |
629 | //whole groups of slice bytes. So either we lost data or are not parsing it correctly. | |
630 | sr_err("ERROR: Stop marker should be byte zero"); | |
631 | devc->rxstate=RX_ABORT; | |
632 | sdi->driver->dev_acquisition_stop(sdi); | |
633 | return FALSE; | |
634 | } | |
635 | for(i=1;i<devc->wrptr;i++){ | |
636 | if(devc->buffer[i]=='+'){ | |
637 | devc->buffer[i]=0; | |
638 | uint64_t rxbytecnt; | |
639 | rxbytecnt=atol(&(devc->buffer[1])); | |
640 | sr_dbg("Byte_cnt check device cnt %llu host cnt %llu",rxbytecnt,devc->byte_cnt); | |
641 | if(rxbytecnt!=devc->byte_cnt){ | |
642 | sr_err("ERROR: received %llu and counted %llu bytecnts don't match, data may be lost",rxbytecnt,devc->byte_cnt); | |
643 | } | |
644 | //Since we got the bytecnt we know the device is done sending data | |
645 | devc->rxstate=RX_IDLE; | |
646 | //We must always call acquisition_stop on all completed runs | |
647 | sdi->driver->dev_acquisition_stop(sdi); | |
648 | return TRUE; | |
649 | } | |
650 | } | |
651 | //It's possible we need one more serial transfer to get the byte_cnt, so print that here | |
652 | sr_dbg("Haven't seen byte_cnt + yet"); | |
653 | }//RX_STOPPED | |
654 | //If at the sample limit, send a "+" in case we are in continuous mode and need | |
655 | //to stop the device. Not that even in non continous mode there might be cases where get an extra | |
656 | //sample or two... | |
dc90146e | 657 | |
bac2a8b8 A |
658 | if((devc->sent_samples>=devc->limit_samples)&&(devc->rxstate==RX_ACTIVE)){ |
659 | sr_dbg("Ending: sent %u of limit %llu samples byte_cnt %llu", | |
660 | devc->sent_samples,devc->limit_samples,devc->byte_cnt); | |
661 | send_serial_char(serial,'+'); | |
662 | ||
663 | } | |
664 | sr_spew("Receive function done: sent %u limit %llu wrptr %u len %d",devc->sent_samples,devc->limit_samples,devc->wrptr,len); | |
665 | return TRUE; | |
666 | }//raspberrypi_pico_receive | |
667 | ||
668 | //Read device specific information from the device | |
669 | SR_PRIV int raspberrypi_pico_get_dev_cfg(const struct sr_dev_inst *sdi) | |
670 | { | |
671 | struct dev_context *devc; | |
672 | struct sr_serial_dev_inst *serial; | |
673 | char *cmd, response[20]; | |
674 | gchar **tokens; | |
675 | unsigned int i; | |
676 | int ret,num_tokens; | |
677 | ||
678 | devc = sdi->priv; | |
679 | sr_dbg("At get_dev_cfg"); | |
680 | serial = sdi->conn; | |
681 | for(i=0;i<devc->num_a_channels;i++){ | |
682 | cmd = g_strdup_printf("a%d\n",i); | |
683 | ret = send_serial_w_resp(serial,cmd,response,20); | |
684 | if(ret<=0){ | |
685 | sr_err("ERROR:No response from device for analog channel query"); | |
686 | return SR_ERR; | |
687 | } | |
688 | //null end of string for strsplit | |
689 | response[ret]=0; | |
690 | tokens=NULL; | |
691 | tokens = g_strsplit(response, "x", 0); | |
692 | num_tokens = g_strv_length(tokens); | |
693 | if (num_tokens == 2) { | |
694 | devc->a_scale[i]=((float)atoi(tokens[0]))/1000000.0; | |
695 | devc->a_offset[i]=((float)atoi(tokens[1]))/1000000.0; | |
696 | sr_dbg("A%d scale %f offset %f response #%s# tokens #%s# #%s#\n",i,devc->a_scale[i],devc->a_offset[i],response,tokens[0],tokens[1]); | |
697 | }else{ | |
698 | sr_err("ERROR:Ascale read c%d got unparseable response %s tokens %d",i,response,num_tokens); | |
699 | //force a legal fixed value assuming a 3.3V scale | |
700 | //a failue in parsing the scale | |
701 | devc->a_scale[i]=0.0257; | |
702 | devc->a_offset[i]=0.0; | |
703 | } | |
704 | g_strfreev(tokens); | |
705 | g_free(cmd); | |
706 | } | |
707 | ||
708 | ||
709 | return SR_OK; | |
dc90146e | 710 | |
dc90146e | 711 | } |
bac2a8b8 | 712 |