This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Ant switch pattern and IQ sampling

Hi,

I'm working on direction finding with nrf52833dk (my own board latter on) and Nordic antenna matrix. I'm using NCS v1.6.0-rc2 and example Direction fing connectionless locator & bacon. I want to compute aoa and since i've only one antenna matrix i disabled aod of bacon example by adding "SET(OVERLAY_CONFIG "overlay-aoa.conf")" to CMakeLists.txt.

After few try, my locator found the beacon and print parameter as expected. I want to compute angle, so i print all IQ sample by modifying main.c with 

static void cte_recv_cb(struct bt_le_per_adv_sync *sync,
			struct bt_df_per_adv_sync_iq_samples_report const *report)
{
	printk("CTE[%u]: samples count %d, cte type %s, slot durations: %u [us], "
	       "packet status %s, RSSI %i\n",
	       bt_le_per_adv_sync_get_index(sync), report->sample_count,
	       cte_type2str(report->cte_type), report->slot_durations,
	       packet_status2str(report->packet_status), report->rssi);

        printk("IQ sample content : \n");
        for(int i=0; i<report->sample_count; i++){
                printk("sample[%d] = I:%d Q:%d\n", i, report->sample[i].i, report->sample[i].q);
        }
}

and include bluetooth/hci.h. I got on my output 

PER_ADV_SYNC[0]: [DEVICE]: 23:13:D2:D8:82:4B (random), tx_power 127, RSSI -63, CTE AOA, data length 0, data: 
CTE[0]: samples count 45, cte type AOA, slot durations: 2 [us], packet status CRC OK, RSSI -630
IQ sample content : 
sample[0] = I:5 Q:0
sample[1] = I:-6 Q:-1
sample[2] = I:5 Q:0
sample[3] = I:-6 Q:0
sample[4] = I:5 Q:-1
sample[5] = I:-6 Q:0
sample[6] = I:5 Q:-1
sample[7] = I:-6 Q:0
sample[8] = I:7 Q:8
sample[9] = I:15 Q:20
sample[10] = I:-17 Q:20
sample[11] = I:-4 Q:-5
sample[12] = I:-6 Q:14
sample[13] = I:-14 Q:-2
sample[14] = I:-7 Q:-6
sample[15] = I:-18 Q:-1
sample[16] = I:-1 Q:4
sample[17] = I:-15 Q:9
sample[18] = I:-7 Q:-32
sample[19] = I:4 Q:-11
sample[20] = I:10 Q:-23
sample[21] = I:26 Q:4
sample[22] = I:-3 Q:4
sample[23] = I:16 Q:-2
sample[24] = I:6 Q:12
sample[25] = I:-2 Q:7
sample[26] = I:9 Q:14
sample[27] = I:4 Q:-2
sample[28] = I:14 Q:8
sample[29] = I:-26 Q:20
sample[30] = I:-11 Q:1
sample[31] = I:-26 Q:3
sample[32] = I:-9 Q:-26
sample[33] = I:5 Q:0
sample[34] = I:-10 Q:-13
sample[35] = I:8 Q:-12
sample[36] = I:8 Q:-2
sample[37] = I:9 Q:-15
sample[38] = I:-3 Q:-4
sample[39] = I:-1 Q:-17
sample[40] = I:30 Q:10
sample[41] = I:6 Q:8
sample[42] = I:14 Q:21
sample[43] = I:-18 Q:21
sample[44] = I:-3 Q:-5

I have several question about the output :

  1. Why am i having 45 samples? I know there is a guard period and then as many samples as ant_pattern_length but it is 12 antenna long.
  2. Since there are more value than i expect, should i make an algorithm in order to discard the wrong one ?
  3. Is the values correct ? i know the swing of IQ value are bigger than those.
  4. Last but not least, where can i find in example project all the parameter such as TSAMPLESPACINGREF / TSAMPLESPACING / TSWITCHSPACING ?

I read very carefully your whitepaper, but i need a little help to put all this fine.

Regards,

Nathan

  • Hi Nathan, 

    may i know how to add overlay-aoa.conf to CMAKElist as you mention above?  are you adding both to RX and TX or just TX will do?

  • Hi Nathan!

    Sadly our support on direction finding is quite limited, but I'll get back to you on this as soon as I can find answers for you.

    From what i can see right now though, the IQ values seem fine. And the number of samples depends on the sample_count variable, not the number of antennas.

    Best regards,

    Elfving

  • Hi Elfving,

    Where can i find the sample_count variable ?

    I've made progress in my understanding. I know that :

    • the amplitude = sqrt(pow(I,2)+pow(Q,2)) 
    • the phase = arctan2(Q,I)

    So i decide to plot the amplitude in order to see any incoherence. (sorry for the bad resolution)

    I put the beacon close to the locator when i reccord the sample. I know for sure that the 8 first sample are the reference, then it's switch slot and then sample slot. I guess the value close to the reference value are valid and all other sample are taken when the module switch antenna.

    I can't find where the code setup the sampling, can you help me ?

    Thanks

    Nathan

  • The spiking antennas are probably caused by multipath issues, this needs to be dealt with. The gain might be the main culprit, that needs to be modified such that the signal doesn't go to saturation. If it goes to saturation, the entire series should be discarded. There should be a field in the IQ samples that show saturation.

    Regarding your previous questions:

    1. This depends on the sample_count, which depends on sample rate and the length of the CTE. The CTE length can be found and edited in the beacon example, seems it is 160us by default. As you can see in section 4 of the whitepaper, the algorithm basically continues at the start of its antenna switching pattern if it runs out of antennas. 

    2. Nothing needs to be discarded per se.

    3. They seem ok, besides what I mentioned above about spikes.

    4. The parameters can be found by using ctrl+shift+F in SES, maybe most notably in zephyr/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c.

    Best regards,

    Elfving

  • Hi Elfving,

    Thanks for the answer. I learn a lot with those info. I have now some explanation about the parameters, correct me if i'm wrong.

    In Bluetooth Core v5.2, 6/B/2.5.1 - "The Constant Tone Extension has a variable length; it shall be at least 16 μs and not greater than 160 μs." That explain the choice of 160µs (0x14U in tx exemple) for the CTE length.

    In Bluetooth Core v5.2, 6/B/2.5.4 - "the receiver shall take an IQ sample each microsecond during the reference period and an IQ sample each sample slot (thus there will be 8 reference IQ samples, 1 to 37 IQ samples with 2 μs slots, and 2 to 74 IQ samples with 1 μs slots, meaning 9 to 82 samples in total)." Since the rx example is configured at 2µs by default, we are in the 8+37 samples case which make 45 samples. So as you say, i do not need to discard any sample since they are all usefull.

    In Bluetooth Core v5.2, 6/A/5.1 - "The first antenna in the pattern shall be used during the reference period [...]. The second antenna in the pattern shall be used during the first sample slot, the third antenna during the second sample slot, and so on. The same antenna ID may appear more than once in the pattern. [...] If the pattern specified by the Host is exhausted before the last sample slot, it shall be restarted from the beginning..." Since i use the 12 antenna patern from Nordic, i expect the pattern to be restart 3 times during the 45 samples. Even with saturation, we can see it in my plot from IQ sampling. But, for some reason, the antenna pattern seem to be 11 antenna long because between two spike i've got 11 IQ samples.

    In zephyr/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c 

    void radio_df_ant_switch_pattern_set(uint8_t *patterns, uint8_t len)
    {
    	/* SWITCHPATTERN is like a moving pointer to underlying buffer.
    	 * Each write stores a value and moves the pointer to new free position.
    	 * When read it returns number of stored elements since last write to
    	 * CLEARPATTERN. There is no need to use subscript operator.
    	 *
    	 * Some storage entries in the buffer has special purpose for DFE
    	 * extension in radio:
    	 * - SWITCHPATTERN[0] for idle period (PDU Tx/Rx),
    	 * - SWITCHPATTERN[1] for guard and reference period,
    	 * - SWITCHPATTERN[2] and following for switch-sampling slots.
    	 * Due to that in SWITCHPATTER[0] there is stored a pattern provided by
    	 * DTS property dfe_pdu_antenna. This limits number of supported antenna
    	 * switch patterns by one.
    	 */
    	NRF_RADIO->SWITCHPATTERN = DT_PROP(RADIO, dfe_pdu_antenna);
    	for (uint8_t idx = 0; idx < len; ++idx) {
    		NRF_RADIO->SWITCHPATTERN = patterns[idx];
    	}
    }

     SWITCHPATTERN[0] = ANT 12 (idle period)

    SWITCHPATTERN[1] = ANT 11 (guard and reference period)

    SWITCHPATTERN[2..11] = ANT 12 - 1 - 2 - 10 - 3 - 9 - 4 - 8 - 7 - 6 - 5

    Could i be that the actual switch pattern repeating is patterns[2...11] and could explain my 11 antenna pattern ?

    Two more thing to add :

    • i didn't find any IQ sample info about satuation. Do you have any link ?
    • If we change slot_durations to 1, the receiver don't sample and print nothing.

    Regards

    Nathan

Related