Fix off frequency transmit. Multiple updates to radio HAL.

pull/4/head
bob 2018-08-05 18:22:05 +10:00
rodzic dc96ff8a8c
commit e8fc1f865e
13 zmienionych plików z 192 dodań i 146 usunięć

Wyświetl plik

@ -119,7 +119,7 @@
#define DEFAULT_OPERATING_FREQ 144800000
#if DEFAULT_OPERATING_FREQ < BAND_MIN_2M_FREQ
#error "Default operating frequency must be an absolute in Hz"
#error "Default operating frequency must be an absolute value in Hz"
#endif
/* Si446x clock setup. */

Wyświetl plik

@ -125,7 +125,7 @@
#define DEFAULT_OPERATING_FREQ 144800000
#if DEFAULT_OPERATING_FREQ < BAND_MIN_2M_FREQ
#error "Default operating frequency must be an absolute in Hz"
#error "Default operating frequency must be an absolute value in Hz"
#endif
/* Si446x clock setup. */

Wyświetl plik

@ -216,8 +216,7 @@ CPPWARN = -Wall -Wextra -Wundef
# List all user C define here, like -D_DEBUG=1
UDEFS = -D_GNU_SOURCE -DARM_MATH_CM4 -DSHELL_CMD_TEST_ENABLED=0 \
-DSHELL_CMD_EXIT_ENABLED=1 -DUSB_TRACE_LEVEL=5 \
-DSHELL_CMD_MEM_ENABLED=0
#-DDISABLE_HW_WATCHDOG=1
-DSHELL_CMD_MEM_ENABLED=0 -DDISABLE_HW_WATCHDOG=1
# Define ASM defines here
UADEFS =

Wyświetl plik

@ -14,10 +14,14 @@
#include <string.h>
#include "pktradio.h"
#include "portab.h"
#include "pktconf.h"
#include "pktservice.h"
static uint32_t lightIntensity;
static uint8_t error;
bool decode_pause;
struct regval_list {
uint16_t reg;
uint8_t val;
@ -744,7 +748,9 @@ uint32_t OV5640_Snapshot2RAM(uint8_t* buffer,
return 0;
}
//const stm32_dma_stream_t *dmastp;
/**
* The pseudo DCMI driver.
*/
#if OV5640_USE_DMA_DBM == TRUE
@ -984,14 +990,20 @@ void vsync_cb(void *arg) {
*/
msg_t OV5640_LockResourcesForCapture(void) {
/* TODO: have to make this a loop which would handle multiple receivers. */
/* Acquire radio after any TX completes. */
/* Acquire radio after any active TX completes. */
msg_t msg = pktAcquireRadio(PKT_RADIO_1, TIME_INFINITE);
if(msg != MSG_OK) {
return msg;
}
if(pktIsReceiveActive(PKT_RADIO_1)) {
pktLLDradioPauseDecoding(PKT_RADIO_1);
decode_pause = true;
} else
decode_pause = false;
I2C_Lock();
pktLLDradioPauseDecoding(PKT_RADIO_1);
//pktLLDradioPauseDecoding(PKT_RADIO_1);
//pktPauseDecoding(PKT_RADIO_1);
/* Hold TRACE output on USB. */
/* if(isUSBactive())
@ -1008,7 +1020,9 @@ void OV5640_UnlockResourcesForCapture(void) {
chMtxUnlock(&trace_mtx);*/
I2C_Unlock();
/* TODO: have to make this a loop which would handle multiple receivers. */
pktLLDradioResumeDecoding(PKT_RADIO_1);
if(pktIsReceivePaused(PKT_RADIO_1) && decode_pause) {
pktLLDradioResumeDecoding(PKT_RADIO_1);
}
//pktResumeDecoding(PKT_RADIO_1);
/* Enable TX tasks to run. */
pktReleaseRadio(PKT_RADIO_1);
@ -1191,7 +1205,7 @@ uint32_t OV5640_Capture(uint8_t* buffer, uint32_t size) {
}
/**
* Initializes GPIO (for pseudo DCMI)
* Initializes GPIO for OV5640 pseudo DCMI
*/
void OV5640_InitGPIO(void)
{
@ -1227,6 +1241,7 @@ void OV5640_TransmitConfig(void)
chThdSleep(TIME_MS2I(500));
/* TODO: Implement a basic JPEG configuration dataset versus using QSXGA. */
TRACE_INFO("CAM > ... Configure JPEG");
for(uint32_t i=0; (OV5640_JPEG_QSXGA[i].reg != 0xffff) || (OV5640_JPEG_QSXGA[i].val != 0xff); i++)
I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_JPEG_QSXGA[i].reg, OV5640_JPEG_QSXGA[i].val);
@ -1321,9 +1336,9 @@ void OV5640_powerup(void) {
// Switch on camera
palSetLine(LINE_CAM_EN); // Switch on camera
chThdSleep(TIME_MS2I(5)); // Spec is >= 1ms delay after DOVDD stable
palSetLine(LINE_CAM_RESET); // Assert reset
palSetLine(LINE_CAM_RESET); // De-assert reset
chThdSleep(TIME_MS2I(50)); // Spec is >= 20ms delay after reset high
chThdSleep(TIME_MS2I(50)); // Spec is >= 20ms delay after reset high to SCCB ready
}

Wyświetl plik

@ -572,19 +572,6 @@ bool Si446x_setBandParameters(const radio_unit_t radio,
radio_freq_t freq,
channel_hz_t step) {
/*
* TODO: The driver should not check for DYNAMIC.
* All frequencies passed to radio should be absolute.
*/
if(freq == FREQ_APRS_DYNAMIC) {
/* Get transmission frequency by geofencing. */
freq = getAPRSRegionFrequency();
/* If using geofence step is not set.
* TODO: Get step from the config for radio.
* Add new function Si446x_getBand(...)
*/
step = 0;
}
/* Check frequency is in range of chip. */
if(freq < 144000000UL || freq > 900000000UL)
return false;
@ -938,12 +925,12 @@ static bool Si446x_checkCCAthreshold(const radio_unit_t radio, uint8_t ms) {
* Wait for a clear time slot and initiate packet transmission.
*/
static bool Si446x_transmit(const radio_unit_t radio,
radio_freq_t freq,
channel_hz_t step,
radio_ch_t chan,
radio_pwr_t power,
uint16_t size,
radio_squelch_t rssi,
const radio_freq_t freq,
const channel_hz_t step,
const radio_ch_t chan,
const radio_pwr_t power,
const uint16_t size,
const radio_squelch_t rssi,
sysinterval_t cca_timeout) {
/* Get an absolute operating frequency in Hz. */
@ -963,8 +950,8 @@ static bool Si446x_transmit(const radio_unit_t radio,
chThdSleep(TIME_MS2I(1));
}
/* Set band parameters. */
Si446x_setBandParameters(radio, freq, step);
/* Frequency is an absolute frequency in Hz. */
Si446x_setBandParameters(radio, op_freq, step);
/* Check for blind send request. */
if(rssi != PKT_SI446X_NO_CCA_RSSI) {
@ -1073,17 +1060,18 @@ bool Si446x_receiveNoLock(const radio_unit_t radio,
}
/*
* Start or restore reception if it was paused for TX.
* Start or restore reception.
*
* return true if RX was enabled and/or resumed OK.
* return false if RX was not enabled.
*/
bool Si4464_resumeReceive(const radio_unit_t radio,
radio_freq_t rx_frequency,
channel_hz_t rx_step,
radio_ch_t rx_chan,
radio_squelch_t rx_rssi,
mod_t rx_mod) {
bool ret = true;
bool Si4464_enableReceive(const radio_unit_t radio,
const radio_freq_t rx_frequency,
const channel_hz_t rx_step,
const radio_ch_t rx_chan,
const radio_squelch_t rx_rssi,
const mod_t rx_mod) {
//bool ret = true;
/* Get an absolute operating frequency in Hz. */
radio_freq_t op_freq = pktComputeOperatingFrequency(radio,
@ -1099,11 +1087,11 @@ bool Si4464_resumeReceive(const radio_unit_t radio,
rx_chan,
rx_rssi, getModulation(rx_mod));
/* Resume reception. */
Si446x_setBandParameters(radio, rx_frequency, rx_step);
ret = Si446x_receiveNoLock(radio, rx_frequency, rx_step,
/* Frequency must be an absolute frequency in Hz. */
if(!Si446x_setBandParameters(radio, op_freq, rx_step))
return false;
return Si446x_receiveNoLock(radio, op_freq, rx_step,
rx_chan, rx_rssi, rx_mod);
return ret;
}
/*
@ -1120,7 +1108,7 @@ void Si446x_disableReceive(const radio_unit_t radio) {
/*
*
*/
void Si446x_pauseReceive(const radio_unit_t radio) {
void Si446x_terminateReceive(const radio_unit_t radio) {
/* FIXME: Should provide status. */
if(Si446x_getState(radio) == Si446x_STATE_RX) {
Si446x_setReadyState(radio);
@ -1128,6 +1116,13 @@ void Si446x_pauseReceive(const radio_unit_t radio) {
}
}
/*
*
*/
void Si446x_terminateTransmit(const radio_unit_t radio) {
/* FIXME: Should provide have timeout. */
while(Si446x_getState(radio) == Si446x_STATE_TX);
}
/*
* AFSK Transmitter
*/
@ -1207,7 +1202,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
rto->step_hz);
/* Set 446x back to READY. */
Si446x_pauseReceive(radio);
Si446x_terminateReceive(radio);
/* Set the radio for AFSK upsampled mode. */
Si446x_setModemAFSK_TX(radio);
@ -1339,7 +1334,7 @@ THD_FUNCTION(bloc_si_fifo_feeder_afsk, arg) {
/* Transmit start failed. */
TRACE_ERROR("SI > Transmit start failed");
exit_msg = MSG_ERROR;
}
} /* End transmit. */
chVTReset(&send_timer);
/*
@ -1455,13 +1450,14 @@ THD_FUNCTION(bloc_si_fifo_feeder_fsk, arg) {
/* We never arrive here. */
}
/* Initialize radio. */
/* Initialize radio.
* TODO: This is redundant as the radio is initialized by the manager. */
Si446x_conditional_init(radio);
/* Set 446x back to READY from RX (if active). */
Si446x_pauseReceive(radio);
Si446x_terminateReceive(radio);
/* Base frequency is an absolute frequency in Hz. */
/* Base frequency must be an absolute frequency in Hz. */
Si446x_setBandParameters(radio, rto->base_frequency, rto->step_hz);
/* Set parameters for 2FSK transmission. */

Wyświetl plik

@ -308,7 +308,7 @@ extern "C" {
bool Si446x_blocSend2FSK(radio_task_object_t *rto);
void Si446x_disableReceive(radio_unit_t radio);
void Si446x_stopDecoder(void);
bool Si4464_resumeReceive(const radio_unit_t radio,
bool Si4464_enableReceive(const radio_unit_t radio,
radio_freq_t rx_frequency,
channel_hz_t rx_step,
radio_ch_t rx_chan,

Wyświetl plik

@ -174,7 +174,8 @@ void pktEnableRadioPWM(const radio_unit_t radio) {
* @post The PWM channel is closed.
* @post All PWM related timers are stopped.
* @post The port for CCA input is disabled.
* @post The ICU remains ready to be restarted.
* @post The ICU capture is stopped.
* @post The ICU remains ready for capture to be restarted.
*
* @param[in] radio radio attached to this PWM handler
*

Wyświetl plik

@ -164,12 +164,14 @@ THD_FUNCTION(pktRadioManager, arg) {
/* The function switches on mod type so no need for switch here. */
switch(task_object->type) {
case MOD_AFSK: {
/* TODO: Add LLD abstraction. */
pktAcquireRadio(radio, TIME_INFINITE);
/* Enable receive. */
if(pktLLDradioEnableReceive(radio, task_object))
pktLLDradioStartDecoder(radio);
if(!pktLLDradioEnableReceive(radio, task_object)) {
TRACE_ERROR("RAD > Receive on radio %d failed to start", radio);
pktReleaseRadio(radio);
break;
}
pktLLDradioStartDecoder(radio);
/* Unlock radio and allow transmit requests. */
pktReleaseRadio(radio);
break;
@ -204,8 +206,12 @@ THD_FUNCTION(pktRadioManager, arg) {
case PKT_RADIO_TX_SEND: {
/* Give each send a sequence number. */
++handler->radio_tx_config.tx_seq_num;
/* Pause the decoder. */
pktLLDradioPauseDecoding(radio);
if(pktIsReceiveActive(radio)) {
/* Pause the decoder. */
pktAcquireRadio(radio, TIME_INFINITE);
pktLLDradioPauseDecoding(radio);
pktReleaseRadio(radio);
}
if(pktLLDradioSendPacket(task_object)) {
/*
* Keep count of active sends.
@ -224,12 +230,15 @@ THD_FUNCTION(pktRadioManager, arg) {
packet_t pp = task_object->packet_out;
pktReleaseBufferChain(pp);
if(pktIsReceivePaused(radio)) {
pktAcquireRadio(radio, TIME_INFINITE);
if(!pktLLDradioResumeReceive(radio)) {
TRACE_ERROR("RAD > Receive on radio %d failed to "
"resume after transmit", radio);
pktReleaseRadio(radio);
break;
}
pktLLDradioResumeDecoding(radio);
pktReleaseRadio(radio);
}
break;
} /* End case PKT_RADIO_TX. */
@ -241,7 +250,9 @@ THD_FUNCTION(pktRadioManager, arg) {
switch(task_object->type) {
case MOD_AFSK: {
/* Stop receive. */
pktAcquireRadio(radio, TIME_INFINITE);
pktLLDradioDisableReceive(radio);
pktReleaseRadio(radio);
/* TODO: This should be a function back in pktservice or rxafsk. */
esp = pktGetEventSource((AFSKDemodDriver *)handler->link_controller);
pktRegisterEventListener(esp, &el, USR_COMMAND_ACK, DEC_CLOSE_EXEC);
@ -577,28 +588,6 @@ void pktSubmitRadioTask(const radio_unit_t radio,
chFifoSendObject(task_queue, object);
}
/**
* @brief Called by transmit threads to schedule release after completing.
* @post A thread release task is posted to the radio manager queue.
*
* @param[in] rto reference to radio task object.
* @param[in] thread thread reference of thread terminating.
*
* @api
*/
void pktLLDradioSendComplete(radio_task_object_t *rto,
thread_t *thread) {
packet_svc_t *handler = rto->handler;
radio_unit_t radio = handler->radio;
/* The handler and radio ID are set in returned object. */
rto->command = PKT_RADIO_TX_THREAD;
rto->thread = thread;
/* Submit guaranteed to succeed by design. */
pktSubmitRadioTask(radio, rto, rto->callback);
}
/**
* @brief Acquire exclusive access to radio.
*
@ -658,7 +647,7 @@ uint8_t pktGetNumRadios(void) {
/**
* @brief Text rendering of frequency code or absolute frequency.
*
* @param[in] buf Pointer to charcater buffer.
* @param[in] buf Pointer to character buffer.
* @param[in] size Size of buffer.
*
* @return Number of characters added to buffer.
@ -724,7 +713,7 @@ radio_freq_t pktGetDefaultOperatingFrequency(const radio_unit_t radio) {
radio_band_t *band = pktCheckAllowedFrequency(radio, conf_sram.freq);
if(band != NULL)
return conf_sram.freq;
radio_config_t *radio_data = pktGetRadioData(radio);
const radio_config_t *radio_data = pktGetRadioData(radio);
if(pktCheckAllowedFrequency(radio, radio_data->def_aprs))
/* Use default APRS frequency in radio configuration. */
return radio_data->def_aprs;
@ -767,9 +756,9 @@ radio_freq_t pktGetReceiveOperatingFrequency(const radio_unit_t radio) {
* @param[in] radio Radio unit ID.
* @param[in] freq Radio frequency in Hz.
*
* @return operating frequency
* @retval an absolute operating frequency in Hz.
* @retval FREQ_RADIO_INVALID if frequency or radio ID is invalid
* @return band object reference
* @retval pointer to band object
* @retval NULL if frequency not valid
*
* @api
*/
@ -791,6 +780,41 @@ radio_band_t *pktCheckAllowedFrequency(const radio_unit_t radio,
return NULL;
}
/**
* @brief Select a radio operable on the required frequency.
* @notes Resolves special frequency codes to absolute frequencies.
*
* @param[in] freq Radio frequency or code in Hz.
* @param[in] step Step size for radio in Hz.
* @param[in] chan Channel for radio.
* @param[in] mode Determines which special codes can be resolved
*
* @return radio unit
* @retval an enumerated radio ID from PKT_RADIO_1 onwards
* @retval PKT_RADIO_NONE if no radio available for the frequency
*
* @api
*/
radio_unit_t pktSelectRadioForFrequency(const radio_freq_t freq,
const channel_hz_t step,
const radio_ch_t chan,
const radio_mode_t mode) {
/* Check for a radio able to operate on the resolved frequency. */
const radio_config_t *radio_data = pktGetRadioList();
while(radio_data->unit != PKT_RADIO_NONE) {
/* Resolve any special codes. */
radio_freq_t op_freq = pktComputeOperatingFrequency(radio_data->unit,
freq,
step,
chan,
mode);
if(pktCheckAllowedFrequency(radio_data->unit, op_freq)) {
return radio_data->unit;
}
} /* End for radios*/
return PKT_RADIO_NONE;
}
/**
* Get radio data.
*/
@ -827,7 +851,7 @@ radio_freq_t pktComputeOperatingFrequency(const radio_unit_t radio,
const radio_mode_t mode) {
if((base_freq == FREQ_APRS_RECEIVE || base_freq == FREQ_APRS_SCAN)
&& mode == RADIO_TX) {
&& (mode == RADIO_TX || mode == RADIO_ALL)) {
/* Get current RX frequency (or default) and use that. */
step = 0;
chan = 0;
@ -931,6 +955,28 @@ bool pktLLDradioSendPacket(radio_task_object_t *rto) {
return status;
}
/**
* @brief Called by transmit threads to schedule release after completing.
* @post A thread release task is posted to the radio manager queue.
*
* @param[in] rto reference to radio task object.
* @param[in] thread thread reference of thread terminating.
*
* @api
*/
void pktLLDradioSendComplete(radio_task_object_t *rto,
thread_t *thread) {
packet_svc_t *handler = rto->handler;
radio_unit_t radio = handler->radio;
/* The handler and radio ID are set in returned object. */
rto->command = PKT_RADIO_TX_THREAD;
rto->thread = thread;
/* Submit guaranteed to succeed by design. */
pktSubmitRadioTask(radio, rto, rto->callback);
}
/**
* @brief Enable reception.
* @notes This is the HAL API to the radio LLD.
@ -953,17 +999,12 @@ bool pktLLDradioEnableReceive(const radio_unit_t radio,
if(handler == NULL)
return false;
Si446x_setBandParameters(radio,
rto->base_frequency,
rto->step_hz);
Si446x_receiveNoLock(radio,
rto->base_frequency,
rto->step_hz,
rto->channel,
rto->squelch,
rto->type);
return true;
return Si4464_enableReceive(radio,
rto->base_frequency,
rto->step_hz,
rto->channel,
rto->squelch,
rto->type);
}
/**
@ -999,7 +1040,7 @@ bool pktLLDradioResumeReceive(const radio_unit_t radio) {
radio_ch_t chan = handler->radio_rx_config.channel;
radio_squelch_t rssi = handler->radio_rx_config.squelch;
mod_t mod = handler->radio_rx_config.type;
bool result = Si4464_resumeReceive(radio, freq, step, chan, rssi, mod);
bool result = Si4464_enableReceive(radio, freq, step, chan, rssi, mod);
return result;
}

Wyświetl plik

@ -113,7 +113,7 @@ struct radioTask {
thread_t *thread;
packet_svc_t *handler;
packet_t packet_out;
uint8_t tx_power;
radio_pwr_t tx_power;
uint32_t tx_speed;
uint8_t tx_seq_num;
};
@ -122,7 +122,7 @@ struct radioTask {
/* External declarations. */
/*===========================================================================*/
extern const ICUConfig pwm_icucfg;
//extern const ICUConfig pwm_icucfg;
#ifdef __cplusplus
extern "C" {
@ -150,6 +150,10 @@ extern "C" {
channel_hz_t step,
radio_ch_t chan,
const radio_mode_t mode);
radio_unit_t pktSelectRadioForFrequency(const radio_freq_t freq,
const channel_hz_t step,
const radio_ch_t chan,
const radio_mode_t mode);
bool pktLLDradioEnableReceive(const radio_unit_t radio,
radio_task_object_t *rto);
void pktLLDradioDisableReceive(const radio_unit_t radio);

Wyświetl plik

@ -366,11 +366,11 @@ void pktStartDecoder(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
//chDbgAssert(handler != NULL, "invalid radio ID");
if(!pktIsReceivePaused(radio))
if(!pktIsReceivePaused(radio)) {
/* Wrong state. */
chDbgAssert(false, "wrong state for decoder start");
return;
}
event_listener_t el;
event_source_t *esp;
@ -465,12 +465,11 @@ void pktStopDecoder(radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
/* if(handler == NULL)
chDbgAssert(false, "invalid radio ID");*/
if(!pktIsReceiveActive(radio))
if(!pktIsReceiveActive(radio)) {
/* Wrong state. */
chDbgAssert(false, "wrong state for decoder stop");
return;
}
event_listener_t el;
event_source_t *esp;

Wyświetl plik

@ -19,28 +19,6 @@
#ifndef PKT_PKTTYPES_H_
#define PKT_PKTTYPES_H_
/*
#ifdef PKT_IS_TEST_PROJECT
// Modulation type.
typedef enum {
MOD_NONE,
MOD_AFSK,
MOD_2FSK
} mod_t;
#endif
*/
/*
#ifdef PKT_IS_TEST_PROJECT
inline const char *getModulation(uint8_t key) {
const char *val[] = {"NONE", "AFSK", "2FSK"};
return val[key];
};
#endif
*/
/* Radio parameters. */
/* Radio frequency in Hz. */
@ -86,7 +64,8 @@ typedef enum radioTypes {
typedef enum radioMode {
RADIO_OFF,
RADIO_RX,
RADIO_TX
RADIO_TX,
RADIO_ALL
} radio_mode_t;
/* Forward declaration. */

Wyświetl plik

@ -431,7 +431,7 @@ static bool transmit_image_packets(const uint8_t *image,
}
if(c == SSDV_EOI) {
TRACE_INFO("SSDV > ssdv_enc_get_packet said EOI");
TRACE_INFO("SSDV > ssdv_enc_get_packet returned EOI");
break;
} else if(c != SSDV_OK) {
TRACE_ERROR("SSDV > ssdv_enc_get_packet failed: %i", c);
@ -571,6 +571,7 @@ uint32_t takePicture(uint8_t* buffer, uint32_t size,
chMtxLock(&camera_mtx);
// Detect camera
/* TODO: Detecting camera powers it up so refactor the below init code? */
if(camInitialized || OV5640_isAvailable()) { // OV5640 available
TRACE_INFO("IMG > OV5640 found");

Wyświetl plik

@ -63,24 +63,21 @@ void mapCallback(pkt_data_object_t *pkt_buff) {
TRACE_INFO("RX > Frame has bad CRC - dropped");
}
}
/**
* TODO: Select a radio based on frequency and start that.
*/
void start_aprs_threads(radio_unit_t radio, radio_freq_t base_freq,
channel_hz_t step,
radio_ch_t chan, radio_squelch_t rssi) {
/* if(base_freq == FREQ_APRS_DYNAMIC) {
base_freq = getAPRSRegionFrequency(); // Get transmission frequency by geofencing
// If using geofence ignore channel and step.
chan = 0;
step = 0;
}*/
if(base_freq == FREQ_APRS_RECEIVE) {
TRACE_ERROR("RX > Cannot specify FREQ_APRS_RECEIVE for receiver");
return;
}
/* Open packet radio service. */
/* Open packet radio service.
* TODO: The parameter should be channel not step.
*/
msg_t omsg = pktOpenRadioReceive(radio,
MOD_AFSK,
base_freq,
@ -105,11 +102,25 @@ void start_aprs_threads(radio_unit_t radio, radio_freq_t base_freq,
/*
*
*/
bool transmitOnRadio(packet_t pp, radio_freq_t base_freq,
channel_hz_t step, radio_ch_t chan,
radio_pwr_t pwr, mod_t mod, radio_squelch_t cca) {
/* TODO: This should select a radio by frequency. For now just use 1. */
radio_unit_t radio = PKT_RADIO_1;
bool transmitOnRadio(packet_t pp, const radio_freq_t base_freq,
const channel_hz_t step, const radio_ch_t chan,
const radio_pwr_t pwr, const mod_t mod,
const radio_squelch_t cca) {
/* Select a radio by frequency. */
radio_unit_t radio = pktSelectRadioForFrequency(base_freq,
step,
chan,
RADIO_TX);
if(radio == PKT_RADIO_NONE) {
char code_s[100];
pktDisplayFrequencyCode(base_freq, code_s, sizeof(code_s));
TRACE_WARN( "RAD > No radio available to transmit on base %s "
"at channel %d)",
code_s, chan);
pktReleaseBufferChain(pp);
return false;
}
if(!pktIsTransmitOpen(radio)) {
TRACE_WARN( "RAD > Transmit is not open on radio");