Direction finding on NRF52811

Hi!
I developed a locator and beacon pcb boards for AoA direction finding using the NRF52811 chip. The locator has 4 patch antennas and the SKY13575-639LF external antenna switch.
Software configuration for the beacon (using infocenter.nordicsemi.com/.../intro.html) :

1. Radio:

/* Enable power to RADIO */
NRF_RADIO->POWER = 1;

/* Set radio transmit power to 0dBm */
NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);

/* Set radio mode to 1Mbit/s Bluetooth Low Energy */
NRF_RADIO->MODE = (RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos);

/* Set the requested channel */
NRF_RADIO->FREQUENCY = GetChannelFrequency(channel);

/* This value needs to correspond to the channel being used */
NRF_RADIO->DATAWHITEIV = channel;

/* Configure Access Address according to the BLE standard */
NRF_RADIO->PREFIX0 = 0x8e;
NRF_RADIO->BASE0 = 0x89bed600;

/* Use logical address 0 (prefix0 + base0) = 0x8E89BED6 when transmitting and receiving */
NRF_RADIO->TXADDRESS = 0x00;
NRF_RADIO->RXADDRESSES = 0x01;

/* PCNF-> Packet Configuration. 
* We now need to configure the sizes S0, S1 and length field to match the
* datapacket format of the advertisement packets.
*/
NRF_RADIO->PCNF0 = (
	(((1UL) << RADIO_PCNF0_S0LEN_Pos) & RADIO_PCNF0_S0LEN_Msk) |  /* Length of S0 field in bytes 0-1.    */
	(((0UL) << RADIO_PCNF0_S1LEN_Pos) & RADIO_PCNF0_S1LEN_Msk) |  /* Length of S1 field in bits 0-8.     */
	(((8UL) << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk)    /* Length of length field in bits 0-8. */
);

/* Packet configuration */
NRF_RADIO->PCNF1 = (
	(((64UL) << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk)   |                      /* Maximum length of payload in bytes [0-255] */
	(((0UL) << RADIO_PCNF1_STATLEN_Pos) & RADIO_PCNF1_STATLEN_Msk)   |                      /* Expand the payload with N bytes in addition to LENGTH [0-255] */
	(((3UL) << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk)       |                      /* Base address length in number of bytes. */
	(((RADIO_PCNF1_ENDIAN_Little) << RADIO_PCNF1_ENDIAN_Pos) & RADIO_PCNF1_ENDIAN_Msk) |  /* Endianess of the S0, LENGTH, S1 and PAYLOAD fields. */
	(((1UL) << RADIO_PCNF1_WHITEEN_Pos) & RADIO_PCNF1_WHITEEN_Msk)                         /* Enable packet whitening */
);

/* CRC config */
NRF_RADIO->CRCCNF  = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |
					 (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos); /* Skip Address when computing CRC */
NRF_RADIO->CRCINIT = 0x555555;                                                  /* Initial value of CRC */
NRF_RADIO->CRCPOLY = 0x00065B;                                                  /* CRC polynomial function */

/* Clear events */
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->EVENTS_END = 0;
NRF_RADIO->EVENTS_READY = 0;
NRF_RADIO->EVENTS_ADDRESS = 0;	
//-------------------------------------
//-------------------------------------
NRF_RADIO->PACKETPTR = (uint32_t) Packet;

// Set up AoA mode
NRF_RADIO->DFEMODE = RADIO_DFEMODE_DFEOPMODE_AoA;

NRF_RADIO->DFECTRL1 = 3 << RADIO_DFECTRL1_NUMBEROF8US_Pos | 1 << RADIO_DFECTRL1_DFEINEXTENSION_Pos;

2. Sending a packet:
NRF_RADIO->EVENTS_READY = 0U;
// Enable radio and wait for ready.
NRF_RADIO->TASKS_TXEN   = 1; 											
while (NRF_RADIO->EVENTS_READY == 0U){}

NRF_RADIO->TASKS_START = 1U;
// Start transmission.
NRF_RADIO->EVENTS_PHYEND = 0;

NRF_RADIO->EVENTS_END  = 0U;


// Wait for end of the transmission packet.	   										

while (NRF_RADIO->EVENTS_PHYEND == 0U)
{
    while (NRF_RADIO->EVENTS_END == 0U)
    {
		//counter1++;
    }
    counter2++;
} 											

NRF_RADIO->EVENTS_DISABLED = 0U;
// Disable the radio.																	
NRF_RADIO->TASKS_DISABLE   = 1U; 									
while (NRF_RADIO->EVENTS_DISABLED == 0U){} 

3. The resulting structure of the packet:

Software configuration for the locator (using infocenter.nordicsemi.com/.../intro.html):

1. Radio:

/* Enable power to RADIO */
NRF_RADIO->POWER = 1;

/* Set radio transmit power to 0dBm */
NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_0dBm << RADIO_TXPOWER_TXPOWER_Pos);

/* Set radio mode to 1Mbit/s Bluetooth Low Energy */
NRF_RADIO->MODE = (RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos);

/* Set the requested channel */
NRF_RADIO->FREQUENCY = GetChannelFrequency(channel);

/* This value needs to correspond to the channel being used */
NRF_RADIO->DATAWHITEIV = channel;

/* Configure Access Address according to the BLE standard */
NRF_RADIO->PREFIX0 = 0x8e;
NRF_RADIO->BASE0 = 0x89bed600;

/* Use logical address 0 (prefix0 + base0) = 0x8E89BED6 when transmitting and receiving */
NRF_RADIO->TXADDRESS = 0x00;
NRF_RADIO->RXADDRESSES = 0x01;

/* PCNF-> Packet Configuration. 
* We now need to configure the sizes S0, S1 and length field to match the
* datapacket format of the advertisement packets.
*/
NRF_RADIO->PCNF0 = (
	(((1UL) << RADIO_PCNF0_S0LEN_Pos) & RADIO_PCNF0_S0LEN_Msk) |  /* Length of S0 field in bytes 0-1.    */
	(((0UL) << RADIO_PCNF0_S1LEN_Pos) & RADIO_PCNF0_S1LEN_Msk) |  /* Length of S1 field in bits 0-8.     */
	(((8UL) << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk)    /* Length of length field in bits 0-8. */
);

/* Packet configuration */
NRF_RADIO->PCNF1 = (
	(((64UL) << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk)   |                      /* Maximum length of payload in bytes [0-255] */
	(((0UL) << RADIO_PCNF1_STATLEN_Pos) & RADIO_PCNF1_STATLEN_Msk)   |                      /* Expand the payload with N bytes in addition to LENGTH [0-255] */
	(((3UL) << RADIO_PCNF1_BALEN_Pos) & RADIO_PCNF1_BALEN_Msk)       |                      /* Base address length in number of bytes. */
	(((RADIO_PCNF1_ENDIAN_Little) << RADIO_PCNF1_ENDIAN_Pos) & RADIO_PCNF1_ENDIAN_Msk) |  /* Endianess of the S0, LENGTH, S1 and PAYLOAD fields. */
	(((1UL) << RADIO_PCNF1_WHITEEN_Pos) & RADIO_PCNF1_WHITEEN_Msk)                         /* Enable packet whitening */
);

/* CRC config */
NRF_RADIO->CRCCNF  = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos) |
					 (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos); /* Skip Address when computing CRC */
NRF_RADIO->CRCINIT = 0x555555;                                                  /* Initial value of CRC */
NRF_RADIO->CRCPOLY = 0x00065B;                                                  /* CRC polynomial function */

/* Clear events */
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->EVENTS_END = 0;
NRF_RADIO->EVENTS_READY = 0;
NRF_RADIO->EVENTS_ADDRESS = 0;	
//-------------------------------------
//-------------------------------------
NRF_RADIO->PACKETPTR = (uint32_t) Packet;

// Set up AoA receiver mode
NRF_RADIO->DFEMODE |= RADIO_DFEMODE_DFEOPMODE_AoA;

NRF_RADIO->DFECTRL1 = 3 << RADIO_DFECTRL1_NUMBEROF8US_Pos | 1 << RADIO_DFECTRL1_DFEINEXTENSION_Pos;

NRF_RADIO->CTEINLINECONF |= (RADIO_CTEINLINECONF_CTEINLINECTRLEN_Enabled << RADIO_CTEINLINECONF_CTEINLINECTRLEN_Pos)
						 | (RADIO_CTEINLINECONF_CTEINFOINS1_NotInS1 << RADIO_CTEINLINECONF_CTEINFOINS1_Pos)
						 | (0x07 << RADIO_CTEINLINECONF_S0CONF_Pos)
						 | (0x0F << RADIO_CTEINLINECONF_S0MASK_Pos);

2. Antenna switching:
#define ANTENNA_SWICTH_PIN0 30
#define ANTENNA_SWICTH_PIN1 28

// Configure antenna switching every 2 µs
NRF_RADIO->DFECTRL1 |= RADIO_DFECTRL1_TSWITCHSPACING_2us << RADIO_DFECTRL1_TSWITCHSPACING_Pos;

// Antenna 1 (for data)
NRF_RADIO->SWITCHPATTERN = 0b00;
// Antenna 1 (guard/reference)
NRF_RADIO->SWITCHPATTERN = 0b00;
// Antenna 2 (guard/reference)
NRF_RADIO->SWITCHPATTERN = 0b01;
// Antenna 3 (guard/reference)
NRF_RADIO->SWITCHPATTERN = 0b10;
// Antenna 4 (guard/reference)
NRF_RADIO->SWITCHPATTERN = 0b11;


// Set up the first switching pin
NRF_RADIO->PSEL.DFEGPIO[0] = ANTENNA_SWICTH_PIN0;
// Set up the second switching pin
NRF_RADIO->PSEL.DFEGPIO[0] = ANTENNA_SWICTH_PIN1;

// Set the switch offset to zero
NRF_RADIO->DFECTRL2 |= (0 << RADIO_DFECTRL2_TSWITCHOFFSET_Pos);

// Config antenna swithcing pins as output
nrf_gpio_cfg_output(ANTENNA_SWICTH_PIN0);
nrf_gpio_cfg_output(ANTENNA_SWICTH_PIN1);
nrf_gpio_pin_write(ANTENNA_SWICTH_PIN0, 0);
nrf_gpio_pin_write(ANTENNA_SWICTH_PIN0, 0);

3. IQ samples receiving:
struct IQ_Sample
{
    int16_t I;
    int16_t Q;
};

static IQ_Sample DFE_Packet[64] = {0};


// Set the sample type to IQ format
NRF_RADIO->DFECTRL1 |= (0 << RADIO_DFECTRL1_SAMPLETYPE_Pos);
// Configure the DMA pointer to RAM
NRF_RADIO->DFEPACKET.PTR = (uint32_t) DFE_Packet;
// Configure the size of the reserved buffer
NRF_RADIO->DFEPACKET.MAXCNT = 0x1C;
// Set the sample spacing to 1 µs for the reference period
NRF_RADIO->DFECTRL1 |= (RADIO_DFECTRL1_TSAMPLESPACINGREF_1us << RADIO_DFECTRL1_TSAMPLESPACINGREF_Pos);
// Set sample offset to 1
NRF_RADIO->DFECTRL2 |= (3 << RADIO_DFECTRL2_TSAMPLEOFFSET_Pos);
// Set sample spacing to 2 µs for the sample slots with Constant Tone Extension (CTE) inline mode
NRF_RADIO->CTEINLINECONF |= (RADIO_CTEINLINECONF_CTEINLINERXMODE2US_2us << RADIO_CTEINLINECONF_CTEINLINERXMODE1US_Pos);

4. Waiting for the packet:
NRF_RADIO->EVENTS_READY = 0U;
// Enable radio and wait for ready
NRF_RADIO->TASKS_RXEN = 1U;

while (NRF_RADIO->EVENTS_READY == 0U)
{
    // wait
}
NRF_RADIO->EVENTS_END = 0U;
// Start listening and wait for address received event
NRF_RADIO->TASKS_START = 1U;

// Wait for end of packet or buttons state changed
while (NRF_RADIO->EVENTS_END == 0U)
{
    // wait
}

if (NRF_RADIO->CRCSTATUS == 1U)
{
    result = 0;
}
NRF_RADIO->EVENTS_DISABLED = 0U;
// Disable radio
NRF_RADIO->TASKS_DISABLE = 1U;

while (NRF_RADIO->EVENTS_DISABLED == 0U)
{
    // wait
}
 

5. Handling the packet:
if (NRF_RADIO->EVENTS_CTEPRESENT)
{
    NRF_RADIO->EVENTS_CTEPRESENT = 0;

    for (uint8_t i = 0; i < 4; i++)
    {
        UART_Instance.Printf("I and Q;");
        UART_Instance.Printf("%d;%d;\r\n", DFE_Packet[i].I, DFE_Packet[i].Q);
    }
}

Why the resulting IQ samples look like random values?

Parents
  • Okay, I think it's safe to say it's not due to the testing environment at least. Indeed, testing with one antenna should give you rather stationary values here.

    What board file did you add for the nRF52811 when trying to build it, and did the compilation and build process return successfully or did you see any error codes?

    Best regards,

    Simon

Reply
  • Okay, I think it's safe to say it's not due to the testing environment at least. Indeed, testing with one antenna should give you rather stationary values here.

    What board file did you add for the nRF52811 when trying to build it, and did the compilation and build process return successfully or did you see any error codes?

    Best regards,

    Simon

Children
Related