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

Bringing up 125Kbps Coded PHY on NRF52840

Ive been working on this for some time and can not get two boards successfully communicating using the 125Kbps on the NRF52840.  I am simply having one chip transmit advertising packets, and the other receive them.  It is working for 1Mbps and 2Mbps, but I can not get 125Kbps working.  Im assuming I should just have to change the radio configuration and the rest of the code should work, correct?  I have tried working with the following examples.

https://devzone.nordicsemi.com/f/nordic-q-a/19945/ble-5-transmiter-receiver-examples-nrff52840/77618#77618

https://devzone.nordicsemi.com/f/nordic-q-a/44581/how-do-i-set-bitrate-125kbit-250kbit-or-500kbit-in-nrf5_sdk_15-2-0_9412b96-examples-proprietary_rf-esb_low_power_prx-and-esb_low_power_prx-projects

https://devzone.nordicsemi.com/f/nordic-q-a/22094/rx-on-le-coded-phy

Here is my working code for 1Mbit.  Any chance I could get some help on getting this to work with 125Kbps?

#define PACKET_S1_FIELD_SIZE      (0UL)  /**< Packet S1 field size in bits. */
#define PACKET_S0_FIELD_SIZE      (0UL)  /**< Packet S0 field size in bits. */
#define PACKET_LENGTH_FIELD_SIZE  (0UL)  /**< Packet length field size in bits. */


#define PACKET_BASE_ADDRESS_LENGTH  (4UL)                   //!< Packet base address length field size in bytes
#define PACKET_STATIC_LENGTH        (1UL)                   //!< Packet static length in bytes
#define PACKET_PAYLOAD_MAXSIZE      (PACKET_STATIC_LENGTH)  //!< Packet payload maximum size in bytes
#define CRC_POLYNOMIAL_INIT_SETTINGS  ((0x5B << 0) | (0x06 << 8) | (0x00 << 16))

uint8_t access_address[4] = {0xD6, 0xBE, 0x89, 0x8E};
uint8_t seed[3] = {0x55, 0x55, 0x55};

void radio_configure(uint8_t *p_data)
{
	NRF_RADIO->POWER = RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos;
	NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos;
	NRF_RADIO->FREQUENCY = 2UL;  
	NRF_RADIO->SHORTS = 0;
	NRF_RADIO->TXPOWER   = (RADIO_TXPOWER_TXPOWER_Pos8dBm << RADIO_TXPOWER_TXPOWER_Pos);
	NRF_RADIO->MODE      = (RADIO_MODE_MODE_Ble_1Mbit << RADIO_MODE_MODE_Pos); 

	// Radio address config
	NRF_RADIO->PREFIX0 = access_address[3];
	NRF_RADIO->BASE0   = ( (((uint32_t)access_address[2]) << 24)
						 | (((uint32_t)access_address[1]) << 16)
						 | (((uint32_t)access_address[0]) << 8) );

	NRF_RADIO->RXADDRESSES = 0x01UL;  

	NRF_RADIO->PCNF0 =   (((1UL) << RADIO_PCNF0_S0LEN_Pos) & RADIO_PCNF0_S0LEN_Msk)
						 | (((2UL) << RADIO_PCNF0_S1LEN_Pos) & RADIO_PCNF0_S1LEN_Msk)
						 | (((6UL) << RADIO_PCNF0_LFLEN_Pos) & RADIO_PCNF0_LFLEN_Msk);

	NRF_RADIO->PCNF1 =   (((RADIO_PCNF1_ENDIAN_Little)        << RADIO_PCNF1_ENDIAN_Pos) & RADIO_PCNF1_ENDIAN_Msk)
						 | (((3UL)                              << RADIO_PCNF1_BALEN_Pos)  & RADIO_PCNF1_BALEN_Msk)
						 | (((0UL)                              << RADIO_PCNF1_STATLEN_Pos)& RADIO_PCNF1_STATLEN_Msk)
						 | ((((uint32_t)37)  << RADIO_PCNF1_MAXLEN_Pos) & RADIO_PCNF1_MAXLEN_Msk)
						 | ((RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) & RADIO_PCNF1_WHITEEN_Msk);

	NRF_RADIO->TIFS = 150; 
	
	// CRC Config

	NRF_RADIO->CRCPOLY = (uint32_t)CRC_POLYNOMIAL_INIT_SETTINGS;
	NRF_RADIO->CRCCNF = (((RADIO_CRCCNF_SKIPADDR_Skip) << RADIO_CRCCNF_SKIPADDR_Pos) & RADIO_CRCCNF_SKIPADDR_Msk)
						| (((RADIO_CRCCNF_LEN_Three)      << RADIO_CRCCNF_LEN_Pos)       & RADIO_CRCCNF_LEN_Msk);
						
	NRF_RADIO->CRCINIT = ((uint32_t)seed[0]) | ((uint32_t)seed[1])<<8 | ((uint32_t)seed[2])<<16;

	//match ID code
	NRF_RADIO->DAB[0]=  0;
	NRF_RADIO->DAP[0]=  0;
	NRF_RADIO->DACNF = 	0;

	//first packet in buffer
	NRF_RADIO->PACKETPTR = (uint32_t)&(p_data[0]);

	//radio should be configured at this point.  Power it up. 
	NRF_RADIO->EVENTS_READY = 0U; //clear the read flad
	
	// Enable radio and wait for ready
	NRF_RADIO->TASKS_RXEN = 1U;
	while (NRF_RADIO->EVENTS_READY == 0U)
	{
		// wait
	}
	
	NRF_RADIO->EVENTS_END = 0U; //radio ready, clear flag

	//ready! run this next line from main
	//NVIC_EnableIRQ(RADIO_IRQn);
	//NRF_RADIO->TASKS_START = 1U; // Start listening and wait for address received event
}

  • Take a look at the dtm example in the SDK (15.3.0), it sets up a connection using 125K or 500K. However, the thing I think you're missing is the PCNF0_PLEN_LongRange setting.

  • That was the problem.  In case anyone else finds this thread, here is a working solution for the nrf52840

    #define DTM_PAYLOAD_MAX_SIZE 255
    void radio_configure_coded_phy()
    {
    	uint32_t          m_address           = 0x71764129;
    	uint8_t           m_crcConfSkipAddr   = 1;
        uint8_t           m_crcLength         = RADIO_CRCCNF_LEN_Three;       /**< CRC Length (in bytes). */
    	uint8_t           m_packetHeaderLFlen = 8;                            /**< Length of length field in packet Header (in bits). */
    	uint8_t           m_packetHeaderS0len = 1;                            /**< Length of S0 field in packet Header (in bytes). */
    	uint8_t           m_packetHeaderS1len = 0;  
    	uint8_t           m_packetHeaderPlen  = RADIO_PCNF0_PLEN_8bit;        /**< Length of the preamble. */
    	uint8_t           m_static_length     = 0;                            /**< Number of bytes sent in addition to the var.length payload. */
    	uint32_t          m_balen             = 3;                            /**< Base address length in bytes. */
    	uint32_t          m_endian            = RADIO_PCNF1_ENDIAN_Little;    /**< On air endianess of packet, this applies to the S0, LENGTH, S1 and the PAYLOAD fields. */
    	uint32_t          m_whitening         = RADIO_PCNF1_WHITEEN_Disabled; /**< Whitening disabled. */
    	uint32_t          m_crc_poly          = 0x0000065B;                   /**< CRC polynomial. */
    	uint32_t          m_crc_init          = 0x00555555;   
    	
    	//reset radio
    	NRF_RADIO->SHORTS          = 0;
    	NRF_RADIO->EVENTS_DISABLED = 0;
    	NRF_RADIO->TASKS_DISABLE   = 1;
    
    	while (NRF_RADIO->EVENTS_DISABLED == 0)
    	{
    			// Do nothing
    	}
    
    	NRF_RADIO->EVENTS_DISABLED = 0;
    	NRF_RADIO->TASKS_RXEN      = 0;
    	NRF_RADIO->TASKS_TXEN      = 0;
    	
    	//prepare
    	NRF_RADIO->CRCPOLY      = m_crc_poly;
        NRF_RADIO->CRCINIT      = m_crc_init;
        NRF_RADIO->FREQUENCY    = 2;
        NRF_RADIO->EVENTS_READY = 0;
        NRF_RADIO->SHORTS       = 0;
    
    
    	NRF_RADIO->TXPOWER = (RADIO_TXPOWER_TXPOWER_Pos8dBm << RADIO_TXPOWER_TXPOWER_Pos);
        NRF_RADIO->MODE    = (RADIO_MODE_MODE_Ble_LR125Kbit << RADIO_MODE_MODE_Pos); //eric
    
    	// Set the access address, address0/prefix0 used for both Rx and Tx address
    	NRF_RADIO->PREFIX0    &= ~RADIO_PREFIX0_AP0_Msk;
    	NRF_RADIO->PREFIX0    |= (m_address >> 24) & RADIO_PREFIX0_AP0_Msk;
    	NRF_RADIO->BASE0       = m_address << 8;
    	NRF_RADIO->RXADDRESSES = RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos;
    	NRF_RADIO->TXADDRESS   = (0x00 << RADIO_TXADDRESS_TXADDRESS_Pos) & RADIO_TXADDRESS_TXADDRESS_Msk;
    
    	// Configure CRC calculation
    	NRF_RADIO->CRCCNF = (m_crcConfSkipAddr << RADIO_CRCCNF_SKIP_ADDR_Pos) |
    											(m_crcLength << RADIO_CRCCNF_LEN_Pos);
    
    	// Coded PHY (Long range)
    	NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) |
    								 (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) |
    								 (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) |
    								 (3 << RADIO_PCNF0_TERMLEN_Pos) |
    								 (2 << RADIO_PCNF0_CILEN_Pos) |
    								 (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos);
    
    
    	NRF_RADIO->PCNF1 = (m_whitening          << RADIO_PCNF1_WHITEEN_Pos) |
    										 (m_endian             << RADIO_PCNF1_ENDIAN_Pos)  |
    										 (m_balen              << RADIO_PCNF1_BALEN_Pos)   |
    										 (m_static_length      << RADIO_PCNF1_STATLEN_Pos) |
    										 (DTM_PAYLOAD_MAX_SIZE << RADIO_PCNF1_MAXLEN_Pos);
    
    	
    		//first packet in buffer
    		NRF_RADIO->PACKETPTR = (uint32_t)&RADIO_RX_BUFFER[advpktbufferptr];
    
    		NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos)|
    												(RADIO_SHORTS_ADDRESS_RSSISTART_Enabled << RADIO_SHORTS_ADDRESS_RSSISTART_Pos);
    	
    	  //radio should be configured at this point.  Power it up. 
    		NRF_RADIO->EVENTS_READY = 0U; //clear the read flad
        // Enable radio and wait for ready
        NRF_RADIO->TASKS_RXEN = 1U;
        while (NRF_RADIO->EVENTS_READY == 0U)
        {
            // wait
        }
        NRF_RADIO->EVENTS_END = 0U; //radio ready, clear flag
        NRF_RADIO->INTENSET=0x00000008; //on event end
    	
    		//ready! run this next line from main
    		NVIC_EnableIRQ(RADIO_IRQn);
    
        NRF_RADIO->TASKS_START = 1U; // Start listening and wait for address received event
    }

Related