* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-//debug print levels are err/warn/info/dbg/spew
#include <config.h>
#include <fcntl.h>
#include <glib.h>
#include "libsigrok-internal.h"
#include "protocol.h"
-//Baud rate is really a don't care because we run USB CDC, dtr must be 1.
-//flow should be zero since we don't
-//use xon/xoff
+/*Baud rate is really a don't care because we run USB CDC, dtr must be 1.
+flow should be zero since we don't use xon/xoff
+*/
#define SERIALCOMM "115200/8n1/dtr=1/rts=0/flow=0"
+/* Use the force_detect scan option as a way to pass user information to the device
+ the string must use only 0-9,a-z,A-Z,'.','=' and '-'* and be less than 60 characters */
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
+ 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 */
+ SR_CONF_FORCE_DETECT
};
-//Sample rate 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
+/*Sample rate 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_KHZ(5),
SR_KHZ(6),
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(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(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 ~1-4Msps
- //Also use 1.2 and 2.4 as likely max values for ADC overclocking
+ /*Give finer granularity near the thresholds of RLE effectiveness ~1-4Msps
+ Also use 1.2 and 2.4 as likely max values for ADC overclocking */
SR_MHZ(1),
SR_MHZ(1.2),
SR_MHZ(1.5),
SR_MHZ(30),
SR_MHZ(40),
SR_MHZ(60),
- //The baseline 120Mhz PICO clock won't support an 80 or 100
- //with non fractional divisor, but an overclocked version or one
- //that modified sysclk could
+ /*The baseline 120Mhz PICO clock won't support an 80 or 100
+ with non fractional divisor, but an overclocked version or one
+ that modified sysclk could */
SR_MHZ(80),
SR_MHZ(100),
SR_MHZ(120),
- //These may not be practically useful, but someone might want to
- //try to make it work with overclocking
+ /*These may not be practically useful, but someone might want to
+ try to make it work with overclocking */
SR_MHZ(150),
SR_MHZ(200),
SR_MHZ(240)
SR_CONF_LOGIC_ANALYZER,
};
-//SW trigger requires this
static const int32_t trigger_matches[] = {
SR_TRIGGER_ZERO,
SR_TRIGGER_ONE,
static const uint32_t devopts[] = {
-//CLI prefers LIMIT_SAMPLES to be a list of high,low
SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
-//pulseview needs a list return to allow sample rate setting
SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
};
struct sr_channel *ch;
GSList *l;
int num_read;
- unsigned int i;
- const char *conn, *serialcomm;
+ int i;
+ const char *conn,*serialcomm,*force_detect;
char buf[32];
+ char ustr[64];
int len;
uint8_t num_a, num_d, a_size;
gchar *channel_name;
- conn = serialcomm = NULL;
+ conn = serialcomm = force_detect = NULL;
for (l = options; l; l = l->next) {
src = l->data;
switch (src->key) {
case SR_CONF_SERIALCOMM:
serialcomm = g_variant_get_string(src->data, NULL);
break;
+ case SR_CONF_FORCE_DETECT:
+ force_detect = g_variant_get_string(src->data, NULL);
+ sr_info("Force detect string %s",force_detect);
+ break;
}
}
if (!conn)
sr_info("Resetting device with *s at %s.", conn);
send_serial_char(serial, '*');
g_usleep(10000);
- //drain any inflight data
do {
sr_warn("Drain reads");
len = serial_read_blocking(serial, buf, 32, 100);
if (len)
sr_dbg("Dropping in flight serial data");
} while (len > 0);
-
-
- //Send identify
- num_read = send_serial_w_resp(serial, "i\n", buf, 17);
+ /*Send the user string with the identify */
+ if(force_detect
+ && (strlen(force_detect)<=60)){
+ sprintf(ustr,"i%s\n",force_detect);
+ sr_info("User string %s",ustr);
+ num_read = send_serial_w_resp(serial, ustr, buf, 17);
+ }else{
+ num_read = send_serial_w_resp(serial, "i\n", buf, 17);
+ }
if (num_read < 16) {
sr_err("1st identify failed");
serial_close(serial);
return NULL;
}
}
- //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 02
+ /*Expected ID response is SRPICO,AxxyDzz,VV
+ where xx are number of analog channels, y is bytes per analog sample (7 bits per byte)
+ 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')
return NULL;
}
a_size = buf[10] - '0';
- buf[10] = '\0'; //Null to end the str for atois
- buf[14] = '\0'; //Null to end the str for atois
+ buf[10] = '\0'; /*Null to end the str for atois */
+ buf[14] = '\0';
num_a = atoi(&buf[8]);
num_d = atoi(&buf[12]);
}
devc = g_malloc0(sizeof(struct dev_context));
devc->a_size = a_size;
- //multiple bytes per analog sample not supported
- if ((num_a > 0) && (devc->a_size != 1)) {
- sr_err("Only Analog Size of 1 supported\n\r");
- return NULL;
- }
devc->num_a_channels = num_a;
devc->num_d_channels = num_d;
devc->a_chan_mask = ((1 << num_a) - 1);
devc->d_chan_mask = ((1 << num_d) - 1);
-//The number of bytes that each digital sample in the buffers sent to the session.
-//All logical channels are packed together, where a slice of N channels takes roundup(N/8) bytes
-//This never changes even if channels are disabled because PV expects disabled channels to still
-//be accounted for in the packing
+/*The number of bytes that each digital sample in the buffers sent to the session.
+All logical channels are packed together, where a slice of N channels takes roundup(N/8) bytes
+This never changes even if channels are disabled because PV expects disabled channels to still
+be accounted for in the packing */
devc->dig_sample_bytes = ((devc->num_d_channels + 7) / 8);
- //These are the slice sizes of the data on the wire
- //1 7 bit field per byte
+ /*These are the slice sizes of the data on the wire
+ 1 7 bit field per byte */
devc->bytes_per_slice = (devc->num_a_channels * devc->a_size);
if (devc->num_d_channels > 0) {
- // logic sent in groups of 7
+ /* logic sent in groups of 7*/
devc->bytes_per_slice += (devc->num_d_channels + 6) / 7;
}
sr_dbg("num channels a %d d %d bps %d dsb %d", num_a, num_d,
devc->bytes_per_slice, devc->dig_sample_bytes);
-//Each analog channel is it's own group
-//Digital are just channels
-//Grouping of channels is rather arbitrary as parameters like sample rate and number of samples
-//apply to all changes. Analog channels do have a scale and offset, but that is applied
-//without involvement of the session.
+/* Each analog channel is it's own group
+Digital are just channels
+Grouping of channels is rather arbitrary as parameters like sample rate and number of samples
+apply to all changes. Analog channels do have a scale and offset, but that is applied
+without involvement of the session.
+*/
devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group *) *
devc->num_a_channels);
for (i = 0; i < devc->num_a_channels; i++) {
channel_name = g_strdup_printf("A%d", i);
- //sdi, index, type, enabled,name
ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
channel_name);
devc->analog_groups[i] =
if (devc->num_d_channels > 0) {
for (i = 0; i < devc->num_d_channels; i++) {
- //Name digital channels starting at D2 to match pico board pin names
+ /*Name digital channels starting at D2 to match pico board pin names*/
channel_name = g_strdup_printf("D%d", i + 2);
sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
channel_name);
}
}
- //In large sample usages we get the call to receive with large transfers.
- //Since the CDC serial implemenation can silenty lose data as it gets close to full, allocate
- //storage for a half buffer which in a worst case scenario has 2x ratio of transmitted bytes
- // to storage bytes.
- //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 32K....
+ /*In large sample usages we get the call to receive with large transfers.
+ Since the CDC serial implemenation can silenty lose data as it gets close to full, allocate
+ storage for a half buffer which in a worst case scenario has 2x ratio of transmitted bytes
+ to storage bytes.
+ 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 32K.... */
devc->serial_buffer_size = 32000;
devc->buffer = NULL;
sr_dbg("Setting serial buffer size: %i.",
devc->serial_buffer_size);
devc->cbuf_wrptr = 0;
- //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.
- //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.
+ /*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.
+ 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->capture_ratio = 10;
devc->rxstate = RX_IDLE;
sdi->priv = devc;
- //Set an initial value as various code relies on an inital value.
+ /*Set an initial value as various code relies on an inital value.*/
devc->limit_samples = 1000;
if (raspberrypi_pico_get_dev_cfg(sdi) != SR_OK) {
-//Note that on the initial driver load we pull all values into local storage.
-//Thus gets can return local data, but sets have to issue commands to device.
+/*Note that on the initial driver load we pull all values into local storage.
+ Thus gets can return local data, but sets have to issue commands to device. */
static int config_set(uint32_t key, GVariant * data,
const struct sr_dev_inst *sdi,
const struct sr_channel_group *cg)
const struct sr_channel_group *cg)
{
(void) cg;
- //scan or device options are the only ones that can be called without a defined instance
+ /*scan or device options are the only ones that can be called without a defined instance*/
if ((key == SR_CONF_SCAN_OPTIONS)
|| (key == SR_CONF_DEVICE_OPTIONS)) {
return STD_CONFIG_LIST(key, data, sdi, cg, scanopts,
std_gvar_samplerates(ARRAY_AND_SIZE
(samplerates));
break;
-//This must be set to get SW trigger support
+ /*This must be set to get SW trigger support*/
case SR_CONF_TRIGGER_MATCH:
*data =
std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
break;
case SR_CONF_LIMIT_SAMPLES:
- //Really this limit is up to the memory capacity of the host,
- //and users that pick huge values deserve what they get.
- //But setting this limit to prevent really crazy things.
+ /*Really this limit is up to the memory capacity of the host,
+ and users that pick huge values deserve what they get.
+ But setting this limit to prevent really crazy things. */
*data = std_gvar_tuple_u64(1LL, 1000000000LL);
sr_dbg("sr_config_list limit samples ");
break;
sr_err("ERROR:serial buffer malloc fail");
return SR_ERR_MALLOC;
}
- //Get device in idle state
+ /*Get device in idle state*/
if (serial_drain(serial) != SR_OK) {
sr_err("Initial Drain Failed\n\r");
return SR_ERR;
} else {
}
- }//for all channels
- //ensure data channels are continuous
+ }/*for all channels*/
+ /*ensure data channels are continuous*/
int invalid = 0;
for (i = 0; i < 32; i++) {
if ((devc->d_chan_mask >> i) & 1) {
invalid = 1;
}
}
- //recalculate bytes_per_slice based on which analog channels are enabled
+ /*recalculate bytes_per_slice based on which analog channels are enabled */
devc->bytes_per_slice = (a_enabled * devc->a_size);
for (i = 0; i < devc->num_d_channels; i += 7) {
}
sr_dbg("bps %d\n", devc->bytes_per_slice);
- //Apply sample rate limits
- //While earlier versions forced a lower sample rate, the PICO seems to allow
- //ADC overclocking, and by not enforcing these limits it may support other devices.
- //Thus call sr_err to get something into the device logs, but allowing it to progress.
+ /*Apply sample rate limits
+ While earlier versions forced a lower sample rate, the PICO seems to allow
+ ADC overclocking, and by not enforcing these limits it may support other devices.
+ Thus call sr_err to get something into the device logs, but allowing it to progress.*/
if ((a_enabled == 3) && (devc->sample_rate > 160000)) {
sr_err
("WARN:3 channel ADC sample rate above 160khz");
sr_err
("WARN:1 channel ADC sample rate above 500khz");
}
- //Depending on channel configs, rates below 5ksps are possible
- //but such a low rate can easily stream and this eliminates a lot
- //of special cases.
+ /*Depending on channel configs, rates below 5ksps are possible
+ but such a low rate can easily stream and this eliminates a lot
+ of special cases. */
if (devc->sample_rate < 5000) {
sr_err("Sample rate override to min of 5ksps");
devc->sample_rate = 5000;
}
- //While PICO specs a max clock ~120-125Mhz, it does overclock in many cases
- //so leaving is a warning.
+ /*While PICO specs a max clock ~120-125Mhz, it does overclock in many cases
+ so leaving is a warning. */
if (devc->sample_rate > 120000000) {
sr_err("WARN: Sample rate above 120Msps");
}
- //It may take a very large number of samples to notice, but if digital and analog are enabled
- //and either PIO or ADC are fractional the samples will skew over time.
- //24Mhz is the max common divisor to the 120Mhz and 48Mhz ADC clock
- //so force an integer divisor to 24Mhz.
+ /*It may take a very large number of samples to notice, but if digital and analog are enabled
+ and either PIO or ADC are fractional the samples will skew over time.
+ 24Mhz is the max common divisor to the 120Mhz and 48Mhz ADC clock
+ so force an integer divisor to 24Mhz. */
if ((a_enabled > 0) && (d_enabled > 0)) {
if (24000000ULL % (devc->sample_rate)) {
uint32_t commondivint =
24000000ULL / (devc->sample_rate);
- //Always increment the divisor so that we go down in frequency to avoid max sample rate issues
+ /*Always increment the divisor so that we go down in frequency to avoid max sample rate issues */
commondivint++;
devc->sample_rate = 24000000ULL / commondivint;
- //Make sure the divisor increement didn't make use go too low.
+ /*Make sure the divisor increement didn't make use go too low. */
if (devc->sample_rate < 5000) {
devc->sample_rate = 50000;
}
}
}
- //If we are only digital or only analog print a warning that the
- //fractional divisors aren't a true PLL fractional feedback loop and thus
- //could have sample to sample variation.
- //These warnings of course assume that the device is programmed with the expected ratios
- //but non PICO implementations, or PICO implementations that use different divisors could avoid.
- //This generally won't be a problem because most of the sampe_rate pulldown values are integer divisors.
+ /*If we are only digital or only analog print a warning that the
+ fractional divisors aren't a true PLL fractional feedback loop and thus
+ could have sample to sample variation.
+ These warnings of course assume that the device is programmed with the expected ratios
+ but non PICO implementations, or PICO implementations that use different divisors could avoid.
+ This generally won't be a problem because most of the sampe_rate pulldown values are integer divisors. */
if (a_enabled > 0) {
if (48000000ULL % (devc->sample_rate * a_enabled)) {
sr_warn
sr_err("Sample limit to device failed");
return SR_ERR;
}
- //To support future devices that may allow the analog scale/offset to change, call get_dev_cfg again to get new values
+ /*To support future devices that may allow the analog scale/offset to change, call get_dev_cfg again to get new values */
if(raspberrypi_pico_get_dev_cfg(sdi) != SR_OK){
sr_err("get_dev_cfg failure on start");
return SR_ERR;
}
- //With all other params set, we use the final sample rate setting as an opportunity for the device
- //to communicate any errors in configuration.
- //A single "*" indicates success.
- //A "*" with subsequent data is success, but allows for the device to print something
- //to the error console without aborting.
- //A non "*" in the first character blocks the start
+ /*With all other params set, we use the final sample rate setting as an opportunity for the device
+ to communicate any errors in configuration.
+ A single "*" indicates success.
+ A "*" with subsequent data is success, but allows for the device to print something
+ to the error console without aborting.
+ A non "*" in the first character blocks the start */
sprintf(tmpstr, "R%llu\n", devc->sample_rate);
num_read = send_serial_w_resp(serial, tmpstr, buf, 30);
buf[num_read]=0;
}
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 effective 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, unless HW based triggers are implemented
+ /*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 effective 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, unless HW based triggers are implemented */
if ((trigger = sr_session_trigger_get(sdi->session))) {
if (g_slist_length(trigger->stages) > 1)
return SR_ERR_NA;
val=-1;
}
sr_info("Trigger value idx %d match %d",idx,match->match);
- //Only set trigger on enabled channels
+ /*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) {
("ERROR:Analog pretrigger buffer malloc failure, disabling");
devc->trigger_fired = TRUE;
}
- } //if chan_mask
- } //for num_a_channels
- } //if pre_trigger
+ }
+ }
+ }
sr_info("Entering sw triggered mode");
- //post the receive before starting the device to ensure we are ready to receive data ASAP
+ /*post the receive before starting the device to ensure we are ready to receive data ASAP*/
serial_source_add(sdi->session, serial, G_IO_IN, 200,
raspberrypi_pico_receive, (void *) sdi);
sprintf(tmpstr, "C\n");
if (devc->trigger_fired)
std_session_send_df_trigger(sdi);
- //Keep this at the end as we don't want to be RX_ACTIVE unless everything is ok
+ /*Keep this at the end as we don't want to be RX_ACTIVE unless everything is ok*/
devc->rxstate = RX_ACTIVE;
return SR_OK;
}
-//This function is called either by the protocol code if we reached all of the samples
-//or an error condition, and also by the user clicking stop in pulseview.
-//It must always be called for any acquistion that was started to free memory.
+/*This function is called either by the protocol code if we reached all of the samples
+or an error condition, and also by the user clicking stop in pulseview.
+It must always be called for any acquistion that was started to free memory. */
static int dev_acquisition_stop(struct sr_dev_inst *sdi)
{
struct dev_context *devc;
serial = sdi->conn;
std_session_send_df_end(sdi);
- //If we reached this while still active it is likely because the stop button was pushed
- //in pulseview.
- //That is generally some kind of error condition, so we don't try to check the bytenct
+ /*If we reached this while still active it is likely because the stop button was pushed
+ in pulseview.
+ That is generally some kind of error condition, so we don't try to check the bytenct */
if (devc->rxstate == RX_ACTIVE) {
sr_err("Reached dev_acquisition_stop in RX_ACTIVE");
}
sr_err("Sending plus to stop device stream\n\r");
send_serial_char(serial, '+');
}
- //In case we get calls to receive force it to exit
+ /*In case we get calls to receive force it to exit */
devc->rxstate = RX_IDLE;
- //drain data from device so that it doesn't confuse subsequent commands
+ /*drain data from device so that it doesn't confuse subsequent commands*/
do {
len =
serial_read_blocking(serial, devc->buffer,