662 Commits

Author SHA1 Message Date
Martin Ling
d755f7a5c8 Correct order of requested mode and flag. 2022-02-28 17:12:45 +00:00
Martin Ling
779483b9bd Make M0 state retrieval endian-safe. 2022-02-13 17:53:34 +00:00
Martin Ling
f3633e285f Replace direct setting of M0 mode with a request/ack mechanism.
This change avoids various possible races in which an autonomous mode
change by the M0 might clobber a mode change made from the M4, as well
as related races on other state fields that can be written by the M4.

The previous mode field is replaced by two separate ones:

- active_mode, which is written only by the M0, and indicates the
  current operating mode.

- requested_mode, which is written by the M4 to request a change.
  This field includes both the requested mode, and a flag bit. The M4
  writes the field with the flag bit set, and must then wait for the
  M0 to signal completion of the request by clearing the flag bit.

Whilst the M4 is blocked waiting for the flag bit to be cleared, the
M0 can safely make all the required changes to the state that are
needed for the transition to the requested mode. Once the transition
is complete, the M0 clears the flag bit and the M4 continues execution.

Request handling is implemented in the idle loop. To handle requests,
mode-specific loops simply need to check the request flag and branch to
idle if it is set.

A request from the M4 to change modes will always require passing
through the idle loop, and is not subject to timing guarantees. Only
transitions made autonomously by the M0 have guaranteed timing
constraints.

The work previously done in reset_counts is now implemented as part of
the request handling, so the tx_start, rx_start and wait_start labels
are no longer required.

An extra two cycles are required in the TX shortfall path because we
must now load the active mode to check whether we are in TX_START.

Two cycles are saved in the normal TX path because updating the active
mode to TX_RUN can now be done without checking the previous value.
2022-02-13 17:53:34 +00:00
Martin Ling
137f2481e5 Make an error code available when a shortfall limit is hit.
Previously, finding the M0 in IDLE mode was ambiguous; it could indicate
either a normal outcome, or a shortfall limit having being hit.

To disambiguate, we add an error field to the M0 state. The errors
currently possible are an RX timeout or a TX timeout, both of which
can be obtained efficiently from the current operating mode due to
the values used.

This adds 3 cycles to both shortfall paths, in order to shift down
the mode to obtain the error code, and store it to the M0 state.
2022-02-13 17:53:34 +00:00
Martin Ling
cca7320fe4 Add a wait mode for the M0.
In wait mode, the byte counter is advanced, but no SGPIO read/writes are
done. This mode is intended to be used for implementing timed operations.
2022-02-13 16:46:12 +00:00
Martin Ling
3618a5352f Add a counter threshold at which the M0 will change to a new mode.
This lays the groundwork for implementing timed operations (#86). The M0
can be configured to automatically change modes when its byte count
reaches a specific value.

Checking the counter against the threshold and dispatching to the next
mode is handled by a new `jump_next_mode` macro, which replaces the
unconditional branches back to the start of the TX and RX loops.

Making this change work requires some rearrangement of the code, such
that the destinations of all conditional branch instructions are within
reach. These branch instructions (`b[cond] label`) have a range of -256
to +254 bytes from the current program counter.

For this reason, the TX shortfall handling is moved earlier in the file,
and branches in the idle loop are restructured to use an unconditional
branch to rx_start, which is furthest away.

The additional code for switching modes adds 9 cycles to the normal RX
path, and 10 to the TX path (the difference is because the dispatch in
`jump_next_mode` is optimised for the longer RX path).
2022-02-13 16:46:12 +00:00
Martin Ling
00b5ed7d62 Add an M0 TX_START mode, in which zeroes are sent until data is ready.
In TX_START mode, a lack of data to send is not treated as a shortfall.
Zeroes are written to SGPIO, but no shortfall is recorded in the stats.
Using this mode helps avoid spurious shortfalls at startup.

As soon as there is data to transmit, the M0 switches to TX_RUN mode.

This change adds five cycles to the normal TX path, in order to check
for TX_START mode before sending data, and to switch to TX_RUN in that
case.

It also adds two cycles to the TX shortfall path, to check for TX_START
mode and skip shortfall processing in that mode.

Note the allocation of r3 to store the mode setting, such that this
value is still available after the tx_zeros routine.
2022-02-13 16:46:12 +00:00
Martin Ling
5abc39c53a Add USB requests and host support to set TX/RX shortfall limits.
This adds `-T` and `-R` options to `hackrf_debug`, which set the TX
underrun and RX overrun limits in bytes.
2022-02-13 16:46:12 +00:00
Martin Ling
2f79c03b2c hackrf_debug: allow parse_int() to handle 32-bit parameters. 2022-02-13 16:46:12 +00:00
Martin Ling
f0bc6eda30 Add a shortfall length limit.
This limit allows implementing a timeout: if a TX underrun or RX overrun
continues for the specified number of bytes, the M0 will revert to idle.

A setting of zero disables the limit.

This change adds 5 cycles to the TX & RX shortfall paths, to check if a
limit is set and to check the shortfall length against the limit.
2022-02-13 16:46:12 +00:00
Martin Ling
2c86f493d9 Keep track of longest shortfall.
This adds six cycles to the TX and RX shortfall paths.
2022-02-13 16:46:12 +00:00
Martin Ling
a7bd1e3ede Keep count of number of shortfalls.
To enable this, we keep a count of the current shortfall length. Each
time an SGPIO read/write cannot be completed due to a shortfall, we
increase this length. Each time an SGPIO read/write is completed
successfully, we reset the shortfall length to zero.

When a shortfall occurs and the existing shortfall length is zero, this
indicates a new shortfall, and the shortfall count is incremented.

This change adds one cycle to the normal RX & TX paths, to zero the
shortfall count. To enable this to be done in a single cycle, we keep a
zero handy in a high register.

The extra accounting adds 10 cycles to the TX and RX shortfall paths,
plus an additional 3 cycles to the RX shortfall path since there are
now two branches involved: one to the shortfall handler, and another
back to the main loop.
2022-02-13 16:46:12 +00:00
Martin Ling
32c725dd61 Add an idle mode for the M0.
In the idle mode, the M0 simply waits for a different mode to be set.
No SGPIO access is done.

One extra cycle is added to both TX code paths, to check whether the
M0 should return to the idle loop based on the mode setting. The RX
paths are unaffected as the branch to RX is handled first.
2022-02-13 16:46:12 +00:00
Martin Ling
5b50b2dfac Replace TX flag with a mode setting.
This is to let us start adding new operatin modes for the M0.
2022-02-13 16:46:12 +00:00
Martin Ling
c8d120ff6c Display total M0 and M4 counts at end of hackrf_transfer.
Doing this requires keeping track of when the 32-bit counters wrap, and
updating 64-bit running totals.
2022-02-13 16:46:12 +00:00
Martin Ling
eb2be7995c Add hackrf_transfer option to display buffer stats.
This adds the `hackrf_transfer -B` option, which displays the number of
bytes currently in the buffer along with the existing per-second stats.

The number of bytes in the buffer is indicated by the difference between
the M0 and M4 byte counters. In TX, the M4 count should lead the M0 count.
In RX, the M0 count should lead the M4 count.
2022-02-13 16:46:12 +00:00
Martin Ling
79853d2b28 Add a second counter to keep track of bytes transferred by the M4.
With both counters in place, the number of bytes in the buffer is now
indicated by the difference between the M0 and M4 counts.

The M4 count needs to be increased whenever the M4 produces or consumes
data in the USB bulk buffer, so that the two counts remain correctly
synchronised.

There are three places where this is done:

1. When a USB bulk transfer in or out of the buffer completes, the count
   is increased by the number of bytes transferred. This is the most
   common case.

2. At TX startup, the M4 effectively sends the M0 16K of zeroes to
   transmit, before the first host-provided data.

   This is done by zeroing the whole 32K buffer area, and then setting
   up the first bulk transfer to write to the second 16K, whilst the M0
   begins transmission of the first 16K.

   The count is therefore increased by 16K during TX startup, to account
   for the initial 16K of zeros.

3. In sweep mode, some data is discarded. When this is done, the count
   is incremented by the size of the discarded data.

   The USB IRQ is masked whilst doing this, since a read-modify-write is
   required, and the bulk transfer completion callback may be called at
   any point, which also increases the count.
2022-02-13 16:46:12 +00:00
Martin Ling
21dabc920f Replace M0 state offset field with a byte count.
Instead of this count wrapping at the buffer size, it now increments
continuously. The offset within the buffer is now obtained from the
lower bits of the count.

This makes it possible to keep track of the total number of bytes
transferred by the M0 core.

The count will wrap at 2^32 bytes, which at 20Msps will occur every
107 seconds.
2022-02-13 16:46:12 +00:00
Martin Ling
fd073e391f Add USB vendor request to read M0 state, and host support for doing so.
This adds a `hackrf_debug [-S|--state]` option, and the necessary
plumbing to libhackrf and the M4 firmware to support it.

The USB API and libhackrf versions are bumped to reflect the changes.
2022-02-13 16:46:12 +00:00
Martin Ling
4c9fcf8665 After cancelling transfers, wait for all handling to complete.
Calling libusb_cancel_transfer only starts the cancellation of a
transfer. The process is not complete until the transfer callback
has been called with status LIBUSB_TRANSFER_CANCELLED.

If hackrf_start_rx() is called soon after hackrf_stop_rx(),
prepare_transfers() may be called before the previous cancellations
are completed, resulting in a LIBUSB_ERROR_BUSY when a transfer is
reused with libusb_submit_transfer().

To prevent this happening, we keep track of which transfers have
finished (either by completion, or cancellation), and make
cancel_transfers() wait until all transfers are finished.

This is implemented using a pthread condition variable which is
signalled from the transfer thread.
2022-02-03 06:44:20 +00:00
Martin Ling
837b5ee9c8 Use a lock to prevent transfers being restarted during cancellation.
Fixes bug #916.

Previously, there was a race which could lead to a transfer being left
active after cancel_transfers() completed. This would then cause the
next prepare_transfers() call to fail, because libusb_submit_transfer()
would return an error due to the transfer already being in use.

The sequence of events that could cause this was:

1. Main thread calls hackrf_stop_rx(), which calls cancel_transfers(),
   which iterates through the 4 transfers in use and cancels them one
   by one with libusb_cancel_transfer().

2. During this time, a transfer is completed. The transfer thread calls
   hackrf_libusb_transfer_callback(), which handles the data and then
   calls libusb_submit_transfer() to resubmit that transfer.

3. Now, cancel_transfers() and hackrf_stop_rx() are completed but one
   transfer is still active.

4. The next hackrf_start_rx() call fails, because prepare_transfers()
   tries to submit a transfer which is already in use.

To fix this, we add a lock which must be held to either cancel transfers
or restart them. This ensures that only one of these actions can happen
for a given transfer; it's no longer possible for a transfer to be
cancelled and then immediately restarted.
2022-02-03 06:44:19 +00:00
Mike Walters
8660e44575 Merge pull request #1018 from greatscottgadgets/oc-bugs
Fix Opera Cake bugs
2022-01-12 17:37:58 +00:00
Michael Ossmann
b1b11e6269 update Opera Cake documentation (#1017) 2021-12-12 17:06:53 -05:00
Michael Ossmann
e25096b17a firmware: add operacake_activate_ports()
Fixes frequency mode which had been broken by operacake_set_ports() only
activating the selected ports when in manual mode (at my suggestion).
2021-12-12 11:56:57 -07:00
Michael Ossmann
3b8c317800 hackrf_operacake: fix long options with arguments 2021-12-11 17:37:36 -07:00
Michael Ossmann
aa0485d4df Revert "Cleanup of host software CMake build system (#664)"
This reverts commit d60fb83320cea49fd20305f22838f948557f1b81.
2021-12-08 16:59:05 -07:00
Jamie Smith
d60fb83320 Cleanup of host software CMake build system (#664)
* Clean up the CMake build system and improve the FindFFTW3 module.

* Fixes for Linux build

* Include winsock.h to get struct timeval

* Couple more fixes for MSVC, also add new FindMath module

* Update host build README for new CMake changes (esp. Windows)

* Try to fix Travis OS X build error

* Add docs about pthread-win32

* Whoops, AppVeyor caught a bug in FindFFTW where the includes not being found weren't generating a fatal error.

* Travis rebuild bump

* One more fix: replace hardcoded include paths with a PATH_SUFFIX to standard include paths

* Invert Windows preprocessor flag so it's only needed when using a static build.  This preserves compatibility with the previous system.

* Fix copy-paste error

* Update cmake modules from amber-cmake upstream, incorporate TryLinkLibrary into FindUSB1

* Fix missing include
2021-12-03 14:11:04 -05:00
Michael Ossmann
0f4f1addd1 libhackrf: document hackrf_transfer struct 2021-11-17 18:38:00 -07:00
Michael Ossmann
c8695e0a44 hackrf_sweep: correct -w (bin_width) minimum 2021-11-14 12:21:29 -07:00
Michael Ossmann
8a3547e71e hackrf_sweep: improve -w (bin_width) guidance 2021-11-14 12:05:29 -07:00
Michael Ossmann
9856452215 hackrf_sweep: eliminate -n option (num_samples)
The firmware has the capability to dwell on each frequency for a
configurable duration in sweep mode, but the hackrf_sweep host tool did
not behave correctly when asked to use a non-default dwell time. The
option has never worked properly, and it is not a feature anyone seems
to want.
2021-11-14 11:41:56 -07:00
Michael Ossmann
2775279fd0 hackrf_sweep: eliminate time stamp adjustment
We previously attempted to adjust the output time stamp according to the
sample rate and placement of the samples within the USB transfer data,
but the end result was a fixed time offset with respect to the time of
USB transfer completion. We are using only those samples closest to the
end of the transfer, so it makes sense to simply use the time the USB
transfer ends and not try to correct that fixed offset.

It may be possible in the future to have a more accurate time stamp
generated in firmware, but I don't think it is worth complicating the
host code with minor time adjustments until and unless firmware-based
time stamps become available.
2021-11-14 11:20:31 -07:00
Michael Ossmann
3589bc4ed3 Merge pull request #950 from miek/operacake-cleanup
Opera Cake CLI/API cleanup
2021-10-28 17:00:55 -06:00
Fabrice Fontaine
3e32f46c79 cmake/modules/FindFFTW.cmake: fix build without fftw3
Build on Linux fails if libfftw3 is not available since commit
a8c1fc92e9
which replaced
pkg_check_modules(FFTW REQUIRED fftw3f)
by
find_package(FFTW REQUIRED)

Fix this build failure by updating FindFFTW.cmake to check for fftw3f

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2021-10-15 23:42:03 +02:00
Mike Walters
f5a7132805 hackrf_operacake: make main options mutually exclusive
ref #930
2021-10-15 14:45:38 +01:00
Mike Walters
4ecbd5d2c9 hackrf_operacake: add option for default dwell time
This allows for usage like this:

  $ hackrf_operacake -m time -w 1e6 -t A1 -t A2 -t A3
  $ hackrf_transfer -r /dev/null -s 1e6

ref #930
2021-10-15 14:45:38 +01:00
Mike Walters
38ed075437 operacake: replace hackrf_set_operacake_ranges with hackrf_set_operacake_freq_ranges 2021-10-15 14:45:38 +01:00
Mike Walters
0e68be7771 hackrf_operacake: simplify frequency range parsing 2021-10-15 14:45:38 +01:00
Mike Walters
07a9dd73d8 hackrf_operacake: swap argument order for frequency-switching
ref #930
2021-10-15 14:45:38 +01:00
Mike Walters
f9b923fce2 hackrf_operacake: default to address 0
ref #930
2021-10-15 14:45:38 +01:00
Mike Walters
e41314f130 operacake: add API function to set port dwell times 2021-10-14 14:41:52 +01:00
Mike Walters
c50ebb1a36 operacake: add time switching mode 2021-10-14 14:41:52 +01:00
Mike Walters
790b5d35cf operacake: add get/set switching mode functions 2021-10-14 14:36:18 +01:00
Mike Walters
6aa64a80d5 hackrf_operacake: clarify output of list command
Now that addresses are in the range 0-7, this would previously output
"Operacakes found: 0" for the default board address. This is confusing
as it looks like it found no Opera Cakes.
2021-07-14 18:35:31 +01:00
Mike Walters
5e2e06b620 hackrf_info: display Opera Cake addresses in decimal
Fixes #899
2021-07-14 18:35:31 +01:00
Mike Walters
0293cf23db Opera Cake: use 0-7 instead of I2C addresses & bump USB API version 2021-07-14 18:35:31 +01:00
Clifford Heath
a9945ffaa3 Report amplitude once per second during receive (#890)
* Report amplitude once per second during receive

* Added missing M_LN10 for Windoze, fixed short frame detection for RSSI

* Tweaks to math expressions

* Tweaks to math expressions
2021-06-13 11:59:26 -06:00
Michael Ossmann
10b7d67ea5 Merge pull request #874 from metayan/sweeprate
hackrf_sweep: Calculate and show sweep rate for subsecond sweeps
2021-04-23 17:35:31 -06:00
Yan
7c14f876a0 hackrf_sweep: initialise sweep_rate
Thanks to dmaltsiniotis for spotting this.
2021-04-10 13:47:33 +02:00
Yan
90acbcff07 hackrf_sweep: Calculate and show sweep rate for subsecond sweeps 2021-04-08 22:46:42 +02:00