#ifdef APP_PA_LNA
nrf_gpio_cfg_output(APP_CPS_PIN);
nrf_gpio_cfg_output(APP_CHL_PIN);
nrf_gpio_pin_set(APP_CHL_PIN); //CHL High = High Power Mode
nrf_gpio_pin_clear(APP_CPS_PIN); //Low = active, High = bypass
pa_lna_prep(APP_PA_PIN,APP_LNA_PIN);
pa_lna_init_sd(APP_PA_PIN,APP_LNA_PIN);
pa_lna_init_thread(APP_PA_PIN,APP_LNA_PIN);
#endif
#include <stdint.h>#include <string.h>#include "fanstel_pa_lna.h"#include "nrf_assert.h"#include "nrf_log.h"#include "ble.h"#include "app_error.h"#include "nrf_drv_gpiote.h"#include "nrf_drv_ppi.h"#include <openthread/platform/platform-fem.h>void pa_lna_prep(uint32_t gpio_pa_pin, uint32_t gpio_lna_pin){ret_code_t err_code;err_code = nrf_drv_gpiote_init();if(err_code != NRF_ERROR_INVALID_STATE)APP_ERROR_CHECK(err_code);nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);err_code = nrf_drv_gpiote_out_init(gpio_pa_pin, &config);APP_ERROR_CHECK(err_code);err_code = nrf_drv_gpiote_out_init(gpio_lna_pin, &config);APP_ERROR_CHECK(err_code);err_code = nrf_drv_ppi_init();if(err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED)APP_ERROR_CHECK(err_code);}void pa_lna_init_sd(uint32_t gpio_pa_pin, uint32_t gpio_lna_pin){ble_opt_t opt;uint32_t gpiote_ch = NULL;ret_code_t err_code;memset(&opt, 0, sizeof(ble_opt_t));nrf_ppi_channel_t ppi_set_ch;nrf_ppi_channel_t ppi_clr_ch;err_code = nrf_drv_ppi_channel_alloc(&ppi_set_ch);APP_ERROR_CHECK(err_code);err_code = nrf_drv_ppi_channel_alloc(&ppi_clr_ch);APP_ERROR_CHECK(err_code);if((gpio_pa_pin == NULL) && (gpio_lna_pin == NULL)){err_code = NRF_ERROR_INVALID_PARAM;APP_ERROR_CHECK(err_code);}if(gpio_pa_pin != NULL){if(gpiote_ch == NULL){gpiote_ch = nrf_drv_gpiote_out_task_addr_get(gpio_pa_pin);}// PA configopt.common_opt.pa_lna.pa_cfg.active_high = 1; // Set the pin to be active highopt.common_opt.pa_lna.pa_cfg.enable = 1; // Enable togglingopt.common_opt.pa_lna.pa_cfg.gpio_pin = gpio_pa_pin; // The GPIO pin to toggle tx}if(gpio_lna_pin != NULL){if(gpiote_ch == NULL){gpiote_ch = nrf_drv_gpiote_out_task_addr_get(gpio_lna_pin);}// LNA configopt.common_opt.pa_lna.lna_cfg.active_high = 1; // Set the pin to be active highopt.common_opt.pa_lna.lna_cfg.enable = 1; // Enable togglingopt.common_opt.pa_lna.lna_cfg.gpio_pin = gpio_lna_pin; // The GPIO pin to toggle rx}// Common PA/LNA configopt.common_opt.pa_lna.gpiote_ch_id = (gpiote_ch - NRF_GPIOTE_BASE) >> 2; // GPIOTE channel used for radio pin togglingopt.common_opt.pa_lna.ppi_ch_id_clr = ppi_clr_ch; // PPI channel used for radio pin clearingopt.common_opt.pa_lna.ppi_ch_id_set = ppi_set_ch; // PPI channel used for radio pin settingerr_code = sd_ble_opt_set(BLE_COMMON_OPT_PA_LNA, &opt);APP_ERROR_CHECK(err_code);if (err_code == NRF_SUCCESS){NRF_LOG_DEBUG("PA/LNA Successfully Enabled for BLE");}return;}void pa_lna_init_thread(uint32_t gpio_pa_pin, uint32_t gpio_lna_pin){PlatformFemConfigParams cfg;uint32_t gpiote_ch_pa = NULL;uint32_t gpiote_ch_lna = NULL;ret_code_t err_code;memset(&cfg, 0, sizeof(cfg));// Get some PPI channels to usenrf_ppi_channel_t ppi_set_ch;nrf_ppi_channel_t ppi_clr_ch;err_code = nrf_drv_ppi_channel_alloc(&ppi_set_ch);APP_ERROR_CHECK(err_code);err_code = nrf_drv_ppi_channel_alloc(&ppi_clr_ch);APP_ERROR_CHECK(err_code);if(gpio_pa_pin != NULL){if(gpiote_ch_pa == NULL){gpiote_ch_pa = nrf_drv_gpiote_out_task_addr_get(gpio_pa_pin);}// PA configcfg.mPaCfg.mEnable = 1;cfg.mPaCfg.mActiveHigh = 1;cfg.mPaCfg.mGpioPin = gpio_pa_pin;}if(gpio_lna_pin != NULL){if(gpiote_ch_lna == NULL){gpiote_ch_lna = nrf_drv_gpiote_out_task_addr_get(gpio_lna_pin);}// LNA configcfg.mLnaCfg.mEnable = 1;cfg.mLnaCfg.mActiveHigh = 1;cfg.mLnaCfg.mGpioPin = gpio_lna_pin;}cfg.mPpiChIdClr = ppi_clr_ch;cfg.mPpiChIdSet = ppi_set_ch;//cfg.mGpiotePaChId = gpiote_ch_pa;cfg.mGpiotePaChId = (gpiote_ch_pa - NRF_GPIOTE_BASE) >> 2; // GPIOTE channel used for pa pin toggling//cfg.mGpioteLnaChId = gpiote_ch_lna;cfg.mGpiotePaChId = (gpiote_ch_lna - NRF_GPIOTE_BASE) >> 2; // GPIOTE channel used for pa pin togglingPlatformFemSetConfigParams(&cfg);return;}
USB840X-V6 with BT840X-V5 module and USB840F-V6 with BT840X-V4 module
If it is so that not enabled PA is reducing the signal strength USB840F-BT840F should give a little better result (version without front end module).
Regards, Pawel
Stuart,
Thanks for all of your previous help. I recently doubled back to your posts on using the Fanstel BT840X variants with FEM. I am also following your issue https://github.com/openthread/openthread/issues/4995 and your related fork https://github.com/vrtsystems/openthread/tree/feature/fanstel-bt840x.
I see that you were working on this as recently as Aug 2020, but the Google group posts on the subject are from late 2019. In this post from Dec 5, 2019, you were seeing a 12dB discrepancy in power compared to a TI design. More recently, in issue 4995, you report success in the field with your forked code, where the comments show that you’re seeing about 22dBm ( 14dBm PA gain plus 8dBm from the radio) – this seems to correspond roughly to the +21dBm max output of the SKY66112-11 (I suppose it saturates?).
I assume you’re controlling the power of the radio itself thru the NCP’s API (wpantund, ot-agent). With your fork and its changes in radio.c, it appears that we should be passing the value desired *after* the PA (e.g., +22dBm) and should let radio.c and the 802.15.4 correct this and set the nrf52 accordingly. Can you confirm my understanding?
FYI, I am using the BT840X on a Pi HAT I designed, using RCP over SPI, not on the USB840X -- so I build with a couple of different switches.
Thanks,
Rob