From: AC0BI Date: Wed, 13 Apr 2022 03:26:42 +0000 (-0600) Subject: raspberrypi-pico: Rev2 updates X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=0c79290002a927a4afd92692566ce67136f306e7;p=libsigrok.git raspberrypi-pico: Rev2 updates --- diff --git a/src/hardware/raspberrypi-pico/api.c b/src/hardware/raspberrypi-pico/api.c index 3842864b..90655701 100644 --- a/src/hardware/raspberrypi-pico/api.c +++ b/src/hardware/raspberrypi-pico/api.c @@ -38,15 +38,59 @@ static const uint32_t scanopts[] = { SR_CONF_CONN, //Required OS name for the port, i.e. /dev/ttyACM0 SR_CONF_SERIALCOMM, //Optional config of the port, i.e. 115200/8n1 }; - -//PulseView reads a sample rate config list as a min, max and step. -//If step is 1 then it creates a 1,2,5,10 set of selects, as well as the max. -//If step is not 1, then it gives a place to enter any value, which gives the greatest flexibility +//The host can either provide a std_gvar_samplerates_steps or a std_gvar_samplerates. +//The latter is just a long list of every supported rate. +//For the steps, pulseview/pv/toolbars/mainbar.cpp will do a min,max,step. If step is +//1 then it provides a 1,2,5,10 select otherwise it allows a spin box. +//Going with the full list because while the spin box is more flexible, it is harder to read +/* static const uint64_t samplerates[] = { SR_HZ(10), SR_MHZ(120), SR_HZ(2), }; +*/ +static const uint64_t samplerates[] = { + SR_KHZ(5), + SR_KHZ(6), + SR_KHZ(8), + SR_KHZ(10), + SR_KHZ(20), + SR_KHZ(30), + SR_KHZ(40), + SR_KHZ(50), + SR_KHZ(60), + SR_KHZ(80), + SR_KHZ(100), + SR_KHZ(125), + SR_KHZ(150), + SR_KHZ(160),//max rate of 3 ADC channels that has integer divisor/dividend + SR_KHZ(200), + SR_KHZ(250), //max rate of 2 ADC channels + SR_KHZ(300), + SR_KHZ(400), + SR_KHZ(500), + SR_KHZ(600), + SR_KHZ(800), + //Give finer granularity near the thresholds of RLE effectiveness + SR_MHZ(1), + SR_MHZ(1.25), + SR_MHZ(1.5), + SR_MHZ(2), + SR_MHZ(2.5), + SR_MHZ(3), + SR_MHZ(4), + SR_MHZ(5), + SR_MHZ(6), + SR_MHZ(8), + SR_MHZ(10), + SR_MHZ(15), + SR_MHZ(20), + SR_MHZ(30), + SR_MHZ(40), + SR_MHZ(60), + SR_MHZ(120) +}; static const uint32_t drvopts[] = { SR_CONF_OSCILLOSCOPE, @@ -151,12 +195,12 @@ static GSList *scan(struct sr_dev_driver *di, GSList * options) } //Expected ID response is SRPICO,AxxyDzz,VV //where xx are number of analog channels, y is bytes per analog sample - //and zz is number of digital channels, and VV is two digit version# which must be 00 + //and zz is number of digital channels, and VV is two digit version# which must be 02 if ((num_read < 16) || (strncmp(buf, "SRPICO,A", 8)) || (buf[11] != 'D') || (buf[15] != '0') - || (buf[16] != '0')) { + || (buf[16] != '2')) { sr_err("ERROR:Bad response string %s %d", buf, num_read); return NULL; } @@ -248,8 +292,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList * options) //Note: The intent of making this buffer large is to prevent CDC serial buffer overflows. //However, it is likely that if the host is running slow (i.e. it's a raspberry pi model 3) that it becomes //compute bound and doesn't service CDC serial responses in time to not overflow the internal CDC buffers. - //And thus no serial buffer is large enough. But, it's only 256K.... - devc->serial_buffer_size = 256000; + //And thus no serial buffer is large enough. But, it's only 32K.... + devc->serial_buffer_size = 32000; devc->buffer = NULL; sr_dbg("Setting serial buffer size: %i.", devc->serial_buffer_size); @@ -257,11 +301,12 @@ static GSList *scan(struct sr_dev_driver *di, GSList * options) //While slices are sent as a group of one sample across all channels, sigrok wants analog //channel data sent as separate packets. //Logical trace values are packed together. - //A serial byte in normal mode never represent more than one sample so a 2x multiplier is plenty. - //In D4 mode a serial byte can represents 100s of samples due to RLE, but process_D4 ensures that - //it breaks up the rle_memset calls to prevent overflowing the sample buffer. - //that it doesn't overflow the sample buffers. - devc->sample_buf_size = devc->serial_buffer_size * 2; + //An RLE byte in normal mode can represent up to 1640 samples. + //In D4 an RLE byte can represents up to 640 samples. + //Rather than making the sample_buf_size 1640x the size of serial buff, we require that the process loops + //push samples to the session as we get anywhere close to full. + + devc->sample_buf_size = devc->serial_buffer_size; for (i = 0; i < devc->num_a_channels; i++) { devc->a_data_bufs[i] = NULL; devc->a_pretrig_bufs[i] = NULL; @@ -377,12 +422,12 @@ static int config_list(uint32_t key, GVariant ** data, } sr_dbg("start config_list with key %X\n", key); switch (key) { -//Pulseview in pulseview/pv/toolbars/mainbar.cpp requires list support for frequencies as a triple -//of min,max,step. If step is 1, then it proves a 1,2,5,10 select, but if not 1 it allows a spin box case SR_CONF_SAMPLERATE: sr_dbg("Return sample rate list"); *data = - std_gvar_samplerates_steps(ARRAY_AND_SIZE +// std_gvar_samplerates_steps(ARRAY_AND_SIZE +// (samplerates)); + std_gvar_samplerates(ARRAY_AND_SIZE (samplerates)); break; //This must be set to get SW trigger support @@ -500,16 +545,10 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) sr_dbg("bps %d\n", devc->bytes_per_slice); //Apply sample rate limits - //Save off the lower rate values which are hacked way of getting configs to the device - uint8_t cfg_bits; - cfg_bits = (devc->sample_rate % 10 & 0x6); //Only bits 2&1 are used as cfg_bits - devc->sample_rate -= cfg_bits; - sr_warn("Capture device cfg_bits of 0x%X from sample rate %lld", - cfg_bits, devc->sample_rate); - if ((a_enabled == 3) && (devc->sample_rate > 166660)) { + if ((a_enabled == 3) && (devc->sample_rate > 160000)) { sr_err - ("ERROR:3 channel ADC sample rate dropped to 166.660khz"); - devc->sample_rate = 166660; + ("ERROR:3 channel ADC sample rate dropped to 160khz"); + devc->sample_rate = 160000; } if ((a_enabled == 2) && (devc->sample_rate > 250000)) { sr_err @@ -543,15 +582,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) //Always increment the divisor so that we go down in frequency to avoid max sample rate issues commondivint++; devc->sample_rate = 24000000ULL / commondivint; - //While the common divisor is an integer, that does not mean the resulting sample rate is, and - //we want to keep the sample_rate divisible by 10 to support the cfg_bits - while ((devc->sample_rate % 10) - && (commondivint < 4800)) { - commondivint++; - devc->sample_rate = - 24000000ULL / commondivint; - //sr_err(" sample rate of %llu div %u\n\r",devc->sample_rate,commondivint); - } //Make sure the divisor increement didn't make use go too low. if (devc->sample_rate < 5000) { devc->sample_rate = 50000; @@ -580,20 +610,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) } } - //modulo 10 to add cfg_bits back in - //All code above should create overrides that are multiples of 10, but add a check just in case. - if (devc->sample_rate % 10) { - sr_err("Output sample rate %llu not mod 10", - devc->sample_rate); - devc->sample_rate = (devc->sample_rate / 10) * 10; - } - - devc->sample_rate += cfg_bits; - if (cfg_bits) { - sr_warn - ("Embedding cfg_bits of 0x%X in sample_rate %lld\n\r", - cfg_bits, devc->sample_rate); - } sprintf(&tmpstr[0], "R%llu\n", devc->sample_rate); if (send_serial_w_ack(serial, tmpstr) != SR_OK) { sr_err("Sample rate to device failed"); @@ -638,10 +654,62 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) return SR_ERR_MALLOC; } } - + devc->pretrig_entries = + (devc->capture_ratio * devc->limit_samples) / 100; + //While the driver supports the passing of trigger info to the device + //it has been found that the sw overhead of supporting triggering and + //pretrigger buffer entries etc.. ends up slowing the cores down enough + //that the effect continous sample rate isn't much higher than that of sending + //untriggered samples across USB. Thus this code will remain but likely may + //not be used by the device. if ((trigger = sr_session_trigger_get(sdi->session))) { - devc->pretrig_entries = - (devc->capture_ratio * devc->limit_samples) / 100; + if (g_slist_length(trigger->stages) > 1) + return SR_ERR_NA; + + struct sr_trigger_stage *stage; + struct sr_trigger_match *match; + GSList *l; + stage = g_slist_nth_data(trigger->stages, 0); + if (!stage) + return SR_ERR_ARG; + for (l = stage->matches; l; l = l->next) { + match = l->data; + if (!match->match) + continue; + if (!match->channel->enabled) + continue; + int idx = match->channel->index; + int8_t val; + switch(match->match){ + case SR_TRIGGER_ZERO: + val=0; break; + case SR_TRIGGER_ONE: + val=1; break; + case SR_TRIGGER_RISING: + val=2; break; + case SR_TRIGGER_FALLING: + val=3; break; + case SR_TRIGGER_EDGE: + val=4; break; + default: + val=-1; + } + sr_info("Trigger value idx %d match %d",idx,match->match); + //Only set trigger on enabled channels + if((val>=0) && ((devc->d_chan_mask>>idx)&1)){ + sprintf(&tmpstr[0], "t%d%02d\n", val,idx+2); + if (send_serial_w_ack(serial, tmpstr) != SR_OK) { + sr_err("Trigger cfg to device failed"); + return SR_ERR; + } + + } + } + sprintf(&tmpstr[0], "p%d\n", devc->pretrig_entries); + if (send_serial_w_ack(serial, tmpstr) != SR_OK) { + sr_err("Pretrig to device failed"); + return SR_ERR; + } devc->stl = soft_trigger_logic_new(sdi, trigger, devc->pretrig_entries); diff --git a/src/hardware/raspberrypi-pico/protocol.c b/src/hardware/raspberrypi-pico/protocol.c index a9ca4723..2bae2f19 100644 --- a/src/hardware/raspberrypi-pico/protocol.c +++ b/src/hardware/raspberrypi-pico/protocol.c @@ -130,7 +130,6 @@ void process_D4(struct sr_dev_inst *sdi, struct dev_context *d) uint8_t cbyte; uint8_t cval; uint32_t rlecnt = 0; - uint32_t sampcnt = 0; //number of samples received with no rles while (d->ser_rdptr < d->bytes_avail) { cbyte = d->buffer[(d->ser_rdptr)]; //RLE only byte @@ -141,46 +140,24 @@ void process_D4(struct sr_dev_inst *sdi, struct dev_context *d) rlecnt += (cbyte & 0x70) >> 4; if (rlecnt) { //On a value change, duplicate the previous values first. - //The maximum value of one rle is 640. - //To ensure we don't overflow the sample buffer but still send it large chunks of data - //(to make the packet sends to the session efficient) only call process group after - //a large number of samples have been seen. - //Likely we could use the max rle value of 640 but 2048 gives some extra room. - if ((rlecnt + d->cbuf_wrptr) > - (d->sample_buf_size - 2048)) { - //process_group is sent the number of slices which is just the cbufwrptr divided by the slice size - //This modulo check should never happen as long the calculations for dig_sample_bytes etc are - //correct, but it's a good cross check for code development. - if ((d->cbuf_wrptr) % - (d->dig_sample_bytes)) { - sr_err - ("Modulo fail %d %d ", - d->cbuf_wrptr, - d->dig_sample_bytes); - } - process_group(sdi, d, - (d->cbuf_wrptr / - d->dig_sample_bytes)); - } rle_memset(d, rlecnt); rlecnt = 0; - sampcnt = 0; } //Finally add in the new values cval = cbyte & 0xF; - d->d_data_buf[d->cbuf_wrptr++] = cval; + uint32_t didx=(d->cbuf_wrptr) * (d->dig_sample_bytes); + d->d_data_buf[didx] = cval; //pad in all other bytes since the sessions even wants disabled channels reported for (j = 1; j < d->dig_sample_bytes; j++) { - d->d_data_buf[d->cbuf_wrptr++] = 0; + d->d_data_buf[didx+j] = 0; } - sampcnt++; d->byte_cnt++; sr_spew - ("Dchan4 rdptr %d wrptr %d bytein 0x%X rle %d cval 0x%X\n", + ("Dchan4 rdptr %d wrptr %d bytein 0x%X rle %d cval 0x%X didx %d\n", (d->ser_rdptr) - 1, d->cbuf_wrptr, cbyte, - rlecnt, cval); + rlecnt, cval,didx); + d->cbuf_wrptr++; rlecnt = 0; - d->d_last[0] = cval; } //Any other character ends parsing - it could be a frame error or a start of the final byte cnt @@ -201,26 +178,35 @@ void process_D4(struct sr_dev_inst *sdi, struct dev_context *d) break; //break from while loop } (d->ser_rdptr)++; - } //while rdptr < wrptr + //To ensure we don't overflow the sample buffer, but still send it large chunks of data + //(to make the packet sends to the session efficient) only call process group after + //a large number of samples have been seen. + //cbuf_wrptr counts slices, so shift right by 2 to create a worst case x4 multiple ratio of + //cbuf_wrptr value to the depth of the sample buffer. + //Likely we could use the max rle value of 640 but 1024 gives some extra room. + //Also do a simple check of rlecnt>2000 since that is a reasonable minimal value to send to the session + if ((rlecnt>=2000) + ||((rlecnt + ((d->cbuf_wrptr)<<2))) > (d->sample_buf_size - 1024)) { + sr_spew("D4 preoverflow wrptr %d bufsize %d rlecnt %d\n\r",d->cbuf_wrptr,d->sample_buf_size,rlecnt); + rle_memset(d, rlecnt); + process_group(sdi, d, d->cbuf_wrptr); + rlecnt=0; + } + + }//while rdptr < wrptr sr_spew("D4 while done rdptr %d", d->ser_rdptr); //If we reach the end of the serial input stream send any remaining values or rles to the session - /*this can also be skipped now the rle_memset handles cbufwrptr - if(sampcnt){ - process_group(sdi,d,sampcnt); - sampcnt=0; - } - */ if (rlecnt) { sr_spew("Residual D4 slice rlecnt %d", rlecnt); rle_memset(d, rlecnt); } if (d->cbuf_wrptr) { sr_spew("Residual D4 data wrptr %d", d->cbuf_wrptr); - process_group(sdi, d, d->cbuf_wrptr / d->dig_sample_bytes); + process_group(sdi, d, d->cbuf_wrptr); } -} //Process_D4 +} //Process_D4 //Process incoming data stream and forward to trigger processing with process_group //The final value of ser_rdptr indicates how many bytes were processed. @@ -230,12 +216,11 @@ void process_slice(struct sr_dev_inst *sdi, struct dev_context *devc) int32_t i; uint32_t tmp32; uint8_t cbyte; - uint32_t slices_avail = 0; uint32_t cword; - uint32_t slice_bytes; //number of bytes that have legal slice values - //Only process legal data values for this mode which are >=0x80 + uint32_t slice_bytes; //number of bytes that have legal slice values including RLE + //Only process legal data values for this mode which are 0x32-0x7F for RLE and 0x80 to 0xFF for data for (slice_bytes = 1; (slice_bytes < devc->bytes_avail) - && (devc->buffer[slice_bytes - 1] >= 0x80); slice_bytes++); + && (devc->buffer[slice_bytes - 1] >= 0x30); slice_bytes++); if (slice_bytes != devc->bytes_avail) { cbyte = devc->buffer[slice_bytes - 1]; slice_bytes--; //Don't process the ending character @@ -258,12 +243,26 @@ void process_slice(struct sr_dev_inst *sdi, struct dev_context *devc) sr_spew("process slice avail %d rdptr %d sb %d byte_cnt %lld", devc->bytes_avail, devc->ser_rdptr, slice_bytes, devc->byte_cnt); - //Must have a full slice - while ((devc->ser_rdptr + devc->bytes_per_slice) <= slice_bytes) { - //The use of devc->cbuf_wrptr is different between analog and digital. - //For analog it targets a float sized offset for that channel's buffer - //For digital it targets a bit, so the 3 lsbs are bit offsets within a byte - slices_avail++; + //Must have a full slice or one rle byte + while (((devc->ser_rdptr + devc->bytes_per_slice) <= slice_bytes) + ||((devc->ser_rdptr < slice_bytes)&&(devc->buffer[devc->ser_rdptr] < 0x80))) { + + if(devc->buffer[devc->ser_rdptr] < 0x80){ + int16_t rlecnt; + if(devc->buffer[devc->ser_rdptr]<=79){ + rlecnt=devc->buffer[devc->ser_rdptr]-47; + }else{ + rlecnt=(devc->buffer[devc->ser_rdptr]-78)*32; + } + sr_info("RLEcnt of %d in %d",rlecnt,devc->buffer[devc->ser_rdptr]); + if((rlecnt < 1)||(rlecnt>1568)){ + sr_err("Bad rlecnt val %d in %d",rlecnt,devc->buffer[devc->ser_rdptr]); + }else{ + rle_memset(devc,rlecnt); + } + devc->ser_rdptr++; + + }else{ cword = 0; //build up a word 7 bits at a time, using only enabled channels for (i = 0; i < devc->num_d_channels; i += 7) { @@ -275,6 +274,11 @@ void process_slice(struct sr_dev_inst *sdi, struct dev_context *devc) } } //and then distribute 8 bits at a time to all possible channels + //but first save of cword for rle + devc->d_last[0]=cword&0xFF; + devc->d_last[1]=(cword>>8)&0xFF; + devc->d_last[2]=(cword>>16)&0xFF; + devc->d_last[3]=(cword>>24)&0xFF; for (i = 0; i < devc->num_d_channels; i += 8) { uint32_t idx = ((devc->cbuf_wrptr) * devc->dig_sample_bytes) + @@ -286,6 +290,7 @@ void process_slice(struct sr_dev_inst *sdi, struct dev_context *devc) devc->d_data_buf[idx], cword); cword >>= 8; } + //Each analog value is a 7 bit value for (i = 0; i < devc->num_a_channels; i++) { if ((devc->a_chan_mask >> i) & 1) { @@ -308,9 +313,19 @@ void process_slice(struct sr_dev_inst *sdi, struct dev_context *devc) } //if channel enabled } //for num_a_channels devc->cbuf_wrptr++; - } //While another slice available - if (slices_avail) { - process_group(sdi, devc, slices_avail); + }//Not an RLE + //RLEs can create a large number of samples relative to the incoming serial buffer + //To prevent overflow of the sample data buffer we call process_group. + //cbuf_wrptr and sample_buf_size are both in terms of slices + //2048 is more than needed for a max rle of 1640 on the next incoming character + if((devc->cbuf_wrptr +2048) > devc->sample_buf_size){ + sr_spew("Drain large buff %d %d\n\r",devc->cbuf_wrptr,devc->sample_buf_size); + process_group(sdi, devc, devc->cbuf_wrptr); + + } + }//While another slice or RLE available + if (devc->cbuf_wrptr){ + process_group(sdi, devc, devc->cbuf_wrptr); } } @@ -462,8 +477,8 @@ int process_group(struct sr_dev_inst *sdi, struct dev_context *devc, sr_spew ("Process_group sending %d post trig samples dsb %d", num_samples, devc->dig_sample_bytes); - //for(int z=0;(zd_data_buf[z]); + //for(int z=0;(zd_data_buf[z]); //} if (devc->num_d_channels) { packet.type = SR_DF_LOGIC; @@ -651,18 +666,22 @@ int process_group(struct sr_dev_inst *sdi, struct dev_context *devc, //This function relies on the caller to ensure d_data_buf has samples to handle the full value of the rle void rle_memset(struct dev_context *devc, uint32_t num_slices) { - uint32_t j, k; - sr_spew("rle_memset val 0x%X,slices %d dsb %d\n", devc->d_last[0], + uint32_t j, k,didx; + sr_spew("rle_memset vals 0x%X, 0x%X, 0x%X slices %d dsb %d\n", devc->d_last[0],devc->d_last[1],devc->d_last[2], num_slices, devc->dig_sample_bytes); //Even if a channel is disabled, PV expects the same location and size for the enabled // channels as if the channel were enabled. for (j = 0; j < num_slices; j++) { + didx=devc->cbuf_wrptr*devc->dig_sample_bytes; for (k = 0; k < devc->dig_sample_bytes; k++) { - devc->d_data_buf[devc->cbuf_wrptr++] = - devc->d_last[k]; - //sr_spew("k %d j %d v 0x%X",k,j,devc->d_data_buf[(devc->cbuf_wrptr)-1]); + devc->d_data_buf[didx + k] = devc->d_last[k]; + // sr_spew("k %d j %d v 0x%X p %d didx %d",k,j,devc->d_data_buf[(devc->cbuf_wrptr)+k],(devc->cbuf_wrptr)+k,didx); } + // cbuf_wrptr always counts slices/samples (and not the bytes in the buffer) + // regardless of mode + devc->cbuf_wrptr++; } + } //This callback function is mapped from api.c with serial_source_add and is created after a capture diff --git a/src/hardware/raspberrypi-pico/protocol.h b/src/hardware/raspberrypi-pico/protocol.h index 8443003c..6a8566ec 100644 --- a/src/hardware/raspberrypi-pico/protocol.h +++ b/src/hardware/raspberrypi-pico/protocol.h @@ -123,7 +123,7 @@ struct dev_context { /* RLE related*/ /*Previous sample values to duplicate for rle */ float a_last[MAX_ANALOG_CHANNELS]; - uint8_t d_last[MAX_DIGITAL_CHANNELS / 8]; + uint8_t d_last[4]; /* SW Trigger Related */ struct soft_trigger_logic *stl;