diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..b748d2397 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,33 @@ +name: Testing + +on: [push, pull_request] + +jobs: + linux-test: + runs-on: ubuntu-latest + container: + image: tfcollins/libiio_ubuntu_22_04-ci:latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.7 + uses: actions/setup-python@v2 + with: + python-version: 3.7 + - name: Install dependencies + run: | + apt update + apt install -y lcov + - name: Build and Test + run: | + mkdir build + cd build + cmake .. -DTESTS=ON -DTESTS_DEBUG=ON -DTESTS_COVERAGE=ON -DWITH_GCOV=ON + make + make coverage + + # - name: Upload coverage to Codecov + # uses: codecov/codecov-action@v1 + # with: + # token: ${{ secrets.CODECOV_TOKEN }} + # file: ./build/coverage.xml + # flags: unittests diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f57a5fbd..50d628d6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -653,6 +653,44 @@ add_subdirectory(bindings) option(WITH_MAN "Generate on-line reference manuals (man pages)" OFF) add_subdirectory(man) +# Testing +option(TESTS "Enabling unit testing" OFF) +option(TESTS_DEBUG "Enable test debugging" OFF) +option(TESTS_COVERAGE "Enable coverage tracing when testing" OFF) +if(TESTS) + include(CTest) + enable_testing() + add_subdirectory(tests) + if(TESTS_COVERAGE) + if(NOT WITH_GCOV) + message(FATAL_ERROR "Coverage report generation only supported with WITH_GCOV also enabled") + endif() + + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux") + message(FATAL_ERROR "Coverage only supported on Linux") + endif() + # Verify that lcov is installed + find_program(LCOV_PATH lcov) + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -Wall -fprofile-arcs -ftest-coverage") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -Wall -W -fprofile-arcs -ftest-coverage") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") + target_compile_options(iio PRIVATE --coverage) + target_link_libraries(iio PRIVATE --coverage) + + # Add custom target to run tests with coverage + add_custom_target( + coverage + COMMAND ${CMAKE_CTEST_COMMAND} --progress && lcov -c -d ${CMAKE_CURRENT_SOURCE_DIR} -o main_coverage.info && genhtml main_coverage.info -o coverage + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + + message(STATUS "Coverage flags enabled") + endif() + +endif() + include(cmake/Install.cmake) # Add uninstall target diff --git a/README_BUILD.md b/README_BUILD.md index d6cb32fa6..cf0ab76d3 100644 --- a/README_BUILD.md +++ b/README_BUILD.md @@ -59,6 +59,9 @@ Cmake Options | Default | Target | Description `WITH_GCOV` | OFF | Linux | Build with gcov profiling flags | `OSX_FRAMEWORK` | ON | Mac | OS X frameworks provide the interfaces you need to write software for Mac. | `OSX_PACKAGE` | ON | Mac | Create a OSX package for installation on local and other machines | +`TESTS` | OFF | All | Build tests and enable tests targets | +`TESTS_DEBUG` | OFF | All | Build tests with debug outputs | +`TESTS_COVERAGE` | OFF | Linux | Enable debug flags and coverage report generation | Which backends the library supports is dependent on the build system, but can be overridden. (If cmake finds libusb, it will use it, unless turned off manually) diff --git a/bindings/python/requirements_test.txt b/bindings/python/requirements_test.txt new file mode 100644 index 000000000..8cfe497b0 --- /dev/null +++ b/bindings/python/requirements_test.txt @@ -0,0 +1,3 @@ +pytest +scipy +numpy \ No newline at end of file diff --git a/bindings/python/tests/tests_ad9361.py b/bindings/python/tests/tests_ad9361.py new file mode 100644 index 000000000..39508b16c --- /dev/null +++ b/bindings/python/tests/tests_ad9361.py @@ -0,0 +1,152 @@ +import pytest + +import iio +import numpy as np +from scipy import signal + +import os + + +def gen_data(fs, fc): + N = 2**12 + ts = 1 / float(fs) + t = np.arange(0, N * ts, ts) + i = np.cos(2 * np.pi * t * fc) * 2**14 + q = np.sin(2 * np.pi * t * fc) * 2**14 + iq = i + 1j * q + return iq + + +def estimate_freq(x, fs): + f, Pxx_den = signal.periodogram(x, fs) + idx = np.argmax(Pxx_den) + return f[idx] + + +## Streaming not supported yet +# def stream_based_tx(buf_tx, iq): +# # Stream version (Does not support cyclic?) +# tx_stream = iio.Stream(buf_tx, 1024) +# block_tx = next(tx_stream) +# block_tx.write(iq) +# block_tx.enqueue(None, True) +# buf_tx.enabled = True + + +def block_based_tx_chans(block_tx, buf_tx, mask_tx, ib, qb): + # Block version channel based + mask_tx.channels[0].write(block_tx, ib) + mask_tx.channels[1].write(block_tx, qb) + block_tx.enqueue(None, True) + buf_tx.enabled = True + + +def block_based_tx_single(block_tx, buf_tx, ib, qb): + iqb = np.stack((ib, qb), axis=-1) + iqb = iqb.flatten() + iqb = bytearray(iqb) + + # Block version single write + block_tx.write(iqb) + block_tx.enqueue(None, True) + buf_tx.enabled = True + + +@pytest.mark.parametrize("tx_buffer_modes", ["dds", "chans", "single"]) +@pytest.mark.parametrize("rx_buffer_modes", ["chans", "single"]) +def test_ad9361_buffers(tx_buffer_modes, rx_buffer_modes): + fs = 4e6 + lo = 1e9 + fc = 5e5 + + uri = os.getenv("URI", "ip:analog.local") + + ctx = iio.Context(uri) + dev = ctx.find_device("ad9361-phy") + dev_rx = ctx.find_device("cf-ad9361-lpc") + dev_tx = ctx.find_device("cf-ad9361-dds-core-lpc") + + chan = dev.find_channel("voltage0") + chan.attrs["sampling_frequency"].value = str(int(fs)) + chan.attrs["rf_bandwidth"].value = str(int(fs)) + + achan = dev.find_channel("altvoltage0", True) + achan.attrs["frequency"].value = str(int(lo)) + achan = dev.find_channel("altvoltage1", True) + achan.attrs["frequency"].value = str(int(lo)) + + dev.debug_attrs["loopback"].value = "1" + + if tx_buffer_modes == "dds": + # DDS + for N in [1]: + for IQ in ["I", "Q"]: + chan = f"TX1_{IQ}_F{N}" + dds = dev_tx.find_channel(chan, True) + if not dds: + raise Exception(f"Could not find channel {chan}") + dds.attrs["frequency"].value = str(int(fc)) + dds.attrs["scale"].value = "0.2" + if IQ == "I": + dds.attrs["phase"].value = "90000" + else: + dds.attrs["phase"].value = "0.0" + + ## Buffer stuff + + # RX Side + chan1 = dev_rx.find_channel("voltage0") + chan2 = dev_rx.find_channel("voltage1") + mask = iio.ChannelsMask(dev_rx) + mask.channels = [chan1, chan2] + + buf = iio.Buffer(dev_rx, mask) + stream = iio.Stream(buf, 1024) + + if tx_buffer_modes != "dds": + # TX Side + chan1_tx = dev_tx.find_channel("voltage0", True) + chan2_tx = dev_tx.find_channel("voltage1", True) + mask_tx = iio.ChannelsMask(dev_tx) + mask_tx.channels = [chan1_tx, chan2_tx] + + # Create a sinewave waveform + fc = 15e5 + iq = gen_data(fs, fc) + # Convert iq to interleaved int16 byte array + ib = np.array(iq.real, dtype=np.int16) + qb = np.array(iq.imag, dtype=np.int16) + + # Send data to iio + buf_tx = iio.Buffer(dev_tx, mask_tx) + block_tx = iio.Block(buf_tx, len(ib)) + + if tx_buffer_modes == "chans": + block_based_tx_chans(block_tx, buf_tx, mask_tx, ib, qb) + + if tx_buffer_modes == "single": + block_based_tx_single(block_tx, buf_tx, ib, qb) + + # Clear buffer queue + for r in range(10): + block = next(stream) + + for r in range(20): + block = next(stream) + + # Single buffer read + if rx_buffer_modes == "single": + x = np.frombuffer(block.read(), dtype=np.int16) + x = x[0::2] + 1j * x[1::2] + else: + # Buffer read by channel + re = mask.channels[0].read(block) + re = np.frombuffer(re, dtype=np.int16) + im = mask.channels[1].read(block) + im = np.frombuffer(im, dtype=np.int16) + x = re + 1j * im + + freq = estimate_freq(x, fs) + print(f"Estimated freq: {freq/1e6} MHz | Expected freq: {fc/1e6} MHz") + + assert np.abs(freq - fc) < 1e3 diff --git a/block.c b/block.c index 8a263100e..f6b0f9bbc 100644 --- a/block.c +++ b/block.c @@ -19,9 +19,8 @@ struct iio_block { size_t size; void *data; - struct iio_task_token *token, *old_token; + struct iio_task_token *token; size_t bytes_used; - bool cyclic; }; struct iio_block * @@ -83,9 +82,6 @@ void iio_block_destroy(struct iio_block *block) struct iio_buffer *buf = block->buffer; const struct iio_backend_ops *ops = buf->dev->ctx->ops; - /* Stop the cyclic task */ - block->cyclic = false; - if (block->token) { iio_task_cancel(block->token); iio_task_sync(block->token, 0); @@ -132,20 +128,12 @@ int iio_block_io(struct iio_block *block) if (!iio_device_is_tx(block->buffer->dev)) return iio_block_read(block); - if (block->old_token) - iio_task_sync(block->old_token, 0); - - if (block->cyclic) { - block->old_token = block->token; - block->token = iio_task_enqueue(block->buffer->worker, block); - } - return iio_block_write(block); } int iio_block_enqueue(struct iio_block *block, size_t bytes_used, bool cyclic) { - const struct iio_buffer *buffer = block->buffer; + struct iio_buffer *buffer = block->buffer; const struct iio_device *dev = buffer->dev; const struct iio_backend_ops *ops = dev->ctx->ops; @@ -164,7 +152,7 @@ int iio_block_enqueue(struct iio_block *block, size_t bytes_used, bool cyclic) } block->bytes_used = bytes_used; - block->cyclic = cyclic; + buffer->cyclic = cyclic; block->token = iio_task_enqueue(buffer->worker, block); return iio_err(block->token); diff --git a/buffer.c b/buffer.c index eb759f8b6..654fd9490 100644 --- a/buffer.c +++ b/buffer.c @@ -46,14 +46,16 @@ static int iio_buffer_set_enabled(const struct iio_buffer *buf, bool enabled) { const struct iio_backend_ops *ops = buf->dev->ctx->ops; size_t sample_size, nb_samples = 0; + bool cyclic = false; if (buf->block_size) { sample_size = iio_device_get_sample_size(buf->dev, buf->mask); nb_samples = buf->block_size / sample_size; + cyclic = buf->cyclic; } if (ops->enable_buffer) - return ops->enable_buffer(buf->pdata, nb_samples, enabled); + return ops->enable_buffer(buf->pdata, nb_samples, enabled, cyclic); return -ENOSYS; } diff --git a/iio-private.h b/iio-private.h index 5d6ec2951..575b5ac73 100644 --- a/iio-private.h +++ b/iio-private.h @@ -146,7 +146,10 @@ struct iio_buffer { struct iio_task *worker; + /* These two fields are set by the last block created. They are only + * used when communicating with v0.x IIOD. */ size_t block_size; + bool cyclic; struct iio_attr_list attrlist; diff --git a/iiod-client.c b/iiod-client.c index 5039f0ace..92dbfde14 100644 --- a/iiod-client.c +++ b/iiod-client.c @@ -1490,7 +1490,7 @@ void iiod_client_free_buffer(struct iiod_client_buffer_pdata *pdata) } int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { struct iiod_client *client = pdata->client; struct iiod_client_io *client_io; @@ -1511,7 +1511,7 @@ int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, if (enable) { client_io = iiod_client_open_with_mask(client, pdata->dev, pdata->mask, - nb_samples, false); + nb_samples, cyclic); err = iio_err(client_io); pdata->io = err ? NULL : client_io; } else { diff --git a/iiod/ops.c b/iiod/ops.c index 0019daf95..473078691 100644 --- a/iiod/ops.c +++ b/iiod/ops.c @@ -398,8 +398,8 @@ static int create_buf_and_blocks(struct DevEntry *entry, size_t samples_count, for (; i; i--) iio_block_destroy(entry->blocks[i - 1]); iio_buffer_destroy(entry->buf); - entry->buf = NULL; err_free_blocks_array: + entry->buf = NULL; free(entry->blocks); entry->blocks = NULL; return err; diff --git a/include/iio/iio-backend.h b/include/iio/iio-backend.h index 73b5fec6c..ae907ba63 100644 --- a/include/iio/iio-backend.h +++ b/include/iio/iio-backend.h @@ -108,7 +108,7 @@ struct iio_backend_ops { struct iio_channels_mask *mask); void (*free_buffer)(struct iio_buffer_pdata *pdata); int (*enable_buffer)(struct iio_buffer_pdata *pdata, - size_t nb_samples, bool enable); + size_t nb_samples, bool enable, bool cyclic); void (*cancel_buffer)(struct iio_buffer_pdata *pdata); ssize_t (*readbuf)(struct iio_buffer_pdata *pdata, diff --git a/include/iio/iiod-client.h b/include/iio/iiod-client.h index 7582f7c60..1ec23f141 100644 --- a/include/iio/iiod-client.h +++ b/include/iio/iiod-client.h @@ -77,7 +77,7 @@ iiod_client_create_buffer(struct iiod_client *client, struct iio_channels_mask *mask); __api void iiod_client_free_buffer(struct iiod_client_buffer_pdata *pdata); __api int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, - size_t nb_samples, bool enable); + size_t nb_samples, bool enable, bool cyclic); __api struct iio_block_pdata * iiod_client_create_block(struct iiod_client_buffer_pdata *pdata, diff --git a/local.c b/local.c index 89b337684..c3ee9731d 100644 --- a/local.c +++ b/local.c @@ -313,7 +313,7 @@ static int local_do_enable_buffer(struct iio_buffer_pdata *pdata, bool enable) } static int local_enable_buffer(struct iio_buffer_pdata *pdata, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { int ret; diff --git a/network.c b/network.c index 4e6dcb3d2..699307c79 100644 --- a/network.c +++ b/network.c @@ -485,9 +485,9 @@ void network_free_buffer(struct iio_buffer_pdata *pdata) } int network_enable_buffer(struct iio_buffer_pdata *pdata, - size_t block_size, bool enable) + size_t block_size, bool enable, bool cyclic) { - return iiod_client_enable_buffer(pdata->pdata, block_size, enable); + return iiod_client_enable_buffer(pdata->pdata, block_size, enable, cyclic); } struct iio_block_pdata * network_create_block(struct iio_buffer_pdata *pdata, diff --git a/serial.c b/serial.c index 390b05ae9..6116faae1 100644 --- a/serial.c +++ b/serial.c @@ -257,9 +257,9 @@ static void serial_free_buffer(struct iio_buffer_pdata *buf) } static int serial_enable_buffer(struct iio_buffer_pdata *buf, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { - return iiod_client_enable_buffer(buf->pdata, nb_samples, enable); + return iiod_client_enable_buffer(buf->pdata, nb_samples, enable, cyclic); } static ssize_t diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..ae872d585 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +add_definitions(-UNDEBUG) +if(TESTS_DEBUG) + add_definitions(-DTESTS_DEBUG) +endif() +add_subdirectory(standalone) +add_subdirectory(hardware) diff --git a/tests/hardware/CMakeLists.txt b/tests/hardware/CMakeLists.txt new file mode 100644 index 000000000..b7330d824 --- /dev/null +++ b/tests/hardware/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(TestBufferAD9361 test_ad9364.c) +target_link_libraries(TestBufferAD9361 LINK_PRIVATE iio) +add_test( + NAME TestBufferAD9361 + COMMAND TestBufferAD9361 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/hardware/test_ad9364.c b/tests/hardware/test_ad9364.c new file mode 100644 index 000000000..d5a79bec7 --- /dev/null +++ b/tests/hardware/test_ad9364.c @@ -0,0 +1,220 @@ +// This test is designed to verify data from transmit to receive buffers by +// using a ramp signal. The ramp signal is generated on the TX side and then +// received on the RX side. The RX side then checks to make sure the ramp is +// continuous within the buffer but not across buffers. However, every buffer is +// checked to make sure the ramp is continuous. + +#include +#include +#include +#include + +#include "iio/iio.h" + +#ifndef TESTS_DEBUG +#define TESTS_DEBUG 0 +#endif + +// Use (void) to silence unused warnings. +#define assertm(exp, msg) assert(((void)msg, exp)) + +#define dprintf(fmt, ...) \ + do { \ + if (TESTS_DEBUG>0) \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + } while (0) + +// User Set +#define N_TX_SAMPLES 128 +#define RX_OVERSAMPLE 4 +#define SUCCESSIVE_BUFFER_TO_CHECK 31 +#define N_RX_BLOCKS 4 + +// Calculated/Constant +#define N_RX_SAMPLES N_TX_SAMPLES *RX_OVERSAMPLE +#define N_CHANNELS 2 +#define BYTES_PER_SAMPLE 2 + +struct iio_context *ctx; +struct iio_device *phy, *rx, *tx; +const struct iio_attr *attr; +struct iio_channel *chn; +struct iio_channels_mask *txmask, *rxmask; +struct iio_buffer *txbuf, *rxbuf; +struct iio_block *txblock; +const struct iio_block *rxblock; +struct iio_stream *rxstream; + +int main() { + + int err; + + const char *uri = getenv("URI_AD9361"); + if (uri == NULL) + exit(0); // Cant find anything don't run tests + ctx = iio_create_context(NULL, uri); + + phy = iio_context_find_device(ctx, "ad9361-phy"); + assertm(phy, "Unable to find AD9361-phy device"); + rx = iio_context_find_device(ctx, "cf-ad9361-lpc"); + assertm(rx, "Unable to find RX device"); + tx = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc"); + assertm(tx, "Unable to find TX device"); + + // Configure device into loopback mode + attr = iio_device_find_debug_attr(phy, "loopback"); + assertm(attr, "Unable to find loopback attribute"); + iio_attr_write_string(attr, "1"); + + // TX Side + txmask = iio_create_channels_mask(iio_device_get_channels_count(tx)); + assertm(txmask, "Unable to create TX mask"); + + chn = iio_device_find_channel(tx, "voltage0", true); + assertm(chn, "Unable to find TX channel"); + iio_channel_enable(chn, txmask); + chn = iio_device_find_channel(tx, "voltage1", true); + assertm(chn, "Unable to find TX channel"); + iio_channel_enable(chn, txmask); + + txbuf = iio_device_create_buffer(tx, 0, txmask); + assertm(txbuf, "Unable to create TX buffer"); + + txblock = iio_buffer_create_block(txbuf, N_TX_SAMPLES * BYTES_PER_SAMPLE * + N_CHANNELS); + assertm(txblock, "Unable to create TX block"); + + // Generate ramp signal on both I and Q channels + int16_t *p_dat, *p_end; + ptrdiff_t p_inc; + int16_t idx = 0; + + p_end = iio_block_end(txblock); + p_inc = iio_device_get_sample_size(tx, txmask); + chn = iio_device_find_channel(tx, "voltage0", true); + + for (p_dat = iio_block_first(txblock, chn); p_dat < p_end; + p_dat += p_inc / sizeof(*p_dat)) { + // Bitshift 4 bits up. During loopback hardware will shift back 4 bits + p_dat[0] = idx << 4; + p_dat[1] = idx << 4; + idx++; + } + iio_block_enqueue(txblock, 0, true); + iio_buffer_enable(txbuf); + sleep(2); + + // RX Side + rxmask = iio_create_channels_mask(iio_device_get_channels_count(rx)); + assertm(rxmask, "Unable to create RX mask"); + + chn = iio_device_find_channel(rx, "voltage0", false); + assertm(chn, "Unable to find RX channel voltage0"); + iio_channel_enable(chn, rxmask); + chn = iio_device_find_channel(rx, "voltage1", false); + assertm(chn, "Unable to find RX channel voltage1"); + iio_channel_enable(chn, rxmask); + + rxbuf = iio_device_create_buffer(rx, 0, rxmask); + assertm(rxbuf, "Unable to create RX buffer"); + + rxstream = iio_buffer_create_stream(rxbuf, N_RX_BLOCKS, N_RX_SAMPLES); + assertm(rxstream, "Unable to create RX stream"); + + p_inc = iio_device_get_sample_size(rx, rxmask); + chn = iio_device_find_channel(rx, "voltage0", false); + + bool found_start = false; + int16_t ramp_indx = 0; + + // Create check vector + bool ramp_found_check_vector[SUCCESSIVE_BUFFER_TO_CHECK]; + bool continuous_check_vector[SUCCESSIVE_BUFFER_TO_CHECK]; + + // Remove first few blocks as they might be old + for (int i = 0; i < 30; i++) { + rxblock = iio_stream_get_next_block(rxstream); + dprintf("Removing block %d\n", i); + } + + // Check several buffers to make sure no glitches occurred + for (int i = 0; i < SUCCESSIVE_BUFFER_TO_CHECK; i++) { + + dprintf("Checking buffer %d of %d\n", i + 1, SUCCESSIVE_BUFFER_TO_CHECK); + + rxblock = iio_stream_get_next_block(rxstream); + p_end = iio_block_end(rxblock); + + // Within a block data should be continuous but not necessarily across + // blocks + found_start = false; + continuous_check_vector[i] = true; // assume good + ramp_indx = 0; + + for (p_dat = iio_block_first(rxblock, chn); p_dat < p_end; + p_dat += p_inc / sizeof(*p_dat)) { + + // Locate top of ramp + if (p_dat[0] == (N_TX_SAMPLES - 1) && p_dat[1] == (N_TX_SAMPLES - 1) && + !found_start) { + found_start = true; + continue; // Wrap to ramp restarts on next sample + } + + // Make sure ramp is continuous + if (found_start) { + dprintf("Expected: %d\n", ramp_indx); + dprintf("Actual: %d, %d (I, Q)\n\n", p_dat[0], p_dat[1]); + if (p_dat[0] != ramp_indx && p_dat[1] != ramp_indx) { + dprintf("--->Expected: %d (Buffer %d)\n", ramp_indx, i); + dprintf("--->Actual: %d, %d (I, Q) [Buffer %d]\n\n", p_dat[0], + p_dat[1], i); + dprintf("\n\n"); + continuous_check_vector[i] = false; + } + if (ramp_indx == (N_TX_SAMPLES - 1)) { + ramp_indx = 0; + } else + ramp_indx++; + } + } + + ramp_found_check_vector[i] = found_start; + if (!found_start) + continuous_check_vector[i] = false; + } + + // Examine check vector + bool failed_c1 = false; + bool failed_c2 = false; + dprintf("1 == Check Passed, 0 == Failed\n"); + dprintf("Ramp Check, Contiguous Check (Buffer #)\n"); + + for (int i = 0; i < SUCCESSIVE_BUFFER_TO_CHECK; i++) { + dprintf("%d, %d (%d)\n", ramp_found_check_vector[i], + continuous_check_vector[i], i); + if (!ramp_found_check_vector[i]) + failed_c1 = true; + if (!continuous_check_vector[i]) + failed_c2 = true; + } + dprintf("\n"); + + assertm(!failed_c1, "Ramp was not found in all buffers"); + assertm(!failed_c2, "Ramp was not contiguous in all buffers"); + + iio_stream_destroy(rxstream); + iio_buffer_destroy(rxbuf); + + // // Manual check RX (disable asserts above first) + // printf("Open up the time scope to see data. Should be a ramp from + // 0->%d\n", + // idx - 1); + // sleep(40); + + // Cleanup + iio_block_destroy(txblock); + iio_buffer_destroy(txbuf); + + return 0; +} \ No newline at end of file diff --git a/tests/standalone/CMakeLists.txt b/tests/standalone/CMakeLists.txt new file mode 100644 index 000000000..050864c8d --- /dev/null +++ b/tests/standalone/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(TestVersion test_version.c) +target_link_libraries(TestVersion LINK_PRIVATE iio) +add_test( + NAME TestVersion + COMMAND TestVersion + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/standalone/test_version.c b/tests/standalone/test_version.c new file mode 100644 index 000000000..8ba916863 --- /dev/null +++ b/tests/standalone/test_version.c @@ -0,0 +1,23 @@ +#include +#include +#include + +#include "iio/iio.h" + +int main() { + + char *expected_version = "1.0"; + char actual_version[10]; + + sprintf(actual_version, "%u.%u", iio_context_get_version_major(NULL), + iio_context_get_version_minor(NULL)); + +#ifdef TESTS_DEBUG + printf("Expected version: %s\n", expected_version); + printf("Actual version: %s\n", actual_version); +#endif + + assert(strcmp(expected_version, actual_version) == 0); + + return 0; +} \ No newline at end of file diff --git a/usb.c b/usb.c index d8e255909..40406324a 100644 --- a/usb.c +++ b/usb.c @@ -490,9 +490,9 @@ static void usb_free_buffer(struct iio_buffer_pdata *buf) } static int usb_enable_buffer(struct iio_buffer_pdata *pdata, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { - return iiod_client_enable_buffer(pdata->pdata, nb_samples, enable); + return iiod_client_enable_buffer(pdata->pdata, nb_samples, enable, cyclic); } static struct iio_block_pdata * diff --git a/utils/iio_common.c b/utils/iio_common.c index bcaae5055..a108a0246 100644 --- a/utils/iio_common.c +++ b/utils/iio_common.c @@ -444,7 +444,7 @@ uint64_t get_time_us(void) #ifdef _MSC_BUILD timespec_get(&tp, TIME_UTC); #else - clock_gettime(CLOCK_REALTIME, &tp); + clock_gettime(CLOCK_MONOTONIC, &tp); #endif return tp.tv_sec * 1000000ull + tp.tv_nsec / 1000;