Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,10 @@ nRF5340 samples
Peripheral samples
------------------

|no_changes_yet_note|
* :ref:`radio_test` sample:

* Added the new ``start_tx_sweep_with_sleep`` shell command.
It allows for running a TX sweep with silent periods between each frequency.

PMIC samples
------------
Expand Down
3 changes: 3 additions & 0 deletions samples/peripheral/radio_test/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ User interface
* - time_on_channel
- <time>
- Time on each channel in ms (between 1 and 99).
* - start_tx_sweep_with_sleep
- <tx_time> (us) <sleep_time> (us)
- Start TX sweep with a controlled sleep cycle
* - toggle_dcdc_state
- <state>
- Toggle DC/DC converter state.
Expand Down
62 changes: 61 additions & 1 deletion samples/peripheral/radio_test/src/radio_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"Toggle DC/DC state regardless of state value"
#endif


/* Radio parameter configuration. */
static struct radio_param_config {
/** Radio transmission pattern. */
Expand All @@ -55,6 +54,12 @@ static struct radio_param_config {
/** Duty cycle. */
uint32_t duty_cycle;

/** Radio transmission time in us */
uint16_t t_tx_us;

/** Radio sleep time in us */
uint16_t t_sleep_us;

/**
* Number of packets to be received.
* Set to zero for continuous RX.
Expand Down Expand Up @@ -630,6 +635,57 @@ static int cmd_tx_sweep_start(const struct shell *shell, size_t argc,
return 0;
}

static int cmd_tx_sweep_with_sleep_start(const struct shell *shell, size_t argc,
char **argv)
{
if (argc == 1) {
shell_help(shell);
return SHELL_CMD_HELP_PRINTED;
}

if (argc != 3) {
shell_error(shell, "%s: bad parameters count", argv[0]);
return -EINVAL;
}

uint8_t tx_time = atoi(argv[1]);
uint8_t sleep_time = atoi(argv[2]);

const uint8_t min_tx_time_us = 20;
const uint8_t min_sleep_time_us = 80;

if (sleep_time < min_sleep_time_us) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this function you handle the tx_time first, and then sleep_time. It might be more readable if you check the tx time provided first, and then sleep time, just to follow the same pattern.

shell_error(shell, "Too short sleep time: %ius.\nNeeds to be at least: %ius",
sleep_time, min_sleep_time_us);
return -EINVAL;
}

if (tx_time < min_tx_time_us) {
shell_error(shell, "Too short tx time: %ius.\nNeeds to be at least: %ius", tx_time,
min_tx_time_us);
return -EINVAL;
}

config.t_tx_us = tx_time;
config.t_sleep_us = sleep_time;

memset(&test_config, 0, sizeof(test_config));
test_config.type = TX_SWEEP_WITH_SLEEP;
test_config.mode = config.mode;
test_config.params.tx_sweep_duty_cycle.channel_index_start = 0;
test_config.params.tx_sweep_duty_cycle.channel_index_end = 71;
test_config.params.tx_sweep_duty_cycle.t_tx_us = config.t_tx_us;
test_config.params.tx_sweep_duty_cycle.t_sleep_us = config.t_sleep_us;
test_config.params.tx_sweep_duty_cycle.txpower = config.txpower;

radio_test_start(&test_config);

test_in_progress = true;

shell_print(shell, "TX sweep with duty cycle");
return 0;
}

static int cmd_rx_start(const struct shell *shell, size_t argc, char **argv)
{
if (test_in_progress) {
Expand Down Expand Up @@ -1470,6 +1526,10 @@ SHELL_CMD_REGISTER(parameters_print, NULL,
cmd_print);
SHELL_CMD_REGISTER(start_rx_sweep, NULL, "Start RX sweep", cmd_rx_sweep_start);
SHELL_CMD_REGISTER(start_tx_sweep, NULL, "Start TX sweep", cmd_tx_sweep_start);
SHELL_CMD_REGISTER(start_tx_sweep_with_sleep, NULL,
"Start TX sweep with sleep cycle, "
"<tx_time> (us) <sleep_time> (us)",
cmd_tx_sweep_with_sleep_start);
SHELL_CMD_REGISTER(start_rx, NULL, "Start RX", cmd_rx_start);
SHELL_CMD_REGISTER(print_rx, NULL, "Print RX payload", cmd_print_payload);
#if defined(TOGGLE_DCDC_HELP)
Expand Down
68 changes: 65 additions & 3 deletions samples/peripheral/radio_test/src/radio_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,17 @@
#define TIMER_CC1_MOD_TX_DUTY NRF_TIMER_CC_CHANNEL1
#define TIMER_CC2_FEM_0 NRF_TIMER_CC_CHANNEL2
#define TIMER_CC3_FEM_1 NRF_TIMER_CC_CHANNEL3
#define TIMER_CC4_SWEEP_DUTY NRF_TIMER_CC_CHANNEL4
#if NRF54H_ERRATA_216_PRESENT
#define TIMER_CC7_ERRATA216 NRF_TIMER_CC_CHANNEL7
#endif /* NRF54H_ERRATA_216_PRESENT */

/* RX timeout counted from the last packet received. */
#define RX_PACKET_TIMEOUT_MS 100

/* Ramp-up time for radio when using fast ramp. */
#define RADIO_RAMP_UP_FAST_US 40

/* Buffer for the radio TX packet */
static uint8_t tx_packet[RADIO_MAX_PAYLOAD_LEN];
/* Buffer for the radio RX packet. */
Expand All @@ -103,6 +107,12 @@ static uint32_t rx_packet_cnt;
/* Radio current channel (frequency). */
static uint8_t current_channel;

/* Radio TX Sweep with sleep channel array */
const static uint8_t channel_array[72] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78};

/* Timer used for channel sweeps and tx with duty cycle. */
static nrfx_timer_t timer =
NRFX_TIMER_INSTANCE(NRF_TIMER_INST_GET(RADIO_TEST_TIMER_INSTANCE));
Expand Down Expand Up @@ -850,24 +860,31 @@ static void radio_mode_set(NRF_RADIO_Type *reg, nrf_radio_mode_t mode)
mltpan_6(mode);
}

static void radio_unmodulated_tx_carrier(uint8_t mode, int8_t txpower, uint8_t channel)
static void radio_unmodulated_tx_carrier_radio_setup(uint8_t mode, int8_t txpower, uint8_t channel,
bool ready_start_short_enable)
{
radio_disable();

radio_mode_set(NRF_RADIO, mode);
nrf_radio_shorts_enable(NRF_RADIO, NRF_RADIO_SHORT_READY_START_MASK);
radio_power_set(mode, channel, txpower);

radio_channel_set(mode, channel);

if (ready_start_short_enable) {
nrf_radio_shorts_enable(NRF_RADIO, NRF_RADIO_SHORT_READY_START_MASK);
}

#if CONFIG_FEM
(void)fem_configure(false, mode, &fem);
#else
if (sweep_processing) {
radio_ppi_config(false);
}
#endif /* CONFIG_FEM */
}

static void radio_unmodulated_tx_carrier(uint8_t mode, int8_t txpower, uint8_t channel)
{
radio_unmodulated_tx_carrier_radio_setup(mode, txpower, channel, true);
radio_start(false, sweep_processing);
}

Expand Down Expand Up @@ -1052,6 +1069,31 @@ static void radio_modulated_tx_carrier_duty_cycle(uint8_t mode, int8_t txpower,
irq_unlock(key);
}

static void radio_tx_sweep_with_sleep(int8_t txpower, uint16_t t_tx_us, uint16_t t_sleep_us)
{
radio_disable();
const uint32_t total_time_per_channel_us = t_tx_us + t_sleep_us;

current_channel = 0;

nrfx_timer_disable(&timer);
nrf_timer_shorts_disable(timer.p_reg, ~0);
nrf_timer_int_disable(timer.p_reg, ~0);

nrfx_timer_compare(&timer,
TIMER_CC0_SWEEP_DWELL,
nrfx_timer_us_to_ticks(&timer, t_tx_us + RADIO_RAMP_UP_FAST_US),
true);

nrfx_timer_extended_compare(&timer,
TIMER_CC4_SWEEP_DUTY,
nrfx_timer_us_to_ticks(&timer, total_time_per_channel_us),
NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK,
true);

nrfx_timer_enable(&timer);
}

void radio_test_start(const struct radio_test_config *config)
{
#if CONFIG_FEM
Expand Down Expand Up @@ -1099,6 +1141,11 @@ void radio_test_start(const struct radio_test_config *config)
config->params.modulated_tx_duty_cycle.pattern,
config->params.modulated_tx_duty_cycle.duty_cycle);
break;
case TX_SWEEP_WITH_SLEEP:
radio_tx_sweep_with_sleep(config->params.tx_sweep_duty_cycle.txpower,
config->params.tx_sweep_duty_cycle.t_tx_us,
config->params.tx_sweep_duty_cycle.t_sleep_us);
break;
}

test_is_running = true;
Expand Down Expand Up @@ -1221,6 +1268,19 @@ static void timer_handler(nrf_timer_event_t event_type, void *context)

channel_start = config->params.rx_sweep.channel_start;
channel_end = config->params.rx_sweep.channel_end;
} else if (config->type == TX_SWEEP_WITH_SLEEP) {

sweep_processing = true;

/* disable radio after tone */
radio_unmodulated_tx_carrier_radio_setup(NRF_RADIO_MODE_BLE_1MBIT,
Comment thread
eriksandgren marked this conversation as resolved.
config->params.tx_sweep_duty_cycle.txpower,
channel_array[current_channel],
Comment thread
eriksandgren marked this conversation as resolved.
false);

/* set up next channel */
channel_start = config->params.tx_sweep_duty_cycle.channel_index_start;
channel_end = config->params.tx_sweep_duty_cycle.channel_index_end;
} else {
printk("Unexpected test type: %d\n", config->type);
return;
Expand All @@ -1236,6 +1296,8 @@ static void timer_handler(nrf_timer_event_t event_type, void *context)
} else if (event_type == NRF_TIMER_EVENT_COMPARE7) { /* HMPAN-216 errata */
errata_216_release();
#endif /* NRF54H_ERRATA_216_PRESENT */
} else if (event_type == NRF_TIMER_EVENT_COMPARE4) {
radio_start(false, true);
} else {
/* Do nothing */
}
Expand Down
20 changes: 20 additions & 0 deletions samples/peripheral/radio_test/src/radio_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ enum radio_test_mode {

/** Duty-cycled modulated TX carrier. */
MODULATED_TX_DUTY_CYCLE,

/** TX carrier sweep with unmodulated carrier wave */
TX_SWEEP_WITH_SLEEP,
};

/**@brief Radio test front-end module (FEM) configuration */
Expand Down Expand Up @@ -173,6 +176,23 @@ struct radio_test_config {
/** Duty cycle. */
uint32_t duty_cycle;
} modulated_tx_duty_cycle;

struct {
/** Radio output power. */
int8_t txpower;

/** Radio start channel index. */
uint8_t channel_index_start;

/** Radio end channel index. */
uint8_t channel_index_end;

/** Radio transmission time in us. */
uint16_t t_tx_us;

/** Radio sleep time in us. */
uint16_t t_sleep_us;
} tx_sweep_duty_cycle;
} params;

#if CONFIG_FEM
Expand Down
Loading