nRF21540EK integration with nRF5340dk

Hi there,

We are trying to integrate an nRF21540EK shield onto our nRF5340DK. Following the instructions on the following link (https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/ug_radio_fem.html#ug-radio-fem-nrf21540-ek-programming) we were able to set up the hardware but we are struggling to find a guide on how to configure the software.

We are seeking to use the nRF21540EK in conjunction with the "Bluetooth: Peripheral UART" sample found in the nRF connect SDK and would like to be able to control the gain and antenna select functions on the nRF21540.

Thanks,

Matt

Parents
  • Hello Mathew,

    We have an example for peripheral_uart which was tested on NCS 1.8.0

     The added configuration for nrf21540 are like the following configurations 

    # FEM
    CONFIG_MPSL_FEM=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0
    CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20

    It also needs a function for setting transmit power and for the getting transmit power.

    static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_write_tx_power_level *cp;
        struct bt_hci_rp_vs_write_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;
    
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }
    
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
        cp->tx_power_level = tx_pwr_lvl;
    
        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_write_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Set Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }
    
        rp = (void *)rsp->data;
        printk("RADIO Tx Power: %d + PA_GAIN(%d) = %d\n", rp->selected_tx_power, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, rp->selected_tx_power + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
        net_buf_unref(rsp);
    }
    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;
    
        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }
    
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
    
        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_read_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Read Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }
    
        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;
    
        net_buf_unref(rsp);
    }
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn *default_conn;
    	uint16_t default_conn_handle;
    	int ret;
    	int8_t txp;
    
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (err) {
    		printk("Connection failed (err %u)\n", err);
    		sys_reboot();
    		return;
    	}
    
    	default_conn = bt_conn_ref(conn);
    	ret = bt_hci_get_conn_handle(default_conn,
    						&default_conn_handle);
    	if (ret) {
    		printk("No connection handle (err %d)\n", ret);
    		sys_reboot();
    		return;
    	}
    	
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    			printk("Connected via connection (%d) at %s\n",
    			       default_conn_handle, addr);
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Initial Radio Tx Power: %d + PA_GAIN (%d) = %d\n",
    			       default_conn_handle, txp, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, txp + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
    			set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle,
    				     TRANSMIT_POWER_dBm);
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Initial Radio Tx Power: %d + PA_GAIN (%d) = %d\n",
    			       default_conn_handle, txp, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, txp + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
    	current_conn = bt_conn_ref(conn);
    
    	dk_set_led_on(CON_STATUS_LED);
    }
    Set_tx_power has to be called from disconnected function to define the transmit power value.
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err = 0;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Disconnected: %s (reason %u)\n", log_strdup(addr), reason);
    
    	if (auth_conn) {
    		bt_conn_unref(auth_conn);
    		auth_conn = NULL;
    	}
    
    	if (current_conn) {
    		bt_conn_unref(current_conn);
    		current_conn = NULL;
    		dk_set_led_off(CON_STATUS_LED);
    	}
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
    			      ARRAY_SIZE(sd));
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		sys_reboot();
    		return;
    	}
    
    	set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, TRANSMIT_POWER_dBm);
    }
    From main function set_tx_power has to be called.
    void main(void) {
    ....
    ..
    
    set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, TRANSMIT_POWER_dBm);
    
    }
    You can try this modification in peripheral_uart sample and see the output.
    Let us know the consequence. 
    Thanks.
    Best Regards,
    Kazi Afroza Sultana
Reply
  • Hello Mathew,

    We have an example for peripheral_uart which was tested on NCS 1.8.0

     The added configuration for nrf21540 are like the following configurations 

    # FEM
    CONFIG_MPSL_FEM=y
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
    CONFIG_MPSL_FEM_NRF21540_RX_GAIN_DB=0
    CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB=20

    It also needs a function for setting transmit power and for the getting transmit power.

    static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_write_tx_power_level *cp;
        struct bt_hci_rp_vs_write_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;
    
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }
    
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
        cp->tx_power_level = tx_pwr_lvl;
    
        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_write_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Set Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }
    
        rp = (void *)rsp->data;
        printk("RADIO Tx Power: %d + PA_GAIN(%d) = %d\n", rp->selected_tx_power, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, rp->selected_tx_power + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
        net_buf_unref(rsp);
    }
    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;
    
        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_create(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                    sizeof(*cp));
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }
    
        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;
    
        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            uint8_t reason = rsp ?
                ((struct bt_hci_rp_vs_read_tx_power_level *)
                  rsp->data)->status : 0;
            printk("Read Tx power err: %d reason 0x%02x\n", err, reason);
            return;
        }
    
        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;
    
        net_buf_unref(rsp);
    }
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	struct bt_conn *default_conn;
    	uint16_t default_conn_handle;
    	int ret;
    	int8_t txp;
    
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	if (err) {
    		printk("Connection failed (err %u)\n", err);
    		sys_reboot();
    		return;
    	}
    
    	default_conn = bt_conn_ref(conn);
    	ret = bt_hci_get_conn_handle(default_conn,
    						&default_conn_handle);
    	if (ret) {
    		printk("No connection handle (err %d)\n", ret);
    		sys_reboot();
    		return;
    	}
    	
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    			printk("Connected via connection (%d) at %s\n",
    			       default_conn_handle, addr);
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Initial Radio Tx Power: %d + PA_GAIN (%d) = %d\n",
    			       default_conn_handle, txp, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, txp + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
    			set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle,
    				     TRANSMIT_POWER_dBm);
    			get_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_CONN,
    				     default_conn_handle, &txp);
    			printk("Connection (%d) - Initial Radio Tx Power: %d + PA_GAIN (%d) = %d\n",
    			       default_conn_handle, txp, CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB, txp + CONFIG_MPSL_FEM_NRF21540_TX_GAIN_DB);
    
    	current_conn = bt_conn_ref(conn);
    
    	dk_set_led_on(CON_STATUS_LED);
    }
    Set_tx_power has to be called from disconnected function to define the transmit power value.
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err = 0;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Disconnected: %s (reason %u)\n", log_strdup(addr), reason);
    
    	if (auth_conn) {
    		bt_conn_unref(auth_conn);
    		auth_conn = NULL;
    	}
    
    	if (current_conn) {
    		bt_conn_unref(current_conn);
    		current_conn = NULL;
    		dk_set_led_off(CON_STATUS_LED);
    	}
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
    			      ARRAY_SIZE(sd));
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		sys_reboot();
    		return;
    	}
    
    	set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, TRANSMIT_POWER_dBm);
    }
    From main function set_tx_power has to be called.
    void main(void) {
    ....
    ..
    
    set_tx_power(BT_HCI_VS_LL_HANDLE_TYPE_ADV, 0, TRANSMIT_POWER_dBm);
    
    }
    You can try this modification in peripheral_uart sample and see the output.
    Let us know the consequence. 
    Thanks.
    Best Regards,
    Kazi Afroza Sultana
Children
No Data
Related