The amplitude value of the IQ data for nrf5340dk is too low

-21	45
17	-47
-16	45
9	-49
-8	46
11	-47
0	48
-19	-47
25	-54
-45	-25
-30	38
31	37
-8	-59
-52	7
-1	50
45	8
-53	-28
-34	40
35	37
43	-25
-59	-1
1	49
48	4
13	-47
-37	49
39	32
41	-26
-22	-40
-2	59
50	5
9	-52
-45	-15
41	41
41	-30
-22	-45
-46	18
59	5
8	-51
-49	-19
-21	44
49	-35
-29	-42
-41	26
17	46
8	-58

hardware:nrf5340dk

The above 45 pairs of IQ data are a set of data that I have received.The maximum amplitude of the IQ data I received seems to be only 128, which means that the quantization of IQ data is only 7 bits, which may result in insufficient accuracy. I would like to know if it is possible to modify the configuration to increase the quantization bit count and thus increase the amplitude value of IQ data? I think the data obtained this way will have higher accuracy.

Thank you in advance for your help!

  • Hi

    IQ samples are set with the SAMPLEYPE field in the DFECTRL1 register and is described below (from the nRF52833 and nRF5340 product specification:

    I would recommend that if you require better accuracy would be to use more antennas in your antenna array. Please see the Direction Finding whitepaper for more information. Also, please note that this is raw IQ data, so it must be converted into vector form to be reviewed properly. We don't have have any specific sample code showing this, but you can check out this page for information on the various formulas used to translate IQ data between polar and rectangular form.

    Best regards,

    Simon

  • Thank you very much for your help. I have carefully looked at the code these days and found that it is indeed possible to change its quantization level to 16 bits.

    20
    10747   -10492  6876    -127
    10491   -11513  -25431  20508
    11011   -10502  156     15926
    10246   -9989   -11543  29935
    10505   9491    641     -32502
    8984    8473    -3463   -23492
    6689    6944    30056   -3544
    4900    3366    9446    -27909
    2087    1321    27043   -6518
    41      -1494   -30938  -20525
    -3031   -5084   -20867  31544
    -6620   -6621   -15004  -5967
    -9194   -9708   -5030   7082
    -9196   -10744  -13391  26017
    -10492  -10497  -8289   -251
    -10753  -10255  -13503  -20074
    -10003  -9237   26885   -28412
    -7199   -6943   -8525   -6925
    -7199   -4135   -2699   -4418
    -1322   -2091   32308   -17825
    -2088   3033    -8606   -24640
    5337    3800    28021   21371
    6876    -127    7238    -28880

  • Hello, I made some changes to the code before and printed the 16 bit data directly, but later I found that there seems to be an error in this modification. Can you share how you modified the code? Looking forward to your help!

    Official zephyr code for receiving IQ data:

    static void cte_recv_cb(struct bt_conn *conn, struct bt_df_conn_iq_samples_report const *report)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (report->err == BT_DF_IQ_REPORT_ERR_SUCCESS) {
    		printk("CTE[%s]: samples type: %s, samples count %d, cte type %s, slot durations: "
    			"%u [us], packet status %s, RSSI %i\n", addr,
    			sample_type2str(report->sample_type), report->sample_count,
    			cte_type2str(report->cte_type), report->slot_durations,
    			packet_status2str(report->packet_status), report->rssi);
    
    		if (IS_ENABLED(CONFIG_DF_CENTRAL_APP_IQ_REPORT_PRINT_IQ_SAMPLES)) {
    			for (uint8_t idx = 0; idx < report->sample_count; idx++) {
    				if (report->sample_type == BT_DF_IQ_SAMPLE_8_BITS_INT) {
    					printk(" IQ[%d]: %d, %d\n", idx, report->sample[idx].i,
    					       report->sample[idx].q);
    				} else if (IS_ENABLED(
    					CONFIG_BT_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES)) {
    					printk(" IQ[%" PRIu8 "]: %d, %d\n", idx,
    					       report->sample16[idx].i, report->sample16[idx].q);
    				} else {
    					printk("Unhandled vendor specific IQ samples type\n");
    					break;
    				}
    			}
    		}
    	} else {
    		printk("CTE[%s]: request failed, err %u\n", addr, report->err);
    	}
    }

    The code modifications I made to IQ data reception:

    static void cte_recv_cb(struct bt_conn *conn, struct bt_df_conn_iq_samples_report const *report)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (report->err == BT_DF_IQ_REPORT_ERR_SUCCESS) {
    		printk("%d\n", report->chan_idx);
    
    		for (uint8_t idx = 0; idx < report->sample_count - 22; idx++) {
    			if (report->sample_type == BT_DF_IQ_SAMPLE_8_BITS_INT) {
    				printk(" %d\t%d\t%d\t%d\n", report->sample16[idx].i,
    				       report->sample16[idx].q, report->sample16[idx + 22].i,
    				       report->sample16[idx + 22].q);
    			}
    		}
    	} else {
    		printk("CTE[%s]: request failed, err %u\n", addr, report->err);
    	}
    }

    After experimental testing, I found that the report received by the

    report->sample_type == BT_DF_IQ_SAMPLE_8_BITS_INT

    instead of BT_DF_IQ_SAMPLE_16_BITS_INT. This means that although I can obtain 16 bit quantized data for sample16, the actual data is not accurate. Therefore, I can obtain sample16 only because sample16 and sample8 are defined in the same union.

    union {
            struct bt_hci_le_iq_sample const *sample;
            struct bt_hci_le_iq_sample16 const *sample16;
        };
    So I have two questions:
    1. Can you modify the code to change the received report ->sample_type to BT-DF-IQ-SAMPLE-16-BITS.INT?
    2. Has the code you modified been validated for accuracy through experiments?
    Looking forward to your help!Thank you in advance!
  • Hi

    I found the pull request of this implementation available here, please refer to this for more details. Please make sure you use the Zephyr controller and that the sample_type returns 16_BITS in your application. Much modification shouldn't be needed and you only have to choose the 16 bits in the following in main.c:

    static const char *sample_type2str(enum bt_df_iq_sample type)
    {
    	switch (type) {
    	case BT_DF_IQ_SAMPLE_8_BITS_INT:
    		return "8 bits int";
    	case BT_DF_IQ_SAMPLE_16_BITS_INT:
    		return "16 bits int";
    	default:
    		return "Unknown";
    	}
    }

    I'm not aware of any specific tests being conducted on our end for accuracy measurements, since this is heavily dependent on the Direction Finding algorithm used to convert the IQ data to vector form to get useful data.

    Best regards,

    Simon

Related