[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] | 61 | static u32 write_iq_checksum_lsb = 0; |
---|
| 62 | static u32 write_iq_checksum_msb = 0; |
---|
[2919] | 63 | |
---|
[4196] | 64 | // Buffer variables |
---|
| 65 | static u32 rx_buffer_size; |
---|
[4234] | 66 | static u32 use_dram_for_buffers = 0; |
---|
[2919] | 67 | |
---|
[4196] | 68 | static void * wl_iq_rx_buff_a; |
---|
| 69 | static void * wl_iq_tx_buff_a; |
---|
| 70 | static void * wl_rssi_buff_a; |
---|
[1915] | 71 | |
---|
[4196] | 72 | static u32 wl_iq_rx_buff_a_size; |
---|
| 73 | static u32 wl_iq_tx_buff_a_size; |
---|
| 74 | static u32 wl_rssi_buff_a_size; |
---|
[1915] | 75 | |
---|
[4196] | 76 | static void * wl_iq_rx_buff_b; |
---|
| 77 | static void * wl_iq_tx_buff_b; |
---|
| 78 | static void * wl_rssi_buff_b; |
---|
[2919] | 79 | |
---|
[4196] | 80 | static u32 wl_iq_rx_buff_b_size; |
---|
| 81 | static u32 wl_iq_tx_buff_b_size; |
---|
| 82 | static u32 wl_rssi_buff_b_size; |
---|
| 83 | |
---|
| 84 | static void * wl_iq_rx_buff_c; |
---|
| 85 | static void * wl_iq_tx_buff_c; |
---|
| 86 | static void * wl_rssi_buff_c; |
---|
| 87 | |
---|
| 88 | static u32 wl_iq_rx_buff_c_size; |
---|
| 89 | static u32 wl_iq_tx_buff_c_size; |
---|
| 90 | static u32 wl_rssi_buff_c_size; |
---|
| 91 | |
---|
| 92 | static void * wl_iq_rx_buff_d; |
---|
| 93 | static void * wl_iq_tx_buff_d; |
---|
| 94 | static void * wl_rssi_buff_d; |
---|
| 95 | |
---|
| 96 | static u32 wl_iq_rx_buff_d_size; |
---|
| 97 | static u32 wl_iq_tx_buff_d_size; |
---|
| 98 | static u32 wl_rssi_buff_d_size; |
---|
| 99 | |
---|
[4284] | 100 | static u32 supported_tx_length = 0xFFFFFFFF; |
---|
| 101 | static u32 supported_rx_length = 0xFFFFFFFF; |
---|
[4196] | 102 | |
---|
[4707] | 103 | // Bit counting vector |
---|
| 104 | const 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 | // |
---|
| 172 | u8 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] | 177 | void read_rx_buffers(u32 cmd_id, u32 buffer_sel, u32 offset, u32 length, u32 dest_addr, warp_ip_udp_buffer * buffer); |
---|
[4234] | 178 | void 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 |
---|
| 181 | void baseband_hw_specific_reset(); |
---|
| 182 | void baseband_transfer_data(u32 src_addr, u32 dest_addr, u32 length); |
---|
[4234] | 183 | void populate_tmp_tx_buffers(u32 buffer_sel, u32 offset, u32 length); |
---|
[4453] | 184 | void baseband_buffers_config(u8 dram_present); |
---|
[4673] | 185 | int baseband_check_parameters(); |
---|
[4196] | 186 | |
---|
[4811] | 187 | // Misc functions |
---|
| 188 | u32 get_buffer_counter(u32 txrx_sel, u32 buffer_sel); |
---|
| 189 | |
---|
[4668] | 190 | // Read IQ transport functions |
---|
| 191 | void 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] | 195 | void print_buffer_info(); |
---|
| 196 | void print_buffer_core_registers(); |
---|
| 197 | void 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 | ******************************************************************************/ |
---|
| 224 | int 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 | *****************************************************************************/ |
---|
| 1778 | void 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] | 1878 | void 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 | ******************************************************************************/ |
---|
| 1956 | void 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] | 2020 | u32 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] | 2029 | u32 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 | ******************************************************************************/ |
---|
| 2052 | int 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 | ******************************************************************************/ |
---|
| 2083 | u32 baseband_get_checksum() { |
---|
[4668] | 2084 | return ((write_iq_checksum_msb << 16) + write_iq_checksum_lsb); |
---|
[4453] | 2085 | } |
---|
| 2086 | |
---|
| 2087 | |
---|
| 2088 | u32 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 | ******************************************************************************/ |
---|
| 2116 | u32 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 | ******************************************************************************/ |
---|
| 2160 | u32 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 | ******************************************************************************/ |
---|
| 2189 | void 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] | 2243 | void 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 | |
---|
| 2254 | void 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] | 2265 | void 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] | 2303 | void wl_buffers_core_rx_int_handler(void *InstancePtr); |
---|
| 2304 | void 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] | 2322 | void 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] | 2340 | void 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] | 2361 | void 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] | 2411 | int 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] | 2438 | void 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 | ******************************************************************************/ |
---|
| 2581 | void 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 | ******************************************************************************/ |
---|
| 2661 | void 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 | ******************************************************************************/ |
---|
| 2830 | int 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 | |
---|