nRF21540 FEM output power

Hi, I'm working with nRF21540, trying to set the maximum output power.

I have a BLE beacon app, where I added the FEM support based on the Direct test mode example from the SDK.
SDK I've used: ncs 2.3.0.
Hardware: nRF21540DK

The issue I'm facing is that the max output power I can set in the firmware is 20dBm.

This is in my prj.conf file:

# Enable Tx power adjustments at runtime
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y

# Enable MPSL and FEM. 
CONFIG_MPSL_FEM_ONLY=n
CONFIG_FEM=y
CONFIG_MPSL=y
CONFIG_MPSL_FEM=y
CONFIG_MPSL_FEM_NRF21540_GPIO_SPI=y

I'm using following method of setting the output power:

oid 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("Actual Tx Power: %d\n", rp->selected_tx_power);

    net_buf_unref(rsp);
}

Am I missing something here? Shouldn't the maximum output power be 21dBm?

Thanks for the support

Emir

Parents Reply Children
  • Hi Kazi,

    Thank you for the reply. Unfortunately, setting these configs didn't allow me to set 21dBm output power.
    By the way, here is the function I'm using to read the set Tx power:

    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);
    }

  • When using the internal power model you can maximum get 20dBm yes. The reason to have 21dBm maximum from the FEM at typical conditions is to ensure that you have enough headroom when using the device over the temperature range. The target is to support 20dBm over operating conditions.

  • Thank you for the reply!
    Just out of curiosity, is this documented anywhere?
    Thanks.

  • Not sure but the fact that we limit the input value to 20dBm is a documentation in it's own.

    Remember you can control the gain in the FEM and the SoC output power yourself but then you won't get the gain compensation over temperature and frequency.

Related