source: ResearchApps/PHY/WARPLAB/WARPLab7/C_Code_Reference/wl_baseband.c

Last change on this file was 5608, checked in by murphpo, 8 years ago

Fixed warplab_set_agc_rx_length() to correctly set the rx_length threshold for the reset-per-rx logic in the AGC core.

File size: 126.4 KB
RevLine 
[4196]1/** @file wl_baseband.c
2 *  @brief WARPLab Framework (Baseband)
3 *
4 *  This contains the code for WARPLab Framework.
5 *
[4668]6 *  @copyright Copyright 2013-2015, Mango Communications. All rights reserved.
[4196]7 *          Distributed under the WARP license  (http://warpproject.org/license)
8 *
9 *  @author Chris Hunter (chunter [at] mangocomm.com)
10 *  @author Patrick Murphy (murphpo [at] mangocomm.com)
11 *  @author Erik Welsh (welsh [at] mangocomm.com)
12 */
[1995]13
[4234]14/******************************* IMPORTANT ***********************************/
15//
16// We are going to assume that all TX, RX and RSSI buffers are the same size.
17// In the future, this might not be true and the code will need to be modified
18// to accommodate this.
19//
[4453]20/******************************* IMPORTANT ***********************************/
21
22
23
24/**********************************************************************************************************************/
25/**
[4668]26 * @brief Common Functions
[4453]27 *
28 **********************************************************************************************************************/
29
[4196]30/***************************** Include Files *********************************/
[4184]31
[4196]32// Xilinx / Standard library includes
[1915]33#include <stdlib.h>
34#include <stdio.h>
[4196]35#include <string.h>
36
37#include <xio.h>
38#include <xparameters.h>
[1915]39#include <xil_io.h>
40#include <xil_types.h>
[4453]41#include <xstatus.h>
[2013]42
[4196]43// WARPLab includes
44#include "wl_common.h"
45#include "wl_baseband.h"
46#include "wl_interface.h"
[4668]47#include "wl_transport.h"
[4196]48#include "wl_node.h"
49#include "wl_trigger_manager.h"
[4184]50
[4514]51// WARP IP/UPD Library includes
52#include <WARP_ip_udp.h>
[4184]53
[4196]54/*************************** Constant Definitions ****************************/
[4234]55
[4196]56/*********************** Global Variable Definitions *************************/
[2919]57
58/*************************** Variable Definitions ****************************/
59
60// Fletcher-32 Checksum variables
[4196]61static u32         write_iq_checksum_lsb = 0;
62static u32         write_iq_checksum_msb = 0;
[2919]63
[4196]64// Buffer variables
65static u32         rx_buffer_size;
[4234]66static u32         use_dram_for_buffers  = 0;
[2919]67
[4196]68static void      * wl_iq_rx_buff_a;
69static void      * wl_iq_tx_buff_a;
70static void      * wl_rssi_buff_a;
[1915]71
[4196]72static u32         wl_iq_rx_buff_a_size;
73static u32         wl_iq_tx_buff_a_size;
74static u32         wl_rssi_buff_a_size;
[1915]75
[4196]76static void      * wl_iq_rx_buff_b;
77static void      * wl_iq_tx_buff_b;
78static void      * wl_rssi_buff_b;
[2919]79
[4196]80static u32         wl_iq_rx_buff_b_size;
81static u32         wl_iq_tx_buff_b_size;
82static u32         wl_rssi_buff_b_size;
83
84static void      * wl_iq_rx_buff_c;
85static void      * wl_iq_tx_buff_c;
86static void      * wl_rssi_buff_c;
87
88static u32         wl_iq_rx_buff_c_size;
89static u32         wl_iq_tx_buff_c_size;
90static u32         wl_rssi_buff_c_size;
91
92static void      * wl_iq_rx_buff_d;
93static void      * wl_iq_tx_buff_d;
94static void      * wl_rssi_buff_d;
95
96static u32         wl_iq_rx_buff_d_size;
97static u32         wl_iq_tx_buff_d_size;
98static u32         wl_rssi_buff_d_size;
99
[4284]100static u32         supported_tx_length = 0xFFFFFFFF;
101static u32         supported_rx_length = 0xFFFFFFFF;
[4196]102
[4707]103// Bit counting vector
104const u8           one_bits[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
[4196]105
[4707]106
[4668]107// Read IQ Packet Buffering:
108//
109// In WARPLab 7.5.x, the baseband explicitly did not allow Read IQ transfers while the node was transmitting
110// or receiving.  This restriction was imposed because the new larger WARPLab buffers, see
111// http://warpproject.org/trac/wiki/WARPLab/BufferSizes, required CPU processing to perform intermediate
112// transfers of IQ data between BRAM and DDR.  This restriction also allowed certain design decisions to be
113// kept from previous versions of WARPLab for both the transport and the baseband.  First, the WARPxilnet
114// transport would only process one Ethernet transaction at a time, ie it was not possible to queue up multiple
115// transactions within the transport (NOTE:  While the transport would only process one transaction at a time,
116// there was some internal buffering within the Ethernet sub-system that allowed the node to achieve almost a
117// continuous 1 Gbps, see http://warpproject.org/trac/wiki/WARPLab/Benchmarks).  Second, given the behavior of
118// the transport, the Read IQ command would perform an in place modification of the Ethernet packet buffer
119// provided by the transport, which meant that no additional memory was needed for the Read IQ command.
120//
121// However, with WARPLab 7.6.0, this restriction on Read IQ transfers was removed.  This was done to 1) increase
122// overall performance of the node by allowing Read IQ transfers to be pipelined with the node transmitting or
123// receiving; and 2) make the new version of WARPLab compatible with older versions of WARPLab (ie WARPLab 7.4.0
124// and older) which did not have this restriction due to the smaller buffer sizes not requiring CPU processing.
125// Removing this restriction, required moving to the WARP IP/UDP transport which was able to process multiple
126// Ethernet transactions at a time, ie it was now possible to queue up multiple transactions within the
127// transport.  This also required updating the Read IQ command to use additional buffering for Ethernet packets
128// and not just perform in place modification of the Ethernet packet buffer provided by the transport.
129//
130// In order to maintain the same performance of Read IQ commands while the node is transmitting or receiving
131// (i.e. to not have Read IQ transfers paused by the transfer of IQ data between BRAM and DDR as part of the
132// transmit and receive processes), the Read IQ command has to issue as multiple transfers back to back so that
133// it can have a buffer for when the CPU is busy transferring IQ data.  Since it is costly to continually query
134// the state of the transport to understand when to issue the next transaction, the easiest course of action is
135// to issue as many transactions as the transport supports and allow the transport to naturally provide the back
136// pressure that will limit the issuing of new transactions.  For the WARP IP/UDP transport, the number of
137// transfers is limited by the number of Transmit Buffer Descriptors (TX BDs).  Based on some high level
138// measurements, when using jumbo frames the transport provides approximately ~460 us of buffer in steady state
139// when using the default configuration of 10 TX BDs (NOTE:  TX BDs are a BSP configuration setting.  Also, each
140// Ethernet packet generally requires 2 or 3 buffer descriptors).  This buffer time will increase or decrease
141// if a user increases or decreases the number of TX BDs, respectively.
142//
143// The issuing of multiple transactions to the transport for the Read IQ command requires the baseband to buffer
144// Ethernet headers (ie the non-IQ data that changes between packets) before they are processed by the transport.
145// Based on experiments, the number of Ethernet header buffers should be more than half the number of TX BDs.
146// For example, in a node with 10 TX BDs, the minimum number of Ethernet header buffers required is 5.  If there
147// are fewer buffers than that, for example 4 Ethernet header buffers in a node with 10 TX BDs, then there will
148// be errors in the Read IQ command as the command overwrites Ethernet header information before it is able to be
149// processed by the transport.  Therefore, we need to define and allocate buffers for Ethernet headers in the
150// baseband:
151//
152// Define Read IQ Ethernet Header Buffer Constants
153//   NOTE:  Given we are not extremely memory constrained in WARPLab 7.6.0, the constants will be defined such
154//          that the buffers are easy to understand and debug:
155//              1)  Each buffer has 128 bytes which is more than needed for an Ethernet header for standard node
156//                  to host communication in WARP reference designs (max 76 bytes as of WARPLab 7.6.0).
157//              2)  5 buffers are allocated which is the minimum number of buffers needed for the default transport
158//                  setting of 10 TX BDs.
159//              3)  Use 64 byte alignment for the buffers which is the same as the WARP IP/UDP transport
160//                  (ie it is the same as WARP_IP_UDP_BUFFER_ALIGNMENT in WARP_ip_udp_config.h)
161//
162#define WL_BASEBAND_ETH_BUFFER_SIZE                        0x80                // Number of bytes per buffer
163#define WL_BASEBAND_ETH_NUM_BUFFER                         0x05                // Number of buffers allocated
164#define WL_BASEBAND_ETH_BUFFER_ALIGNMENT                   0x40                // Buffer alignment (64 byte boundary)
165
166
167// Allocate Read IQ Ethernet Header buffer
168//     NOTE:  The buffer memory must be placed in DMA accessible BRAM such that it can be fetched by the AXI DMA
169//            attached to the Ethernet module.  Therefore, we will use the same section as other buffers for
170//            Ethernet data, ie section ".eth_data".
171//
172u8                 ETH_IQ_buffer[WL_BASEBAND_ETH_NUM_BUFFER * WL_BASEBAND_ETH_BUFFER_SIZE] __attribute__ ((aligned(WL_BASEBAND_ETH_BUFFER_ALIGNMENT))) __attribute__ ((section (".eth_data")));
173
174
[4196]175/*************************** Functions Prototypes ****************************/
176
[4668]177void read_rx_buffers(u32 cmd_id, u32 buffer_sel, u32 offset, u32 length, u32 dest_addr, warp_ip_udp_buffer * buffer);
[4234]178void write_tx_buffers(u32 buffer_sel, u32 src_addr, u32 offset, u32 length);
[4453]179
180// Functions implemented in HW specific sections of the file
181void baseband_hw_specific_reset();
182void baseband_transfer_data(u32 src_addr, u32 dest_addr, u32 length);
[4234]183void populate_tmp_tx_buffers(u32 buffer_sel, u32 offset, u32 length);
[4453]184void baseband_buffers_config(u8 dram_present);
[4673]185int  baseband_check_parameters();
[4196]186
[4811]187// Misc functions
188u32  get_buffer_counter(u32 txrx_sel, u32 buffer_sel);
189
[4668]190// Read IQ transport functions
191void send_read_iq_packet(int socket_index, void * to, wl_cmd_resp_hdr * resp_hdr, void ** buffers, u32 num_buffers);
192
[4453]193// Debug functions
[4196]194#ifdef _DEBUG_
[4453]195void print_buffer_info();
196void print_buffer_core_registers();
197void print_agc_registers();
[4196]198#endif
199
200
[2919]201/******************************** Functions **********************************/
202
[4453]203/*****************************************************************************/
204/**
[4514]205 * Process Baseband Commands
206 *
207 * This function is part of the Ethernet processing system and will process the
208 * various baseband related commands.
209 *
210 * @param   socket_index     - Index of the socket on which to send message
211 * @param   from             - Pointer to socket address structure (struct sockaddr *) where command is from
212 * @param   command          - Pointer to WARPLab Command
213 * @param   response         - Pointer to WARPLab Response
214 *
[4668]215 * @return  int              - Status of the command:
216 *                                 NO_RESP_SENT       - No response has been sent
217 *                                 RESP_SENT          - A response has been sent
218 *                                 NODE_NOT_READY     - Node is not ready to respond to the command
[4514]219 *
220 * @note    See on-line documentation for more information about the Ethernet
221 *          packet structure for WARPLab:  www.warpproject.org
222 *
223 ******************************************************************************/
224int baseband_process_cmd(int socket_index, void * from, wl_cmd_resp * command, wl_cmd_resp * response) {
[1915]225
[4668]226    //
[4514]227    // IMPORTANT ENDIAN NOTES:
[4668]228    //     - command
229    //         - header - Already endian swapped by the framework (safe to access directly)
230    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
231    //     - response
232    //         - header - Will be endian swapped by the framework (safe to write directly)
233    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
234    //
[1915]235
[4668]236    // Standard variables
[4514]237    u32                 resp_sent      = NO_RESP_SENT;
238
239    wl_cmd_resp_hdr   * cmd_hdr        = command->header;
240    u32               * cmd_args_32    = command->args;
241    u32                 cmd_id         = WL_CMD_TO_CMDID(cmd_hdr->cmd);
242
243    wl_cmd_resp_hdr   * resp_hdr       = response->header;
244    u32               * resp_args_32   = response->args;
245    u32                 resp_index     = 0;
246
247    // Specific command variables
[4668]248    u32                 status;
249    u32                 msg_cmd;
[4333]250
[4668]251    u32                 i;
252    u32                 tx_delay;
253    u32                 sample_length;
254    u32                 byte_length;
255    u32                 mode;
[4811]256    u32                 rf_sel, buff_sel, txrx_sel;
[4684]257    u32                 buff_enable;
[4811]258    u32                 buff_counter;
[4668]259    u32                 start_samp, curr_samp, start_byte, num_samp, samp_len, num_pkts, offset;
260    u32                 total_samp, max_samp_len_per_pkt, max_samp_per_pkt, next_start_samp;
261    u8                  sample_iq_id;
[1915]262
[4668]263    warp_ip_udp_buffer  header_buffer;
264    warp_ip_udp_buffer  sample_buffer;
265    void              * read_iq_resp[2];
266    u32                 header_length;
267    u16                 ip_length;
268    u16                 udp_length;
269    u16                 data_length;
270    u32                 total_hdr_length;
271    u8                  dest_hw_addr[ETH_MAC_ADDR_LEN];
272    u32                 dest_ip_addr;
273    u16                 dest_port;
274    u32                 eth_dev_num;
275    u8                * header_base_addr;
276    u32                 header_offset;
277    u8                * header_addr;
278    u32                 header_buffer_size;
279    u8                  tmp_header[80];                         // Temporary header (80 bytes)
[4453]280
[4668]281    u32                 temp;
[4692]282    u32                 temp_offset;
283    u32                 temp_status;
284    u32                 temp_threshold;
[4668]285    u32                 threshold;
[4707]286    u32                 check_status;
287    u32                 raw_status;
[4453]288
[4668]289    u32                 curr_checksum;
290    u32                 checksum_input_32;
291    u16                 checksum_input_16;
[1942]292
[4668]293    u8                  flags;
294    void              * samp_addr;
295    u32               * samp_addr_32;
296    wl_bb_samp_hdr    * samp_hdr;
[1915]297
[4668]298    u16                 agc_target;
[4783]299    u32                 agc_dco_enable;
[4196]300
[4783]301    u32                 rssi_avg_length;
302    u32                 v_db_adjust;
303    u32                 init_bb_gain;
304
305    u32                 a1_coeff;
306    u32                 b0_coeff;
307
308    u32                 thresh_3_2;
309    u32                 thresh_2_1;
310
311    u32                 capture_rssi_1;
312    u32                 capture_rssi_2;
313    u32                 capture_v_db;
314    u32                 agc_done;
315
316    u32                 start_dco;
317    u32                 start_iir_filter;
318
[4668]319    u32                 dest_addr;
[1915]320
[4668]321    warp_ip_udp_header     * eth_ip_udp_header;
322    wl_transport_header    * wl_header_tx;
323
324
325    // Set up the response header
326    resp_hdr->cmd       = cmd_hdr->cmd;
327    resp_hdr->length    = 0;
328    resp_hdr->num_args  = 0;
329
[4284]330    // Process the command
[4668]331    switch(cmd_id){
[1915]332
[4184]333        //---------------------------------------------------------------------
[4811]334        case CMDID_BASEBAND_TX_DELAY:
[4333]335            // Get / Set the TX Delay
[4668]336            //
337            // Message format:
338            //     cmd_args_32[0]      Command:
339            //                             - Write       (NODE_WRITE_VAL)
340            //                             - Read        (NODE_READ_VAL)
341            //
342            // Response format:
343            //     resp_args_32[0]     Status
344            //     resp_args_32[1]     Current TX Delay
345            //
346            status  = CMD_PARAM_SUCCESS;
347            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4184]348
[4668]349            switch (msg_cmd) {
350                case CMD_PARAM_WRITE_VAL:
351                    tx_delay = Xil_Ntohl(cmd_args_32[1]);
352                    wl_bb_set_tx_delay(tx_delay);
353                break;
[4333]354
[4668]355                case CMD_PARAM_READ_VAL:
356                break;
[4333]357
[4668]358                default:
359                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
360                    status = CMD_PARAM_ERROR;
361                break;
362            }
[4234]363
[4668]364            // Send response
365            resp_args_32[resp_index++] = Xil_Htonl(status);
366            resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_tx_delay());
[4333]367
[4668]368            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
369            resp_hdr->num_args = resp_index;
370        break;
[4184]371
372
[4668]373        //---------------------------------------------------------------------
[4811]374        case CMDID_BASEBAND_TX_LENGTH:
[4333]375            // Get / Set the TX Length
[4668]376            //
377            // Message format:
378            //     cmd_args_32[0]      Command:
379            //                             - Write       (NODE_WRITE_VAL)
380            //                             - Read        (NODE_READ_VAL)
381            //
382            // Response format:
383            //     resp_args_32[0]     Status
384            //     resp_args_32[1]     Current TX Length
385            //
386            status  = CMD_PARAM_SUCCESS;
387            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4184]388
[4668]389            switch (msg_cmd) {
390                case CMD_PARAM_WRITE_VAL:
391                    sample_length = Xil_Ntohl(cmd_args_32[1]);
[4290]392
[4668]393                    // Check that the length is supported
394                    if (sample_length != 0) {
395                        sample_length -= 1;                // Adjust sample length for buffers core
[4290]396
[4668]397                        if (sample_length > supported_tx_length) {
398                            wl_printf(WL_PRINT_WARNING, print_type_baseband,
399                                      "Tx length greater than max supported length.  Setting to %d\n", supported_tx_length);
[4453]400
[4668]401                            sample_length = supported_tx_length;
402                        }
403                    }
[4333]404
[4668]405                    wl_bb_set_tx_length(sample_length);
406                break;
[4333]407
[4668]408                case CMD_PARAM_READ_VAL:
409                break;
[4333]410
[4668]411                default:
412                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
413                    status = CMD_PARAM_ERROR;
414                break;
415            }
[4234]416
[4668]417            // Send response
418            resp_args_32[resp_index++] = Xil_Htonl(status);
419            resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_tx_length() + 1);
[4333]420
[4668]421            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
422            resp_hdr->num_args = resp_index;
423        break;
[4184]424
425
[4668]426        //---------------------------------------------------------------------
[4811]427        case CMDID_BASEBAND_RX_LENGTH:
[4333]428            // Get / Set the RX Length
[4668]429            //
430            // Message format:
431            //     cmd_args_32[0]      Command:
432            //                             - Write       (NODE_WRITE_VAL)
433            //                             - Read        (NODE_READ_VAL)
434            //
435            // Response format:
436            //     resp_args_32[0]     Status
437            //     resp_args_32[1]     Current RX Length
438            //
439            status  = CMD_PARAM_SUCCESS;
440            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4184]441
[4668]442            switch (msg_cmd) {
443                case CMD_PARAM_WRITE_VAL:
444                    sample_length = Xil_Ntohl(cmd_args_32[1]);
445                    byte_length   = (sample_length << 2);
[4284]446
[4668]447                    if (sample_length != 0) {
448                        // Check that the length is less than the supported maximum number of samples
449                        if ((sample_length - 1) > supported_rx_length) {
450                            wl_printf(WL_PRINT_WARNING, print_type_baseband,
451                                      "Rx length greater than max supported length.  Setting to %d\n", supported_rx_length);
[4453]452
[4668]453                            sample_length = supported_rx_length;
454                        }
[4290]455
[4668]456                        // Set the global variable of the RX buffer size (in bytes) aligned to the RX transfer boundary
457                        rx_buffer_size = byte_length & WL_BUF_RX_TRANSFER_BYTE_ALIGNMENT_MASK;
[4284]458
[4668]459                        // Adjust the rx_buffer_size so that it is greater than the requested RX length
460                        //     NOTE:  This is necessary so that we run through the ISR the correct number of times
461                        //
462                        if (byte_length > rx_buffer_size) {
463                            rx_buffer_size += WL_BUF_RX_TRANSFER_THRESHOLD_BYTES;
464                        }
[4290]465
[4668]466                        //
467                        //
468                        // NOTE:  Due to the buffering scheme, if the length is greater than the RX IQ threshold,
469                        //     then we need to make sure the RX length is aligned to the Rx transfer boundary so that
470                        //     we do not run into any interrupt timing issues.  This means that for length values that
471                        //     are not already aligned, we will capture some extra samples.  This will cause those
472                        //     samples to be overwritten in the DDR buffer but that should be fine.
473                        //
474                        //
[4284]475
[4668]476                        // Get the current RX IQ threshold value
477                        threshold = wl_bb_get_rf_rx_iq_threshold();
[4284]478
[4668]479                        if (sample_length > threshold) {
480                            // Align the length the transfer threshold
481                            temp = sample_length & WL_BUF_RX_SAMPLE_ALIGNMENT_MASK;
[4284]482
[4668]483                            // Check to see if the length was actually longer than the aligned value
484                            if (sample_length > temp) {
485                                temp = temp + WL_BUF_RX_TRANSFER_THRESHOLD_SAMPLES;
486                            }
487                        } else {
488                            temp = sample_length;
489                        }
[4284]490
[4668]491                        // Set the Rx length in the buffers core to new value
492                        wl_bb_set_rx_length(temp - 1);
[4352]493
[4805]494                        // Update the AGC rx length
495                        warplab_set_agc_rx_length(temp + 100);
[4352]496
[4668]497                    } else {
498                        // Set the Rx length in the buffers core to new value
499                        wl_bb_set_rx_length(sample_length);
500                    }
501                break;
[4333]502
[4668]503                case CMD_PARAM_READ_VAL:
504                break;
[4333]505
[4668]506                default:
507                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
508                    status = CMD_PARAM_ERROR;
509                break;
510            }
[4234]511
[4668]512            // Send response
513            resp_args_32[resp_index++] = Xil_Htonl(status);
514            resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rx_length() + 1);
[4333]515
[4668]516            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
517            resp_hdr->num_args = resp_index;
518        break;
[4184]519
520
[4668]521        //---------------------------------------------------------------------
[4811]522        case CMDID_BASEBAND_MAX_NUM_SAMPLES:
[4333]523            // Get the maximum number of samples for a given RF interface
[4668]524            //
525            // Message format:
526            //     cmd_args_32[0]      Command:
527            //                             - Write       (NODE_WRITE_VAL)
528            //                             - Read        (NODE_READ_VAL)
529            //     cmd_args_32[1]      RF selection
530            //
531            // Response format:
532            //     resp_args_32[0]     Status
533            //     resp_args_32[1]     Max TX samples
534            //     resp_args_32[2]     Max RX samples
535            //
[4673]536            // NOTE:  Since we have assumed that all buffers have the same capabilities, we ignore the
537            //     RF selection parameter since that does not affect the return value.  In the future,
538            //     if we violate this assumption, this function will need to be updated.
539            //
[4668]540            status  = CMD_PARAM_SUCCESS;
541            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4333]542
[4668]543            switch (msg_cmd) {
544                case CMD_PARAM_WRITE_VAL:
545                    status = CMD_PARAM_ERROR;
546                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Write for max num samples not supported\n");
547                break;
[4333]548
[4668]549                case CMD_PARAM_READ_VAL:
550                break;
[4333]551
[4668]552                default:
553                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
554                    status = CMD_PARAM_ERROR;
555                break;
556            }
[4333]557
[4668]558            // Send response
559            resp_args_32[resp_index++] = Xil_Htonl(status);
560            resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_supported_tx_length() + 1);
561            resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_supported_rx_length() + 1);
[4333]562
[4668]563            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
564            resp_hdr->num_args = resp_index;
565        break;
[4333]566
567
[4668]568        //---------------------------------------------------------------------
[4811]569        case CMDID_BASEBAND_TX_MODE:
[4668]570            // Set TX mode to "continuous tx" or "normal"
571            //
572            // Message format:
573            //     cmd_args_32[0]      Mode:
574            //                             - 1        - Set Continuous TX mode
575            //                             - 0        - Clear Continuous TX mode (normal TX mode)
576            //
577            mode = Xil_Ntohl(cmd_args_32[0]);
[4184]578
[4668]579            if(mode) {
580                sample_length = wl_bb_get_tx_length() + 1;
[4333]581
[4668]582                if ((sample_length > WL_BUF_DEFAULT_TX_NUM_SAMPLES) && ((sample_length % WL_BUF_TX_TRANSFER_THRESHOLD_SAMPLES) != 0) ) {
583                    wl_printf(WL_PRINT_WARNING, print_type_baseband,
584                              "Tx length not a multiple of %d.\n    Tx waveform not fully defined.\n", WL_BUF_TX_TRANSFER_THRESHOLD_SAMPLES);
585                }
[4333]586
[4668]587                wl_bb_set_config(WL_BUF_REG_CONFIG_CONT_TX);
588            } else {
589                wl_bb_clear_config(WL_BUF_REG_CONFIG_CONT_TX);
590            }
591        break;
[1915]592
[4184]593
[4668]594        //---------------------------------------------------------------------
[4811]595        case CMDID_BASEBAND_TX_BUFF_EN:
[4668]596            // Enable TX buffers
597            //
598            // Message format:
599            //     cmd_args_32[0]      Buffer Select (bit selects):
600            //                             - [0]      - Select RFA buffer
601            //                             - [1]      - Select RFB buffer
602            //                             - [2]      - Select RFC buffer
603            //                             - [3]      - Select RFD buffer
604            //
605            // NOTE:  While it is technically feasible to enable the RFC and RFD buffers of the
606            //     WARPLab Buffers core in a 2RF design, that ability is restricted in the default
607            //     reference design.  First, in a 2RF design, the default DDR configuration allocates
608            //     all DDR memory to RFA and RFB, so there is no DDR available for RFC and RFD. Second,
609            //     the BRAM blocks that the core uses for "temporary local storage" are not present
610            //     for RFC and RFD in the 2RF design.  This makes the design easier to build within
611            //     XPS but means that there is no ability to actually transmit or receive data on
612            //     RFC or RFD.
613            //
[4811]614            // NOTE:  This will enable the buffers set in the buff_sel input argument.  However, it
615            //     will not affect the state of the other buffers.  To disable a buffer, you must use
616            //     the BB_TXRX_BUFF_DIS command.
617            //
[4668]618            if (WARPLAB_CONFIG_4RF) {
619                buff_sel = Xil_Ntohl(cmd_args_32[0]) & 0x0000000F;
620            } else {
621                buff_sel = Xil_Ntohl(cmd_args_32[0]) & 0x00000003;
622            }
[4184]623
[4668]624            // Enable the selected buffers in the WARPLab Buffers core
625            wl_bb_set_tx_buffer_en(buff_sel);
[4234]626
[4684]627            // Since the node cannot transmit and receive on the same interface, we explicitly disable
628            // the RX buffers for the enabled TX buffers.
629            //
630            // NOTE:  This might not be true in future revisions of WARPLab.
631            //
632            buff_enable = wl_bb_get_tx_buffer_en();
633
634            wl_bb_clear_rx_buffer_en(buff_enable);
635
[4668]636            // Pre-load data into the enabled buffers so they are ready to go.
637            populate_tmp_tx_buffers(buff_sel, 0x0, WARPLAB_IQ_TX_BUF_SIZE);
638        break;
[4234]639
[1915]640
[4668]641        //---------------------------------------------------------------------
[4811]642        case CMDID_BASEBAND_RX_BUFF_EN:
[4668]643            // Enable RX buffers
644            //
645            // Message format:
646            //     cmd_args_32[0]      Buffer Select (bit selects):
647            //                             - [0]      - Select RFA buffer
648            //                             - [1]      - Select RFB buffer
649            //                             - [2]      - Select RFC buffer
650            //                             - [3]      - Select RFD buffer
651            //
652            // NOTE:  While it is technically feasible to enable the RFC and RFD buffers of the
653            //     WARPLab Buffers core in a 2RF design, that ability is restricted in the default
654            //     reference design.  First, in a 2RF design, the default DDR configuration allocates
655            //     all DDR memory to RFA and RFB, so there is no DDR available for RFC and RFD. Second,
656            //     the BRAM blocks that the core uses for "temporary local storage" are not present
657            //     for RFC and RFD in the 2RF design.  This makes the design easier to build within
658            //     XPS but means that there is no ability to actually transmit or receive data on
659            //     RFC or RFD.
660            //
[4811]661            // NOTE:  This will enable the buffers set in the buff_sel input argument.  However, it
662            //     will not affect the state of the other buffers.  To disable a buffer, you must use
663            //     the BB_TXRX_BUFF_DIS command.
664            //
[4668]665            if (WARPLAB_CONFIG_4RF) {
666                buff_sel = Xil_Ntohl(cmd_args_32[0]) & 0x0000000F;
667            } else {
668                buff_sel = Xil_Ntohl(cmd_args_32[0]) & 0x00000003;
669            }
[4184]670
[4684]671            // Enable the selected buffers in the WARPLab Buffers core
[4668]672            wl_bb_set_rx_buffer_en(buff_sel);
[4684]673
674            // Since the node cannot transmit and receive on the same interface, we explicitly disable
675            // the RX buffers for the enabled TX buffers.
676            //
677            // NOTE:  This might not be true in future revisions of WARPLab.
678            //
679            buff_enable = wl_bb_get_rx_buffer_en();
680
681            wl_bb_clear_tx_buffer_en(buff_enable);
[4668]682        break;
[4184]683
[1915]684
[4668]685        //---------------------------------------------------------------------
[4811]686        case CMDID_BASEBAND_TXRX_BUFF_DIS:
[4668]687            // Disable TX and RX buffers
688            //
689            // Message format:
690            //     cmd_args_32[0]      Buffer Select (bit selects):
691            //                             - [0]      - Select RFA buffer
692            //                             - [1]      - Select RFB buffer
693            //                             - [2]      - Select RFC buffer
694            //                             - [3]      - Select RFD buffer
695            //
696            // NOTE:  While it is technically feasible to enable the RFC and RFD buffers of the
697            //     WARPLab Buffers core in a 2RF design, that ability is restricted in the default
698            //     reference design.  First, in a 2RF design, the default DDR configuration allocates
699            //     all DDR memory to RFA and RFB, so there is no DDR available for RFC and RFD. Second,
700            //     the BRAM blocks that the core uses for "temporary local storage" are not present
701            //     for RFC and RFD in the 2RF design.  This makes the design easier to build within
702            //     XPS but means that there is no ability to actually transmit or receive data on
703            //     RFC or RFD.
704            //
705            if (WARPLAB_CONFIG_4RF) {
706                buff_sel = Xil_Ntohl(cmd_args_32[0]) & 0x0000000F;
707            } else {
708                buff_sel = Xil_Ntohl(cmd_args_32[0]) & 0x00000003;
709            }
[4234]710
[4668]711            wl_bb_clear_tx_buffer_en(buff_sel);
712            wl_bb_clear_rx_buffer_en(buff_sel);
[4234]713
[4668]714            // Return all disabled buffers to their default state
715            populate_tmp_tx_buffers(buff_sel, 0x0, WARPLAB_IQ_TX_BUF_SIZE);
716        break;
[4184]717
[4234]718
[4668]719        //---------------------------------------------------------------------
[4811]720        case CMDID_BASEBAND_TXRX_BUFF_STATE:
[4684]721            // Return the state of the TX and RX buffers
722            //
723            // Message format:
724            //     cmd_args_32[0]      Buffer Select (bit selects):
725            //                             - [0]      - Select RFA buffer
726            //                             - [1]      - Select RFB buffer
727            //                             - [2]      - Select RFC buffer
728            //                             - [3]      - Select RFD buffer
[4811]729            //
[4684]730            // Response format:
731            //     resp_args_32[0]     RFA state (optional)
732            //     resp_args_32[1]     RFB state (optional)
733            //     resp_args_32[2]     RFC state (optional)
734            //     resp_args_32[3]     RFD state (optional)
735            //
[4811]736            // NOTE:  The return value of the RF state will only get added to the return
737            //     arguments if the given RF interface is selected.
[4684]738            //
739            buff_sel    = Xil_Ntohl(cmd_args_32[0]);
740
741            if (buff_sel & RF_SEL_A) {
742                buff_enable = BUF_STATE_STANDBY;
743
744                if (wl_bb_get_rx_buffer_en() & RF_SEL_A) { buff_enable = BUF_STATE_RX; }
745                if (wl_bb_get_tx_buffer_en() & RF_SEL_A) { buff_enable = BUF_STATE_TX; }
746
747                resp_args_32[resp_index++] = Xil_Htonl(buff_enable);
748            }
749
750            if (buff_sel & RF_SEL_B) {
751                buff_enable = BUF_STATE_STANDBY;
752
753                if (wl_bb_get_rx_buffer_en() & RF_SEL_B) { buff_enable = BUF_STATE_RX; }
754                if (wl_bb_get_tx_buffer_en() & RF_SEL_B) { buff_enable = BUF_STATE_TX; }
755
756                resp_args_32[resp_index++] = Xil_Htonl(buff_enable);
757            }
758
759            if (buff_sel & RF_SEL_C) {
760                buff_enable = BUF_STATE_STANDBY;
761
762                if (wl_bb_get_rx_buffer_en() & RF_SEL_C) { buff_enable = BUF_STATE_RX; }
763                if (wl_bb_get_tx_buffer_en() & RF_SEL_C) { buff_enable = BUF_STATE_TX; }
764
765                resp_args_32[resp_index++] = Xil_Htonl(buff_enable);
766            }
767
768            if (buff_sel & RF_SEL_D) {
769                buff_enable = BUF_STATE_STANDBY;
770
771                if (wl_bb_get_rx_buffer_en() & RF_SEL_D) { buff_enable = BUF_STATE_RX; }
772                if (wl_bb_get_tx_buffer_en() & RF_SEL_D) { buff_enable = BUF_STATE_TX; }
773
774                resp_args_32[resp_index++] = Xil_Htonl(buff_enable);
775            }
776
777            // Send response
778            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
779            resp_hdr->num_args = resp_index;
780        break;
781
782
783        //---------------------------------------------------------------------
[4811]784        case CMDID_BASEBAND_WRITE_IQ:
[4417]785            // BB_WRITE_IQ Packet Format:
[4668]786            //
787            //   - cmd_args            - Samples:  wl_bb_samp_hdr followed by the
788            //                           defined number of samples.
789            //
[4417]790            //   - resp_args_32[0]     - Status
[4668]791            //                           - CMD_PARAM_SUCCESS
792            //                           - SAMPLE_HDR_FLAG_IQ_NOT_READY
793            //                           - SAMPLE_HDR_FLAG_IQ_ERROR
794            //   - resp_args_32[1]     - IQ ID
[4417]795            //   - resp_args_32[2]     - Current checksum            (ignore if Status != CMD_PARAM_SUCCESS)
[4668]796            //   - resp_args_32[3]     - Tx status                   (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY)
[4417]797            //   - resp_args_32[4]     - Current Tx read pointer     (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY)
798            //   - resp_args_32[5]     - Tx length                   (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY)
799            //   - resp_args_32[6]     - Rx status                   (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY)
800            //   - resp_args_32[7]     - Current Rx write pointer    (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY)
801            //   - resp_args_32[8]     - Rx length                   (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY)
[4668]802            //
803            //   NOTE:  When SAMPLE_HDR_FLAG_IQ_NOT_READY is returned, then the host
804            //       can compute the wait time by the following calculation:
805            //           max(((tx_status) ? (tx_length - tx_read_pointer) : 0), ((rx_status) ? (rx_length - rx_write_pointer) : 0));
806            //
807            //   NOTE:  Node will return SAMPLE_HDR_FLAG_IQ_ERROR if in continuous Tx
808            //       mode since the node will never be ready.
809            //
810            samp_hdr         = (wl_bb_samp_hdr *)cmd_args_32;
[4184]811
[4668]812            // Parse the command arguments
813            buff_sel         = (u32) Xil_Ntohs(samp_hdr->buff_sel);
814            start_samp       = Xil_Ntohl(samp_hdr->start_samp);
815            offset           = start_samp * sizeof(wl_samp);
816            flags            = samp_hdr->flags;
817            sample_iq_id     = samp_hdr->sample_iq_id;
818            num_samp         = Xil_Ntohl(samp_hdr->num_samp);
[4438]819
[4668]820            //
[4707]821            // NOTE: Based on experimental results, jumbo Ethernet frames from Write IQ command can interfere
822            //     with the operation of the Read IQ and Write IQ processes.  This is due to the processing
823            //     of the frames interfering with the latency requirements of the transfers to / from DDR
824            //     (Basically, since there is only one DMA to service both the Write IQ commands and the
825            //     Read IQ / Write IQ processes, the DMA transfers for jumbo frames can cause latencies that
826            //     result in overflow / underflow conditions in the IQ processes.  This does not occur in
827            //     the Read IQ command because the Ethernet DMA is used to transfer data from DDR.  One option
828            //     to address this in the future would be to have a separate DMA for only the Read IQ / Write
829            //     IQ processes.)  However, with non-jumbo frames, there is no issue.  Therefore, we can
830            //     allow the Write IQ to proceed if we are using non-jumbo frames but need to request the
831            //     host wait if we are using jumbo frames.
[4673]832            //
[4707]833            check_status     = 0;
834            status           = 0;
835            raw_status       = wl_bb_get_raw_status();                         // Get raw status so there is only one register read from the baseband peripheral
[4811]836            temp_status      = (raw_status & WL_BUF_REG_STATUS_TX_RUNNING);    // Current TX status
[4673]837
[4811]838            // Check size of packet
[4707]839            if (num_samp < 400) {
840                // Number of samples is for a non-jumbo frame (approx 400 samples); process the Write IQ command
[4811]841                check_status = 1;
[4673]842
[4707]843            } else {
[4811]844                //
845                // NOTE:  For jumbo frames, if the Write IQ process is running for 2 buffers or less, then it is
846                //     ok to process the Write IQ command.  Otherwise, we need to tell the host to wait.
847                //
848                // NOTE:  There is a special case that we are ignoring:  If the node is in continuous transmit
849                //     mode and the waveform is less than WL_BUF_DEFAULT_TX_NUM_SAMPLES, then the DMA is not
850                //     in use and it would be ok to process the Write IQ command so long as the Write IQ command
851                //     is not to the buffer that is transmitting.  However, this additional checking would require
852                //     a read from the baseband buffers peripheral and many additional operations.  Given that
853                //     the Write IQ command is performance critical, we leave out this use case.  If this use case
854                //     is critical for your experiment, then you can update the code to perform the check.
855                //
856                if (raw_status & WL_BUF_REG_STATUS_RX_RUNNING) {
857                    // Read IQ process is running, tell host to wait
858                    status = 1;
[4707]859
[4811]860                } else {
[4707]861                    if (one_bits[temp_status] > 2) {
[4811]862                        // Write IQ process is running for more than two buffers, tell host to wait
863                        status = 1;
[4707]864
865                    } else {
[4811]866                        // Write IQ process is running on two or less buffers so it is ok to process the Write IQ command
867                        check_status = 1;
[4707]868
869                    }
[4811]870                }
[4707]871            }
872
873            // Check Write IQ command parameters
874            if (check_status) {
875                //
876                // NOTE:  We will only allow a write of an IQ buffer that is currently transmitting data if the
877                //     requested write is at least 16 kSamples (64 kB) behind the current write pointer (ie the
878                //     current read byte offset of the baseband transmit process is 16 kSamples greater than that
879                //     of the requested write).  This serves multiple purposes:
880                //         1) It will ensure that the data is does not have any issues with the "chunking" that occurs
881                //            in the transmit process (ie the Write IQ process moves 16 kSample "chunks" from DDR to
882                //            BRAM to be used by the baseband buffers module.
883                //         2) It will ensure that the read of IQ data over Ethernet does not exceed the writing of
884                //            IQ data into the buffer from the baseband core.  While this could not happen when
885                //            capturing 40 MHz of bandwidth, at higher decimation levels (ie capturing less bandwidth)
886                //            this could be an issue.
887                //
888                temp_threshold = ((start_samp + (WL_BUF_TX_TRANSFER_THRESHOLD_SAMPLES)) << 2);     // Threshold in bytes
889                temp_status    = (temp_status) & buff_sel;                                         // Are we trying to write to the currently transmitting buffer
890                temp_offset    = (wl_bb_get_rf_tx_iq_buf_rd_byte_offset() + 4);
891                status         = (temp_status) && (temp_offset < temp_threshold);
892            }
893
[4668]894            // Check if there is a transmission in progress to a buffer that is currently transmitting
895            //     If yes, then tell the host to wait and request again.
896            if (status) {
[1915]897
[4668]898                if (wl_bb_get_config() & WL_BUF_REG_CONFIG_CONT_TX) {
899                    // If we are in 'continuous tx' mode, then return 'error'
900                    resp_args_32[resp_index++] = Xil_Htonl(SAMPLE_HDR_FLAG_IQ_ERROR);                        // Status
901                    resp_args_32[resp_index++] = Xil_Htonl(sample_iq_id);                                    // ID
[4437]902
[4668]903                } else {
904                    // If we are not in 'continuous tx' mode, then return 'not ready'
905                    resp_args_32[resp_index++] = Xil_Htonl(SAMPLE_HDR_FLAG_IQ_NOT_READY);                    // Status
906                    resp_args_32[resp_index++] = Xil_Htonl(sample_iq_id);                                    // ID
907                    resp_args_32[resp_index++] = 0x00000000;                                                 // Checksum
908                    resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_tx_status());                           // Tx status
909                    resp_args_32[resp_index++] = Xil_Htonl((wl_bb_get_rf_tx_iq_buf_rd_byte_offset() + 4));   // Tx pointer
910                    resp_args_32[resp_index++] = Xil_Htonl(((wl_bb_get_tx_length() + 1) << 2));              // Tx length
911                    resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rx_status());                           // Rx status
912                    resp_args_32[resp_index++] = Xil_Htonl((wl_bb_get_rf_rx_iq_buf_wr_byte_offset() + 4));   // Rx pointer
913                    resp_args_32[resp_index++] = Xil_Htonl(((wl_bb_get_rx_length() + 1) << 2));              // Rx length
914                }
[2071]915
[4668]916                resp_hdr->length      += (resp_index * sizeof(resp_args_32));
917                resp_hdr->num_args     = resp_index;
[1915]918
[4668]919                resp_sent              = NODE_NOT_READY;
920            } else {
921                // Samples start after the sample header
922                samp_addr              = (void *)samp_hdr + sizeof(wl_bb_samp_hdr);
923                samp_addr_32           = (u32 *)samp_addr;
924                samp_len               = num_samp * sizeof(wl_samp);
925                checksum_input_32      = Xil_Ntohl(samp_addr_32[num_samp-1]);
926                checksum_input_16      = (checksum_input_32 >> 16) ^ (0xFFFF & checksum_input_32);
[1915]927
[4668]928                // Update the write checksum
929                if(flags & SAMPLE_HDR_FLAG_CHKSUM_RESET){
930                    curr_checksum = baseband_update_checksum( (start_samp & 0xFFFF), 1);
931                }else{
932                    curr_checksum = baseband_update_checksum( (start_samp & 0xFFFF), 0);
933                }
934                curr_checksum = baseband_update_checksum(checksum_input_16, 0);
[1915]935
[4668]936                // Populate response header
937                resp_args_32[resp_index++]  = Xil_Htonl(CMD_PARAM_SUCCESS);                        // Status
938                resp_args_32[resp_index++]  = Xil_Htonl(sample_iq_id);                             // ID
939                resp_args_32[resp_index++]  = Xil_Htonl(curr_checksum);                            // Checksum
940                resp_hdr->length           += (resp_index * sizeof(resp_args_32));
941                resp_hdr->num_args          = resp_index;
[4417]942
[4668]943                write_tx_buffers(buff_sel, (u32)(samp_addr), offset, samp_len);
[4417]944
[4692]945                // If this is the last transfer for a WRITE IQ, then we need to populate the temporary buffers
946                // that have been written
947                //
948                // NOTE:  If there is currently a write to a buffer, then do not populate that TX buffer when
949                //     the write IQ ends since the buffers will be populated by the final interrupt in the
950                //     Write IQ process.
951                //
[4668]952                if (flags & SAMPLE_HDR_FLAG_LAST_WRITE) {
[4692]953
954                    populate_tmp_tx_buffers(((~wl_bb_get_tx_status()) & buff_sel), 0x0, WARPLAB_IQ_TX_BUF_SIZE);
[4668]955                }
956            }
957        break;
[4417]958
[4184]959       
[4668]960        //---------------------------------------------------------------------
[4811]961        case CMDID_BASEBAND_WRITE_IQ_CHECKSUM:
[4668]962            // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "Get Write IQ checksum\n");
[4196]963
[4668]964            resp_args_32[resp_index++] = Xil_Htonl(baseband_get_checksum());
[4514]965
[4668]966            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
967            resp_hdr->num_args = resp_index;
968        break;
[2919]969
[4184]970       
[4668]971        //---------------------------------------------------------------------
[4811]972        case CMDID_BASEBAND_READ_IQ:
973        case CMDID_BASEBAND_READ_RSSI:
[4417]974            // BB_READ_IQ / BB_READ_RSSI Packet Format:
[4668]975            //
976            //   - cmd_args_32[0]      - Buffer selection (guaranteed to be singular) (uint16)
977            //   - cmd_args_32[1]      - Start sample
978            //   - cmd_args_32[2]      - Total samples in transfer
979            //   - cmd_args_32[3]      - Maximum number of samples per packet
980            //   - cmd_args_32[4]      - Number of packets in transfer
981            //
982            //   - resp_args           - Samples:  wl_bb_samp_hdr followed by appropriate samples
983            //
984            //   NOTE:  If the sample header flags == SAMPLE_HDR_FLAG_IQ_NOT_READY, then the "samples"
985            //       after the sample header need to be interpreted in the following manner:
986            //
987            //       - sample[0]       - Tx status
[4417]988            //       - sample[1]       - Current Tx read pointer
989            //       - sample[2]       - Tx length
990            //       - sample[3]       - Rx status
991            //       - sample[4]       - Current Rx write pointer
992            //       - sample[5]       - Rx length
[4668]993            //
994            //   NOTE:  When SAMPLE_HDR_FLAG_IQ_NOT_READY is returned, then the host
995            //       can compute the maximum wait time by the following calculation:
996            //           max(((tx_status) ? (tx_length - tx_read_pointer) : 0), ((rx_status) ? (rx_length - rx_write_pointer) : 0));
997            //
998            //   NOTE:  The response buffer (ie the response->buffer in the wl_cmd_resp) starts at the transport header.  Therefore,
999            //       we need to increase the size of the buffer by:  sizeof(wl_cmd_resp_hdr) + sizeof(wl_bb_samp_hdr);  The size of
1000            //       the sample buffer will be (num_samples * 4);
1001            //
[1915]1002
[4668]1003            // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "Read IQ\n");
[4438]1004
[4668]1005            // Process command arguments
1006            buff_sel              = Xil_Ntohl(cmd_args_32[0]);
1007            start_samp            = Xil_Ntohl(cmd_args_32[1]);
1008            total_samp            = Xil_Ntohl(cmd_args_32[2]);
1009            max_samp_len_per_pkt  = Xil_Ntohl(cmd_args_32[3]);
1010            num_pkts              = Xil_Ntohl(cmd_args_32[4]);
[1915]1011
[4811]1012            // Set the sample_iq_id
1013            //   NOTE:  This is the lower 8 bits of the RX counter for the given buffer.  Since buff_sel is
1014            //       guaranteed to be a single value (ie one of RFA, RFB, RFC, or RFD), this will always
1015            //       select the appropriate RX counter.
1016            //
1017            sample_iq_id          = 0;
1018
1019            if      (buff_sel & RF_SEL_A) { sample_iq_id = (wl_bb_get_rfa_rx_count() & 0x000000FF); }
1020            else if (buff_sel & RF_SEL_B) { sample_iq_id = (wl_bb_get_rfb_rx_count() & 0x000000FF); }
1021            else if (buff_sel & RF_SEL_C) { sample_iq_id = (wl_bb_get_rfc_rx_count() & 0x000000FF); }
1022            else if (buff_sel & RF_SEL_D) { sample_iq_id = (wl_bb_get_rfd_rx_count() & 0x000000FF); }
1023
[4668]1024            // Calculate the maximum samples per packet
1025            max_samp_per_pkt      = max_samp_len_per_pkt / sizeof(wl_samp);      // This is an constant integer division that is optimized away by the compiler
[1915]1026
[4668]1027            // Initialize loop variables
1028            num_samp              = 0;
1029            curr_samp             = start_samp;
1030            dest_addr             = (u32)((void*)resp_args_32 + sizeof(wl_bb_samp_hdr));
[4284]1031
[4668]1032            //
1033            // NOTE:  We will only allow a read of an IQ buffer that is currently receiving data if the
[4692]1034            //     requested read has been completely received (ie the current write byte offset of the
1035            //     baseband receive process is greater than the last sample of the requested read).  This
1036            //     serves multiple purposes:
1037            //         1) It will ensure that the data is not known garbage data.  (A user could still read a
1038            //            buffer that has never been populated with real data or mistakenly read a buffer.
1039            //            However, there is no way to protect against that.)
1040            //         2) It will ensure that the read of IQ data over Ethernet does not exceed the writing of
1041            //            IQ data into the buffer from the baseband core.  While this could not happen when
1042            //            capturing 40 MHz of bandwidth, at higher decimation levels (ie capturing less bandwidth)
1043            //            this could be an issue.
[4668]1044            //
[4692]1045            // NOTE:  The threshold is based on the starting sample and then the Read IQ "chunk" size (ie the
1046            //     Read IQ process will transfer 16 kSample "chunks" from BRAM to DDR, which is where is it
1047            //     read for the Read IQ command).
1048            //
1049            temp_threshold = ((start_samp + (WL_BUF_RX_TRANSFER_THRESHOLD_SAMPLES)) << 2);
1050            temp_status    = (wl_bb_get_rx_status()) & buff_sel;
1051            temp_offset    = (wl_bb_get_rf_rx_iq_buf_wr_byte_offset() + 4);
1052            status         = (temp_status) && (temp_offset < temp_threshold);
[4668]1053
1054
1055            // Check if we need to defer the read request due to an ongoing reception
1056            //     If yes, then tell the host to wait and request again
1057            //
1058            if (status) {
[4196]1059
[4668]1060                // Fill in parts of sample header that do not change between Write IQ packets
1061                samp_hdr                   = (wl_bb_samp_hdr *)resp_args_32;
1062                samp_hdr->buff_sel         = (u16)buff_sel;
1063                samp_hdr->buff_sel         = Xil_Htons(samp_hdr->buff_sel);
[4196]1064
[4668]1065                samp_hdr->flags            = SAMPLE_HDR_FLAG_IQ_NOT_READY;
[4417]1066
[4668]1067                resp_args_32               = (u32 *)dest_addr;
[4417]1068
[4668]1069                resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_tx_status());                           // Tx status
1070                resp_args_32[resp_index++] = Xil_Htonl((wl_bb_get_rf_tx_iq_buf_rd_byte_offset() + 4));   // Tx pointer
1071                resp_args_32[resp_index++] = Xil_Htonl(((wl_bb_get_tx_length() + 1) << 2));              // Tx length
1072                resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rx_status());                           // Rx status
1073                resp_args_32[resp_index++] = Xil_Htonl((wl_bb_get_rf_rx_iq_buf_wr_byte_offset() + 4));   // Rx pointer
1074                resp_args_32[resp_index++] = Xil_Htonl(((wl_bb_get_rx_length() + 1) << 2));              // Rx length
[4417]1075
[4811]1076                samp_hdr->sample_iq_id     = sample_iq_id;
1077                samp_hdr->start_samp       = 0;
1078                samp_hdr->num_samp         = 0;
[4417]1079
[4811]1080                resp_hdr->length           = sizeof(wl_bb_samp_hdr) + (resp_index * sizeof(resp_args_32));
1081                resp_hdr->num_args         = 1;
[4417]1082
[4811]1083                resp_sent                  = NODE_NOT_READY;
[4284]1084
[4668]1085            } else {
1086                //
1087                // NOTE:  Currently, the Ethernet send function only blocks when it runs out of transmit
1088                //   buffer descriptors.  If we perform all header modifications in place, this will cause
1089                //   problems with Read IQ when WARP_IP_UDP_TXBD_CNT (ie the number of TX BDs) is greater
1090                //   than 5 because the Ethernet DMA will not have transfered the header before the next
1091                //   round of processing that modifies the header.  In order to fix this, we are going to
1092                //   create multiple copies of the packet header in the buffer we allocated above.  The
1093                //   contents of the packet header are:
1094                //
1095                //   Read IQ Packet Header (76 bytes total):
1096                //       Eth header       = 14 bytes
1097                //       IP header        = 20 bytes
1098                //       UDP header       =  8 bytes
1099                //       Delimiter        =  2 bytes
1100                //       Transport header = 12 bytes
1101                //       Command header   =  8 bytes
1102                //       Sample header    = 12 bytes;
1103                //
1104                //   In order to minimize the impact to performance, we are going to pull the header from
1105                //   AXI BRAM into LMB memory for processing and then copy the completed header back to
1106                //   AXI BRAM so the Ethernet DMA can fetch it.  This way we can maintain the header for
1107                //   the current packet and then copy it to multiple locations to avoid overwriting the
1108                //   header before the DMA can transfer its contents.
1109                //
[2071]1110
[4668]1111                // Initialize Read IQ response buffer array
1112                //     NOTE:  header_buffer fields will be set here; sample_buffer fields will be set in read_rx_buffers
1113                //
1114                read_iq_resp[0]   = (void *) &header_buffer;
1115                read_iq_resp[1]   = (void *) &sample_buffer;
[1915]1116
[4668]1117                // Set up temporary pointers to the header data
1118                eth_ip_udp_header = (warp_ip_udp_header  *)(&tmp_header[0]);
1119                wl_header_tx      = (wl_transport_header *)(&tmp_header[sizeof(warp_ip_udp_header)]);
1120                resp_hdr          = (wl_cmd_resp_hdr     *)(&tmp_header[sizeof(warp_ip_udp_header) + sizeof(wl_transport_header)]);
1121                samp_hdr          = (wl_bb_samp_hdr      *)(&tmp_header[sizeof(warp_ip_udp_header) + sizeof(wl_transport_header) + sizeof(wl_cmd_resp_hdr)]);
[1915]1122
[4668]1123                // Set up temporary variables with the length values of the header
1124                ip_length         = WARP_IP_UDP_DELIM_LEN + UDP_HEADER_LEN + IP_HEADER_LEN_BYTES;
1125                udp_length        = WARP_IP_UDP_DELIM_LEN + UDP_HEADER_LEN;
1126                header_length     = sizeof(wl_transport_header) + sizeof(wl_cmd_resp_hdr) + sizeof(wl_bb_samp_hdr);
1127                total_hdr_length  = sizeof(warp_ip_udp_header) + header_length;
[1915]1128
[4668]1129                // Get values out of the socket address structure
1130                dest_ip_addr      = ((struct sockaddr_in*)from)->sin_addr.s_addr;    // NOTE:  Value big endian
1131                dest_port         = ((struct sockaddr_in*)from)->sin_port;
[1915]1132
[4668]1133                // Get hardware address of the destination
1134                eth_dev_num       = socket_get_eth_dev_num(socket_index);
1135                arp_get_hw_addr(eth_dev_num, dest_hw_addr, (u8 *)(&dest_ip_addr));
[1915]1136
[4668]1137                // Pull in header information into local LMB memory:
1138                //   - Copy the header information from the socket
1139                //   - Copy the information from the response
1140                //
1141                memcpy((void *)eth_ip_udp_header, (void *)socket_get_warp_ip_udp_header(socket_index), sizeof(warp_ip_udp_header));
1142                memcpy((void *)wl_header_tx, (void *)(((warp_ip_udp_buffer *)(response->buffer))->data), header_length);
[1915]1143
[4668]1144                // Initialize header buffer size/length (see above for description)
1145                header_buffer.length = total_hdr_length;
1146                header_buffer.size   = total_hdr_length;
[4234]1147
[4668]1148                //
1149                // NOTE:  In order to make large Read IQ transfers more efficient, we can pre-process most of
1150                //   of the response packet such that the transport has to do only the minimal amount of
1151                //   processing per packet.  This should not cause any additional overhead for a single packet
1152                //   but will have have reduced overhead for all other packets.
1153                //
[2013]1154
[4811]1155                // Fill in parts of sample header that do not change between Read IQ packets
[4668]1156                samp_hdr->buff_sel     = (u16)buff_sel;
1157                samp_hdr->buff_sel     = Xil_Htons(samp_hdr->buff_sel);
[4811]1158                samp_hdr->sample_iq_id = sample_iq_id;
[4668]1159                samp_hdr->flags        = 0;
[2071]1160
[4668]1161                // Populate response header fields with static data
1162                resp_hdr->cmd          = Xil_Ntohl(resp_hdr->cmd);
1163                resp_hdr->num_args     = Xil_Ntohs(1);
[4514]1164
[4668]1165                // Populate transport header fields with static data
1166                wl_header_tx->dest_id  = Xil_Htons(wl_header_tx->dest_id);
1167                wl_header_tx->src_id   = Xil_Htons(wl_header_tx->src_id);
1168                wl_header_tx->seq_num  = Xil_Htons(wl_header_tx->seq_num);
1169                wl_header_tx->flags    = Xil_Htons(wl_header_tx->flags);
[4514]1170
[4668]1171                // Update the Ethernet header
1172                //     NOTE:  dest_hw_addr must be big-endian; ethertype must be little-endian
1173                //     NOTE:  Adapted from the function:
1174                //                eth_update_header(&(eth_ip_udp_header->eth_hdr), dest_hw_addr, ETHERTYPE_IP_V4);
1175                //
1176                memcpy((void *)eth_ip_udp_header->eth_hdr.dest_mac_addr, (void *)dest_hw_addr, ETH_MAC_ADDR_LEN);
1177                eth_ip_udp_header->eth_hdr.ethertype  = Xil_Htons(ETHERTYPE_IP_V4);
[2071]1178
[4668]1179                // Update the UDP header
1180                //     NOTE:  Requires dest_port to be big-endian; udp_length to be little-endian
1181                //     NOTE:  Adapted from the function:
1182                //                udp_update_header(&(eth_ip_udp_header->udp_hdr), dest_port, (udp_length + data_length));
1183                //
1184                eth_ip_udp_header->udp_hdr.dest_port  = dest_port;
1185                eth_ip_udp_header->udp_hdr.checksum   = UDP_NO_CHECKSUM;
[4292]1186
[4668]1187                // Set AXI BRAM address for the header
1188                header_base_addr       = ETH_IQ_buffer;             // Use the buffer allocated above
1189                header_offset          = 0;
1190                header_buffer_size     = WL_BASEBAND_ETH_BUFFER_SIZE * WL_BASEBAND_ETH_NUM_BUFFER;
[4184]1191
[4668]1192                // Process the Read IQ / Read RSSI packets
1193                for(i = 0; i < num_pkts; i++){
[4184]1194
[4668]1195                    // Update loop variables
1196                    header_addr     = (u8 *)(((u32)header_base_addr) + header_offset);
1197                    next_start_samp = curr_samp + max_samp_per_pkt;
[1915]1198
[4668]1199                    if(next_start_samp > (start_samp + total_samp)){
1200                        num_samp = (start_samp + total_samp) - curr_samp;
1201                    } else {
1202                        num_samp = max_samp_per_pkt;
1203                    }
[4184]1204
[4668]1205                    samp_len             = num_samp * sizeof(wl_samp);
1206                    start_byte           = curr_samp * sizeof(wl_samp);
1207                    data_length          = samp_len + header_length;
[1915]1208
[4668]1209                    // Populate sample header fields with per packet data
1210                    samp_hdr->start_samp = Xil_Htonl(curr_samp);
1211                    samp_hdr->num_samp   = Xil_Htonl(num_samp);
[4184]1212
[4668]1213                    // Populate response header fields with per packet data
1214                    resp_hdr->length     = Xil_Ntohs(samp_len + sizeof(wl_bb_samp_hdr));
[4184]1215
[4668]1216                    // Populate transport header fields with per packet data
1217                    wl_header_tx->length = Xil_Htons(data_length + WARP_IP_UDP_DELIM_LEN);
[4184]1218
[4668]1219                    // Update the UDP header
1220                    //     NOTE:  Requires dest_port to be big-endian; udp_length to be little-endian
1221                    //     NOTE:  Adapted from the function:
1222                    //                udp_update_header(&(eth_ip_udp_header->udp_hdr), dest_port, (udp_length + data_length));
1223                    //
1224                    eth_ip_udp_header->udp_hdr.length = Xil_Htons(udp_length + data_length);
[4184]1225
[4668]1226                    // Update the IPv4 header
1227                    //     NOTE:  Requires dest_ip_addr to be big-endian; ip_length to be little-endian
1228                    //     NOTE:  We did not break this function apart like the other header updates b/c the IP ID counter is
1229                    //            maintained in the library and we did not want to violate that.
1230                    //
1231                    ipv4_update_header(&(eth_ip_udp_header->ip_hdr), dest_ip_addr, (ip_length + data_length), IP_PROTOCOL_UDP);
[4184]1232
[4668]1233                    // Copy the completed header to DMA accessible BRAM
1234                    memcpy((void *)header_addr, (void *)tmp_header, total_hdr_length);
[1915]1235
[4668]1236                    // Set the header buffer data / offset
1237                    header_buffer.data   = (u8 *)header_addr;
1238                    header_buffer.offset = (u8 *)header_addr;
[4328]1239
[4668]1240                    // Set up the IQ data for the Ethernet packet buffer
1241                    read_rx_buffers(cmd_id, buff_sel, start_byte, samp_len, dest_addr, &sample_buffer);
[1915]1242
[4668]1243                    // Update the green LEDs for every packet sent
1244                    increment_green_leds_one_hot();
[4184]1245
[4668]1246                    // Send the Ethernet packet
1247                    //   NOTE:  In an effort to reduce overhead (ie improve performance) for Read IQ, we are using the "raw"
1248                    //       socket_sendto method which transmits the provided buffers "as is" (ie there are no header updates
1249                    //       or other modifications to the buffer data).  Also, we have consolidated all the headers into a
1250                    //       single buffer so that a Read IQ Ethernet packet only requires two Transmit Buffer Descriptors
1251                    //       (TX BDs).
1252                    //
1253                    status = socket_sendto_raw(socket_index, (warp_ip_udp_buffer **)read_iq_resp, 0x2);
[4184]1254
[4668]1255                    // Check that the packet was sent correctly
1256                    if (status == WARP_IP_UDP_FAILURE) {
1257                        wl_printf(WL_PRINT_WARNING, print_type_baseband, "Issue sending read IQ packet to host.\n");
1258                    }
[1994]1259
[4668]1260                    // Update loop variables
1261                    curr_samp          = next_start_samp;
1262                    header_offset      = (header_offset + WL_BASEBAND_ETH_BUFFER_SIZE) % header_buffer_size;
1263                }
[1994]1264
[4668]1265                //
1266                // NOTE:  With the current processing, the state of the transmit buffer has not been modified
1267                //   from what was passed in to this function.  All modifications occurred on temporary headers
1268                //   that were buffered in either LMB or BRAM memory.
1269                //
[1915]1270
[4668]1271                resp_sent = RESP_SENT;
1272            }
1273        break;
[4184]1274
1275
[4668]1276        //---------------------------------------------------------------------
[4811]1277        case CMDID_BASEBAND_TXRX_COUNT_RESET:
1278            // Reset the TX / RX counters
1279            //
1280            // Message format:
1281            //     cmd_args_32[0]      Command:
1282            //                             - Write       (NODE_WRITE_VAL)
1283            //                             - Read        (NODE_READ_VAL)
1284            //     cmd_args_32[1]      Buffer Select
1285            //     cmd_args_32[2]      TX = 0 / RX = 1
1286            //
1287            // Response format:
1288            //     resp_args_32[0]     Status
1289            //
1290            status      = CMD_PARAM_SUCCESS;
1291            msg_cmd     = Xil_Ntohl(cmd_args_32[0]);
1292            buff_sel    = Xil_Ntohl(cmd_args_32[1]);
1293            txrx_sel    = Xil_Ntohl(cmd_args_32[2]);
1294
1295            switch (msg_cmd) {
1296                case CMD_PARAM_WRITE_VAL:
1297                    if (txrx_sel) {
1298                        wl_bb_clear_txrx_counter_reset();
1299                        wl_bb_set_txrx_counter_reset(buff_sel << 8);
1300                        wl_bb_clear_txrx_counter_reset();
1301                    } else {
1302                        wl_bb_clear_txrx_counter_reset();
1303                        wl_bb_set_txrx_counter_reset(buff_sel);
1304                        wl_bb_clear_txrx_counter_reset();
1305                    }
1306                break;
1307
1308                case CMD_PARAM_READ_VAL:
1309                    status = CMD_PARAM_ERROR;
1310                break;
1311
1312                default:
1313                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1314                    status = CMD_PARAM_ERROR;
1315                break;
1316            }
1317
1318            // Send response
1319            resp_args_32[resp_index++] = Xil_Htonl(status);
1320
1321            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1322            resp_hdr->num_args = resp_index;
1323        break;
1324
1325
1326        //---------------------------------------------------------------------
1327        case CMDID_BASEBAND_TXRX_COUNT_GET:
1328            // Get the TX / RX counter value
1329            //
1330            // Message format:
1331            //     cmd_args_32[0]      Command:
1332            //                             - Write       (NODE_WRITE_VAL)
1333            //                             - Read        (NODE_READ_VAL)
1334            //     cmd_args_32[1]      Buffer Select
1335            //     cmd_args_32[2]      TX / RX Select
1336            //                             - TX          (CMD_PARAM_BASEBAND_TXRX_COUNT_GET_TX)
1337            //                             - RX          (CMD_PARAM_BASEBAND_TXRX_COUNT_GET_RX)
1338            //
1339            // Response format:
1340            //     resp_args_32[0]     Status
1341            //     resp_args_32[1]     Selected ounter value
1342            //
1343            status           = CMD_PARAM_SUCCESS;
1344            msg_cmd          = Xil_Ntohl(cmd_args_32[0]);
1345            buff_sel         = Xil_Ntohl(cmd_args_32[1]);
1346            txrx_sel         = Xil_Ntohl(cmd_args_32[2]);
1347            buff_counter     = CMD_PARAM_BASEBAND_TXRX_COUNT_GET_COUNT_RSVD;
1348
1349            switch (msg_cmd) {
1350                case CMD_PARAM_WRITE_VAL:
1351                    status = CMD_PARAM_ERROR;
1352                break;
1353
1354                case CMD_PARAM_READ_VAL:
1355                    buff_counter = get_buffer_counter(txrx_sel, buff_sel);
1356                break;
1357
1358                default:
1359                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1360                    status = CMD_PARAM_ERROR;
1361                break;
1362            }
1363
1364            // Send response
1365            resp_args_32[resp_index++] = Xil_Htonl(status);
1366            resp_args_32[resp_index++] = Xil_Htonl(buff_counter);
1367
1368            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1369            resp_hdr->num_args = resp_index;
1370        break;
1371
1372
1373        //---------------------------------------------------------------------
1374        case CMDID_BASEBAND_AGC_STATE:
[4783]1375            // Get the AGC State
1376            //
1377            // Response format:
1378            //     resp_args_32[N]     Gains ([1:0] RF gain; [6:2] BB gain)
1379            //     resp_args_32[N + 1] RSSI observed when gains were locked
1380            //
[4668]1381            // NOTE:  Host side processing of the return value needs to be careful that it understands
1382            //     which RF interfaces were requested since the below implementation will collapse the
[4783]1383            //     return value to transmit the minimal amount of data.
[4668]1384            //
1385            rf_sel =  Xil_Ntohl(cmd_args_32[0]);
[4184]1386
[4668]1387            if(rf_sel & AGC_A){
[4783]1388                resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_A) + (wl_get_agc_BBG(ANT_A) << 2));
[4668]1389                resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfa_agc_done_rssi());
1390            }
1391            if(rf_sel & AGC_B){
[4783]1392                resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_B) + (wl_get_agc_BBG(ANT_B) << 2));
[4668]1393                resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfb_agc_done_rssi());
1394            }
1395            if(rf_sel & AGC_C){
[4783]1396                resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_C) + (wl_get_agc_BBG(ANT_C) << 2));
[4668]1397                resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfc_agc_done_rssi());
1398            }
1399            if(rf_sel & AGC_D){
[4783]1400                resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_D) + (wl_get_agc_BBG(ANT_D) << 2));
[4668]1401                resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfd_agc_done_rssi());
1402            }
[4514]1403
[4668]1404            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1405            resp_hdr->num_args = resp_index;
1406        break;
[1915]1407
[4184]1408
[4668]1409        //---------------------------------------------------------------------
[4811]1410        case CMDID_BASEBAND_AGC_DONE_ADDR:
[4783]1411            // Get the address the AGC finished
1412            //
1413            // Response format:
1414            //     resp_args_32[0]     Sample address AGC finished
1415            //
1416            resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_agc_done_addr());
[4184]1417
[4783]1418            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1419            resp_hdr->num_args = resp_index;
[4668]1420        break;
[4514]1421
[2852]1422
[4668]1423        //---------------------------------------------------------------------
[4811]1424        case CMDID_BASEBAND_AGC_RESET:
[4783]1425            // Reset the AGC
1426            //
1427            // NOTE:  No arguments are expected and nothing is returned
1428            //
1429            warplab_agc_reset();
1430        break;
1431
1432
1433        //---------------------------------------------------------------------
[4811]1434        case CMDID_BASEBAND_AGC_RESET_MODE:
[4805]1435            // Get / Set the AGC reset mode
[4783]1436            //
1437            // Message format:
1438            //     cmd_args_32[0]      Command:
1439            //                             - Write       (NODE_WRITE_VAL)
1440            //                             - Read        (NODE_READ_VAL)
[4805]1441            //     cmd_args_32[1]      Enable / Disable reset per rx  (Write only)
[4783]1442            //
1443            // Response format:
1444            //     resp_args_32[0]     Status
[4805]1445            //     resp_args_32[1]     Value of the reset mode
[4783]1446            //
1447            status  = CMD_PARAM_SUCCESS;
1448            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
1449
1450            switch (msg_cmd) {
1451                case CMD_PARAM_WRITE_VAL:
[4811]1452                    if (Xil_Ntohl(cmd_args_32[1]) == WL_AGC_RESET_MODE_RESET_PER_RX_MASK) {
1453                        wl_agc_enable_reset_per_rx();
1454                    } else {
1455                        wl_agc_disable_reset_per_rx();
1456                    }
[4783]1457                break;
1458
1459                case CMD_PARAM_READ_VAL:
1460                break;
1461
1462                default:
1463                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1464                    status = CMD_PARAM_ERROR;
1465                break;
1466            }
1467
1468            // Send response
1469            resp_args_32[resp_index++] = Xil_Htonl(status);
[4805]1470            resp_args_32[resp_index++] = Xil_Htonl(wl_agc_get_reset_mode());
[4783]1471
1472            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1473            resp_hdr->num_args = resp_index;
1474        break;
1475
1476
1477        //---------------------------------------------------------------------
[4811]1478        case CMDID_BASEBAND_AGC_TARGET:
[4783]1479            // Set the AGC target
1480            //
1481            // Message format:
[4811]1482            //     cmd_args_32[0]      AGC target
[4783]1483            //
[4668]1484            agc_target = Xil_Ntohl(cmd_args_32[0]);
1485
1486            wl_agc_set_target(agc_target);       // Note:  AGC target is a Fix_6_0 value
1487        break;
1488
1489
1490        //---------------------------------------------------------------------
[4811]1491        case CMDID_BASEBAND_AGC_DCO_EN_DIS:
1492            // Enable / Disable AGC DC Offset (DCO) correction
1493            //
1494            // Message format:
1495            //     cmd_args_32[0]      Enable = 1 / Disable = 0
1496            //
[4783]1497            agc_dco_enable = Xil_Ntohl(cmd_args_32[0]);
[4668]1498
[4783]1499            warplab_agc_enable_DCO(agc_dco_enable);
[4668]1500        break;
1501
1502
1503        //---------------------------------------------------------------------
[4811]1504        case CMDID_BASEBAND_AGC_CONFIG:
[4783]1505            // Get / Set AGC configuration
1506            //
1507            // Message format:
1508            //     cmd_args_32[0]      Command:
1509            //                             - Write       (NODE_WRITE_VAL)
1510            //                             - Read        (NODE_READ_VAL)
1511            //     cmd_args_32[1]      RSSI Averaging length
1512            //     cmd_args_32[2]      Voltage DB Adjust
1513            //     cmd_args_32[3]      Initial BB Gain
1514            //
1515            // Response format:
1516            //     resp_args_32[0]     Status
1517            //
1518            status  = CMD_PARAM_SUCCESS;
1519            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4668]1520
[4783]1521            switch (msg_cmd) {
1522                case CMD_PARAM_WRITE_VAL:
1523                    rssi_avg_length = Xil_Ntohl(cmd_args_32[1]) & 0x00000003;
1524                    v_db_adjust     = Xil_Ntohl(cmd_args_32[2]) & 0x0000003F;
1525                    init_bb_gain    = Xil_Ntohl(cmd_args_32[3]) & 0x0000001F;
1526
1527                    wl_agc_set_config(rssi_avg_length, v_db_adjust, init_bb_gain);
1528                break;
1529
1530                case CMD_PARAM_READ_VAL:
1531                    // Read not supported
1532                    status = CMD_PARAM_ERROR;
1533                break;
1534
1535                default:
1536                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1537                    status = CMD_PARAM_ERROR;
1538                break;
1539            }
1540
1541            // Send response
1542            resp_args_32[resp_index++] = Xil_Htonl(status);
1543
1544            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1545            resp_hdr->num_args = resp_index;
1546        break;
1547
1548
1549        //---------------------------------------------------------------------
[4811]1550        case CMDID_BASEBAND_AGC_IIR_HPF:
[4783]1551            // Get / Set Infinite Impulse Response (IIR) High Pass Filter (HPF) coefficients
[4668]1552            //
[4783]1553            // Message format:
1554            //     cmd_args_32[0]      Command:
1555            //                             - Write       (NODE_WRITE_VAL)
1556            //                             - Read        (NODE_READ_VAL)
1557            //     cmd_args_32[1]      A1 coefficient (value is already converted Fix_18_17)
1558            //     cmd_args_32[2]      B0 coefficient (value is already converted UFix_18_17)
1559            //
1560            // Response format:
1561            //     resp_args_32[0]     Status
1562            //
1563            // NOTE:  The values are assumed to already be in the correct format
1564            //
1565            status  = CMD_PARAM_SUCCESS;
1566            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4668]1567
[4783]1568            switch (msg_cmd) {
1569                case CMD_PARAM_WRITE_VAL:
1570                    a1_coeff = Xil_Ntohl(cmd_args_32[1]) & 0x0003FFFF;
1571                    b0_coeff = Xil_Ntohl(cmd_args_32[2]) & 0x0003FFFF;
[4668]1572
[4783]1573                    wl_agc_set_iir_coef_a1(a1_coeff);               // This value is  Fix_18_17
1574                    wl_agc_set_iir_coef_b0(b0_coeff);               // This value is UFix_18_17
1575                break;
1576
1577                case CMD_PARAM_READ_VAL:
1578                    // Read not supported
1579                    status = CMD_PARAM_ERROR;
1580                break;
1581
1582                default:
1583                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1584                    status = CMD_PARAM_ERROR;
1585                break;
1586            }
1587
1588            // Send response
1589            resp_args_32[resp_index++] = Xil_Htonl(status);
1590
1591            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1592            resp_hdr->num_args = resp_index;
[4668]1593        break;
1594
1595
1596        //---------------------------------------------------------------------
[4811]1597        case CMDID_BASEBAND_AGC_RF_GAIN_THRESHOLD:
[4783]1598            // Get / Set RF gain (LNA) thresholds
1599            //
1600            // Message format:
1601            //     cmd_args_32[0]      Command:
1602            //                             - Write       (NODE_WRITE_VAL)
1603            //                             - Read        (NODE_READ_VAL)
1604            //     cmd_args_32[1]      3 -> 2 RF gain power threshold
1605            //     cmd_args_32[2]      2 -> 1 RF gain power threshold
1606            //
1607            // Response format:
1608            //     resp_args_32[0]     Status
1609            //
1610            // NOTE:  The thresholds are assumed to be in UFix_8_0 two's compliment format
1611            //
1612            status  = CMD_PARAM_SUCCESS;
1613            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4668]1614
[4783]1615            switch (msg_cmd) {
1616                case CMD_PARAM_WRITE_VAL:
1617                    thresh_3_2 = Xil_Ntohl(cmd_args_32[1]) & 0x000000FF;
1618                    thresh_2_1 = Xil_Ntohl(cmd_args_32[2]) & 0x000000FF;
1619
1620                    wl_agc_set_config_thresh(thresh_3_2, thresh_2_1);
1621                break;
1622
1623                case CMD_PARAM_READ_VAL:
1624                    // Read not supported
1625                    status = CMD_PARAM_ERROR;
1626                break;
1627
1628                default:
1629                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1630                    status = CMD_PARAM_ERROR;
1631                break;
1632            }
1633
1634            // Send response
1635            resp_args_32[resp_index++] = Xil_Htonl(status);
1636
1637            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1638            resp_hdr->num_args = resp_index;
[4668]1639        break;
1640
1641
1642        //---------------------------------------------------------------------
[4811]1643        case CMDID_BASEBAND_AGC_TIMING:
[4783]1644            // Get / Set
1645            //
1646            // Message format:
1647            //     cmd_args_32[0]      Command:
1648            //                             - Write       (NODE_WRITE_VAL)
1649            //                             - Read        (NODE_READ_VAL)
1650            //     cmd_args_32[1]      Capture RSSI 1
1651            //     cmd_args_32[2]      Capture RSSI 2
1652            //     cmd_args_32[3]      Capture Voltage DB
1653            //     cmd_args_32[4]      AGC Done
1654            //
1655            // Response format:
1656            //     resp_args_32[0]     Status
1657            //
1658            status  = CMD_PARAM_SUCCESS;
1659            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4668]1660
[4783]1661            switch (msg_cmd) {
1662                case CMD_PARAM_WRITE_VAL:
1663                    capture_rssi_1 = Xil_Ntohl(cmd_args_32[1]) & 0x000000FF;
1664                    capture_rssi_2 = Xil_Ntohl(cmd_args_32[2]) & 0x000000FF;
1665                    capture_v_db   = Xil_Ntohl(cmd_args_32[3]) & 0x000000FF;
1666                    agc_done       = Xil_Ntohl(cmd_args_32[4]) & 0x000000FF;
[4805]1667
[4783]1668                    wl_agc_set_AGC_timing(capture_rssi_1, capture_rssi_2, capture_v_db, agc_done);
1669                break;
1670
1671                case CMD_PARAM_READ_VAL:
1672                    // Read not supported
1673                    status = CMD_PARAM_ERROR;
1674                break;
1675
1676                default:
1677                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1678                    status = CMD_PARAM_ERROR;
1679                break;
1680            }
1681
1682            // Send response
1683            resp_args_32[resp_index++] = Xil_Htonl(status);
1684
[4668]1685            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1686            resp_hdr->num_args = resp_index;
1687        break;
1688
1689
1690        //---------------------------------------------------------------------
[4811]1691        case CMDID_BASEBAND_AGC_DCO_TIMING:
[4783]1692            // Get / Set
1693            //
1694            // Message format:
1695            //     cmd_args_32[0]      Command:
1696            //                             - Write       (NODE_WRITE_VAL)
1697            //                             - Read        (NODE_READ_VAL)
1698            //     cmd_args_32[1]      Start DCO
1699            //     cmd_args_32[2]      Start IIR HPF
1700            //
1701            // Response format:
1702            //     resp_args_32[0]     Status
1703            //
1704            status  = CMD_PARAM_SUCCESS;
1705            msg_cmd = Xil_Ntohl(cmd_args_32[0]);
[4668]1706
[4783]1707            switch (msg_cmd) {
1708                case CMD_PARAM_WRITE_VAL:
1709                    start_dco        = Xil_Ntohl(cmd_args_32[1]) & 0x000000FF;
1710                    start_iir_filter = Xil_Ntohl(cmd_args_32[2]) & 0x000000FF;
[4668]1711
[4783]1712                    wl_agc_set_DCO_timing(start_dco, start_iir_filter);
1713                break;
1714
1715                case CMD_PARAM_READ_VAL:
1716                    // Read not supported
1717                    status = CMD_PARAM_ERROR;
1718                break;
1719
1720                default:
1721                    wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command for 0x%6x: %d\n", cmd_id, msg_cmd);
1722                    status = CMD_PARAM_ERROR;
1723                break;
[4668]1724            }
[4783]1725
1726            // Send response
1727            resp_args_32[resp_index++] = Xil_Htonl(status);
1728
1729            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
1730            resp_hdr->num_args = resp_index;
[4668]1731        break;
1732
1733
1734        //---------------------------------------------------------------------
1735        // case BB_DEBUG_TX_OUTPUT_CONFIGURE:
[4331]1736        //     wl_printf(WL_PRINT_DEBUG, print_type_baseband, "Tx debug output configure\n");
1737        //
1738        //     // Clear current Tx debug output configuration
1739        //     temp = (WL_BUF_REG_CONFIG_DEBUG_TX_OUTPUT_SEL | WL_BUF_REG_CONFIG_DEBUG_TX_BUF_SEL);
1740        //     wl_bb_clear_config(temp);
1741        //
1742        //     // Set new Tx debug output configuration
1743        //     temp = (Xil_Ntohl(cmd_args_32[0]) & temp);
1744        //     wl_bb_set_config(temp);
1745        // break;
[4184]1746
[4331]1747
[4668]1748        //---------------------------------------------------------------------
1749        default:
1750            wl_printf(WL_PRINT_ERROR, print_type_baseband, "Unknown command ID: %d\n", cmd_id);
1751        break;
1752    }
1753    return resp_sent;
[1915]1754}
1755
1756
[4184]1757
[4234]1758/*****************************************************************************/
1759/**
[4668]1760 * Read RX buffers
1761 *
1762 *   Sets up the warp_ip_udp_buffer with data from the buffer indicated by the buffer_sel
1763 * parameter, using the priority RFA -> RFB -> RFC -> RFD.  If there is an addressing
1764 * issue, then the function copies zeros into the given destination address and uses that
1765 * for the warp_ip_udp_buffer.
1766 *
1767 * @param   cmd_id           - Command ID (Differentiates between READ_IQ and READ_RSSI commands
1768 * @param   buffer_sel       - Buffer select (Indicates which buffer should be read)
1769 * @param   offset           - Starting byte offset into RX buffer (in bytes; must be 16 byte
1770 *                             aligned due to CDMA usage)
1771 * @param   length           - Length of the transfer (in bytes)
1772 * @param   dest_addr        - Destination address of the transfer (in bytes; must be 16 byte
1773 *                             aligned due to CDMA usage)
1774 *
1775 * @return  None
1776 *
1777 *****************************************************************************/
1778void read_rx_buffers(u32 cmd_id, u32 buffer_sel, u32 offset, u32 length, u32 dest_addr, warp_ip_udp_buffer * buffer) {
[4184]1779
[4668]1780    u32 src_addr       = 0;
[4234]1781    u32 buffer_size    = 0;
[4668]1782    u32 end_byte       = offset + length - 1;
[4234]1783
[4668]1784    // Process Read IQ
[4811]1785    if(cmd_id == CMDID_BASEBAND_READ_IQ) {
[4668]1786        if(buffer_sel & RF_SEL_A) {
1787            buffer_size = wl_iq_rx_buff_a_size;
1788            src_addr    = (u32)(wl_iq_rx_buff_a + offset);
[4234]1789
[4668]1790        } else if(buffer_sel & RF_SEL_B) {
1791            buffer_size = wl_iq_rx_buff_b_size;
1792            src_addr    = (u32)(wl_iq_rx_buff_b + offset);
[4234]1793
[4668]1794        } else if(buffer_sel & RF_SEL_C) {
1795            if (WARPLAB_CONFIG_4RF) {
1796                buffer_size = wl_iq_rx_buff_c_size;
1797                src_addr    = (u32)(wl_iq_rx_buff_c + offset);
1798            } else {
1799                wl_printf(WL_PRINT_ERROR, print_type_baseband, "Trying to read to RF C buffer on a 2RF design.\n");
1800            }
[4234]1801
[4668]1802        } else if(buffer_sel & RF_SEL_D) {
1803            if (WARPLAB_CONFIG_4RF) {
1804                buffer_size = wl_iq_rx_buff_d_size;
1805                src_addr    = (u32)(wl_iq_rx_buff_d + offset);
1806            } else {
1807                wl_printf(WL_PRINT_ERROR, print_type_baseband, "Trying to read to RF D buffer on a 2RF design.\n");
1808            }
1809        }
1810    }
[4234]1811
[4668]1812    // Process Read RSSI
[4811]1813    if(cmd_id == CMDID_BASEBAND_READ_RSSI) {
[4668]1814        if(buffer_sel & RF_SEL_A) {
1815            buffer_size = wl_rssi_buff_a_size;
1816            src_addr    = (u32)(wl_rssi_buff_a + offset);
[4234]1817
[4668]1818        } else if(buffer_sel & RF_SEL_B) {
1819            buffer_size = wl_rssi_buff_b_size;
1820            src_addr    = (u32)(wl_rssi_buff_b + offset);
[4234]1821
[4668]1822        } else if(buffer_sel & RF_SEL_C) {
1823            if (WARPLAB_CONFIG_4RF) {
1824                buffer_size = wl_rssi_buff_c_size;
1825                src_addr    = (u32)(wl_rssi_buff_c + offset);
1826            } else {
1827                wl_printf(WL_PRINT_ERROR, print_type_baseband, "Trying to read to RF C RSSI buffer on a 2RF design.\n");
1828            }
[4234]1829
[4668]1830        } else if(buffer_sel & RF_SEL_D) {
1831            if (WARPLAB_CONFIG_4RF) {
1832                buffer_size = wl_rssi_buff_d_size;
1833                src_addr    = (u32)(wl_rssi_buff_d + offset);
1834            } else {
1835                wl_printf(WL_PRINT_ERROR, print_type_baseband, "Trying to read to RF D RSSI buffer on a 2RF design.\n");
1836            }
1837        }
1838    }
[4234]1839
[4668]1840    // Transfer data or zeros
1841    //   NOTE:  buffer_size is initialized to zero so it will return zeros when RFC / RFD errors occur
1842    if (end_byte <= buffer_size) {
1843        buffer->data   = (u8 *)src_addr;
1844        buffer->offset = (u8 *)src_addr;
1845        buffer->length = length;
1846        buffer->size   = length;
1847    } else {
1848        wl_printf(WL_PRINT_ERROR, print_type_baseband, "Too many bytes read from buffer - Size = %d;  Read end = %d\n", buffer_size, end_byte);
1849        bzero((void *)(dest_addr), length);
1850
1851        // Create an error buffer w/ zero data
1852        buffer->data   = (u8 *)dest_addr;
1853        buffer->offset = (u8 *)dest_addr;
1854        buffer->length = length;
1855        buffer->size   = length;
1856    }
[4234]1857}
1858
1859
1860
[4196]1861/*****************************************************************************/
1862/**
[4668]1863 * Write TX buffers
1864 *
1865 *     Writes from the source address to all of the buffers indicated by the buffer_sel
1866 * parameter.
1867 *
1868 * @param   buffer_sel       - Buffer select (Indicates which buffer(s) should be written)
1869 * @param   src_addr         - Source address of the transfer (in bytes; must be 16 byte
1870 *                             aligned due to CDMA usage)
1871 * @param   offset           - Starting byte offset into TX buffer (in bytes; must be 16 byte
1872 *                             aligned due to CDMA usage)
1873 * @param   length           - Length of the transfer (in bytes)
1874 *
1875 * @return  None
1876 *
1877 *****************************************************************************/
[4234]1878void write_tx_buffers(u32 buffer_sel, u32 src_addr, u32 offset, u32 length) {
1879
[4668]1880    u32 dest_addr      = 0;
1881    u32 end_byte       = offset + length - 1;
[4234]1882
[4668]1883    // Process RFA
1884    if(buffer_sel & RF_SEL_A) {
1885        dest_addr = (u32)(wl_iq_tx_buff_a) + offset;
[4234]1886
[4668]1887        if ( end_byte <= wl_iq_tx_buff_a_size ) {
[4453]1888            baseband_transfer_data(src_addr, dest_addr, length);
[4668]1889        } else {
1890            wl_printf(WL_PRINT_ERROR, print_type_baseband, "Too many bytes written to buffer RFA - Size = %d;  Write end = %d\n", wl_iq_tx_buff_a_size, end_byte);
1891            bzero((void *)(dest_addr), length);
1892        }
1893    }
[4234]1894
[4668]1895    // Process RFB
1896    if(buffer_sel & RF_SEL_B) {
1897        dest_addr = (u32)(wl_iq_tx_buff_b) + offset;
[4234]1898
[4668]1899        if ( end_byte <= wl_iq_tx_buff_b_size ) {
[4453]1900            baseband_transfer_data(src_addr, dest_addr, length);
[4668]1901        } else {
1902            wl_printf(WL_PRINT_ERROR, print_type_baseband, "Too many bytes written to buffer RFB - Size = %d;  Write end = %d\n", wl_iq_tx_buff_b_size, end_byte);
1903            bzero((void *)(dest_addr), length);
1904        }
1905    }
[4234]1906
[4668]1907    // Process RFC
1908    if(buffer_sel & RF_SEL_C) {
1909        if (WARPLAB_CONFIG_4RF) {
1910            dest_addr = (u32)(wl_iq_tx_buff_c) + offset;
[4234]1911
[4668]1912            if ( end_byte <= wl_iq_tx_buff_c_size ) {
[4453]1913                baseband_transfer_data(src_addr, dest_addr, length);
[4668]1914            } else {
1915                wl_printf(WL_PRINT_ERROR, print_type_baseband, "Too many bytes written to buffer RFC - Size = %d;  Write end = %d\n", wl_iq_tx_buff_c_size, end_byte);
1916                bzero((void *)(dest_addr), length);
1917            }
1918        } else {
1919            wl_printf(WL_PRINT_ERROR, print_type_baseband, "Trying to write to RF C buffer on a 2RF design.\n");
1920        }
1921    }
[4234]1922
[4668]1923    // Process RFD
[4234]1924    if(buffer_sel & RF_SEL_D) {
[4668]1925        if (WARPLAB_CONFIG_4RF) {
1926            dest_addr = (u32)(wl_iq_tx_buff_d) + offset;
[4234]1927
[4668]1928            if ( end_byte <= wl_iq_tx_buff_d_size ) {
[4453]1929                baseband_transfer_data(src_addr, dest_addr, length);
[4668]1930            } else {
1931                wl_printf(WL_PRINT_ERROR, print_type_baseband, "Too many bytes written to buffer RFD - Size = %d;  Write end = %d\n", wl_iq_tx_buff_d_size, end_byte);
1932                bzero((void *)(dest_addr), length);
1933            }
1934        } else {
1935            wl_printf(WL_PRINT_ERROR, print_type_baseband, "Trying to write to RF D buffer on a 2RF design.\n");
1936        }
1937    }
1938
1939    //
1940    // TBD - Could rework this function to reduce the code overhead due to printing
1941    //
1942
[4453]1943}
[4234]1944
1945
[4453]1946
1947/*****************************************************************************/
1948/**
1949 * @brief Baseband reset
1950 *
[4668]1951 * @param   None
[4453]1952 *
[4668]1953 * @return  None
[4453]1954 *
1955 ******************************************************************************/
1956void baseband_reset(){
[4668]1957    // ------------------------------------------
1958    // Reset the global variables
1959    //
1960    write_iq_checksum_lsb = 0;
1961    write_iq_checksum_msb = 0;
[4453]1962
1963
[4668]1964    // ------------------------------------------
1965    // Reset the buffers core
1966    //
[4453]1967   
1968    // Perform any HW specific resets
1969    baseband_hw_specific_reset();
1970
[4668]1971    // Set default config register values
1972    wl_bb_clear_config(
[4453]1973            WL_BUF_REG_CONFIG_CONT_TX |               // Disable continuous Tx
1974            WL_BUF_REG_CONFIG_STOP_TX |               // Stop any TX that are currently active
1975            WL_BUF_REG_CONFIG_AGC_IQ_SEL_RF_ALL );    // Select non-AGC IQ for all RF interfaces
1976
1977
[4668]1978    // Set RSSI clock to be 1/4 of the IQ sample clock
1979    wl_bb_set_rssi_clk(1);
[4453]1980
[4668]1981    // Set the TX delay to INIT_TX_DELAY
1982    wl_bb_set_tx_delay(INIT_TX_DELAY);
[4453]1983
1984    // Turn off all RX and TX buffers
[4668]1985    wl_bb_clear_rx_buffer_en(RF_SEL_ALL);
1986    wl_bb_clear_tx_buffer_en(RF_SEL_ALL);
[4453]1987
[4668]1988    // Set the Buffer to RF mapping:
1989    //     Buffer A - RFA
1990    //     Buffer B - RFB
1991    //     Buffer C - RFC
1992    //     Buffer D - RFD
1993    wl_bb_set_rf_buffer_sel(ANT_A, ANT_B, ANT_C, ANT_D);
[4453]1994
[4668]1995    // Initialize the RD/WR byte offsets in the core
1996    //   NOTE:  We initialize the TX write offset to the buffer size because we assume
1997    //     that the TX buffer will be populated by the time the transmission starts.
1998    wl_bb_set_rf_rx_iq_buf_rd_byte_offset(0);
1999    wl_bb_set_rf_rx_iq_buf_wr_byte_offset(0);
[4453]2000
[4668]2001    wl_bb_set_rf_tx_iq_buf_wr_byte_offset(WARPLAB_IQ_TX_BUF_SIZE);
[4811]2002
2003    // Reset the TX / RX counters
2004    wl_bb_clear_txrx_counter_reset();
2005    wl_bb_set_txrx_counter_reset(WL_BUF_TXRX_COUNTER_RESET_TXRX_ALL);
2006    wl_bb_clear_txrx_counter_reset();
[4453]2007}
2008
2009
2010
[4668]2011/*****************************************************************************/
2012/**
2013 * @brief Accessor methods
2014 *
2015 * @param   None
2016 *
2017 * @return  u32              - Value of parameter
2018 *
2019 ******************************************************************************/
[4453]2020u32 wl_bb_get_supported_tx_length() {
[4668]2021    if (supported_tx_length != 0xFFFFFFFF) {
2022        return supported_tx_length;
2023    } else {
2024        wl_printf(WL_PRINT_ERROR, print_type_baseband, "TX baseband buffers not configured.\n");
2025        return 0;
2026    }
[4234]2027}
2028
[4453]2029u32 wl_bb_get_supported_rx_length() {
[4668]2030    if (supported_rx_length != 0xFFFFFFFF) {
2031        return supported_rx_length;
2032    } else {
2033        wl_printf(WL_PRINT_ERROR, print_type_baseband, "RX baseband buffers not configured.\n");
2034        return 0;
2035    }
[4453]2036}
[4234]2037
2038
[4668]2039
[4234]2040/*****************************************************************************/
2041/**
[4453]2042 * @brief Baseband subsystem initialization
2043 *
[4668]2044 * @param   dram_present          - Status flag to indicate if DRAM is present
2045 * @param   configure_buffers     - Flag to indicate if the buffer sizes / locations should be configured
[4453]2046 *
[4668]2047 * @return  int              - Status of the command:
2048 *                                 XST_SUCCESS - Command completed successfully
2049 *                                 XST_FAILURE - There was an error in the command
[4453]2050 *
2051 ******************************************************************************/
2052int baseband_init(u8 dram_present, u8 configure_buffers){
[4668]2053    u32  status         = XST_SUCCESS;
[4453]2054
[4668]2055    // Configure the sample buffers (if necessary)
2056    if (configure_buffers) {
2057        baseband_buffers_config(dram_present);
2058    }
[4453]2059
[4668]2060    // Initialize the baseband
2061    baseband_reset();
[4453]2062
[4668]2063    // Initialize the AGC core
2064    warplab_agc_init();
2065    warplab_agc_reset();
[4783]2066    trigger_proc_out1_set_delay(2000);          // Configure initial delay for 12.5 us
[4453]2067
[4673]2068    // Check baseband parameters
2069    status = baseband_check_parameters();
2070
[4668]2071    return status;
[4453]2072}
2073
2074
2075
2076/*****************************************************************************/
2077/**
2078 * @brief IQ Checksums
2079 *
[4668]2080 * WARPLab uses the Fletcher-32 checksum algorithm
[4453]2081 *
2082 ******************************************************************************/
2083u32 baseband_get_checksum() {
[4668]2084    return ((write_iq_checksum_msb << 16) + write_iq_checksum_lsb);
[4453]2085}
2086
2087
2088u32 baseband_update_checksum(u16 newdata, u8 reset ){
[4668]2089    // xil_printf("Checksum input: %d, reset: %d\n", newdata, reset);
[4453]2090
[4668]2091    if(reset){
2092        write_iq_checksum_lsb = 0;
2093        write_iq_checksum_msb = 0;
2094    }
[4453]2095
[4668]2096    write_iq_checksum_lsb = (write_iq_checksum_lsb + newdata) % 65535;
2097    write_iq_checksum_msb = (write_iq_checksum_msb + write_iq_checksum_lsb) % 65535;
[4453]2098
[4668]2099    // xil_printf("sum1: %d sum2: %d\n", write_iq_checksum_lsb, write_iq_checksum_msb);
[4453]2100
[4668]2101    return baseband_get_checksum();
[4453]2102}
2103
2104
2105
2106/*****************************************************************************/
2107/**
2108 * @brief Get the selected buffer's buffer size
2109 *
[4668]2110 * @param   cmd_id           - Command ID is used as a proxy to get the TX / RX or RSSI buffer sizes
2111 * @param   buffer_sel       - Which of the buffers to get the size
[4453]2112 *
[4668]2113 * @return  u32              - Buffer Size
2114 *
[4453]2115 ******************************************************************************/
2116u32  get_buffer_size(u32 cmd_id, u32 buffer_sel) {
2117
[4668]2118    u32 buffer_size = 0;
[4453]2119
[4668]2120    switch(cmd_id) {
[4811]2121        case CMDID_BASEBAND_WRITE_IQ:
[4668]2122            if(buffer_sel & RF_SEL_A) { buffer_size = wl_iq_tx_buff_a_size; }
2123            if(buffer_sel & RF_SEL_B) { buffer_size = wl_iq_tx_buff_b_size; }
2124            if(buffer_sel & RF_SEL_C) { buffer_size = wl_iq_tx_buff_c_size; }
2125            if(buffer_sel & RF_SEL_D) { buffer_size = wl_iq_tx_buff_d_size; }
[4453]2126        break;
2127
[4811]2128        case CMDID_BASEBAND_READ_IQ:
[4668]2129            if(buffer_sel & RF_SEL_A) { buffer_size = wl_iq_rx_buff_a_size; }
2130            if(buffer_sel & RF_SEL_B) { buffer_size = wl_iq_rx_buff_b_size; }
2131            if(buffer_sel & RF_SEL_C) { buffer_size = wl_iq_rx_buff_c_size; }
2132            if(buffer_sel & RF_SEL_D) { buffer_size = wl_iq_rx_buff_d_size; }
[4453]2133        break;
2134
[4811]2135        case CMDID_BASEBAND_READ_RSSI:
[4668]2136            if(buffer_sel & RF_SEL_A) { buffer_size = wl_rssi_buff_a_size; }
2137            if(buffer_sel & RF_SEL_B) { buffer_size = wl_rssi_buff_b_size; }
2138            if(buffer_sel & RF_SEL_C) { buffer_size = wl_rssi_buff_c_size; }
2139            if(buffer_sel & RF_SEL_D) { buffer_size = wl_rssi_buff_d_size; }
[4453]2140        break;
[4668]2141    }
[4453]2142
[4668]2143    return buffer_size;
[4453]2144}
2145
2146
2147
2148/*****************************************************************************/
2149/**
[4811]2150 * @brief Get the selected buffer's counter
2151 *
2152 * @param   txrx_sel         - Get TX / RX buffer counter value
2153 *                                 TX = CMD_PARAM_BASEBAND_TXRX_COUNT_GET_TX
2154 *                                 RX = CMD_PARAM_BASEBAND_TXRX_COUNT_GET_RX
2155 * @param   buffer_sel       - Which of the buffers to get the counter value
2156 *
2157 * @return  u32              - Counter value
2158 *
2159 ******************************************************************************/
2160u32  get_buffer_counter(u32 txrx_sel, u32 buffer_sel) {
2161
2162    u32 buffer_count = 0;
2163
2164    if (txrx_sel == CMD_PARAM_BASEBAND_TXRX_COUNT_GET_RX) {
2165        if(buffer_sel & RF_SEL_A) { buffer_count = wl_bb_get_rfa_rx_count(); }
2166        if(buffer_sel & RF_SEL_B) { buffer_count = wl_bb_get_rfb_rx_count(); }
2167        if(buffer_sel & RF_SEL_C) { buffer_count = wl_bb_get_rfc_rx_count(); }
2168        if(buffer_sel & RF_SEL_D) { buffer_count = wl_bb_get_rfd_rx_count(); }
2169    } else {
2170        if(buffer_sel & RF_SEL_A) { buffer_count = wl_bb_get_rfa_tx_count(); }
2171        if(buffer_sel & RF_SEL_B) { buffer_count = wl_bb_get_rfb_tx_count(); }
2172        if(buffer_sel & RF_SEL_C) { buffer_count = wl_bb_get_rfc_tx_count(); }
2173        if(buffer_sel & RF_SEL_D) { buffer_count = wl_bb_get_rfd_tx_count(); }
2174    }
2175
2176    return buffer_count;
2177}
2178
2179
2180
2181/*****************************************************************************/
2182/**
[4453]2183 * @brief AGC Commands
2184 *
2185 * The WARPLab AGC is based on the 802.11 Reference design AGC.  The initialization
2186 * is much the same between the two, except where noted.
2187 *
2188 ******************************************************************************/
2189void warplab_agc_init(){
[4668]2190    // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "AGC init\n");
[4453]2191
[4668]2192    // ant_mode argument allows per-antenna AGC settings, in case FMC module has different
2193    //     response than on-board RF interfaces. Testing so far indicates the settings below
2194    //     work fine for all RF interfaces
[4453]2195
[4668]2196    // Post Rx_done reset delays for [rxhp, g_rf, g_bb]
2197    wl_agc_set_reset_timing(4, 250, 250);
[4453]2198
[4668]2199    // AGC config:
2200    //     RFG Thresh 3->2, 2->1, Avg_len_sel, V_DB_Adj, Init G_BB
2201    //       NOTE:  V_DB_Adj has a different value from the 802.11 reference design (4 vs 6)
2202    //              so that the agc_target command has roughly the same behavior between WARPLab
2203    //              7.4.0 and WARPLab 7.5.0.
2204    //
[4811]2205    wl_agc_set_config_all((256 - 56), (256 - 37), 2, 4, 24);
[4453]2206
[4668]2207    //     AGC RSSI->Rx power offsets
[4800]2208    wl_agc_set_RSSI_pwr_calib(100, 79, 70);
[4453]2209
[4668]2210    //     AGC timing: capt_rssi_1, capt_rssi_2, capt_v_db, agc_done
[4800]2211    wl_agc_set_AGC_timing(1, 60, 180, 192);
[4453]2212
[4668]2213    //     AGC timing: start_dco, en_iir_filt
[4811]2214    wl_agc_set_DCO_timing(100, (100 + 34));
[4453]2215
[4668]2216    //     AGC target output power (log scale)
[4811]2217    wl_agc_set_target((64 - 13));
[4453]2218
2219    //     Set IIR coefficients
2220    //         IIR HPF filter with 3dB cutoff at 20kHz with 40MHz sampling
2221    //             DCO_IIR_Coef_A1 = -0.996863331833438  ( Fix_18_17) => -130661  => 0x0002019B
2222    //             DCO_IIR_Coef_B0 = 0.99843166591671906 (UFix_18_17) =>  130866  => 0x0001FF32
[4668]2223    //
2224    //         To convert to a fixed point number, we first multiple by 2^17, then round
2225    //             and then represent the number as a 2's complement value (18 bits).
2226    //
[4453]2227    wl_agc_set_iir_coef_a1(0x0002019B);               // This value is  Fix_18_17
2228    wl_agc_set_iir_coef_b0(0x0001FF32);               // This value is UFix_18_17
2229
[4805]2230    // Enable the "reset per rx" mode
2231    wl_agc_enable_reset_per_rx();
[4453]2232
[4805]2233    // Initialize the AGC rx length to a sane default (ie 100 samples more than the current baseband rx length)
2234    warplab_set_agc_rx_length(wl_bb_get_rx_length() + 100);
2235
[4668]2236    // AGC is now reset and enabled, ready to go!
[4453]2237
[4668]2238    // Override the AGC functionality
2239    // wl_agc_set_override(0x00008080);
[4453]2240}
2241
2242
[4783]2243void warplab_agc_enable_DCO(u32 enable){
[4668]2244    // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "AGC set DCO\n");
[4453]2245
[4668]2246    // Enables DCO and DCO subtraction (correction scheme and butterworth hipass are active)
[4783]2247    if(enable)
[4668]2248        wl_agc_set_DCO_timing(100, (100+34));
2249    else
2250        wl_agc_set_DCO_timing(255, 255);
[4453]2251}
2252
2253
2254void warplab_agc_reset(){
[4668]2255    // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "AGC reset\n");
[4453]2256
[4668]2257    // Cycle the AGC software reset port
2258    wl_agc_set_reset(1);
2259    usleep(10);
2260    wl_agc_set_reset(0);
2261    usleep(100);
[4453]2262}
2263
2264
[4805]2265void warplab_set_agc_rx_length(u32 num_samples) {
[4453]2266
[5608]2267    // The AGC core implements a 32-bit sample counter that increments at 40MHz
2268    //  This counter is compared to the rx_length when the reset-per-Rx mode is enabled
2269    //  The AGC rx_length value must be non-zero
2270    if(num_samples == 0) {
2271        wl_agc_set_rx_length(1);
2272    } else {
2273        wl_agc_set_rx_length(num_samples);
2274    }
[4453]2275
[5608]2276    return;
[4453]2277}
2278
2279
2280
[4783]2281
2282
2283
2284
[4453]2285/**********************************************************************************************************************/
2286/**
2287 * @brief WARP v3 Specific Functions
2288 *
2289 **********************************************************************************************************************/
2290
2291/***************************** Include Files *********************************/
2292
2293#include <xintc.h>
2294
2295/*************************** Constant Definitions ****************************/
2296
2297/*********************** Global Variable Definitions *************************/
2298
2299/*************************** Variable Definitions ****************************/
2300
2301/*************************** Functions Prototypes ****************************/
2302
[4458]2303void wl_buffers_core_rx_int_handler(void *InstancePtr);
2304void wl_buffers_core_tx_int_handler(void *InstancePtr);
2305
2306
[4453]2307/******************************** Functions **********************************/
2308
2309/*****************************************************************************/
2310/**
[4668]2311 * @brief Transfer Baseband Data
2312 *
2313 *     Uses CDMA to transfer baseband data.
2314 *
2315 * @param   src_addr         - Source address of the data
2316 * @param   dest_addr        - Destination address of the data
2317 * @param   length           - Length of the transfer (in bytes)
2318 *
2319 * @return  None
2320 *
2321 *****************************************************************************/
[4453]2322void baseband_transfer_data( u32 src_addr, u32 dest_addr, u32 length ) {
2323    wl_cdma_transfer(src_addr, dest_addr, length);
2324}
2325
2326
2327
2328/*****************************************************************************/
2329/**
[4668]2330 * @brief Hardware Specific Baseband Reset
2331 *
2332 *     Performs any hardware specific initialization required during a baseband
2333 * reset.
2334 *
2335 * @param   None
2336 *
2337 * @return  None
2338 *
2339 *****************************************************************************/
[4453]2340void baseband_hw_specific_reset() {
2341    // Enable byte swapping
2342    wl_bb_set_config(WL_BUF_REG_CONFIG_RX_BYTE_ORDER | WL_BUF_REG_CONFIG_TX_BYTE_ORDER);
2343}
2344
2345
2346
2347/*****************************************************************************/
2348/**
[4668]2349 * @brief Populate Temporary TX buffers
2350 *
2351 *     Copies data from the RF buffer in DDR to the temporary BRAM buffer based
2352 * on the buffer_sel parameter.  This method will not transfer to RFC and RFD if
2353 * they do not exist.
2354 *
2355 * @param   buffer_sel       - Buffer select (Indicates which buffer(s) should be copied)
2356 * @param   length           - Length of the transfer (in bytes)
2357 *
2358 * @return  None
2359 *
2360 *****************************************************************************/
[4234]2361void populate_tmp_tx_buffers(u32 buffer_sel, u32 offset, u32 length) {
2362
[4668]2363    u32 src_addr;
2364    u32 dest_addr;
[4234]2365
[4668]2366    // Only transfer if DDR is being used for buffers
2367    if (use_dram_for_buffers) {
[4333]2368
[4668]2369        // Process RFA
2370        if(buffer_sel & RF_SEL_A) {
2371            src_addr  = (u32)(wl_iq_tx_buff_a) + offset;
2372            dest_addr = WARPLAB_IQ_TX_BUF_A + (offset % WARPLAB_IQ_TX_BUF_SIZE);
2373            wl_cdma_transfer(src_addr, dest_addr, length);
2374        }
[4234]2375
[4668]2376        // Process RFB
2377        if(buffer_sel & RF_SEL_B) {
2378            src_addr = (u32)(wl_iq_tx_buff_b) + offset;
2379            dest_addr = WARPLAB_IQ_TX_BUF_B + (offset % WARPLAB_IQ_TX_BUF_SIZE);
2380            wl_cdma_transfer(src_addr, dest_addr, length);
2381        }
[4234]2382
[4668]2383        // Process RFC
2384        if ((buffer_sel & RF_SEL_C) && (WARPLAB_CONFIG_4RF)) {
2385            src_addr = (u32)(wl_iq_tx_buff_c) + offset;
2386            dest_addr = WARPLAB_IQ_TX_BUF_C + (offset % WARPLAB_IQ_TX_BUF_SIZE);
2387            wl_cdma_transfer(src_addr, dest_addr, length);
2388        }
[4234]2389
[4668]2390        // Process RFD
2391        if ((buffer_sel & RF_SEL_D) && (WARPLAB_CONFIG_4RF)) {
2392            src_addr = (u32)(wl_iq_tx_buff_d) + offset;
2393            dest_addr = WARPLAB_IQ_TX_BUF_D + (offset % WARPLAB_IQ_TX_BUF_SIZE);
2394            wl_cdma_transfer(src_addr, dest_addr, length);
2395        }
2396    }
[4234]2397}
2398
2399
2400
2401/*****************************************************************************/
2402/**
[4668]2403 * @brief Set up the Baseband interrupts
2404 *
2405 * @param   intc             - Pointer to instance of interrupt controller
2406 *
2407 * @return  int              - Status of the command:
2408 *                                 XST_SUCCESS - Command completed successfully
2409 *
2410 *****************************************************************************/
[4196]2411int wl_baseband_setup_interrupt(XIntc* intc){
[4668]2412    int status;
[4196]2413
[4668]2414    // Connect buffers core RX interrupt to Interrupt Controller
2415    status =  XIntc_Connect(intc, WL_BUF_RX_INTERRUPT_ID, (XInterruptHandler)wl_buffers_core_rx_int_handler, NULL);
2416    XIntc_Enable(intc, WL_BUF_RX_INTERRUPT_ID);
[4196]2417
[4668]2418    // Connect buffers core TX interrupt to Interrupt Controller
2419    status =  XIntc_Connect(intc, WL_BUF_TX_INTERRUPT_ID, (XInterruptHandler)wl_buffers_core_tx_int_handler, NULL);
2420    XIntc_Enable(intc, WL_BUF_TX_INTERRUPT_ID);
[4234]2421
[4668]2422    return status;
[4184]2423}
2424
2425
2426
[4196]2427/*****************************************************************************/
2428/**
[4234]2429 * @brief Buffers Core RX Interrupt Handler
[4196]2430 *
2431 * Handles interrupts that occur from the Buffers core.
2432 *
[4668]2433 * @param   InstancePtr      - Pointer to the Buffers core instance
[4196]2434 *
[4668]2435 * @return  None
2436 *
[4196]2437 ******************************************************************************/
[4234]2438void wl_buffers_core_rx_int_handler(void *InstancePtr){
[4184]2439
[4668]2440    u32 src_addr;
2441    u32 dest_addr;
2442    u32 iq_buf_size;
2443    u32 rssi_buf_size;
2444    u32 iq_xfer_length;
2445    u32 rssi_xfer_length;
[4184]2446
[4196]2447    u32 buff_en;
2448    u32 iq_read_offset;
2449    u32 iq_read_offset_mod_buf_size;
2450    u32 iq_write_offset;
2451    u32 iq_write_offset_mod_buf_size;
2452    u32 rssi_read_offset;
2453    u32 rssi_read_offset_mod_buf_size;
[4184]2454
[4668]2455    if (use_dram_for_buffers) {
2456        // Check if there was a RX error
2457        if (wl_bb_get_rf_rx_iq_rssi_error()) {
2458            wl_printf(WL_PRINT_ERROR, print_type_baseband, "RX temp buffer overflowed.\n");
2459            return;
2460        }
[4184]2461
[4668]2462        // Get buffers core register values
2463        //   NOTE:  Since we are transferring both IQ and RSSI data, we need to align the write offset
2464        //          To transfer the correct number of RSSI bytes.  Note that IQ data is 8x RSSI data (in bytes).
2465        buff_en          = wl_bb_get_rx_buffer_en();
2466        iq_read_offset   = wl_bb_get_rf_rx_iq_buf_rd_byte_offset();
2467        rssi_read_offset = (iq_read_offset >> 3);
2468        iq_write_offset  = (wl_bb_get_rf_rx_iq_buf_wr_byte_offset() + 4) & WL_BUF_RX_TRANSFER_BYTE_ALIGNMENT_MASK;
[1915]2469
[4668]2470        // ASSUMPTION:  We are going to assume that all RX and RSSI buffers are the same size.
2471        //   In the future, this might not be true and the *_xfer_length calculations will need to be
2472        //   done per buffer.  Note that IQ data is 8x RSSI data (in bytes).
2473        iq_buf_size                   = (u32)(WARPLAB_IQ_RX_BUF_SIZE);
2474        iq_read_offset_mod_buf_size   = (u32)(iq_read_offset % iq_buf_size);
2475        iq_write_offset_mod_buf_size  = (u32)(iq_write_offset % iq_buf_size);
[1915]2476
[4668]2477        rssi_buf_size                 = (u32)(WARPLAB_RSSI_BUF_SIZE);
2478        rssi_read_offset_mod_buf_size = (u32)(rssi_read_offset % rssi_buf_size);
[1915]2479
[4668]2480        // Compute transfer lengths based on the buffer sizes
2481        if (iq_write_offset_mod_buf_size > iq_read_offset_mod_buf_size) {
2482            iq_xfer_length           = (u32)(iq_write_offset - iq_read_offset);
2483        } else {
2484            iq_xfer_length           = (u32)(iq_buf_size - iq_read_offset_mod_buf_size);
2485        }
2486        rssi_xfer_length             = (u32)(iq_xfer_length >> 3);
[1915]2487
[4829]2488        // NOTE:  All steps below are conditioned on at least one of the buffers being enabled.  Otherwise,
2489        //   this function will do nothing to the state of the buffers core.
2490
[4668]2491        // For each buffer, transfer relevant data
2492        if (buff_en & RF_SEL_A) {
2493            // Transfer IQ data
2494            src_addr    = (u32)(WARPLAB_IQ_RX_BUF_A + iq_read_offset_mod_buf_size);
2495            dest_addr   = (u32)(wl_iq_rx_buff_a + iq_read_offset);
[4184]2496
[4668]2497            wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length);
[4184]2498
[4668]2499            // Transfer RSSI data (RSSI data is 8x less bytes than IQ data)
2500            src_addr    = (u32)(WARPLAB_RSSI_BUF_A + rssi_read_offset_mod_buf_size);
2501            dest_addr   = (u32)(wl_rssi_buff_a + rssi_read_offset);
[1915]2502
[4668]2503            wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length);
2504        }
[4196]2505
[4668]2506        if (buff_en & RF_SEL_B) {
2507            // Transfer IQ data
2508            src_addr    = (u32)(WARPLAB_IQ_RX_BUF_B + iq_read_offset_mod_buf_size);
2509            dest_addr   = (u32)(wl_iq_rx_buff_b + iq_read_offset);
[4196]2510
[4668]2511            wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length);
[4196]2512
[4668]2513            // Transfer RSSI data (RSSI data is 8x less bytes than IQ data)
2514            src_addr    = (u32)(WARPLAB_RSSI_BUF_B + rssi_read_offset_mod_buf_size);
2515            dest_addr   = (u32)(wl_rssi_buff_b + rssi_read_offset);
[4196]2516
[4668]2517            wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length);
2518        }
[4196]2519
[4668]2520        if ((buff_en & RF_SEL_C) && (WARPLAB_CONFIG_4RF)) {
2521            // Transfer IQ data
2522            src_addr    = (u32)(WARPLAB_IQ_RX_BUF_C + iq_read_offset_mod_buf_size);
2523            dest_addr   = (u32)(wl_iq_rx_buff_c + iq_read_offset);
[4196]2524
[4668]2525            wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length);
[4196]2526
[4668]2527            // Transfer RSSI data (RSSI data is 8x less bytes than IQ data)
2528            src_addr    = (u32)(WARPLAB_RSSI_BUF_C + rssi_read_offset_mod_buf_size);
2529            dest_addr   = (u32)(wl_rssi_buff_c + rssi_read_offset);
[4196]2530
[4668]2531            wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length);
2532        }
[4196]2533
[4668]2534        if ((buff_en & RF_SEL_D) && (WARPLAB_CONFIG_4RF)) {
2535            // Transfer IQ data
2536            src_addr    = (u32)(WARPLAB_IQ_RX_BUF_D + iq_read_offset_mod_buf_size);
2537            dest_addr   = (u32)(wl_iq_rx_buff_d + iq_read_offset);
[4196]2538
[4668]2539            wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length);
[4196]2540
[4668]2541            // Transfer RSSI data (RSSI data is 8x less bytes than IQ data)
2542            src_addr    = (u32)(WARPLAB_RSSI_BUF_D + rssi_read_offset_mod_buf_size);
2543            dest_addr   = (u32)(wl_rssi_buff_d + rssi_read_offset);
[4196]2544
[4668]2545            wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length);
2546        }
[4196]2547
[4668]2548        // If we are done, then reset the read / write offsets.  Otherwise, update
[4829]2549        //     the read offset to reflect the bytes read only if at least one of
2550        //     the buffers is enabled.
2551        if (buff_en) {
2552            if (iq_write_offset == rx_buffer_size) {
2553                wl_bb_set_rf_rx_iq_buf_rd_byte_offset(0);
2554                wl_bb_set_rf_rx_iq_buf_wr_byte_offset(0);
2555            } else {
2556                wl_bb_set_rf_rx_iq_buf_rd_byte_offset(iq_write_offset);
2557            }
[4668]2558        }
[4196]2559
[4668]2560    } else {
2561        // Since we should not use the interrupt since DDR is not present; reset the
2562        //     read / write offsets so we don't hit any weird conditions
2563        wl_bb_set_rf_rx_iq_buf_rd_byte_offset(0);
2564        wl_bb_set_rf_rx_iq_buf_wr_byte_offset(0);
2565    }
[4196]2566}
2567
2568
[4234]2569
[4196]2570/*****************************************************************************/
2571/**
[4234]2572 * @brief Buffers Core TX Interrupt Handler
2573 *
2574 * Handles interrupts that occur from the Buffers core.
2575 *
[4668]2576 * @param   InstancePtr      - Pointer to the Buffers core instance
[4234]2577 *
[4668]2578 * @return  None
2579 *
[4234]2580 ******************************************************************************/
2581void wl_buffers_core_tx_int_handler(void *InstancePtr){
2582
2583    u32 buff_en;
2584    u32 tx_iq_status;
[4333]2585    u32 continuous_tx;
[4668]2586    u32 iq_xfer_length;
[4234]2587    u32 iq_write_offset;
2588
[4668]2589    // Only perform a transfer if the node is using DDR for buffers
[4234]2590    if (use_dram_for_buffers) {
2591
[4668]2592        // Check if there was a RX error
2593        if (wl_bb_get_rf_tx_iq_error()) {
2594            wl_printf(WL_PRINT_ERROR, print_type_baseband, "TX temp buffer underflowed.\n");
2595            return;
2596        }
[4234]2597
[4668]2598        // Get buffers core register values
2599        buff_en          = wl_bb_get_tx_buffer_en();
2600        tx_iq_status     = wl_bb_get_rf_tx_iq_status();
2601        continuous_tx    = ((wl_bb_get_config() & WL_BUF_REG_CONFIG_CONT_TX) == WL_BUF_REG_CONFIG_CONT_TX);
[4333]2602
[4668]2603        // For the last write we need to prep the buffer for the next write IQ.  This means
2604        //   that we fill the temporary buffer completely.  For every other write, we need to
2605        //   transfer a threshold number of bytes to the buffer.
2606        //
2607        // ASSUMPTION:  We are going to assume that all TX buffers are the same size.
2608        //   In the future, this might not be true and the *_xfer_length calculations will need to be
2609        //   done per buffer.
2610        //
[4829]2611        // NOTE:  All steps below are conditioned on at least one of the buffers being enabled.  Otherwise,
2612        //   this function will do nothing to the state of the buffers core.
2613        //
2614        if (buff_en) {
2615            if (tx_iq_status & WL_BUF_TX_IQ_STATUS_WR_DONE) {
2616                iq_write_offset  = 0x00000000;
[4234]2617
[4829]2618                // If we are in continuous TX mode, the "done" means we need to start the TX waveform over,
2619                // but can't over-write what we are currently transmitting (ie only write half the buffer).
2620                if (continuous_tx) {
2621                    iq_xfer_length   = (u32)(WARPLAB_IQ_TX_BUF_SIZE >> 1);
2622                } else {
2623                    iq_xfer_length   = (u32)(WARPLAB_IQ_TX_BUF_SIZE);
2624                }
2625            } else {
2626                iq_write_offset  = (wl_bb_get_rf_tx_iq_buf_wr_byte_offset() & WL_BUF_TX_TRANSFER_BYTE_ALIGNMENT_MASK);
[4668]2627                iq_xfer_length   = (u32)(WARPLAB_IQ_TX_BUF_SIZE >> 1);
2628            }
2629
[4829]2630            // Transfer the data
2631            populate_tmp_tx_buffers(buff_en, iq_write_offset, iq_xfer_length);
[4234]2632
[4829]2633            // Update the write_offset in the buffers core
2634            wl_bb_set_rf_tx_iq_buf_wr_byte_offset(iq_write_offset + iq_xfer_length);
2635        }
[4234]2636
2637    } else {
[4668]2638        // Since we should not use the interrupt since DDR is not present; reset the
2639        //     read / write offsets so we don't hit any weird conditions
2640        wl_bb_set_rf_tx_iq_buf_wr_byte_offset(WARPLAB_IQ_TX_BUF_SIZE);
2641    }
[4196]2642}
2643
2644
2645
2646/*****************************************************************************/
2647/**
[4668]2648 * @brief Configure Baseband Buffers
[4196]2649 *
[4668]2650 *   This function will configure the size of the buffers used in this sub-system
2651 * and configure the WARPLab Buffers core with appropriate settings based on the
2652 * WARP hardware that is present (ie is the DDR available).
[4196]2653 *
[4668]2654 * @param   dram_present     - Flag to indicate if DRAM is present
[4196]2655 *
[4668]2656 * @return  int              - Status of the command:
2657 *                                 XST_SUCCESS - Command completed successfully
2658 *                                 XST_FAILURE - There was an error in the command
2659 *
[4196]2660 ******************************************************************************/
2661void baseband_buffers_config(u8 dram_present){
[4284]2662
[4668]2663    //
2664    //
2665    // NOTE:  For WARPLab 7.5.0, for compatibility reasons, the default tx/rx_num_samples
2666    //     is not tx/rx_max_samples.  For WARPLab 7.5.0, tx/rx_num_samples will be the
2667    //     same as WARPLab 7.4.0 (ie WL_BUF_DEFAULT_RX_NUM_SAMPLES / WL_BUF_DEFAULT_TX_NUM_SAMPLES)
2668    //
2669    //
[4284]2670
[4668]2671    u32  rx_max_samples;
2672    u32  tx_max_samples;
[4196]2673
[4668]2674    u32  tx_num_samples;
2675    u32  rx_num_samples;
[4196]2676
[4668]2677    wl_printf(WL_PRINT_NONE, NULL, "Configuring baseband ...\n");
[4196]2678
[4668]2679    // Set the number of samples and sample buffers based on if the DRAM is present
2680    if (dram_present) {
2681        wl_printf(WL_PRINT_NONE, NULL, "  Using DDR for buffers\n");
[4196]2682
[4668]2683        use_dram_for_buffers = 1;
[4196]2684
[4668]2685        // DDR Buffer Allocation
2686        //     See defines in wl_baseband.h for DDR buffer allocations
2687        //
2688        rx_max_samples       = WL_BUF_DEFAULT_RX_MAX_SAMPLES;
2689        tx_max_samples       = WL_BUF_DEFAULT_TX_MAX_SAMPLES;
[4196]2690
[4668]2691        rx_num_samples       = WL_BUF_DEFAULT_RX_NUM_SAMPLES;
2692        tx_num_samples       = WL_BUF_DEFAULT_TX_NUM_SAMPLES;
[4196]2693
[4668]2694        wl_bb_set_rf_rx_iq_threshold(WL_BUF_RX_TRANSFER_THRESHOLD_SAMPLES);
2695        wl_bb_set_rf_tx_iq_threshold(WL_BUF_TX_TRANSFER_THRESHOLD_SAMPLES);
[4196]2696
[4668]2697        wl_iq_rx_buff_a      = (void *) WL_BUF_DEFAULT_IQ_RX_BUF_A_ADDR;
2698        wl_iq_tx_buff_a      = (void *) WL_BUF_DEFAULT_IQ_TX_BUF_A_ADDR;
2699        wl_rssi_buff_a       = (void *) WL_BUF_DEFAULT_RSSI_BUF_A_ADDR;
2700        wl_iq_rx_buff_a_size = (u32)    WL_BUF_DEFAULT_IQ_RX_BUF_A_SIZE;
2701        wl_iq_tx_buff_a_size = (u32)    WL_BUF_DEFAULT_IQ_TX_BUF_A_SIZE;
2702        wl_rssi_buff_a_size  = (u32)    WL_BUF_DEFAULT_RSSI_BUF_A_SIZE;
[4196]2703
[4668]2704        wl_iq_rx_buff_b      = (void *) WL_BUF_DEFAULT_IQ_RX_BUF_B_ADDR;
2705        wl_iq_tx_buff_b      = (void *) WL_BUF_DEFAULT_IQ_TX_BUF_B_ADDR;
2706        wl_rssi_buff_b       = (void *) WL_BUF_DEFAULT_RSSI_BUF_B_ADDR;
2707        wl_iq_rx_buff_b_size = (u32)    WL_BUF_DEFAULT_IQ_RX_BUF_B_SIZE;
2708        wl_iq_tx_buff_b_size = (u32)    WL_BUF_DEFAULT_IQ_TX_BUF_B_SIZE;
2709        wl_rssi_buff_b_size  = (u32)    WL_BUF_DEFAULT_RSSI_BUF_B_SIZE;
[4196]2710
[4668]2711        wl_iq_rx_buff_c      = (void *) WL_BUF_DEFAULT_IQ_RX_BUF_C_ADDR;
2712        wl_iq_tx_buff_c      = (void *) WL_BUF_DEFAULT_IQ_TX_BUF_C_ADDR;
2713        wl_rssi_buff_c       = (void *) WL_BUF_DEFAULT_RSSI_BUF_C_ADDR;
2714        wl_iq_rx_buff_c_size = (u32)    WL_BUF_DEFAULT_IQ_RX_BUF_C_SIZE;
2715        wl_iq_tx_buff_c_size = (u32)    WL_BUF_DEFAULT_IQ_TX_BUF_C_SIZE;
2716        wl_rssi_buff_c_size  = (u32)    WL_BUF_DEFAULT_RSSI_BUF_C_SIZE;
[4196]2717
[4668]2718        wl_iq_rx_buff_d      = (void *) WL_BUF_DEFAULT_IQ_RX_BUF_D_ADDR;
2719        wl_iq_tx_buff_d      = (void *) WL_BUF_DEFAULT_IQ_TX_BUF_D_ADDR;
2720        wl_rssi_buff_d       = (void *) WL_BUF_DEFAULT_RSSI_BUF_D_ADDR;
2721        wl_iq_rx_buff_d_size = (u32)    WL_BUF_DEFAULT_IQ_RX_BUF_D_SIZE;
2722        wl_iq_tx_buff_d_size = (u32)    WL_BUF_DEFAULT_IQ_TX_BUF_D_SIZE;
2723        wl_rssi_buff_d_size  = (u32)    WL_BUF_DEFAULT_RSSI_BUF_D_SIZE;
[4234]2724
[4668]2725    } else {
2726        wl_printf(WL_PRINT_NONE, NULL, "  Using BRAM for buffers\n");
[4196]2727
[4668]2728        use_dram_for_buffers = 0;
[4196]2729
[4668]2730        // BRAM Buffer Allocation
2731        //     See defines in wl_baseband.h for BRAM buffer allocations
2732        //
2733        rx_max_samples       = WL_BUF_DEFAULT_RX_NUM_SAMPLES;
2734        tx_max_samples       = WL_BUF_DEFAULT_TX_NUM_SAMPLES;
[4284]2735
[4668]2736        rx_num_samples       = WL_BUF_DEFAULT_RX_NUM_SAMPLES;
2737        tx_num_samples       = WL_BUF_DEFAULT_TX_NUM_SAMPLES;
[4284]2738
[4668]2739        // Set the threshold after the end of the buffer
2740        wl_bb_set_rf_rx_iq_threshold(rx_num_samples + 1);
2741        wl_bb_set_rf_tx_iq_threshold(tx_num_samples + 1);
[4196]2742
[4668]2743        wl_iq_rx_buff_a      = (void *) WARPLAB_IQ_RX_BUF_A;
2744        wl_iq_tx_buff_a      = (void *) WARPLAB_IQ_TX_BUF_A;
2745        wl_rssi_buff_a       = (void *) WARPLAB_RSSI_BUF_A;
2746        wl_iq_rx_buff_a_size = (u32)    WARPLAB_IQ_RX_BUF_SIZE;
2747        wl_iq_tx_buff_a_size = (u32)    WARPLAB_IQ_TX_BUF_SIZE;
2748        wl_rssi_buff_a_size  = (u32)    WARPLAB_RSSI_BUF_SIZE;
[4196]2749
[4668]2750        wl_iq_rx_buff_b      = (void *) WARPLAB_IQ_RX_BUF_B;
2751        wl_iq_tx_buff_b      = (void *) WARPLAB_IQ_TX_BUF_B;
2752        wl_rssi_buff_b       = (void *) WARPLAB_RSSI_BUF_B;
2753        wl_iq_rx_buff_b_size = (u32)    WARPLAB_IQ_RX_BUF_SIZE;
2754        wl_iq_tx_buff_b_size = (u32)    WARPLAB_IQ_TX_BUF_SIZE;
2755        wl_rssi_buff_b_size  = (u32)    WARPLAB_RSSI_BUF_SIZE;
[4196]2756
[4668]2757        wl_iq_rx_buff_c      = (void *) WARPLAB_IQ_RX_BUF_C;
2758        wl_iq_tx_buff_c      = (void *) WARPLAB_IQ_TX_BUF_C;
2759        wl_rssi_buff_c       = (void *) WARPLAB_RSSI_BUF_C;
2760        wl_iq_rx_buff_c_size = (u32)    WARPLAB_IQ_RX_BUF_SIZE;
2761        wl_iq_tx_buff_c_size = (u32)    WARPLAB_IQ_TX_BUF_SIZE;
2762        wl_rssi_buff_c_size  = (u32)    WARPLAB_RSSI_BUF_SIZE;
[4196]2763
[4668]2764        wl_iq_rx_buff_d      = (void *) WARPLAB_IQ_RX_BUF_D;
2765        wl_iq_tx_buff_d      = (void *) WARPLAB_IQ_TX_BUF_D;
2766        wl_rssi_buff_d       = (void *) WARPLAB_RSSI_BUF_D;
2767        wl_iq_rx_buff_d_size = (u32)    WARPLAB_IQ_RX_BUF_SIZE;
2768        wl_iq_tx_buff_d_size = (u32)    WARPLAB_IQ_TX_BUF_SIZE;
2769        wl_rssi_buff_d_size  = (u32)    WARPLAB_RSSI_BUF_SIZE;
[4453]2770    }
[2149]2771
[4668]2772    wl_printf(WL_PRINT_NONE, NULL, "  Rx samples:  %10d (%10d max)\n", (rx_num_samples + 1), (rx_max_samples + 1));
2773    wl_printf(WL_PRINT_NONE, NULL, "  Tx samples:  %10d (%10d max)\n", (tx_num_samples + 1), (tx_max_samples + 1));
[4333]2774
[4668]2775    // Set the TX/RX supported length global variables based on the maximum number of samples
2776    supported_tx_length = tx_max_samples;
2777    supported_rx_length = rx_max_samples;
[4196]2778
[4668]2779    // Set the TX/RX length based on the number of samples
2780    //    NOTE:  This is for backward compatibility with WARPLab 7.4.0
2781    //
2782    wl_bb_set_tx_length(tx_num_samples);
2783    wl_bb_set_rx_length(rx_num_samples);
[4196]2784
[4668]2785    // Set the global variable of the RX buffer size (in bytes) based on the number of samples
2786    rx_buffer_size = (rx_num_samples + 1) << 2;
[4196]2787
[4668]2788    // NOTE:  This can be used to generate a known data stream in the RX buffers that
2789    //    can be used to debug higher level SW issues with the RX buffers.
[4453]2790    //
2791    if (USE_GENERATED_RX_DATA) {
[4668]2792        wl_bb_set_config(WL_BUF_REG_CONFIG_COUNTER_DATA_SEL);
2793        wl_printf(WL_PRINT_NONE, NULL, "  Using fake counter data\n");
[4453]2794    }
2795
[4668]2796    // NOTE:  This can be used to directly loopback the TX data to the RX buffer to
2797    //    debug higher level software issues with the TX buffers.  This only affects
2798    //    IQ data and not RSSI data (ie IQ samples that are actually received are
2799    //    ignored but received RSSI data is captured normally).  Also, the loopback
2800    //    mode will only connect RFA -> RFB and RFC -> RFD.  This means that data
2801    //    transmitted on RFA will be received on RFB and vice versa.  Similarly, RFC
2802    //    and RFD are connected but due to timing considerations, we did not allow the
2803    //    full crossbar of RF interfaces for loopback data.
2804    //
2805    // NOTE:  USE_TX_RX_LOOPBACK mode has higher precedence than USE_GENERATED_RX_DATA
2806    //
2807    if (USE_TX_RX_LOOPBACK) {
2808        wl_bb_set_config(WL_BUF_REG_CONFIG_TX_RX_LOOPBACK_SEL);
2809        wl_printf(WL_PRINT_NONE, NULL, "  Using TX -> RX Loopback\n");
2810    }
[4328]2811
[4453]2812#ifdef _DEBUG_
[4668]2813    print_buffer_info();
[4453]2814#endif
[1915]2815}
2816
[4184]2817
[1915]2818
[4673]2819/*****************************************************************************/
2820/**
2821 * @brief Check Baseband Parameters
2822 *
2823 * @param   None
2824 *
2825 * @return  int              - Status of the command:
2826 *                                 XST_SUCCESS - Command completed successfully
2827 *                                 XST_FAILURE - There was an error in the command
2828 *
2829 ******************************************************************************/
2830int baseband_check_parameters() {
2831    u32  status         = XST_SUCCESS;
2832    u32  bd_count;
2833
2834    // Check that the number of Transmit Buffer Descriptors (TX BDs) is less that or
2835    // equal to 2x the number of Ethernet Header buffers.
2836    //
2837    bd_count = eth_get_num_tx_descriptors();
2838
2839    if (bd_count > (2 * WL_BASEBAND_ETH_NUM_BUFFER)){
2840        wl_printf(WL_PRINT_ERROR, print_type_baseband, "ERROR: Not enough Ethernet Buffers to support %d TX BDs for Read IQ command!\n", bd_count);
2841
2842        status = XST_FAILURE;
2843    }
2844
2845    return status;
2846}
2847
2848
Note: See TracBrowser for help on using the repository browser.