- If libusb-1.0 is not found, do not compile in ezusb.c and usb.c since
they require libusb.h. The respective hardware drivers that use
libusb-1.0, and usb.c and/or ezusb.c will be excluded from the build
elsewhere in configure.ac. Rename NEED_EZUSB to NEED_USB.
- Drop the NEED_SERIAL check and always compile in serial.c. This is a
very small chunk of code, it does not depend on any external
libraries that might be missing, and it compiles on all architectures.
Thus there's no need to conditionally include or exclude it.
The currently supported model LAP-C(16032) doesn't support the
samplerates 150MHz and 200MHz which some of the other models have.
Thus, do not report these samplerates to the frontends. E.g. sigrok-cli
should not show them via --show and GUIs should not list them in their
"Samplerates" drop-down.
- Explicitly list .config_get in all drivers for consistency, and set it
to NULL if unused (whether or not a driver implements it is optional).
- List all 'struct sr_dev_driver' entries in the same order in all drivers.
- Move the check whether .config_set/.config_list exist (i.e., are non-NULL)
into sanity_check_all_drivers().
This is a small helper function which sends the SR_DF_HEADER packet that
drivers usually emit in their hw_dev_acquisition_start() API callback.
It simplifies and shortens the hw_dev_acquisition_start() functions
quite a bit.
It also simplifies the input modules which send an SR_DF_HEADER packet, too.
This patch also automatically removes some unneeded malloc/free in some
drivers for the 'packet' and 'header' structs used for SR_DF_HEADER.
Check the relevant arguments for != NULL before calling the actual
driver-specific function, so that the driver can safely assume those
arguments are non-NULL. This removes the need to duplicate these
checks in every driver.
This patch might also work for a number of other Brymen models
-- 859(a), 867, 869---
including their respective rebadges from Greenlee, Extech, and Amprobe.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Check the relevant arguments for != NULL before calling the actual
driver-specific function, so that the driver can safely assume those
arguments are non-NULL. This removes the need to duplicate these
checks in every driver.
Also, do some minor whitespace and consistency improvements.
Check the relevant arguments for != NULL before calling the actual
driver-specific function, so that the driver can safely assume those
arguments are non-NULL. This removes the need to duplicate these
checks in every driver.
Also, change one SR_ERR to the more correct SR_ERR_MALLOC, and assign
sr_ctx in the rigol-ds1xx2's hw_init() function, like all the other
drivers do.
Sending an SR_DF_META packet at the start of every stream is not
mandatory; the frontend should ask for what it needs, and any extra
information the driver wants to send will come in due time.
Currently hw_info_get() can receive requests for entries (info_id) that
the specific driver doesn't support. That is (right now) a valid
use-case and not an error (might change later, though).
Thus, for now, don't output messages for such requests at all (certainly
not as sr_err() where they show up in e.g. sigrok-cli output per default).
Errors while opening or configuring ALSA devices during scan for devices
should not be shown by default (i.e., no sr_err() usage). Non-working
or non-accessible devices (due to permissions or other reasons) will
simply not show up in frontends. Use sr_dbg() instead of sr_err().
Fix the bare minumum of whitespace/indentation/coding-style via
automatic 'indent' run, followed by some minor manual fixes.
Some more fixes and cleanups might follow later.
Bring back the original (C) lines from before the split into api.c
and protocol.[ch].
Add "Copyright (C) 2013 Lior Elazary <lelazary@yahoo.com>" since there
were nontrivial changes to those files.
Since we are using the 'hw' interface of ALSA, we don't have the luxury of
samplerate conversion, given by the 'plughw' interface. If we try to set a
samplerate that is not supported, ALSA will just throw an error.
We can test for the supported samplerates, and create a list of supported
samplerates, then limit the selection to only those values. The frontend can
query the list of supported samplerates.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
The alsa driver requested signed 16-bit integers from ALSA, but casted them to
to an unsigned 16bit before finally casting them to a float. The end result was
that half of the wave would be clipped off.
We also requested data in little endian format. ALSA can be instructed to send
data with the correct endianness for the platform, without needing to worry
about what that is.
This patch attempts three points, which, together, fix the acquisition:
1) Request data from ALSA without specifying endianness; ALSA will handle the
endianness.
2) Simplify the int16_t to float loop by using straightforward indexes.
3) Normalize every value before sending it on the session bus.
NOTE: If testing with PulseView, it will appear as if sigrok is sending all
zeroes. sigrok is sending correct data, but since the data is normalized,
PulseView will incorrectly plot it as a straight line.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
The alsa driver only works with device "default". This limits the driver's
scope to whatever device ALSA deems to be "default". It is desirable to have
access to all ALSA devices from sigrok.
Change the alsa device scan so that:
Each alsa device (not alsa card) gets its own sigrok device
For example,
hw:1,0 == sigrok device 0
hw:1,1 == sigrok device 1
hw:2,0 == sigrok device 2
hw:2,1 == sigrok device 3
hw:2,2 == sigrok device 4
[...]
We don't currently look at alsa subdevices. We only use subdevice 0.
Every input device will have its own channels (left, right, etc). Each of
those channels gets mapped to a different sigrok probe. A device with 4
channels will have 4 probes from sigrok's perspective.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
snd_pcm_hw_params_set_rate_near() will try to use the samplerate closest to the
given value, potentially starting the acquisition with a different samplerate
than the one specified.
Instead, use snd_pcm_hw_params_set_rate(). It will return an error if the
samplerate is not supported by the hardware, which is arguably better than
collecting data with a different samplerate than the one specified.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
asix-sigma.c:648:9: warning: 'ret' may be used uninitialized in this
function [-Wmaybe-uninitialized]
asix-sigma.c:1337:20: warning: 'triggerselect' may be used uninitialized
in this function [-Wmaybe-uninitialized]
This matches the _ser suffix of the other functions/variables for this
device ("ser" denotes that it is used with the serial UNI-T UT-D02 cable
as opposed the USB/HID based cables which are handled by the uni-t-dmm driver).
But more importantly, the _SER suffix for the enum value will prevent
name clashes later, when the uni-t-dmm driver gets a VOLTCRAFT_VC820 enum.
Do the same for VOLTCRAFT_VC840.
Check whether a sample limit was actually set (> 0) before checking if
that sample limit is reached. This also fixes continuous acquisition mode
for drivers which have that.
Implement SR_HWCAP_LIMIT_MSEC capability, to allow acquisition to automatically
stop after a specified amount of time.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Some unusual modes required re-parsing the value. Instead of assigning the
re-parsed value to *floatval, it was reassigned directly to *analog->data;
however, analog->data is not initialized at this point, causing a segfault.
This situation was created when moving the radioshack-dmm code to serial-dmm,
with the segfault not being observed at that time.
Do not write directly to analog->data, but instead use the intermediate
variable rawval.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Convert bit masks from hardcoded hex values to bit shifts. For example 0x80
becomes (1 << 7). This also fixes a typo error in the definition of INFO_DIODE.
Add comments explaining that some case values in sr_rs9lcd_parse() are meant to
fall through without a 'break;', and explain some of the unusual modes.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Unfortunately the device doesn't have an EEPROM on board at all, and so
initially enumerates with the default Cypress FX2 VID:PID (04b4:8613).
Since we already support using plain FX2* as basic logic analyzers using
the fx2lafw firmware, we cannot support that same VID:PID for the
OsciPrime. Therefore a USB conn is required for the initial scan.
However, once the firmware is uploaded the device re-enumerates as
04b4:1004, which we do detect for scanning automatically.
Thus, the OsciPrime driver requires one scan with conn parameter to get
the firmware uploaded, but it will then keep working until powered off.
This is the driver model agreed upon for all drivers.
As a result of the split, a devc->num_probes field had to be added in order to
reduce the interdependence between api.c and protocol.c .
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
serial-dmm does not check if a sample limit is actually in place before deciding
to stop acquisition. Since the sample limit is set at 0 by default, operating
in continuous mode will cause acquisition to stop before even sending the first
sample.
Check to make sure we actually are in a sample-limited mode before stopping for
this reason.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
The alsa driver was out of date wrt APIs and libsigrok conventions in
general, and wasn't compiling.
This fixes the compile and updates it to _basically_ work with the current
state of analog support in libsigrok.
This is not finished/full support for ALSA analog sampling yet, though,
various TODOs remain that will be addressed later.
Hardware scanning creates an ftdi_context before attempting to locate devices
based on PID/VID. If no devices are detected, execution jumps to cleanup. The
context is freed with free(), instead of ftdi_free().
We cannot assume that the libftdi context is stored in a contiguous memory
region, and thus cannot use a simple free. Case in point, this situation is
identified by valgrind as a "definitely lost" memory leak.
Use ftdi_free() instead of a simple free() in hw_scan(). Valgrind no longer
complains about a memory leak in this area.
clear_instances() does not need any modification, as it correctly uses
ftdi_free().
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
commit 378abfeac6 tried to solve a bug where
the fx2lafw driver would print "Device came back" even if a timeout had occured.
It solved that issue, but inadvertently introduced a new bug:
"Device came back" would be printed even if no firmware upload was performed.
This is counterintuitive, as the device is only reset when a firmware upload is
performed.
There are three cases:
i) Firmware upload was successful
ii) Firmware upload failed
iii) Firmware upload was NOT needed
Each case warrants a separate message from the driver. Print the
following messages depending on the outcome:
i) "Device came back"
ii) "Device failed to renumerate"
iii) "Firmware upload was not needed."
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Use the new DRIVER_LOG_DOMAIN mechanism, where explicitly writing
the driver name in the message string is no longer required.
Thus:
- sr_err("fx2lafw: Something bad happened.");
becomes:
+ sr_err("Something bad happened.");
In either case, the log output is the same.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
This works with the UNI-T UT-D02 (RS232) cable. For the USB/HID
based cable (UNI-T UT-D04), the uni-t-dmm driver must be used.
Note: This is untested, but should work just fine for all settings, with
the possible exception of temperature (testers needed!)
Just use the 'int dmm' + wrapper method that is used for all other
functions which need this information. There is no real need to
special-case the hw_dev_acquisition_start() API call here.
The rs9lcd parser, which is used for the RadioShack 22-812 does not use its
*info parameter, and therefore did not have a rs9lcd_info struct declared.
With recent re-factoring of the receive data callbacks, it became necessary to
pass a struct pointer. This made the RECV_DATA macro look like:
- RECV_DATA(RADIOSHACK_22_812, metex14)
giving the wrong impression that the RadioShack 22-182 uses the
metex14 protocol, which is not the case.
Create a dummy rs9lcd_info struct, and correctly identify the parser
as rs9lcd in the RECV_DATA macro:
+ RECV_DATA(RADIOSHACK_22_812, rs9lcd)
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Not all drivers use subdrivers. The only reason the subdriver field was
introduced was to accomodate the model of serial-dmm.
The sr_dev_driver struct is available to the frontend. Exposing the subdriver
field creates the problem of exposing knowledge of libsigrok's internal driver
layout, even though the drivers are designed to be a flat list to the frontend.
Store the subdriver in the dev_context struct of serial-dmm.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
The global *di alias was used to keep track of the driver context.
It caused issues with trying to use several subdrivers at once, so
its use was obsoleted.
The correct context is preserved through different mechanisms, either
the *sdi pointer, or wrappers which pass the correct context.
The *di alias is no longer used, so remove it.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Wrappers for hw_init, hw_cleanup, clear_instances, and hw_scan are needed for
each subdriver due to the nature of serial-dmm. These wrappers are implemented
as macros, in order to reduce the number of lines of code.
For each of those functions, we have a separate wrapper list, then we connect
them together in a first-class driver using a DRV macro, and yet another list
(the DRV list).
Instead of declaring those wrappers in separate lists, include them in the DRV
macro. This approach reduces the number of macro lists from five to just one.
From the perspective of adding a new subdriver, this also greatly reduces the
number of places needed to hook in a new device.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Store/use the receive_data() function and a pointer to the driver struct
in the dmms[] array. Use a ".subdriver" entry in the driver struct.
Use a macro to simplify hw_init() wrappers.
Declare dmm_info dmms as extern in protocol.h to prevent duplicate
symbol error from the linker.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
di was initialized as NULL. If no device covered by this driver
is used, di remains NULL. This causes a segmentation fault when
calling clear_instances().
Check for di being NULL.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Use the infrastructure of serial-dmm to handle the RadioShack 22-812,
and completely remove radioshack-dmm.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Move the parsing part of radioshack-dmm into a separate protocol
parser, following the model from hardware/common/dmm.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
During scan the serial port is opened with SERIAL_RDONLY | SERIAL_NONBLOCK,
which works fine, but when acquisition starts, it is opened only with
SERIAL_RDONLY. On Linux, if cdc_acm can make a claim to the USB to serial
converter, opening the port will fail.
Open port with SERIAL_RDONLY | SERIAL_NONBLOCK.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
We already have an event-based mechanism in place. Using a thread just
adds unneeded complexity, especially for a driver designed not for
performance, but for providing a testbed to frontends.
Generate the data in the event handler, not in a separate thread.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
strcmp(buf + 9, " mA") does not work because buf is CR-terminated,
while " mA" is NUL-terminated.
Drop ambiguities arising from the termination of the strings, and
only compare the characters we care about, using strncmp().
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
When the parser found a space, it treated it as an invalid digit
and discarded the whole packet. This behavior was incorrect on
2000 count devices, where the first digit can be sent as a space
rather than a '0'.
Convert spaces to '0' and parse them as usual.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Prepare the tekpower-dmm driver to be able to support various simple
serial port based DMMs.
Also, make a 'tekpower-tp4000zc' "first-class" driver which is currently
the only user of this generic driver.
The demo driver was using sr_session_source_add_channel() to add
a poll source, but was relying on sr_session_run_poll() to call
sr_session_source_remove(). This, coupled with the design of the
driver caused errors once the samples were collected.
The error stream was most likely related to failing to properly close
one of the channels.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
This is the first step in fixing the demo driver: figuring out what is
being called and what is not _and_ have it show up in the logs.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Options in addition to the usual "9600/8n1" syntax start with a
slash, and take the form of key=value, where different options are
also separated by slashes. For example:
"9600/8n1/rts=0/dtr=1"
This sets RTS low and DTR high.
The packet mode byte is akin to a signature. If that is invalid, there's
no point in calculating the checksum, so check the mode first.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Serial detection was using serial_readline, which stripped carriage
return from the packets. This made for a very unreliable detection
mechanism.
Switch to a timeout-based detection mechanism that parses the data
as it comes in. This also allows us to stop parsing once we found
our first valid packet.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
ols driver used to probe a series of available serial ports obtained
by regexp matching of common serial port names.
There are a number of problems with this approach:
1. It will probe all serial devices, including devices that do not
like to be probed, potentially causing them to act up.
2. It will try to probe serial ports which may already be opened in
other applications for other purposes.
3. It assumes the naming of the serial ports is set in stone, and
creates an unnecessary OS-specific list.
4. It produces unnecessary debug output even when an OLS device is
not connected.
5. etc...
Do not implicitly probe serial ports. Only probe the port specified
by the frontend, if any; otherwise, just quit.
Also get rid of all functionality in serial.c which was designed
specifically for random probing.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
In the case of USB drivers, a driver's dev_acquisition_stop() cannot
simply remove its fd sources from the session and close its devices:
a USB transfer might still be underway, and it needs to be finished
(and its memory freed) properly.
An sr_dev_inst->status value is added: SR_ST_STOPPING, which should
be set when the driver's dev_acquisition_stop() is called, and acts
as a marker for the USB event handler to wind up its operations.
In order for dev_acquisition_stop() to be able to set the sdi status,
however, it needs to be unconstified.
- Default to 1MHz.
The default sample rate is the lowest frequency (100Hz),
but it takes a very long time until 128K memory is full.
- Fix the 1MHz setting.
- Use samplerate list.
- Fix 10MHz frequency.
- Fix trigger.
- Change the size of memory according to the number of samples.
- Add pre-trigger (capture ratio) setting.
- Fix the first acquisition after power on.
Move sr_usb_connect() and sr_usb_open() to hardware/common/usb.c in a
slightly more generic form and add more error checks and logging.
Let genericdmm use the new/moved functions.
Merge parts of the tekpower-dmm code (the chip of the TekPower
TP4000ZC seems to be an FS9721_LP3 too) and rework parts of the functions.
Adapt the tekpower-dmm and uni-t-dmm code accordingly.
So far, it seems we can make this work with just hw_init() needing to
be subdriver-specific (it will point 'di' to the respective per-subdriver
entry), the rest of the API functions can then use a strcmp() on di->name to
learn which subdriver they belong to.
The 'uni-t-dmm' driver/directory will not appear as a "driver" to
frontends anymore, it's just an internal thing.
The frontends will see a uni-t-ut61d and voltcraft-vc820 driver now,
with the correct names and parsers etc. attached to them.
This is not fully finished yet, but it's a start (and works mostly):
$ sigrok-cli -D
The following devices were found:
UNI-T UT61D with 1 probe: P1
Voltcraft VC-820 with 1 probe: P1
$ sigrok-cli --driver voltcraft-vc820 -D
The following devices were found:
Voltcraft VC-820 with 1 probe: P1
$ sigrok-cli --driver uni-t-ut61d -D
The following devices were found:
UNI-T UT61D with 1 probe: P1
# Now attaching a UNI-T UT61D device via USB.
$ sigrok-cli --driver uni-t-ut61d --samples 3 -O analog
P1: -0.017800 V DC
P1: -0.017600 V DC
P1: -0.017700 V DC
# Now attaching a Voltcraft VC-820 device via USB instead.
$ sigrok-cli --driver voltcraft-vc820 --samples 3 -O analog
P1: -0.319200 V DC
P1: -0.319300 V DC
P1: -0.319300 V DC
The Fortune Semiconductor FS9721_LP3 and FS9721B/Q100 DMM chips are very
similar and the protocol looks identical.
Tested on a Voltcraft VC-820 (FS9721_LP3) with the uni-t-dmm driver
(needs some small changes, tbd).
LOGIC mode sends the following data:
V < 0 : actual voltage
0 <= V < 1 : LOW
1 <= V < 2 : actual voltage
2 <= V : HIGH
We follow the same idea, and set our unit to BOOLEAN for the crazy
case (HIGH or LOW).
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
While testing the new radioshack-dmm driver with pulseview, I found
a few inconvenients.
1. Print an info message when a port is probed, and when a device is
found. This makes it easy to tell if and where the driver is looking.
2. num_samples was not reset after the first aquisition, so the
second aquisition would quit right away. Reset num_samples at start
of a new aquisition.
3. There's no need to open the serial port RW, so change O_RDWR to
O_RDONLY when opening the port.
These changes are too trivial to split into different patches.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Only tested on U1233A, but it just might work.
The U125x protocol decoding only supports voltage, current, resistance,
capacitance and diode measurements for now.
These are used to list the device instances currently known to the driver,
and clear that list.
Drivers that don't necessarily clear their list of instances on every scan,
such as genericdmm, need to provide these to the frontend to keep instance
management sane.
Since probes now live in a struct sr_dev_inst owned by the driver, it
already knows about them. Instead of a frontend telling the driver to
configure probes, all driver now do this just before starting acquisition.
It's obsolete: no frontend ever used it, and neither did libsigrok.
The sdi->status field is only used internally by some drivers, and
should probably be moved to the driver-specific context structs.
This changes the semantics of the init() call as well. That now only
initializes the driver -- an administrative affair, no hardware gets
touched during this call. It returns a standard SR_OK or SR_ERR* code.
The scan() call does a discovery run for devices it knows, and returns
the number found. It can be called at any time.
It was actually used in one way: the session file loaded abused it for
passing in the filename -- something it definitely wasn't intended for.
This now uses the proper way to pass arguments to a driver: the new
SR_HWCAP_SESSIONFILE.
The OLS driver could also use it as an indication of the serial port to
use instead of actively probing all serial ports on the system, but there
wasn't any frontend code that passed in such a parameter, making it
entirely useless. That will soon be handled differently with the new
scan() API call, regardless.
Both pipe channels are currently configured as blocking. We read from the pipe
in receive_data. Since the channel is configured as blocking we'll block in
receive_data until all data has been received. receive_data will be called from
the mainloop, so as consequence the mainloop will be blocked until the demo
device has finished sampling. This is not so much of a problem if we are
sampling in blocking mode (using sr_session_run()) and the demo device is the
only device in the session, but it will fail badly for all other configurations
(e.g. multiple devices or async sampling).
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Free the USB transfers in the reverse order of which they were submitted. This
will avoid that while transfer 0 is cancelledd transfer 1 is started by the
host controller, and so on.
Reported-by: Peter Stuge <peter@stuge.se>
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The session and demo device code contain a hack to make the demo device work on
Windows. This was neccessary since polling on windows requires special handling
and we can not just pass in the raw fd to poll.
With the previous patches which added support for non-fd based event sources
this hack is no longer required. The patch moves the GIOChannels used by the
demo device to the demo device context and uses sr_session_source_add_channel
to register a source for the channels instead of using the raw pipe fds.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
All frontends will have to include <libsigrok/libsigrok.h> from now on.
This header includes proto.h and version.h, both installed from the
distribution into $INCLUDE/libsigrok/ as well.
The only dynamically changed header is now version.h, which has both
libsigrok and libtool compile-time versions in it.
Only one limit should be active at a time. Make sure that the sample limit is
disabled when a time limit is set and vice versa.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Call abort_acquisition if starting sampling fails in acquisition_start, this
will ensure that all already allocated resources are being freed again.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This may happen if the acquisition_start is called right after calling
acquisition_stop and not all transfers have been freed or on repeated calls to
acquisition_start. If it happens we'll enter an undefined state and all kind of
strange behavior may occur, so error out in such a case.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The recent reworks of the fx2lafw made sure that the total buffer size is large
enough hold 500ms of data. This was done to improve performance and stability.
That the timeout value for a transfer was also increased to over 500ms, a side
effect of this is that when sampling is stopped there will be a additional delay
of 500ms. This is because the driver waits for all transfers to be freed
before it sends a SR_DF_END packet. Once sampling has stopped this will only
happen once a transfer times out. This patch cancels all pending transfers when
sampling is stopped, this will cause them to be freed almost immediately and the
additional delay will disappear.
Also make sure, that if we know, that we just have received the last transfer to
not resubmit this transfer again.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Currently timeout and buffer size are hard-coded in the fx2lafw driver which is
non-optimal if we want to get good results at both high and low sample rates.
The timeout is hard-coded to 40ms, which doesn't work well when sampling at
a low sample rate. E.g. at 20kHz filling all available buffer space alone takes
6 seconds. So naturally we'll see a lot of transfers timeout in this case.
The buffer size is hard-coded to 4096 bytes, which does not work well with high
sample rates. E.g. at 24MHz these 4096 bytes are enough space for 0.17ms of
data. The total buffer size is enough for about 5ms of data. Sooner or later the
application won't be able to resubmit a transfer within this time span and the
device will abort data acquisition. Usually this happens within the first few
seconds of sampling.
This patch adds a few new helper functions which calculate the buffer size and
timeout based on the current sample rate.
The buffer size is chosen to be large enough to hold about 10ms of data and it
also must be a multiple of 512 bytes since the firmware will send us the data
in 512 byte chunks.
The timeout is set to the time it would take to fill the whole available buffer
space plus a 25% headroom to accommodate for jitter. This is more than enough,
but there is no need to make the timeout a tight deadline, since it is only
meant as a last resort in case the device stops submitting data. And in this
case data acquisition will be aborted anyway.
The patch also limits the the number of transfers so that the total buffer
space is not much more of 500ms. This will ensure that we do not have to
wait too long when aborting data acquisition.
This patch also significantly reduces the number of context switches when
sampling at a higher sample rate. On my system for example the CPU load of
sigrok-cli when sampling at 24MHz goes down from ~25% to 3-4%.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
While errors are usually already implicitly caught by looking at the packet
length field there is one error status which is worth special handling. If the
device has been removed there is not really a chance to recover from this error
so data acquisition can be stopped immediately.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In receive_transfer for each completed transfer a new buffer is allocated and
the old one is freed. We can avoid this by simply reusing the buffer for the
next transfer. This is possible if we only resubmit the transfer after all
processing on the data buffer has been done. A new buffer is only allocated if
the size of the old one is not 4096 bytes.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
When freeing a transfer we also have to free the transfer buffer. We also have
to keep track of the number of allocated transfers and if the freed transfer was
the last one stop acquisition. This patch introduces a helper function which
takes care of all of this.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The header and packet struct are only used in the scope of this function and
they are freed at the end of it. Also these structs are rather small, so they
can safely be allocated on the stack. By doing so memory leaks on the error
paths are avoided.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Samples received before the trigger point are stored. From the
trigger point on, every chunk received from the device is sent
up the session bus. After the device has finished sending, the
stored samples are transmitted.
Commit 88b75eb719 ("fx2lafw: Added device caps and added support for wide
sampling") increased the size of the trigger buffer from 8 to 16 bit, but forgot
to adjust the unitsize logic packet which is used to send the contents of the
trigger buffer. This patch sets the unitsize to sizeof() of the trigger buffer.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Multistage triggers currently do no work, because there is a return statement
in the middle of the trigger detector which will be hit as soon as the first
stage in a multistage trigger matches. This patch removes the return statement
so that the trigger detector can continue to try to match the next stage. In
order for this to work we also make sure that the trigger stage is only reset
if the current sample does not match.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
There are a few memory leaks in the receive_transfer transfer function. The most
serve of them is that a sample buffer is not freed if the triggered has not
matched yet, which causes a sigrok process which is waiting for a trigger to
consume several megabytes of memory within seconds. The other leaks are on the
error paths in that function.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
We should generally use api.c for API related functions and put the other
functions (mostly hardware-specific low-level code) into other C file(s)
for better readability.
MQ is the measured quantity, e.g. voltage, current, temperature.
UNIT is the unit in which these quantities are measured, e.g. volt,
ampere, celsius, kelvin, etc. etc.
The same MQ can be specified in different UNITs by the driver, depending
on what the hardware reports. Conversion is left to the frontends.
Not yet used, but it's the key to knowing where in the frame to
start displaying; the frame is used as a circular buffer, and what
is sent is effectively a snapshot.
The ntohs() from <arpa/inet.h> is not available on MinGW/Windows. There
are ways to work around this, but as we use glib already, using g_ntohs()
is the best option anyway.