1+ // This test is designed to verify data from transmit to receive buffers by
2+ // using a ramp signal. The ramp signal is generated on the TX side and then
3+ // received on the RX side. The RX side then checks to make sure the ramp is
4+ // continuous within the buffer but not across buffers. However, every buffer is
5+ // checked to make sure the ramp is continuous.
6+
17#include <assert.h>
28#include <stdio.h>
39#include <stdlib.h>
410#include <unistd.h>
511
612#include "iio/iio.h"
713
8- #define N_TX_SAMPLES 512
14+ // Use (void) to silence unused warnings.
15+ #define assertm (exp , msg ) assert(((void)msg, exp))
16+
17+ // User Set
18+ #define N_TX_SAMPLES 16
19+ #define RX_OVERSAMPLE 4
20+ #define SUCCESSIVE_BUFFER_TO_CHECK 2
21+ #define N_RX_BLOCKS 4
22+
23+ // Calculated/Constant
24+ #define N_RX_SAMPLES N_TX_SAMPLES *RX_OVERSAMPLE
25+ #define N_CHANNELS 2
926#define BYTES_PER_SAMPLE 2
1027
1128struct iio_context * ctx ;
@@ -14,7 +31,9 @@ const struct iio_attr *attr;
1431struct iio_channel * chn ;
1532struct iio_channels_mask * txmask , * rxmask ;
1633struct iio_buffer * txbuf , * rxbuf ;
17- struct iio_block * txblock , * rxblock ;
34+ struct iio_block * txblock ;
35+ const struct iio_block * rxblock ;
36+ struct iio_stream * rxstream ;
1837
1938int main () {
2039
@@ -26,36 +45,34 @@ int main() {
2645 ctx = iio_create_context (NULL , uri );
2746
2847 phy = iio_context_find_device (ctx , "ad9361-phy" );
29- assert (phy );
48+ assertm (phy , "Unable to find AD9361-phy device" );
3049 rx = iio_context_find_device (ctx , "cf-ad9361-lpc" );
31- assert (rx );
50+ assertm (rx , "Unable to find RX device" );
3251 tx = iio_context_find_device (ctx , "cf-ad9361-dds-core-lpc" );
33- assert (tx );
52+ assertm (tx , "Unable to find TX device" );
3453
3554 // Configure device into loopback mode
3655 attr = iio_device_find_debug_attr (phy , "loopback" );
37- assert (attr );
56+ assertm (attr , "Unable to find loopback attribute" );
3857 iio_attr_write_string (attr , "1" );
3958
4059 // TX Side
4160 txmask = iio_create_channels_mask (iio_device_get_channels_count (tx ));
42- assert (txmask );
61+ assertm (txmask , "Unable to create TX mask" );
4362
4463 chn = iio_device_find_channel (tx , "voltage0" , true);
45- assert (chn );
64+ assertm (chn , "Unable to find TX channel" );
4665 iio_channel_enable (chn , txmask );
4766 chn = iio_device_find_channel (tx , "voltage1" , true);
48- assert (chn );
67+ assertm (chn , "Unable to find TX channel" );
4968 iio_channel_enable (chn , txmask );
5069
5170 txbuf = iio_device_create_buffer (tx , 0 , txmask );
52- err = iio_err (txbuf );
53- if (err ) {
54- // dev_perror(tx, err, "Unable to create TX buffer");
55- assert (err == 0 );
56- }
71+ assertm (txbuf , "Unable to create TX buffer" );
5772
58- txblock = iio_buffer_create_block (txbuf , N_TX_SAMPLES * BYTES_PER_SAMPLE );
73+ txblock = iio_buffer_create_block (txbuf , N_TX_SAMPLES * BYTES_PER_SAMPLE *
74+ N_CHANNELS );
75+ assertm (txblock , "Unable to create TX block" );
5976
6077 // Generate ramp signal on both I and Q channels
6178 int16_t * p_dat , * p_end ;
@@ -75,10 +92,127 @@ int main() {
7592 }
7693 iio_block_enqueue (txblock , 0 , true);
7794 iio_buffer_enable (txbuf );
95+ sleep (2 );
96+
97+ // RX Side
98+ rxmask = iio_create_channels_mask (iio_device_get_channels_count (rx ));
99+ assertm (rxmask , "Unable to create RX mask" );
100+
101+ chn = iio_device_find_channel (rx , "voltage0" , false);
102+ assertm (chn , "Unable to find RX channel voltage0" );
103+ iio_channel_enable (chn , rxmask );
104+ chn = iio_device_find_channel (rx , "voltage1" , false);
105+ assertm (chn , "Unable to find RX channel voltage1" );
106+ iio_channel_enable (chn , rxmask );
107+
108+ rxbuf = iio_device_create_buffer (rx , 0 , rxmask );
109+ assertm (rxbuf , "Unable to create RX buffer" );
110+
111+ rxstream = iio_buffer_create_stream (rxbuf , N_RX_BLOCKS , N_RX_SAMPLES );
112+ assertm (rxstream , "Unable to create RX stream" );
113+
114+ p_inc = iio_device_get_sample_size (rx , rxmask );
115+ chn = iio_device_find_channel (rx , "voltage0" , false);
116+
117+ bool found_start = false;
118+ int16_t ramp_indx = 0 ;
119+ int16_t looped = 0 ;
120+
121+ // Create check vector
122+ bool ramp_found_check_vector [SUCCESSIVE_BUFFER_TO_CHECK ];
123+ bool continuous_check_vector [SUCCESSIVE_BUFFER_TO_CHECK ];
124+
125+ // Remove first few blocks as they might be old
126+ for (int i = 0 ; i < 30 ; i ++ ) {
127+ rxblock = iio_stream_get_next_block (rxstream );
128+ printf ("Removing block %d\n" , i );
129+ }
130+
131+ // Check several buffers to make sure no glitches occurred
132+ for (int i = 0 ; i < SUCCESSIVE_BUFFER_TO_CHECK ; i ++ ) {
133+
134+ printf ("Checking buffer %d of %d\n" , i + 1 , SUCCESSIVE_BUFFER_TO_CHECK );
135+
136+ rxblock = iio_stream_get_next_block (rxstream );
137+
138+ // Within a block data should be continuous but not necessarily across
139+ // blocks
140+ found_start = false;
141+ continuous_check_vector [i ] = true; // assume good
142+
143+ for (p_dat = iio_block_first (rxblock , chn ); p_dat < p_end ;
144+ p_dat += p_inc / sizeof (* p_dat )) {
145+
146+ // Locate top of ramp
147+ if (p_dat [0 ] == (N_TX_SAMPLES - 1 ) && p_dat [1 ] == (N_TX_SAMPLES - 1 ) &&
148+ !found_start ) {
149+ found_start = true;
150+ continue ;
151+ }
152+
153+ // Make sure ramp is continuous
154+ if (found_start ) {
155+ #ifdef TESTS_DEBUG
156+ printf ("Expected: %d\n" , ramp_indx );
157+ printf ("Actual: %d, %d (I, Q)\n\n" , p_dat [0 ], p_dat [1 ]);
158+ #endif
159+ if (p_dat [0 ] != ramp_indx && p_dat [1 ] != ramp_indx ) {
160+ #ifdef TESTS_DEBUG
161+ printf ("--->Expected: %d (Buffer %d)\n" , ramp_indx , i );
162+ printf ("--->Actual: %d, %d (I, Q) [Buffer %d]\n\n" , p_dat [0 ],
163+ p_dat [1 ], i );
164+ printf ("\n\n" );
165+ #endif
166+ continuous_check_vector [i ] = false;
167+ }
168+ if (ramp_indx == (N_TX_SAMPLES - 1 )) {
169+ ramp_indx = 0 ;
170+ looped ++ ;
171+ } else
172+ ramp_indx ++ ;
173+ }
174+ }
175+
176+ ramp_found_check_vector [i ] = found_start ;
177+ if (!found_start )
178+ continuous_check_vector [i ] = false;
179+ }
180+
181+ // Examine check vector
182+ bool failed_c1 = false;
183+ bool failed_c2 = false;
184+ #ifdef TESTS_DEBUG
185+ printf ("1 == Check Passed, 0 == Failed\n" );
186+ printf ("Ramp Check, Contiguous Check (Buffer #)\n" );
187+ #endif
188+ for (int i = 0 ; i < SUCCESSIVE_BUFFER_TO_CHECK ; i ++ ) {
189+ #ifdef TESTS_DEBUG
190+ printf ("%d, %d (%d)\n" , ramp_found_check_vector [i ],
191+ continuous_check_vector [i ], i );
192+ #endif
193+ if (!ramp_found_check_vector [i ])
194+ failed_c1 = true;
195+ if (!continuous_check_vector [i ])
196+ failed_c2 = true;
197+ }
198+ #ifdef TESTS_DEBUG
199+ printf ("\n" );
200+ #endif
201+ assertm (!failed_c1 , "Ramp was not found in all buffers" );
202+ assertm (!failed_c2 , "Ramp was not contiguous in all buffers" );
203+
204+ iio_stream_destroy (rxstream );
205+ iio_buffer_destroy (rxbuf );
206+
207+ // // Manual check RX (disable asserts above first)
208+ // printf("Open up the time scope to see data. Should be a ramp from 0->%d\n",
209+ // idx - 1);
210+ // sleep(40);
211+
212+ // Cleanup
213+ iio_block_destroy (txblock );
214+ iio_buffer_destroy (txbuf );
78215
79- // Sleep for 40 seconds
80- printf ("Open up the time scope to see data. Should be a ramp from 0->%d\n" , N_TX_SAMPLES );
81- sleep (40 );
82216
83217 return 0 ;
84218}
0 commit comments