1 | /** @file wl_baseband.c |
---|
2 | * @brief WARPLab Framework (Baseband) |
---|
3 | * |
---|
4 | * This contains the code for WARPLab Framework. |
---|
5 | * |
---|
6 | * @copyright Copyright 2013-2015, Mango Communications. All rights reserved. |
---|
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 | */ |
---|
13 | |
---|
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 | // |
---|
20 | /******************************* IMPORTANT ***********************************/ |
---|
21 | |
---|
22 | |
---|
23 | |
---|
24 | /**********************************************************************************************************************/ |
---|
25 | /** |
---|
26 | * @brief Common Functions |
---|
27 | * |
---|
28 | **********************************************************************************************************************/ |
---|
29 | |
---|
30 | /***************************** Include Files *********************************/ |
---|
31 | |
---|
32 | // Xilinx / Standard library includes |
---|
33 | #include <stdlib.h> |
---|
34 | #include <stdio.h> |
---|
35 | #include <string.h> |
---|
36 | |
---|
37 | #include <xio.h> |
---|
38 | #include <xparameters.h> |
---|
39 | #include <xil_io.h> |
---|
40 | #include <xil_types.h> |
---|
41 | #include <xstatus.h> |
---|
42 | |
---|
43 | // WARPLab includes |
---|
44 | #include "wl_common.h" |
---|
45 | #include "wl_baseband.h" |
---|
46 | #include "wl_interface.h" |
---|
47 | #include "wl_transport.h" |
---|
48 | #include "wl_node.h" |
---|
49 | #include "wl_trigger_manager.h" |
---|
50 | |
---|
51 | // WARP IP/UPD Library includes |
---|
52 | #include <WARP_ip_udp.h> |
---|
53 | |
---|
54 | /*************************** Constant Definitions ****************************/ |
---|
55 | |
---|
56 | /*********************** Global Variable Definitions *************************/ |
---|
57 | |
---|
58 | /*************************** Variable Definitions ****************************/ |
---|
59 | |
---|
60 | // Fletcher-32 Checksum variables |
---|
61 | static u32 write_iq_checksum_lsb = 0; |
---|
62 | static u32 write_iq_checksum_msb = 0; |
---|
63 | |
---|
64 | // Buffer variables |
---|
65 | static u32 rx_buffer_size; |
---|
66 | static u32 use_dram_for_buffers = 0; |
---|
67 | |
---|
68 | static void * wl_iq_rx_buff_a; |
---|
69 | static void * wl_iq_tx_buff_a; |
---|
70 | static void * wl_rssi_buff_a; |
---|
71 | |
---|
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; |
---|
75 | |
---|
76 | static void * wl_iq_rx_buff_b; |
---|
77 | static void * wl_iq_tx_buff_b; |
---|
78 | static void * wl_rssi_buff_b; |
---|
79 | |
---|
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 | |
---|
100 | static u32 supported_tx_length = 0xFFFFFFFF; |
---|
101 | static u32 supported_rx_length = 0xFFFFFFFF; |
---|
102 | |
---|
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}; |
---|
105 | |
---|
106 | |
---|
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 | |
---|
175 | /*************************** Functions Prototypes ****************************/ |
---|
176 | |
---|
177 | void read_rx_buffers(u32 cmd_id, u32 buffer_sel, u32 offset, u32 length, u32 dest_addr, warp_ip_udp_buffer * buffer); |
---|
178 | void write_tx_buffers(u32 buffer_sel, u32 src_addr, u32 offset, u32 length); |
---|
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); |
---|
183 | void populate_tmp_tx_buffers(u32 buffer_sel, u32 offset, u32 length); |
---|
184 | void baseband_buffers_config(u8 dram_present); |
---|
185 | int baseband_check_parameters(); |
---|
186 | |
---|
187 | // Misc functions |
---|
188 | u32 get_buffer_counter(u32 txrx_sel, u32 buffer_sel); |
---|
189 | |
---|
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 | |
---|
193 | // Debug functions |
---|
194 | #ifdef _DEBUG_ |
---|
195 | void print_buffer_info(); |
---|
196 | void print_buffer_core_registers(); |
---|
197 | void print_agc_registers(); |
---|
198 | #endif |
---|
199 | |
---|
200 | |
---|
201 | /******************************** Functions **********************************/ |
---|
202 | |
---|
203 | /*****************************************************************************/ |
---|
204 | /** |
---|
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 | * |
---|
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 |
---|
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) { |
---|
225 | |
---|
226 | // |
---|
227 | // IMPORTANT ENDIAN NOTES: |
---|
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 | // |
---|
235 | |
---|
236 | // Standard variables |
---|
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 |
---|
248 | u32 status; |
---|
249 | u32 msg_cmd; |
---|
250 | |
---|
251 | u32 i; |
---|
252 | u32 tx_delay; |
---|
253 | u32 sample_length; |
---|
254 | u32 byte_length; |
---|
255 | u32 mode; |
---|
256 | u32 rf_sel, buff_sel, txrx_sel; |
---|
257 | u32 buff_enable; |
---|
258 | u32 buff_counter; |
---|
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; |
---|
262 | |
---|
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) |
---|
280 | |
---|
281 | u32 temp; |
---|
282 | u32 temp_offset; |
---|
283 | u32 temp_status; |
---|
284 | u32 temp_threshold; |
---|
285 | u32 threshold; |
---|
286 | u32 check_status; |
---|
287 | u32 raw_status; |
---|
288 | |
---|
289 | u32 curr_checksum; |
---|
290 | u32 checksum_input_32; |
---|
291 | u16 checksum_input_16; |
---|
292 | |
---|
293 | u8 flags; |
---|
294 | void * samp_addr; |
---|
295 | u32 * samp_addr_32; |
---|
296 | wl_bb_samp_hdr * samp_hdr; |
---|
297 | |
---|
298 | u16 agc_target; |
---|
299 | u32 agc_dco_enable; |
---|
300 | |
---|
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 | |
---|
319 | u32 dest_addr; |
---|
320 | |
---|
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 | |
---|
330 | // Process the command |
---|
331 | switch(cmd_id){ |
---|
332 | |
---|
333 | //--------------------------------------------------------------------- |
---|
334 | case CMDID_BASEBAND_TX_DELAY: |
---|
335 | // Get / Set the TX Delay |
---|
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]); |
---|
348 | |
---|
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; |
---|
354 | |
---|
355 | case CMD_PARAM_READ_VAL: |
---|
356 | break; |
---|
357 | |
---|
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 | } |
---|
363 | |
---|
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()); |
---|
367 | |
---|
368 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
369 | resp_hdr->num_args = resp_index; |
---|
370 | break; |
---|
371 | |
---|
372 | |
---|
373 | //--------------------------------------------------------------------- |
---|
374 | case CMDID_BASEBAND_TX_LENGTH: |
---|
375 | // Get / Set the TX Length |
---|
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]); |
---|
388 | |
---|
389 | switch (msg_cmd) { |
---|
390 | case CMD_PARAM_WRITE_VAL: |
---|
391 | sample_length = Xil_Ntohl(cmd_args_32[1]); |
---|
392 | |
---|
393 | // Check that the length is supported |
---|
394 | if (sample_length != 0) { |
---|
395 | sample_length -= 1; // Adjust sample length for buffers core |
---|
396 | |
---|
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); |
---|
400 | |
---|
401 | sample_length = supported_tx_length; |
---|
402 | } |
---|
403 | } |
---|
404 | |
---|
405 | wl_bb_set_tx_length(sample_length); |
---|
406 | break; |
---|
407 | |
---|
408 | case CMD_PARAM_READ_VAL: |
---|
409 | break; |
---|
410 | |
---|
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 | } |
---|
416 | |
---|
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); |
---|
420 | |
---|
421 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
422 | resp_hdr->num_args = resp_index; |
---|
423 | break; |
---|
424 | |
---|
425 | |
---|
426 | //--------------------------------------------------------------------- |
---|
427 | case CMDID_BASEBAND_RX_LENGTH: |
---|
428 | // Get / Set the RX Length |
---|
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]); |
---|
441 | |
---|
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); |
---|
446 | |
---|
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); |
---|
452 | |
---|
453 | sample_length = supported_rx_length; |
---|
454 | } |
---|
455 | |
---|
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; |
---|
458 | |
---|
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 | } |
---|
465 | |
---|
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 | // |
---|
475 | |
---|
476 | // Get the current RX IQ threshold value |
---|
477 | threshold = wl_bb_get_rf_rx_iq_threshold(); |
---|
478 | |
---|
479 | if (sample_length > threshold) { |
---|
480 | // Align the length the transfer threshold |
---|
481 | temp = sample_length & WL_BUF_RX_SAMPLE_ALIGNMENT_MASK; |
---|
482 | |
---|
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 | } |
---|
490 | |
---|
491 | // Set the Rx length in the buffers core to new value |
---|
492 | wl_bb_set_rx_length(temp - 1); |
---|
493 | |
---|
494 | // Update the AGC rx length |
---|
495 | warplab_set_agc_rx_length(temp + 100); |
---|
496 | |
---|
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; |
---|
502 | |
---|
503 | case CMD_PARAM_READ_VAL: |
---|
504 | break; |
---|
505 | |
---|
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 | } |
---|
511 | |
---|
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); |
---|
515 | |
---|
516 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
517 | resp_hdr->num_args = resp_index; |
---|
518 | break; |
---|
519 | |
---|
520 | |
---|
521 | //--------------------------------------------------------------------- |
---|
522 | case CMDID_BASEBAND_MAX_NUM_SAMPLES: |
---|
523 | // Get the maximum number of samples for a given RF interface |
---|
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 | // |
---|
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 | // |
---|
540 | status = CMD_PARAM_SUCCESS; |
---|
541 | msg_cmd = Xil_Ntohl(cmd_args_32[0]); |
---|
542 | |
---|
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; |
---|
548 | |
---|
549 | case CMD_PARAM_READ_VAL: |
---|
550 | break; |
---|
551 | |
---|
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 | } |
---|
557 | |
---|
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); |
---|
562 | |
---|
563 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
564 | resp_hdr->num_args = resp_index; |
---|
565 | break; |
---|
566 | |
---|
567 | |
---|
568 | //--------------------------------------------------------------------- |
---|
569 | case CMDID_BASEBAND_TX_MODE: |
---|
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]); |
---|
578 | |
---|
579 | if(mode) { |
---|
580 | sample_length = wl_bb_get_tx_length() + 1; |
---|
581 | |
---|
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 | } |
---|
586 | |
---|
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; |
---|
592 | |
---|
593 | |
---|
594 | //--------------------------------------------------------------------- |
---|
595 | case CMDID_BASEBAND_TX_BUFF_EN: |
---|
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 | // |
---|
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 | // |
---|
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 | } |
---|
623 | |
---|
624 | // Enable the selected buffers in the WARPLab Buffers core |
---|
625 | wl_bb_set_tx_buffer_en(buff_sel); |
---|
626 | |
---|
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 | |
---|
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; |
---|
639 | |
---|
640 | |
---|
641 | //--------------------------------------------------------------------- |
---|
642 | case CMDID_BASEBAND_RX_BUFF_EN: |
---|
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 | // |
---|
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 | // |
---|
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 | } |
---|
670 | |
---|
671 | // Enable the selected buffers in the WARPLab Buffers core |
---|
672 | wl_bb_set_rx_buffer_en(buff_sel); |
---|
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); |
---|
682 | break; |
---|
683 | |
---|
684 | |
---|
685 | //--------------------------------------------------------------------- |
---|
686 | case CMDID_BASEBAND_TXRX_BUFF_DIS: |
---|
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 | } |
---|
710 | |
---|
711 | wl_bb_clear_tx_buffer_en(buff_sel); |
---|
712 | wl_bb_clear_rx_buffer_en(buff_sel); |
---|
713 | |
---|
714 | // Return all disabled buffers to their default state |
---|
715 | populate_tmp_tx_buffers(buff_sel, 0x0, WARPLAB_IQ_TX_BUF_SIZE); |
---|
716 | break; |
---|
717 | |
---|
718 | |
---|
719 | //--------------------------------------------------------------------- |
---|
720 | case CMDID_BASEBAND_TXRX_BUFF_STATE: |
---|
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 |
---|
729 | // |
---|
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 | // |
---|
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. |
---|
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 | //--------------------------------------------------------------------- |
---|
784 | case CMDID_BASEBAND_WRITE_IQ: |
---|
785 | // BB_WRITE_IQ Packet Format: |
---|
786 | // |
---|
787 | // - cmd_args - Samples: wl_bb_samp_hdr followed by the |
---|
788 | // defined number of samples. |
---|
789 | // |
---|
790 | // - resp_args_32[0] - Status |
---|
791 | // - CMD_PARAM_SUCCESS |
---|
792 | // - SAMPLE_HDR_FLAG_IQ_NOT_READY |
---|
793 | // - SAMPLE_HDR_FLAG_IQ_ERROR |
---|
794 | // - resp_args_32[1] - IQ ID |
---|
795 | // - resp_args_32[2] - Current checksum (ignore if Status != CMD_PARAM_SUCCESS) |
---|
796 | // - resp_args_32[3] - Tx status (ignore if Status != SAMPLE_HDR_FLAG_IQ_NOT_READY) |
---|
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) |
---|
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; |
---|
811 | |
---|
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); |
---|
819 | |
---|
820 | // |
---|
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. |
---|
832 | // |
---|
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 |
---|
836 | temp_status = (raw_status & WL_BUF_REG_STATUS_TX_RUNNING); // Current TX status |
---|
837 | |
---|
838 | // Check size of packet |
---|
839 | if (num_samp < 400) { |
---|
840 | // Number of samples is for a non-jumbo frame (approx 400 samples); process the Write IQ command |
---|
841 | check_status = 1; |
---|
842 | |
---|
843 | } else { |
---|
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; |
---|
859 | |
---|
860 | } else { |
---|
861 | if (one_bits[temp_status] > 2) { |
---|
862 | // Write IQ process is running for more than two buffers, tell host to wait |
---|
863 | status = 1; |
---|
864 | |
---|
865 | } else { |
---|
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; |
---|
868 | |
---|
869 | } |
---|
870 | } |
---|
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 | |
---|
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) { |
---|
897 | |
---|
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 |
---|
902 | |
---|
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 | } |
---|
915 | |
---|
916 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
917 | resp_hdr->num_args = resp_index; |
---|
918 | |
---|
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); |
---|
927 | |
---|
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); |
---|
935 | |
---|
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; |
---|
942 | |
---|
943 | write_tx_buffers(buff_sel, (u32)(samp_addr), offset, samp_len); |
---|
944 | |
---|
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 | // |
---|
952 | if (flags & SAMPLE_HDR_FLAG_LAST_WRITE) { |
---|
953 | |
---|
954 | populate_tmp_tx_buffers(((~wl_bb_get_tx_status()) & buff_sel), 0x0, WARPLAB_IQ_TX_BUF_SIZE); |
---|
955 | } |
---|
956 | } |
---|
957 | break; |
---|
958 | |
---|
959 | |
---|
960 | //--------------------------------------------------------------------- |
---|
961 | case CMDID_BASEBAND_WRITE_IQ_CHECKSUM: |
---|
962 | // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "Get Write IQ checksum\n"); |
---|
963 | |
---|
964 | resp_args_32[resp_index++] = Xil_Htonl(baseband_get_checksum()); |
---|
965 | |
---|
966 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
967 | resp_hdr->num_args = resp_index; |
---|
968 | break; |
---|
969 | |
---|
970 | |
---|
971 | //--------------------------------------------------------------------- |
---|
972 | case CMDID_BASEBAND_READ_IQ: |
---|
973 | case CMDID_BASEBAND_READ_RSSI: |
---|
974 | // BB_READ_IQ / BB_READ_RSSI Packet Format: |
---|
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 |
---|
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 |
---|
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 | // |
---|
1002 | |
---|
1003 | // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "Read IQ\n"); |
---|
1004 | |
---|
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]); |
---|
1011 | |
---|
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 | |
---|
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 |
---|
1026 | |
---|
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)); |
---|
1031 | |
---|
1032 | // |
---|
1033 | // NOTE: We will only allow a read of an IQ buffer that is currently receiving data if the |
---|
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. |
---|
1044 | // |
---|
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); |
---|
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) { |
---|
1059 | |
---|
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); |
---|
1064 | |
---|
1065 | samp_hdr->flags = SAMPLE_HDR_FLAG_IQ_NOT_READY; |
---|
1066 | |
---|
1067 | resp_args_32 = (u32 *)dest_addr; |
---|
1068 | |
---|
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 |
---|
1075 | |
---|
1076 | samp_hdr->sample_iq_id = sample_iq_id; |
---|
1077 | samp_hdr->start_samp = 0; |
---|
1078 | samp_hdr->num_samp = 0; |
---|
1079 | |
---|
1080 | resp_hdr->length = sizeof(wl_bb_samp_hdr) + (resp_index * sizeof(resp_args_32)); |
---|
1081 | resp_hdr->num_args = 1; |
---|
1082 | |
---|
1083 | resp_sent = NODE_NOT_READY; |
---|
1084 | |
---|
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 | // |
---|
1110 | |
---|
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; |
---|
1116 | |
---|
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)]); |
---|
1122 | |
---|
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; |
---|
1128 | |
---|
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; |
---|
1132 | |
---|
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)); |
---|
1136 | |
---|
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); |
---|
1143 | |
---|
1144 | // Initialize header buffer size/length (see above for description) |
---|
1145 | header_buffer.length = total_hdr_length; |
---|
1146 | header_buffer.size = total_hdr_length; |
---|
1147 | |
---|
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 | // |
---|
1154 | |
---|
1155 | // Fill in parts of sample header that do not change between Read IQ packets |
---|
1156 | samp_hdr->buff_sel = (u16)buff_sel; |
---|
1157 | samp_hdr->buff_sel = Xil_Htons(samp_hdr->buff_sel); |
---|
1158 | samp_hdr->sample_iq_id = sample_iq_id; |
---|
1159 | samp_hdr->flags = 0; |
---|
1160 | |
---|
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); |
---|
1164 | |
---|
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); |
---|
1170 | |
---|
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); |
---|
1178 | |
---|
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; |
---|
1186 | |
---|
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; |
---|
1191 | |
---|
1192 | // Process the Read IQ / Read RSSI packets |
---|
1193 | for(i = 0; i < num_pkts; i++){ |
---|
1194 | |
---|
1195 | // Update loop variables |
---|
1196 | header_addr = (u8 *)(((u32)header_base_addr) + header_offset); |
---|
1197 | next_start_samp = curr_samp + max_samp_per_pkt; |
---|
1198 | |
---|
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 | } |
---|
1204 | |
---|
1205 | samp_len = num_samp * sizeof(wl_samp); |
---|
1206 | start_byte = curr_samp * sizeof(wl_samp); |
---|
1207 | data_length = samp_len + header_length; |
---|
1208 | |
---|
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); |
---|
1212 | |
---|
1213 | // Populate response header fields with per packet data |
---|
1214 | resp_hdr->length = Xil_Ntohs(samp_len + sizeof(wl_bb_samp_hdr)); |
---|
1215 | |
---|
1216 | // Populate transport header fields with per packet data |
---|
1217 | wl_header_tx->length = Xil_Htons(data_length + WARP_IP_UDP_DELIM_LEN); |
---|
1218 | |
---|
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); |
---|
1225 | |
---|
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); |
---|
1232 | |
---|
1233 | // Copy the completed header to DMA accessible BRAM |
---|
1234 | memcpy((void *)header_addr, (void *)tmp_header, total_hdr_length); |
---|
1235 | |
---|
1236 | // Set the header buffer data / offset |
---|
1237 | header_buffer.data = (u8 *)header_addr; |
---|
1238 | header_buffer.offset = (u8 *)header_addr; |
---|
1239 | |
---|
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); |
---|
1242 | |
---|
1243 | // Update the green LEDs for every packet sent |
---|
1244 | increment_green_leds_one_hot(); |
---|
1245 | |
---|
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); |
---|
1254 | |
---|
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 | } |
---|
1259 | |
---|
1260 | // Update loop variables |
---|
1261 | curr_samp = next_start_samp; |
---|
1262 | header_offset = (header_offset + WL_BASEBAND_ETH_BUFFER_SIZE) % header_buffer_size; |
---|
1263 | } |
---|
1264 | |
---|
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 | // |
---|
1270 | |
---|
1271 | resp_sent = RESP_SENT; |
---|
1272 | } |
---|
1273 | break; |
---|
1274 | |
---|
1275 | |
---|
1276 | //--------------------------------------------------------------------- |
---|
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: |
---|
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 | // |
---|
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 |
---|
1383 | // return value to transmit the minimal amount of data. |
---|
1384 | // |
---|
1385 | rf_sel = Xil_Ntohl(cmd_args_32[0]); |
---|
1386 | |
---|
1387 | if(rf_sel & AGC_A){ |
---|
1388 | resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_A) + (wl_get_agc_BBG(ANT_A) << 2)); |
---|
1389 | resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfa_agc_done_rssi()); |
---|
1390 | } |
---|
1391 | if(rf_sel & AGC_B){ |
---|
1392 | resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_B) + (wl_get_agc_BBG(ANT_B) << 2)); |
---|
1393 | resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfb_agc_done_rssi()); |
---|
1394 | } |
---|
1395 | if(rf_sel & AGC_C){ |
---|
1396 | resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_C) + (wl_get_agc_BBG(ANT_C) << 2)); |
---|
1397 | resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfc_agc_done_rssi()); |
---|
1398 | } |
---|
1399 | if(rf_sel & AGC_D){ |
---|
1400 | resp_args_32[resp_index++] = Xil_Htonl(wl_get_agc_RFG(ANT_D) + (wl_get_agc_BBG(ANT_D) << 2)); |
---|
1401 | resp_args_32[resp_index++] = Xil_Htonl(wl_bb_get_rfd_agc_done_rssi()); |
---|
1402 | } |
---|
1403 | |
---|
1404 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
1405 | resp_hdr->num_args = resp_index; |
---|
1406 | break; |
---|
1407 | |
---|
1408 | |
---|
1409 | //--------------------------------------------------------------------- |
---|
1410 | case CMDID_BASEBAND_AGC_DONE_ADDR: |
---|
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()); |
---|
1417 | |
---|
1418 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
1419 | resp_hdr->num_args = resp_index; |
---|
1420 | break; |
---|
1421 | |
---|
1422 | |
---|
1423 | //--------------------------------------------------------------------- |
---|
1424 | case CMDID_BASEBAND_AGC_RESET: |
---|
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 | //--------------------------------------------------------------------- |
---|
1434 | case CMDID_BASEBAND_AGC_RESET_MODE: |
---|
1435 | // Get / Set the AGC reset mode |
---|
1436 | // |
---|
1437 | // Message format: |
---|
1438 | // cmd_args_32[0] Command: |
---|
1439 | // - Write (NODE_WRITE_VAL) |
---|
1440 | // - Read (NODE_READ_VAL) |
---|
1441 | // cmd_args_32[1] Enable / Disable reset per rx (Write only) |
---|
1442 | // |
---|
1443 | // Response format: |
---|
1444 | // resp_args_32[0] Status |
---|
1445 | // resp_args_32[1] Value of the reset mode |
---|
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: |
---|
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 | } |
---|
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); |
---|
1470 | resp_args_32[resp_index++] = Xil_Htonl(wl_agc_get_reset_mode()); |
---|
1471 | |
---|
1472 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
1473 | resp_hdr->num_args = resp_index; |
---|
1474 | break; |
---|
1475 | |
---|
1476 | |
---|
1477 | //--------------------------------------------------------------------- |
---|
1478 | case CMDID_BASEBAND_AGC_TARGET: |
---|
1479 | // Set the AGC target |
---|
1480 | // |
---|
1481 | // Message format: |
---|
1482 | // cmd_args_32[0] AGC target |
---|
1483 | // |
---|
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 | //--------------------------------------------------------------------- |
---|
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 | // |
---|
1497 | agc_dco_enable = Xil_Ntohl(cmd_args_32[0]); |
---|
1498 | |
---|
1499 | warplab_agc_enable_DCO(agc_dco_enable); |
---|
1500 | break; |
---|
1501 | |
---|
1502 | |
---|
1503 | //--------------------------------------------------------------------- |
---|
1504 | case CMDID_BASEBAND_AGC_CONFIG: |
---|
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]); |
---|
1520 | |
---|
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 | //--------------------------------------------------------------------- |
---|
1550 | case CMDID_BASEBAND_AGC_IIR_HPF: |
---|
1551 | // Get / Set Infinite Impulse Response (IIR) High Pass Filter (HPF) coefficients |
---|
1552 | // |
---|
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]); |
---|
1567 | |
---|
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; |
---|
1572 | |
---|
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; |
---|
1593 | break; |
---|
1594 | |
---|
1595 | |
---|
1596 | //--------------------------------------------------------------------- |
---|
1597 | case CMDID_BASEBAND_AGC_RF_GAIN_THRESHOLD: |
---|
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]); |
---|
1614 | |
---|
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; |
---|
1639 | break; |
---|
1640 | |
---|
1641 | |
---|
1642 | //--------------------------------------------------------------------- |
---|
1643 | case CMDID_BASEBAND_AGC_TIMING: |
---|
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]); |
---|
1660 | |
---|
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; |
---|
1667 | |
---|
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 | |
---|
1685 | resp_hdr->length += (resp_index * sizeof(resp_args_32)); |
---|
1686 | resp_hdr->num_args = resp_index; |
---|
1687 | break; |
---|
1688 | |
---|
1689 | |
---|
1690 | //--------------------------------------------------------------------- |
---|
1691 | case CMDID_BASEBAND_AGC_DCO_TIMING: |
---|
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]); |
---|
1706 | |
---|
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; |
---|
1711 | |
---|
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; |
---|
1724 | } |
---|
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; |
---|
1731 | break; |
---|
1732 | |
---|
1733 | |
---|
1734 | //--------------------------------------------------------------------- |
---|
1735 | // case BB_DEBUG_TX_OUTPUT_CONFIGURE: |
---|
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; |
---|
1746 | |
---|
1747 | |
---|
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; |
---|
1754 | } |
---|
1755 | |
---|
1756 | |
---|
1757 | |
---|
1758 | /*****************************************************************************/ |
---|
1759 | /** |
---|
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) { |
---|
1779 | |
---|
1780 | u32 src_addr = 0; |
---|
1781 | u32 buffer_size = 0; |
---|
1782 | u32 end_byte = offset + length - 1; |
---|
1783 | |
---|
1784 | // Process Read IQ |
---|
1785 | if(cmd_id == CMDID_BASEBAND_READ_IQ) { |
---|
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); |
---|
1789 | |
---|
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); |
---|
1793 | |
---|
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 | } |
---|
1801 | |
---|
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 | } |
---|
1811 | |
---|
1812 | // Process Read RSSI |
---|
1813 | if(cmd_id == CMDID_BASEBAND_READ_RSSI) { |
---|
1814 | if(buffer_sel & RF_SEL_A) { |
---|
1815 | buffer_size = wl_rssi_buff_a_size; |
---|
1816 | src_addr = (u32)(wl_rssi_buff_a + offset); |
---|
1817 | |
---|
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); |
---|
1821 | |
---|
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 | } |
---|
1829 | |
---|
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 | } |
---|
1839 | |
---|
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 | } |
---|
1857 | } |
---|
1858 | |
---|
1859 | |
---|
1860 | |
---|
1861 | /*****************************************************************************/ |
---|
1862 | /** |
---|
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 | *****************************************************************************/ |
---|
1878 | void write_tx_buffers(u32 buffer_sel, u32 src_addr, u32 offset, u32 length) { |
---|
1879 | |
---|
1880 | u32 dest_addr = 0; |
---|
1881 | u32 end_byte = offset + length - 1; |
---|
1882 | |
---|
1883 | // Process RFA |
---|
1884 | if(buffer_sel & RF_SEL_A) { |
---|
1885 | dest_addr = (u32)(wl_iq_tx_buff_a) + offset; |
---|
1886 | |
---|
1887 | if ( end_byte <= wl_iq_tx_buff_a_size ) { |
---|
1888 | baseband_transfer_data(src_addr, dest_addr, length); |
---|
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 | } |
---|
1894 | |
---|
1895 | // Process RFB |
---|
1896 | if(buffer_sel & RF_SEL_B) { |
---|
1897 | dest_addr = (u32)(wl_iq_tx_buff_b) + offset; |
---|
1898 | |
---|
1899 | if ( end_byte <= wl_iq_tx_buff_b_size ) { |
---|
1900 | baseband_transfer_data(src_addr, dest_addr, length); |
---|
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 | } |
---|
1906 | |
---|
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; |
---|
1911 | |
---|
1912 | if ( end_byte <= wl_iq_tx_buff_c_size ) { |
---|
1913 | baseband_transfer_data(src_addr, dest_addr, length); |
---|
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 | } |
---|
1922 | |
---|
1923 | // Process RFD |
---|
1924 | if(buffer_sel & RF_SEL_D) { |
---|
1925 | if (WARPLAB_CONFIG_4RF) { |
---|
1926 | dest_addr = (u32)(wl_iq_tx_buff_d) + offset; |
---|
1927 | |
---|
1928 | if ( end_byte <= wl_iq_tx_buff_d_size ) { |
---|
1929 | baseband_transfer_data(src_addr, dest_addr, length); |
---|
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 | |
---|
1943 | } |
---|
1944 | |
---|
1945 | |
---|
1946 | |
---|
1947 | /*****************************************************************************/ |
---|
1948 | /** |
---|
1949 | * @brief Baseband reset |
---|
1950 | * |
---|
1951 | * @param None |
---|
1952 | * |
---|
1953 | * @return None |
---|
1954 | * |
---|
1955 | ******************************************************************************/ |
---|
1956 | void baseband_reset(){ |
---|
1957 | // ------------------------------------------ |
---|
1958 | // Reset the global variables |
---|
1959 | // |
---|
1960 | write_iq_checksum_lsb = 0; |
---|
1961 | write_iq_checksum_msb = 0; |
---|
1962 | |
---|
1963 | |
---|
1964 | // ------------------------------------------ |
---|
1965 | // Reset the buffers core |
---|
1966 | // |
---|
1967 | |
---|
1968 | // Perform any HW specific resets |
---|
1969 | baseband_hw_specific_reset(); |
---|
1970 | |
---|
1971 | // Set default config register values |
---|
1972 | wl_bb_clear_config( |
---|
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 | |
---|
1978 | // Set RSSI clock to be 1/4 of the IQ sample clock |
---|
1979 | wl_bb_set_rssi_clk(1); |
---|
1980 | |
---|
1981 | // Set the TX delay to INIT_TX_DELAY |
---|
1982 | wl_bb_set_tx_delay(INIT_TX_DELAY); |
---|
1983 | |
---|
1984 | // Turn off all RX and TX buffers |
---|
1985 | wl_bb_clear_rx_buffer_en(RF_SEL_ALL); |
---|
1986 | wl_bb_clear_tx_buffer_en(RF_SEL_ALL); |
---|
1987 | |
---|
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); |
---|
1994 | |
---|
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); |
---|
2000 | |
---|
2001 | wl_bb_set_rf_tx_iq_buf_wr_byte_offset(WARPLAB_IQ_TX_BUF_SIZE); |
---|
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(); |
---|
2007 | } |
---|
2008 | |
---|
2009 | |
---|
2010 | |
---|
2011 | /*****************************************************************************/ |
---|
2012 | /** |
---|
2013 | * @brief Accessor methods |
---|
2014 | * |
---|
2015 | * @param None |
---|
2016 | * |
---|
2017 | * @return u32 - Value of parameter |
---|
2018 | * |
---|
2019 | ******************************************************************************/ |
---|
2020 | u32 wl_bb_get_supported_tx_length() { |
---|
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 | } |
---|
2027 | } |
---|
2028 | |
---|
2029 | u32 wl_bb_get_supported_rx_length() { |
---|
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 | } |
---|
2036 | } |
---|
2037 | |
---|
2038 | |
---|
2039 | |
---|
2040 | /*****************************************************************************/ |
---|
2041 | /** |
---|
2042 | * @brief Baseband subsystem initialization |
---|
2043 | * |
---|
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 |
---|
2046 | * |
---|
2047 | * @return int - Status of the command: |
---|
2048 | * XST_SUCCESS - Command completed successfully |
---|
2049 | * XST_FAILURE - There was an error in the command |
---|
2050 | * |
---|
2051 | ******************************************************************************/ |
---|
2052 | int baseband_init(u8 dram_present, u8 configure_buffers){ |
---|
2053 | u32 status = XST_SUCCESS; |
---|
2054 | |
---|
2055 | // Configure the sample buffers (if necessary) |
---|
2056 | if (configure_buffers) { |
---|
2057 | baseband_buffers_config(dram_present); |
---|
2058 | } |
---|
2059 | |
---|
2060 | // Initialize the baseband |
---|
2061 | baseband_reset(); |
---|
2062 | |
---|
2063 | // Initialize the AGC core |
---|
2064 | warplab_agc_init(); |
---|
2065 | warplab_agc_reset(); |
---|
2066 | trigger_proc_out1_set_delay(2000); // Configure initial delay for 12.5 us |
---|
2067 | |
---|
2068 | // Check baseband parameters |
---|
2069 | status = baseband_check_parameters(); |
---|
2070 | |
---|
2071 | return status; |
---|
2072 | } |
---|
2073 | |
---|
2074 | |
---|
2075 | |
---|
2076 | /*****************************************************************************/ |
---|
2077 | /** |
---|
2078 | * @brief IQ Checksums |
---|
2079 | * |
---|
2080 | * WARPLab uses the Fletcher-32 checksum algorithm |
---|
2081 | * |
---|
2082 | ******************************************************************************/ |
---|
2083 | u32 baseband_get_checksum() { |
---|
2084 | return ((write_iq_checksum_msb << 16) + write_iq_checksum_lsb); |
---|
2085 | } |
---|
2086 | |
---|
2087 | |
---|
2088 | u32 baseband_update_checksum(u16 newdata, u8 reset ){ |
---|
2089 | // xil_printf("Checksum input: %d, reset: %d\n", newdata, reset); |
---|
2090 | |
---|
2091 | if(reset){ |
---|
2092 | write_iq_checksum_lsb = 0; |
---|
2093 | write_iq_checksum_msb = 0; |
---|
2094 | } |
---|
2095 | |
---|
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; |
---|
2098 | |
---|
2099 | // xil_printf("sum1: %d sum2: %d\n", write_iq_checksum_lsb, write_iq_checksum_msb); |
---|
2100 | |
---|
2101 | return baseband_get_checksum(); |
---|
2102 | } |
---|
2103 | |
---|
2104 | |
---|
2105 | |
---|
2106 | /*****************************************************************************/ |
---|
2107 | /** |
---|
2108 | * @brief Get the selected buffer's buffer size |
---|
2109 | * |
---|
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 |
---|
2112 | * |
---|
2113 | * @return u32 - Buffer Size |
---|
2114 | * |
---|
2115 | ******************************************************************************/ |
---|
2116 | u32 get_buffer_size(u32 cmd_id, u32 buffer_sel) { |
---|
2117 | |
---|
2118 | u32 buffer_size = 0; |
---|
2119 | |
---|
2120 | switch(cmd_id) { |
---|
2121 | case CMDID_BASEBAND_WRITE_IQ: |
---|
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; } |
---|
2126 | break; |
---|
2127 | |
---|
2128 | case CMDID_BASEBAND_READ_IQ: |
---|
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; } |
---|
2133 | break; |
---|
2134 | |
---|
2135 | case CMDID_BASEBAND_READ_RSSI: |
---|
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; } |
---|
2140 | break; |
---|
2141 | } |
---|
2142 | |
---|
2143 | return buffer_size; |
---|
2144 | } |
---|
2145 | |
---|
2146 | |
---|
2147 | |
---|
2148 | /*****************************************************************************/ |
---|
2149 | /** |
---|
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 | /** |
---|
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(){ |
---|
2190 | // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "AGC init\n"); |
---|
2191 | |
---|
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 |
---|
2195 | |
---|
2196 | // Post Rx_done reset delays for [rxhp, g_rf, g_bb] |
---|
2197 | wl_agc_set_reset_timing(4, 250, 250); |
---|
2198 | |
---|
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 | // |
---|
2205 | wl_agc_set_config_all((256 - 56), (256 - 37), 2, 4, 24); |
---|
2206 | |
---|
2207 | // AGC RSSI->Rx power offsets |
---|
2208 | wl_agc_set_RSSI_pwr_calib(100, 79, 70); |
---|
2209 | |
---|
2210 | // AGC timing: capt_rssi_1, capt_rssi_2, capt_v_db, agc_done |
---|
2211 | wl_agc_set_AGC_timing(1, 60, 180, 192); |
---|
2212 | |
---|
2213 | // AGC timing: start_dco, en_iir_filt |
---|
2214 | wl_agc_set_DCO_timing(100, (100 + 34)); |
---|
2215 | |
---|
2216 | // AGC target output power (log scale) |
---|
2217 | wl_agc_set_target((64 - 13)); |
---|
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 |
---|
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 | // |
---|
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 | |
---|
2230 | // Enable the "reset per rx" mode |
---|
2231 | wl_agc_enable_reset_per_rx(); |
---|
2232 | |
---|
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 | |
---|
2236 | // AGC is now reset and enabled, ready to go! |
---|
2237 | |
---|
2238 | // Override the AGC functionality |
---|
2239 | // wl_agc_set_override(0x00008080); |
---|
2240 | } |
---|
2241 | |
---|
2242 | |
---|
2243 | void warplab_agc_enable_DCO(u32 enable){ |
---|
2244 | // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "AGC set DCO\n"); |
---|
2245 | |
---|
2246 | // Enables DCO and DCO subtraction (correction scheme and butterworth hipass are active) |
---|
2247 | if(enable) |
---|
2248 | wl_agc_set_DCO_timing(100, (100+34)); |
---|
2249 | else |
---|
2250 | wl_agc_set_DCO_timing(255, 255); |
---|
2251 | } |
---|
2252 | |
---|
2253 | |
---|
2254 | void warplab_agc_reset(){ |
---|
2255 | // wl_printf(WL_PRINT_DEBUG, print_type_baseband, "AGC reset\n"); |
---|
2256 | |
---|
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); |
---|
2262 | } |
---|
2263 | |
---|
2264 | |
---|
2265 | void warplab_set_agc_rx_length(u32 num_samples) { |
---|
2266 | |
---|
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 | } |
---|
2275 | |
---|
2276 | return; |
---|
2277 | } |
---|
2278 | |
---|
2279 | |
---|
2280 | |
---|
2281 | |
---|
2282 | |
---|
2283 | |
---|
2284 | |
---|
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 | |
---|
2303 | void wl_buffers_core_rx_int_handler(void *InstancePtr); |
---|
2304 | void wl_buffers_core_tx_int_handler(void *InstancePtr); |
---|
2305 | |
---|
2306 | |
---|
2307 | /******************************** Functions **********************************/ |
---|
2308 | |
---|
2309 | /*****************************************************************************/ |
---|
2310 | /** |
---|
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 | *****************************************************************************/ |
---|
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 | /** |
---|
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 | *****************************************************************************/ |
---|
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 | /** |
---|
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 | *****************************************************************************/ |
---|
2361 | void populate_tmp_tx_buffers(u32 buffer_sel, u32 offset, u32 length) { |
---|
2362 | |
---|
2363 | u32 src_addr; |
---|
2364 | u32 dest_addr; |
---|
2365 | |
---|
2366 | // Only transfer if DDR is being used for buffers |
---|
2367 | if (use_dram_for_buffers) { |
---|
2368 | |
---|
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 | } |
---|
2375 | |
---|
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 | } |
---|
2382 | |
---|
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 | } |
---|
2389 | |
---|
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 | } |
---|
2397 | } |
---|
2398 | |
---|
2399 | |
---|
2400 | |
---|
2401 | /*****************************************************************************/ |
---|
2402 | /** |
---|
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 | *****************************************************************************/ |
---|
2411 | int wl_baseband_setup_interrupt(XIntc* intc){ |
---|
2412 | int status; |
---|
2413 | |
---|
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); |
---|
2417 | |
---|
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); |
---|
2421 | |
---|
2422 | return status; |
---|
2423 | } |
---|
2424 | |
---|
2425 | |
---|
2426 | |
---|
2427 | /*****************************************************************************/ |
---|
2428 | /** |
---|
2429 | * @brief Buffers Core RX Interrupt Handler |
---|
2430 | * |
---|
2431 | * Handles interrupts that occur from the Buffers core. |
---|
2432 | * |
---|
2433 | * @param InstancePtr - Pointer to the Buffers core instance |
---|
2434 | * |
---|
2435 | * @return None |
---|
2436 | * |
---|
2437 | ******************************************************************************/ |
---|
2438 | void wl_buffers_core_rx_int_handler(void *InstancePtr){ |
---|
2439 | |
---|
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; |
---|
2446 | |
---|
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; |
---|
2454 | |
---|
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 | } |
---|
2461 | |
---|
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; |
---|
2469 | |
---|
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); |
---|
2476 | |
---|
2477 | rssi_buf_size = (u32)(WARPLAB_RSSI_BUF_SIZE); |
---|
2478 | rssi_read_offset_mod_buf_size = (u32)(rssi_read_offset % rssi_buf_size); |
---|
2479 | |
---|
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); |
---|
2487 | |
---|
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 | |
---|
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); |
---|
2496 | |
---|
2497 | wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length); |
---|
2498 | |
---|
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); |
---|
2502 | |
---|
2503 | wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length); |
---|
2504 | } |
---|
2505 | |
---|
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); |
---|
2510 | |
---|
2511 | wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length); |
---|
2512 | |
---|
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); |
---|
2516 | |
---|
2517 | wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length); |
---|
2518 | } |
---|
2519 | |
---|
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); |
---|
2524 | |
---|
2525 | wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length); |
---|
2526 | |
---|
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); |
---|
2530 | |
---|
2531 | wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length); |
---|
2532 | } |
---|
2533 | |
---|
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); |
---|
2538 | |
---|
2539 | wl_cdma_transfer(src_addr, dest_addr, iq_xfer_length); |
---|
2540 | |
---|
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); |
---|
2544 | |
---|
2545 | wl_cdma_transfer(src_addr, dest_addr, rssi_xfer_length); |
---|
2546 | } |
---|
2547 | |
---|
2548 | // If we are done, then reset the read / write offsets. Otherwise, update |
---|
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 | } |
---|
2558 | } |
---|
2559 | |
---|
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 | } |
---|
2566 | } |
---|
2567 | |
---|
2568 | |
---|
2569 | |
---|
2570 | /*****************************************************************************/ |
---|
2571 | /** |
---|
2572 | * @brief Buffers Core TX Interrupt Handler |
---|
2573 | * |
---|
2574 | * Handles interrupts that occur from the Buffers core. |
---|
2575 | * |
---|
2576 | * @param InstancePtr - Pointer to the Buffers core instance |
---|
2577 | * |
---|
2578 | * @return None |
---|
2579 | * |
---|
2580 | ******************************************************************************/ |
---|
2581 | void wl_buffers_core_tx_int_handler(void *InstancePtr){ |
---|
2582 | |
---|
2583 | u32 buff_en; |
---|
2584 | u32 tx_iq_status; |
---|
2585 | u32 continuous_tx; |
---|
2586 | u32 iq_xfer_length; |
---|
2587 | u32 iq_write_offset; |
---|
2588 | |
---|
2589 | // Only perform a transfer if the node is using DDR for buffers |
---|
2590 | if (use_dram_for_buffers) { |
---|
2591 | |
---|
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 | } |
---|
2597 | |
---|
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); |
---|
2602 | |
---|
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 | // |
---|
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; |
---|
2617 | |
---|
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); |
---|
2627 | iq_xfer_length = (u32)(WARPLAB_IQ_TX_BUF_SIZE >> 1); |
---|
2628 | } |
---|
2629 | |
---|
2630 | // Transfer the data |
---|
2631 | populate_tmp_tx_buffers(buff_en, iq_write_offset, iq_xfer_length); |
---|
2632 | |
---|
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 | } |
---|
2636 | |
---|
2637 | } else { |
---|
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 | } |
---|
2642 | } |
---|
2643 | |
---|
2644 | |
---|
2645 | |
---|
2646 | /*****************************************************************************/ |
---|
2647 | /** |
---|
2648 | * @brief Configure Baseband Buffers |
---|
2649 | * |
---|
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). |
---|
2653 | * |
---|
2654 | * @param dram_present - Flag to indicate if DRAM is present |
---|
2655 | * |
---|
2656 | * @return int - Status of the command: |
---|
2657 | * XST_SUCCESS - Command completed successfully |
---|
2658 | * XST_FAILURE - There was an error in the command |
---|
2659 | * |
---|
2660 | ******************************************************************************/ |
---|
2661 | void baseband_buffers_config(u8 dram_present){ |
---|
2662 | |
---|
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 | // |
---|
2670 | |
---|
2671 | u32 rx_max_samples; |
---|
2672 | u32 tx_max_samples; |
---|
2673 | |
---|
2674 | u32 tx_num_samples; |
---|
2675 | u32 rx_num_samples; |
---|
2676 | |
---|
2677 | wl_printf(WL_PRINT_NONE, NULL, "Configuring baseband ...\n"); |
---|
2678 | |
---|
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"); |
---|
2682 | |
---|
2683 | use_dram_for_buffers = 1; |
---|
2684 | |
---|
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; |
---|
2690 | |
---|
2691 | rx_num_samples = WL_BUF_DEFAULT_RX_NUM_SAMPLES; |
---|
2692 | tx_num_samples = WL_BUF_DEFAULT_TX_NUM_SAMPLES; |
---|
2693 | |
---|
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); |
---|
2696 | |
---|
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; |
---|
2703 | |
---|
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; |
---|
2710 | |
---|
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; |
---|
2717 | |
---|
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; |
---|
2724 | |
---|
2725 | } else { |
---|
2726 | wl_printf(WL_PRINT_NONE, NULL, " Using BRAM for buffers\n"); |
---|
2727 | |
---|
2728 | use_dram_for_buffers = 0; |
---|
2729 | |
---|
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; |
---|
2735 | |
---|
2736 | rx_num_samples = WL_BUF_DEFAULT_RX_NUM_SAMPLES; |
---|
2737 | tx_num_samples = WL_BUF_DEFAULT_TX_NUM_SAMPLES; |
---|
2738 | |
---|
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); |
---|
2742 | |
---|
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; |
---|
2749 | |
---|
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; |
---|
2756 | |
---|
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; |
---|
2763 | |
---|
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; |
---|
2770 | } |
---|
2771 | |
---|
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)); |
---|
2774 | |
---|
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; |
---|
2778 | |
---|
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); |
---|
2784 | |
---|
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; |
---|
2787 | |
---|
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. |
---|
2790 | // |
---|
2791 | if (USE_GENERATED_RX_DATA) { |
---|
2792 | wl_bb_set_config(WL_BUF_REG_CONFIG_COUNTER_DATA_SEL); |
---|
2793 | wl_printf(WL_PRINT_NONE, NULL, " Using fake counter data\n"); |
---|
2794 | } |
---|
2795 | |
---|
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 | } |
---|
2811 | |
---|
2812 | #ifdef _DEBUG_ |
---|
2813 | print_buffer_info(); |
---|
2814 | #endif |
---|
2815 | } |
---|
2816 | |
---|
2817 | |
---|
2818 | |
---|
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 | |
---|