Hi Nordic QA,
How to add PA in direct_test_mode demo.
I use nrf52832,Need to add Pa control program to complete DTM.

Hi Nordic QA,
How to add PA in direct_test_mode demo.
I use nrf52832,Need to add Pa control program to complete DTM.

Hi,Kenneth.
The FEM used in ou product is SKYWORK RFX2401C, It only have TXEN and RXEN, we already update the project to use the nRF52832 instead and modified as follows,But the TRX_EN GPIO Can't be controlled properly.
Please check it for me, Whether you want to add any changes?
modifiy keys:
APP_ERROR_CHECK(nrf21540_init());
NRF21540_TXEN_PIN,
NRF21540_RXEN_PIN,
#define NRF21540_RXEN_PIN NRF_GPIO_PIN_MAP(0,13)
#define NRF21540_TXEN_PIN NRF_GPIO_PIN_MAP(0,12)
Code:
/**@brief Function for application main entry.
*
* @details This function serves as an adaptation layer between a 2-wire UART interface and the
* dtmlib. After initialization, DTM commands submitted through the UART are forwarded to
* dtmlib and events (i.e. results from the command) is reported back through the UART.
*/
int main(void)
{
uint32_t current_time;
uint32_t dtm_error_code;
uint32_t msb_time = 0; // Time when MSB of the DTM command was read. Used to catch stray bytes from "misbehaving" testers.
bool is_msb_read = false; // True when MSB of the DTM command has been read and the application is waiting for LSB.
uint16_t dtm_cmd_from_uart = 0; // Packed command containing command_code:freqency:length:payload in 2:6:6:2 bits.
uint8_t rx_byte; // Last byte read from UART.
dtm_event_t result; // Result of a DTM operation.
bsp_board_init(BSP_INIT_LEDS);
uart_init();
dtm_error_code = dtm_init();
APP_ERROR_CHECK(nrf21540_init());
#if defined(NRF21540_DRIVER_ENABLE) && (NRF21540_DRIVER_ENABLE == 1)
//Initialization of nRF21540 front-end Bluetooth® range extender chip. Do not use if your hardware doesn't support it.
APP_ERROR_CHECK(nrf21540_init());
#endif
if (dtm_error_code != DTM_SUCCESS)
{
// If DTM cannot be correctly initialized, then we just return.
return -1;
}
for (;;)
{
// Will return every timeout, 625 us.
current_time = dtm_wait();
if (app_uart_get(&rx_byte) != NRF_SUCCESS)
{
// Nothing read from the UART.
continue;
}
if (!is_msb_read)
{
// This is first byte of two-byte command.
is_msb_read = true;
dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
msb_time = current_time;
// Go back and wait for 2nd byte of command word.
continue;
}
// This is the second byte read; combine it with the first and process command
if (current_time > (msb_time + MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE))
{
// More than ~5mS after msb: Drop old byte, take the new byte as MSB.
// The variable is_msb_read will remains true.
// Go back and wait for 2nd byte of the command word.
dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
msb_time = current_time;
continue;
}
// 2-byte UART command received.
is_msb_read = false;
dtm_cmd_from_uart |= (dtm_cmd_t)rx_byte;
if (dtm_cmd(dtm_cmd_from_uart) != DTM_SUCCESS)
{
// Extended error handling may be put here.
// Default behavior is to return the event on the UART (see below);
// the event report will reflect any lack of success.
}
// Retrieve result of the operation. This implementation will busy-loop
// for the duration of the byte transmissions on the UART.
if (dtm_event_get(&result))
{
// Report command status on the UART.
// Transmit MSB of the result.
while (app_uart_put((result >> 8) & 0xFF));
// Transmit LSB of the result.
while (app_uart_put(result & 0xFF));
}
}
}
ret_code_t nrf21540_init(void)
{
driver_reset();
// GPIOTE for PDN pin configuration
nrf_gpiote_task_configure(NRF21540_PDN_GPIOTE_CHANNEL_NO,
NRF21540_PDN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_PDN_GPIOTE_CHANNEL_NO);
nrf21540_gpio_init();
NVIC_SetPriority(NRF21540_TIMER_IRQn, NRF21540_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(NRF21540_TIMER_IRQn);
nrf_timer_int_enable(NRF21540_TIMER, NRF21540_TIM_INTERRUPT_MASK);
#if NRF21540_USE_SPI_MANAGEMENT
ret_code_t ret = NRF_SUCCESS;
ret = nrf21540_spi_init();
if (ret != NRF_SUCCESS)
{
device_state_set(NRF21540_STATE_ERROR);
return ret;
}
#endif //NRF21540_USE_SPI_MANAGEMENT
#if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL,
nrf_radio_event_address_get(NRF_RADIO_EVENT_READY),
(uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_READY_EGU_TASK));
nrf_ppi_channel_enable(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL);
nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL,
nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
(uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_DISABLED_EGU_TASK));
nrf_ppi_channel_enable(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL);
#endif
NVIC_SetPriority(NRF21540_RADIO_IRQn, NRF21540_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(NRF21540_RADIO_IRQn);
return NRF_SUCCESS;
}
void nrf21540_gpio_init(void)
{
nrf_gpio_cfg_output(NRF21540_ANTSEL_PIN);
#if NRF21540_USE_GPIO_MANAGEMENT
nrf_gpio_cfg_output(NRF21540_MODE_PIN);
//GPIOTE for TXEN pin configuration
nrf_gpio_cfg_output(NRF21540_TXEN_PIN);
nrf_gpiote_task_configure(NRF21540_PA_GPIOTE_CHANNEL_NO,
NRF21540_TXEN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_Toggle, //GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_PA_GPIOTE_CHANNEL_NO);
//GPIOTE for RXEN pin configuration
nrf_gpiote_task_configure(NRF21540_LNA_GPIOTE_CHANNEL_NO,
NRF21540_RXEN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_Toggle, //GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_LNA_GPIOTE_CHANNEL_NO);
#endif /*NRF21540_USE_GPIO_MANAGEMENT*/
}
#define NRF21540_RXEN_PIN NRF_GPIO_PIN_MAP(0,13)
#define NRF21540_TXEN_PIN NRF_GPIO_PIN_MAP(0,12)
Hi,Kenneth.
The FEM used in ou product is SKYWORK RFX2401C, It only have TXEN and RXEN, we already update the project to use the nRF52832 instead and modified as follows,But the TRX_EN GPIO Can't be controlled properly.
Please check it for me, Whether you want to add any changes?
modifiy keys:
APP_ERROR_CHECK(nrf21540_init());
NRF21540_TXEN_PIN,
NRF21540_RXEN_PIN,
#define NRF21540_RXEN_PIN NRF_GPIO_PIN_MAP(0,13)
#define NRF21540_TXEN_PIN NRF_GPIO_PIN_MAP(0,12)
Code:
/**@brief Function for application main entry.
*
* @details This function serves as an adaptation layer between a 2-wire UART interface and the
* dtmlib. After initialization, DTM commands submitted through the UART are forwarded to
* dtmlib and events (i.e. results from the command) is reported back through the UART.
*/
int main(void)
{
uint32_t current_time;
uint32_t dtm_error_code;
uint32_t msb_time = 0; // Time when MSB of the DTM command was read. Used to catch stray bytes from "misbehaving" testers.
bool is_msb_read = false; // True when MSB of the DTM command has been read and the application is waiting for LSB.
uint16_t dtm_cmd_from_uart = 0; // Packed command containing command_code:freqency:length:payload in 2:6:6:2 bits.
uint8_t rx_byte; // Last byte read from UART.
dtm_event_t result; // Result of a DTM operation.
bsp_board_init(BSP_INIT_LEDS);
uart_init();
dtm_error_code = dtm_init();
APP_ERROR_CHECK(nrf21540_init());
#if defined(NRF21540_DRIVER_ENABLE) && (NRF21540_DRIVER_ENABLE == 1)
//Initialization of nRF21540 front-end Bluetooth® range extender chip. Do not use if your hardware doesn't support it.
APP_ERROR_CHECK(nrf21540_init());
#endif
if (dtm_error_code != DTM_SUCCESS)
{
// If DTM cannot be correctly initialized, then we just return.
return -1;
}
for (;;)
{
// Will return every timeout, 625 us.
current_time = dtm_wait();
if (app_uart_get(&rx_byte) != NRF_SUCCESS)
{
// Nothing read from the UART.
continue;
}
if (!is_msb_read)
{
// This is first byte of two-byte command.
is_msb_read = true;
dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
msb_time = current_time;
// Go back and wait for 2nd byte of command word.
continue;
}
// This is the second byte read; combine it with the first and process command
if (current_time > (msb_time + MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE))
{
// More than ~5mS after msb: Drop old byte, take the new byte as MSB.
// The variable is_msb_read will remains true.
// Go back and wait for 2nd byte of the command word.
dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
msb_time = current_time;
continue;
}
// 2-byte UART command received.
is_msb_read = false;
dtm_cmd_from_uart |= (dtm_cmd_t)rx_byte;
if (dtm_cmd(dtm_cmd_from_uart) != DTM_SUCCESS)
{
// Extended error handling may be put here.
// Default behavior is to return the event on the UART (see below);
// the event report will reflect any lack of success.
}
// Retrieve result of the operation. This implementation will busy-loop
// for the duration of the byte transmissions on the UART.
if (dtm_event_get(&result))
{
// Report command status on the UART.
// Transmit MSB of the result.
while (app_uart_put((result >> 8) & 0xFF));
// Transmit LSB of the result.
while (app_uart_put(result & 0xFF));
}
}
}
ret_code_t nrf21540_init(void)
{
driver_reset();
// GPIOTE for PDN pin configuration
nrf_gpiote_task_configure(NRF21540_PDN_GPIOTE_CHANNEL_NO,
NRF21540_PDN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_PDN_GPIOTE_CHANNEL_NO);
nrf21540_gpio_init();
NVIC_SetPriority(NRF21540_TIMER_IRQn, NRF21540_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(NRF21540_TIMER_IRQn);
nrf_timer_int_enable(NRF21540_TIMER, NRF21540_TIM_INTERRUPT_MASK);
#if NRF21540_USE_SPI_MANAGEMENT
ret_code_t ret = NRF_SUCCESS;
ret = nrf21540_spi_init();
if (ret != NRF_SUCCESS)
{
device_state_set(NRF21540_STATE_ERROR);
return ret;
}
#endif //NRF21540_USE_SPI_MANAGEMENT
#if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL,
nrf_radio_event_address_get(NRF_RADIO_EVENT_READY),
(uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_READY_EGU_TASK));
nrf_ppi_channel_enable(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL);
nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL,
nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
(uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_DISABLED_EGU_TASK));
nrf_ppi_channel_enable(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL);
#endif
NVIC_SetPriority(NRF21540_RADIO_IRQn, NRF21540_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(NRF21540_RADIO_IRQn);
return NRF_SUCCESS;
}
void nrf21540_gpio_init(void)
{
nrf_gpio_cfg_output(NRF21540_ANTSEL_PIN);
#if NRF21540_USE_GPIO_MANAGEMENT
nrf_gpio_cfg_output(NRF21540_MODE_PIN);
//GPIOTE for TXEN pin configuration
nrf_gpio_cfg_output(NRF21540_TXEN_PIN);
nrf_gpiote_task_configure(NRF21540_PA_GPIOTE_CHANNEL_NO,
NRF21540_TXEN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_Toggle, //GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_PA_GPIOTE_CHANNEL_NO);
//GPIOTE for RXEN pin configuration
nrf_gpiote_task_configure(NRF21540_LNA_GPIOTE_CHANNEL_NO,
NRF21540_RXEN_PIN,
(nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_Toggle, //GPIOTE_CONFIG_POLARITY_None,
NRF_GPIOTE_INITIAL_VALUE_LOW);
nrf_gpiote_task_enable(NRF21540_LNA_GPIOTE_CHANNEL_NO);
#endif /*NRF21540_USE_GPIO_MANAGEMENT*/
}
#define NRF21540_RXEN_PIN NRF_GPIO_PIN_MAP(0,13)
#define NRF21540_TXEN_PIN NRF_GPIO_PIN_MAP(0,12)