Skip to content

Commit c792074

Browse files
samples: radio_test: adding new test mode for tx sweep
the current TX sweep command in the radio test uses a near 100% duty cycle. Adding a new version of the TX sweep command that allows us to set a TX time and a "wait" time to use controlled duty cycles. Signed-off-by: Thomas Johansen <thomas.johansen@nordicsemi.no>
1 parent 31d6d16 commit c792074

3 files changed

Lines changed: 155 additions & 4 deletions

File tree

samples/peripheral/radio_test/src/radio_cmd.c

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
"Toggle DC/DC state regardless of state value"
3232
#endif
3333

34-
3534
/* Radio parameter configuration. */
3635
static struct radio_param_config {
3736
/** Radio transmission pattern. */
@@ -55,6 +54,12 @@ static struct radio_param_config {
5554
/** Duty cycle. */
5655
uint32_t duty_cycle;
5756

57+
/** Radio transmission time in us */
58+
uint16_t t_tx_us;
59+
60+
/** Radio sleep time in us */
61+
uint16_t t_sleep_us;
62+
5863
/**
5964
* Number of packets to be received.
6065
* Set to zero for continuous RX.
@@ -73,6 +78,8 @@ static struct radio_param_config {
7378
.channel_end = 80,
7479
.delay_ms = 10,
7580
.duty_cycle = 50,
81+
.t_tx_us = 80,
82+
.t_sleep_us = 160,
7683
#if CONFIG_FEM
7784
.fem.tx_power_control = FEM_USE_DEFAULT_TX_POWER_CONTROL
7885
#endif /* CONFIG_FEM */
@@ -215,6 +222,45 @@ static int cmd_data_rate_set(const struct shell *shell, size_t argc,
215222
return 0;
216223
}
217224

225+
static int cmd_sweep_duty_cycle_timings_set(const struct shell *shell, size_t argc,
226+
char **argv)
227+
{
228+
if (argc == 1) {
229+
shell_help(shell);
230+
return SHELL_CMD_HELP_PRINTED;
231+
}
232+
233+
if (argc != 3) {
234+
shell_error(shell, "%s: bad parameters count", argv[0]);
235+
return -EINVAL;
236+
}
237+
238+
if (argc == 3) {
239+
uint8_t tx_time = atoi(argv[1]);
240+
uint8_t sleep_time = atoi(argv[2]);
241+
242+
const uint8_t min_tx_time_us = 20;
243+
const uint8_t min_sleep_time_us = 80;
244+
245+
if (sleep_time < min_sleep_time_us) {
246+
shell_error(shell, "Too short sleep time: %ius.\nNeeds to be at least: %ius", sleep_time,
247+
min_sleep_time_us);
248+
return -EINVAL;
249+
}
250+
251+
if (tx_time < min_tx_time_us) {
252+
shell_error(shell, "Too short tx time: %ius.\nNeeds to be at least: %ius", tx_time,
253+
min_tx_time_us);
254+
return -EINVAL;
255+
}
256+
257+
config.t_tx_us = tx_time;
258+
config.t_sleep_us = sleep_time;
259+
}
260+
261+
return 0;
262+
}
263+
218264
static int cmd_tx_carrier_start(const struct shell *shell, size_t argc,
219265
char **argv)
220266
{
@@ -630,6 +676,26 @@ static int cmd_tx_sweep_start(const struct shell *shell, size_t argc,
630676
return 0;
631677
}
632678

679+
static int cmd_tx_sweep_duty_cycle_start(const struct shell *shell, size_t argc,
680+
char **argv)
681+
{
682+
memset(&test_config, 0, sizeof(test_config));
683+
test_config.type = TX_SWEEP_WITH_DUTY_CYCLE;
684+
test_config.mode = config.mode;
685+
test_config.params.tx_sweep_duty_cycle.channel_index_start = 0;
686+
test_config.params.tx_sweep_duty_cycle.channel_index_end = 71;
687+
test_config.params.tx_sweep_duty_cycle.t_tx_us = config.t_tx_us;
688+
test_config.params.tx_sweep_duty_cycle.t_sleep_us = config.t_sleep_us;
689+
test_config.params.tx_sweep_duty_cycle.txpower = config.txpower;
690+
691+
radio_test_start(&test_config);
692+
693+
test_in_progress = true;
694+
695+
shell_print(shell, "TX sweep with duty cycle");
696+
return 0;
697+
}
698+
633699
static int cmd_rx_start(const struct shell *shell, size_t argc, char **argv)
634700
{
635701
if (test_in_progress) {
@@ -1439,6 +1505,8 @@ SHELL_CMD_REGISTER(cancel, NULL, "Cancel the sweep or the carrier",
14391505
cmd_cancel);
14401506
SHELL_CMD_REGISTER(data_rate, &sub_data_rate, "Set data rate <sub_cmd>",
14411507
cmd_data_rate_set);
1508+
SHELL_CMD_REGISTER(sweep_duty_cycle_timings, NULL, "Set timings for sweep <tx_time> (us) <sleep_time> (us)",
1509+
cmd_sweep_duty_cycle_timings_set);
14421510
SHELL_CMD_REGISTER(start_tx_carrier, NULL, "Start the TX carrier",
14431511
cmd_tx_carrier_start);
14441512
SHELL_CMD_REGISTER(start_tx_modulated_carrier, NULL,
@@ -1470,6 +1538,7 @@ SHELL_CMD_REGISTER(parameters_print, NULL,
14701538
cmd_print);
14711539
SHELL_CMD_REGISTER(start_rx_sweep, NULL, "Start RX sweep", cmd_rx_sweep_start);
14721540
SHELL_CMD_REGISTER(start_tx_sweep, NULL, "Start TX sweep", cmd_tx_sweep_start);
1541+
SHELL_CMD_REGISTER(start_tx_sweep_duty_cycle, NULL, "Start TX sweep with duty cycle", cmd_tx_sweep_duty_cycle_start);
14731542
SHELL_CMD_REGISTER(start_rx, NULL, "Start RX", cmd_rx_start);
14741543
SHELL_CMD_REGISTER(print_rx, NULL, "Print RX payload", cmd_print_payload);
14751544
#if defined(TOGGLE_DCDC_HELP)

samples/peripheral/radio_test/src/radio_test.c

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,17 @@
8484
#define TIMER_CC1_MOD_TX_DUTY NRF_TIMER_CC_CHANNEL1
8585
#define TIMER_CC2_FEM_0 NRF_TIMER_CC_CHANNEL2
8686
#define TIMER_CC3_FEM_1 NRF_TIMER_CC_CHANNEL3
87+
#define TIMER_CC4_SWEEP_DUTY NRF_TIMER_CC_CHANNEL4
8788
#if NRF54H_ERRATA_216_PRESENT
8889
#define TIMER_CC7_ERRATA216 NRF_TIMER_CC_CHANNEL7
8990
#endif /* NRF54H_ERRATA_216_PRESENT */
9091

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

95+
/* Ram-up time for radio when using fast ramp. */
96+
#define RADIO_RAMP_UP_FAST_US 40
97+
9498
/* Buffer for the radio TX packet */
9599
static uint8_t tx_packet[RADIO_MAX_PAYLOAD_LEN];
96100
/* Buffer for the radio RX packet. */
@@ -103,6 +107,12 @@ static uint32_t rx_packet_cnt;
103107
/* Radio current channel (frequency). */
104108
static uint8_t current_channel;
105109

110+
/* Radio Sweep with duty-cycle channel array */
111+
const static uint8_t channel_array[72] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
112+
17, 18, 19, 20, 21, 22, 23, 24, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
113+
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
114+
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78};
115+
106116
/* Timer used for channel sweeps and tx with duty cycle. */
107117
static nrfx_timer_t timer =
108118
NRFX_TIMER_INSTANCE(NRF_TIMER_INST_GET(RADIO_TEST_TIMER_INSTANCE));
@@ -848,24 +858,31 @@ static void radio_mode_set(NRF_RADIO_Type *reg, nrf_radio_mode_t mode)
848858
mltpan_6(mode);
849859
}
850860

851-
static void radio_unmodulated_tx_carrier(uint8_t mode, int8_t txpower, uint8_t channel)
861+
static void radio_unmodulated_tx_carrier_radio_setup(uint8_t mode, int8_t txpower, uint8_t channel,
862+
bool start_ready_short_enable)
852863
{
853864
radio_disable();
854865

855866
radio_mode_set(NRF_RADIO, mode);
856-
nrf_radio_shorts_enable(NRF_RADIO, NRF_RADIO_SHORT_READY_START_MASK);
857867
radio_power_set(mode, channel, txpower);
858-
859868
radio_channel_set(mode, channel);
860869

870+
if (start_ready_short_enable) {
871+
nrf_radio_shorts_enable(NRF_RADIO, NRF_RADIO_SHORT_READY_START_MASK);
872+
}
873+
861874
#if CONFIG_FEM
862875
(void)fem_configure(false, mode, &fem);
863876
#else
864877
if (sweep_processing) {
865878
radio_ppi_config(false);
866879
}
867880
#endif /* CONFIG_FEM */
881+
}
868882

883+
static void radio_unmodulated_tx_carrier(uint8_t mode, int8_t txpower, uint8_t channel)
884+
{
885+
radio_unmodulated_tx_carrier_radio_setup(mode, txpower, channel, true);
869886
radio_start(false, sweep_processing);
870887
}
871888

@@ -1050,6 +1067,31 @@ static void radio_modulated_tx_carrier_duty_cycle(uint8_t mode, int8_t txpower,
10501067
irq_unlock(key);
10511068
}
10521069

1070+
static void radio_tx_sweep_with_sleep(int8_t txpower, uint16_t t_tx_us, uint16_t t_sleep_us)
1071+
{
1072+
radio_disable();
1073+
const uint32_t total_time_per_channel_us = t_tx_us + t_sleep_us;
1074+
1075+
current_channel = 0;
1076+
1077+
nrfx_timer_disable(&timer);
1078+
nrf_timer_shorts_disable(timer.p_reg, ~0);
1079+
nrf_timer_int_disable(timer.p_reg, ~0);
1080+
1081+
nrfx_timer_compare(&timer,
1082+
TIMER_CC0_SWEEP_DWELL,
1083+
nrfx_timer_us_to_ticks(&timer, t_tx_us + RADIO_RAMP_UP_FAST_US),
1084+
true);
1085+
1086+
nrfx_timer_extended_compare(&timer,
1087+
TIMER_CC4_SWEEP_DUTY,
1088+
nrfx_timer_us_to_ticks(&timer, total_time_per_channel_us),
1089+
NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK,
1090+
true);
1091+
1092+
nrfx_timer_enable(&timer);
1093+
}
1094+
10531095
void radio_test_start(const struct radio_test_config *config)
10541096
{
10551097
#if CONFIG_FEM
@@ -1097,6 +1139,11 @@ void radio_test_start(const struct radio_test_config *config)
10971139
config->params.modulated_tx_duty_cycle.pattern,
10981140
config->params.modulated_tx_duty_cycle.duty_cycle);
10991141
break;
1142+
case TX_SWEEP_WITH_DUTY_CYCLE:
1143+
radio_tx_sweep_with_sleep(config->params.tx_sweep_duty_cycle.txpower,
1144+
config->params.tx_sweep_duty_cycle.t_tx_us,
1145+
config->params.tx_sweep_duty_cycle.t_sleep_us);
1146+
break;
11001147
}
11011148

11021149
test_is_running = true;
@@ -1219,6 +1266,19 @@ static void timer_handler(nrf_timer_event_t event_type, void *context)
12191266

12201267
channel_start = config->params.rx_sweep.channel_start;
12211268
channel_end = config->params.rx_sweep.channel_end;
1269+
} else if (config->type == TX_SWEEP_WITH_DUTY_CYCLE) {
1270+
1271+
sweep_processing = true;
1272+
1273+
/* disable radio after tone */
1274+
radio_unmodulated_tx_carrier_radio_setup(NRF_RADIO_MODE_BLE_1MBIT,
1275+
config->params.tx_sweep_duty_cycle.txpower,
1276+
channel_array[current_channel],
1277+
false);
1278+
1279+
/* set up next channel */
1280+
channel_start = config->params.tx_sweep_duty_cycle.channel_index_start;
1281+
channel_end = config->params.tx_sweep_duty_cycle.channel_index_end;
12221282
} else {
12231283
printk("Unexpected test type: %d\n", config->type);
12241284
return;
@@ -1234,6 +1294,8 @@ static void timer_handler(nrf_timer_event_t event_type, void *context)
12341294
} else if (event_type == NRF_TIMER_EVENT_COMPARE7) { /* HMPAN-216 errata */
12351295
errata_216_release();
12361296
#endif /* NRF54H_ERRATA_216_PRESENT */
1297+
} else if (event_type == NRF_TIMER_EVENT_COMPARE4) {
1298+
radio_start(false, true);
12371299
} else {
12381300
/* Do nothing */
12391301
}

samples/peripheral/radio_test/src/radio_test.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ enum radio_test_mode {
6767

6868
/** Duty-cycled modulated TX carrier. */
6969
MODULATED_TX_DUTY_CYCLE,
70+
71+
/** TX carrier sweep with unmodulated carrier wave */
72+
TX_SWEEP_WITH_DUTY_CYCLE,
7073
};
7174

7275
/**@brief Radio test front-end module (FEM) configuration */
@@ -173,6 +176,23 @@ struct radio_test_config {
173176
/** Duty cycle. */
174177
uint32_t duty_cycle;
175178
} modulated_tx_duty_cycle;
179+
180+
struct {
181+
/** Radio output power. */
182+
int8_t txpower;
183+
184+
/** Radio start channel (frequency). */
185+
uint8_t channel_index_start;
186+
187+
/** Radio end channel (frequency). */
188+
uint8_t channel_index_end;
189+
190+
/** Radio transmission time in us */
191+
uint16_t t_tx_us;
192+
193+
/** Radio sleep time in us */
194+
uint16_t t_sleep_us;
195+
} tx_sweep_duty_cycle;
176196
} params;
177197

178198
#if CONFIG_FEM

0 commit comments

Comments
 (0)