WIP on abstraction layer for radio LLD.

pull/4/head
bob 2018-08-03 01:09:25 +10:00
rodzic 5b06fd76ef
commit bf655b6d54
15 zmienionych plików z 457 dodań i 273 usunięć

Wyświetl plik

@ -41,13 +41,30 @@ const si446x_mcucfg_t radio1_cfg = {
.nirq = LINE_RADIO_NIRQ,
.sdn = LINE_RADIO_SDN,
.cs = LINE_RADIO_CS,
.spi = PKT_RADIO_SPI
.spi = PKT_RADIO_SPI,
.icu = RADIO1_ICU_DRIVER,
.alt = (PAL_MODE_INPUT | PAL_MODE_ALTERNATE(2)),
.cfg = {
ICU_INPUT_ACTIVE_HIGH,
ICU_COUNT_FREQUENCY, /* ICU clock frequency. */
#if LINE_PWM_MIRROR != PAL_NOLINE
pktRadioICUWidth, /* ICU width callback. */
#else
NULL, /* ICU width callback. */
#endif
pktRadioICUPeriod, /* ICU period callback. */
pktRadioICUOverflow, /* ICU overflow callback. */
ICU_CHANNEL_1, /* Timer channel 0. */
0
}
};
/* Definition of radio specific data for radio on this board. */
si446x_data_t radio1_dat = {
.lastTemp = 0x7FFF
// TODO: Move part and func structs into here and add functions to get
/* TODO: Move part and func structs into here
* Add functions to set/get values
*/
};
/* Radios on this board. */
@ -104,11 +121,11 @@ void pktConfigSerialDiag(void) {
* TODO: Move this into pktradio.c or make it an Si446x function in si446x.c
* The GPIO assignments per radio should be in the radio record.
*/
ioline_t pktSetLineModeICU(const radio_unit_t radio) {
/*ioline_t pktSetLineModeICU(const radio_unit_t radio) {
(void)radio;
palSetLineMode(LINE_ICU, PAL_MODE_INPUT | PAL_MODE_ALTERNATE(2));
return LINE_ICU;
}
}*/
/*
* Read GPIO that are used for:

Wyświetl plik

@ -138,8 +138,8 @@
#define LINE_PWM_MIRROR PAL_NOLINE
/* Radio ports. */
#define LINE_CCA LINE_RADIO_NIRQ
#define LINE_ICU LINE_RADIO_GPIO1
//#define LINE_CCA LINE_RADIO_NIRQ
//#define LINE_ICU LINE_RADIO_GPIO1
//#define LINE_UART4_TX PAL_LINE(GPIOA, 12U)
//#define LINE_UART4_RX PAL_LINE(GPIOA, 11U)
@ -171,8 +171,8 @@
/**
* ICU related definitions.
*/
#define PWM_ICU ICUD4
#define PWM_TIMER_CHANNEL 0
#define RADIO1_ICU_DRIVER &ICUD4
#define PWM_ICU_CLK STM32_TIMCLK1
/* ICU counter frequency. */
@ -280,6 +280,9 @@ extern "C" {
int dbgPrintf(uint8_t level, const char *format, ...);
void pktWrite(uint8_t *buf, uint32_t len);
uint8_t pktReadIOlines(void);
void pktRadioICUWidth(ICUDriver *icup);
void pktRadioICUPeriod(ICUDriver *icup);
void pktRadioICUOverflow(ICUDriver *icup);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -39,9 +39,24 @@ const si446x_mcucfg_t radio1_cfg = {
.gpio2 = PAL_NOLINE,
.gpio3 = PAL_NOLINE,
.nirq = LINE_RADIO_NIRQ,
.spi = PKT_RADIO_SPI,
.sdn = LINE_RADIO_SDN,
.cs = LINE_RADIO_CS,
.spi = PKT_RADIO_SPI,
.icu = RADIO1_ICU_DRIVER,
.alt = (PAL_MODE_INPUT | PAL_MODE_ALTERNATE(2)),
.cfg = {
ICU_INPUT_ACTIVE_HIGH,
ICU_COUNT_FREQUENCY, /* ICU clock frequency. */
#if LINE_PWM_MIRROR != PAL_NOLINE
pktRadioICUWidth, /* ICU width callback. */
#else
NULL, /* ICU width callback. */
#endif
pktRadioICUPeriod, /* ICU period callback. */
pktRadioICUOverflow, /* ICU overflow callback. */
ICU_CHANNEL_1, /* Timer channel 0. */
0
}
};
si446x_data_t radio1_dat = {
@ -49,7 +64,7 @@ si446x_data_t radio1_dat = {
// TODO: Move part and func structs into here and add functions to get
};
/* Radios on this board. */
/* Array of radios on this board. */
const radio_config_t radio_list[] = {
{ /* Radio #1 */
.unit = PKT_RADIO_1,
@ -63,9 +78,12 @@ const radio_config_t radio_list[] = {
}, /* End radio1 */
{
.unit = PKT_RADIO_NONE
}
} /* End radios. */
};
/**
*
*/
const SerialConfig debug_config = {
115200,
0,
@ -100,11 +118,11 @@ void pktConfigSerialDiag(void) {
* TODO: Move this into pktradio.c or make it an Si446x function in si446x.c
* The GPIO assignments per radio should be in the radio record.
*/
ioline_t pktSetLineModeICU(const radio_unit_t radio) {
/*ioline_t pktSetLineModeICU(const radio_unit_t radio) {
(void)radio;
palSetLineMode(LINE_ICU, PAL_MODE_INPUT | PAL_MODE_ALTERNATE(2));
return LINE_ICU;
}
}*/
/*
* Read GPIO that are used for:

Wyświetl plik

@ -137,8 +137,8 @@
#define LINE_PWM_MIRROR PAL_NOLINE
/* Radio ports. */
#define LINE_CCA LINE_RADIO_NIRQ
#define LINE_ICU LINE_RADIO_GPIO1
//#define LINE_CCA LINE_RADIO_NIRQ
//#define LINE_ICU LINE_RADIO_GPIO1
//#define LINE_UART4_TX PAL_LINE(GPIOA, 12U)
//#define LINE_UART4_RX PAL_LINE(GPIOA, 11U)
@ -168,8 +168,8 @@
/**
* ICU related definitions.
*/
#define PWM_ICU ICUD4
#define PWM_TIMER_CHANNEL 0
#define RADIO1_ICU_DRIVER &ICUD4
#define PWM_ICU_CLK STM32_TIMCLK1
/* ICU counter frequency. */
@ -277,6 +277,9 @@ extern "C" {
int dbgPrintf(uint8_t level, const char *format, ...);
void pktWrite(uint8_t *buf, uint32_t len);
uint8_t pktReadIOlines(void);
void pktRadioICUWidth(ICUDriver *icup);
void pktRadioICUPeriod(ICUDriver *icup);
void pktRadioICUOverflow(ICUDriver *icup);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -56,14 +56,14 @@ const conf_t conf_flash_default = {
.img_pri = {
.svc_conf = {
.active = false,
.cycle = CYCLE_CONTINUOUSLY,
.cycle = TIME_S2I(60 * 30),
.init_delay = TIME_S2I(90),
.send_spacing = TIME_S2I(0)
.send_spacing = TIME_S2I(30)
},
.radio_conf = {
.pwr = 0x7F,
.freq = 144800000,
.mod = MOD_2FSK,
.freq = APRS_FREQ_AUSTRALIA,
.mod = MOD_AFSK,
.cca = 0x4F
},
@ -81,8 +81,8 @@ const conf_t conf_flash_default = {
// Secondary image app
.img_sec = {
.svc_conf = {
.active = true,
.cycle = TIME_S2I(60 * 30),
.active = false,
.cycle = TIME_S2I(60 * 15),
.init_delay = TIME_S2I(60 * 1),
.send_spacing = TIME_S2I(30)
},

Wyświetl plik

@ -133,6 +133,7 @@ typedef struct {
char path[16];
resolution_t res; // Picture resolution
uint8_t quality; // SSDV Quality ranging from 0-7
bool flip; // 180 image rotation
uint32_t buf_size; // SRAM buffer size for the picture
} img_app_conf_t;

Wyświetl plik

@ -25,11 +25,9 @@ struct regval_list {
static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
{
{ 0x4740, 0x24 },
{ 0x4740, 0x24 },
{ 0x4050, 0x6e },
{ 0x4051, 0x8f },
{ 0x4051, 0x8f },
{ 0x3008, 0x42 },
{ 0x3103, 0x03 },
{ 0x3017, 0x7f },
@ -73,7 +71,8 @@ static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
{ 0x3c0a, 0x9c },
{ 0x3c0b, 0x40 },
{ 0x3820, 0x47 },
// Mirror and flip
{ 0x3820, 0x40 }, //47
{ 0x3821, 0x00 }, //07
//windows setup
@ -144,7 +143,7 @@ static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
{ 0x4407, 0x04 },
{ 0x460b, 0x35 },
{ 0x460c, 0x22 },//add by bright
{ 0x3824, 0x01 },//add by bright
{ 0x3824, 0x01 },//add by bright
{ 0x5001, 0xa3 },
{ 0x3406, 0x01 },//awbinit
@ -321,18 +320,23 @@ static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
{ 0x4005, 0x1a },
{ 0x3406, 0x00 },//awbinit
{ 0x3503, 0x00 },//awbinit
{ 0x3503, 0x00 },//awbinit
{ 0x3008, 0x02 },
{ 0xffff, 0xff },
{ 0xffff, 0xff } // end
};
/*
* TODO: This resolution configuration is currently used as the JPEG setup.
* There should be a generic JPEG setup.
*/
//2592x1944 QSXGA
static const struct regval_list OV5640_JPEG_QSXGA[] =
{
{0x3820 ,0x47},
{0x3821 ,0x20},
// Mirror and flip
{0x3820 ,0x46}, //46 for flip (was 47)
{0x3821 ,0x20},
{0x3814 ,0x11},
{0x3815 ,0x11},
{0x3803 ,0x00},
@ -366,7 +370,7 @@ static const struct regval_list OV5640_JPEG_QSXGA[] =
{0x3036 ,0x69},
{0x3035 ,0x31},
{0x4005 ,0x1A},
{0xffff, 0xff},
{0xffff, 0xff},
};
//5MP
@ -490,7 +494,7 @@ static const struct regval_list OV5640_QSXGA2VGA[] =
{0x5685 ,0x0 },
{0x5686 ,0x7 },
{0x5687 ,0x98},
{0xffff, 0xff},
{0xffff, 0xff},
};
//800x480 WVGA

Wyświetl plik

@ -1671,7 +1671,72 @@ bool Si446x_blocSend2FSK(radio_task_object_t *rt) {
* Used by collector. At the moment it collects for PKT_RADIO_1 only.
* There should be an LLD API selecting the radio type via VMT etc.
*/
int16_t Si446x_getLastTemperature(const radio_unit_t radio) {
si446x_temp_t Si446x_getLastTemperature(const radio_unit_t radio) {
return Si446x_getData(radio)->lastTemp;
}
/**
*
*/
ICUDriver *Si446x_attachPWM(const radio_unit_t radio) {
/* The RX_RAW_DATA input is routed to ICU timer channel.
* TODO: The STM32 Alternate mode should be in the radio config data.
* Then the ICU GPIO setting can be generalized.
*/
//(void)pktSetLineModeICU(Si446x_getConfig(radio)->gpio1);
pktSetGPIOlineMode(Si446x_getConfig(radio)->gpio1,
Si446x_getConfig(radio)->alt);
/*
* Set up GPIO port where the NIRQ from the radio is connected.
* The NIRQ line is configured in the radio to output the CCA condition.
*/
pktSetGPIOlineMode(Si446x_getConfig(radio)->nirq, PAL_MODE_INPUT_PULLUP);
/*
* Return the ICU this radio is assigned to.
* TODO: Check that the ICU is not already taken?
* This would only be a config error.
* Packet channel control enforces single use of decoder PWM for AFSK.
*/
return Si446x_getConfig(radio)->icu;
}
/**
*
*/
bool Si446x_detachPWM(const radio_unit_t radio) {
(void)radio;
return true;
}
/**
*
*/
const ICUConfig *Si446x_startPWM(const radio_unit_t radio,
palcallback_t cb) {
/* Set callback for squelch events. */
palSetLineCallback(Si446x_getConfig(radio)->nirq, cb,
Si446x_getConfig(radio)->icu);
/* Enabling events on both edges of CCA.*/
palEnableLineEvent(Si446x_getConfig(radio)->nirq,
PAL_EVENT_MODE_BOTH_EDGES);
//extern const ICUConfig pwm_icucfg;
//return &pwm_icucfg;
return &Si446x_getConfig(radio)->cfg;
}
/**
*
*/
void Si446x_stopPWM(radio_unit_t radio) {
palDisableLineEvent(Si446x_getConfig(radio)->nirq);
}
/**
*
*/
uint8_t Si446x_readCCA(const radio_unit_t radio) {
return palReadLine(Si446x_getConfig(radio)->nirq);
}

Wyświetl plik

@ -243,16 +243,19 @@ typedef struct {
uint8_t current_byte;
} up_sampler_t;
/* MCU IO pin assignments for a specific radio. */
/* MCU IO configuration for a specific radio. */
typedef struct Si446x_MCUCFG {
ioline_t gpio0;
ioline_t gpio1;
ioline_t gpio2;
ioline_t gpio3;
ioline_t nirq;
ioline_t sdn;
ioline_t cs;
SPIDriver *spi;
const ioline_t gpio0;
const ioline_t gpio1;
const ioline_t gpio2;
const ioline_t gpio3;
const ioline_t nirq;
const ioline_t sdn;
const ioline_t cs;
SPIDriver *spi;
ICUDriver *icu;
const iomode_t alt; /* Alt GPIO mode used to gate to timer. */
const ICUConfig cfg;
} si446x_mcucfg_t;
/* Configuration of GPIO in a specific radio. */
@ -266,6 +269,8 @@ typedef struct Si446x_GPIO {
uint8_t cfg;
} si446x_gpio_t;
typedef int16_t si446x_temp_t;
/* Si446x part info. */
typedef struct {
uint8_t info[10];
@ -278,7 +283,7 @@ typedef struct {
/* Data associated with a specific radio. */
typedef struct Si446x_DAT {
int16_t lastTemp;
si446x_temp_t lastTemp;
} si446x_data_t;
/* External. */
@ -293,7 +298,7 @@ extern void pktReleasePacketBuffer(packet_t pp);
#ifdef __cplusplus
extern "C" {
#endif
int16_t Si446x_getLastTemperature(const radio_unit_t radio);
si446x_temp_t Si446x_getLastTemperature(const radio_unit_t radio);
bool Si446x_radioStartup(const radio_unit_t radio);
void Si446x_radioShutdown(const radio_unit_t radio);
void Si446x_radioStandby(const radio_unit_t radio);
@ -324,6 +329,11 @@ extern "C" {
radio_freq_t freq,
channel_hz_t step);
radio_signal_t Si446x_getCurrentRSSI(const radio_unit_t radio);
ICUDriver *Si446x_attachPWM(const radio_unit_t radio);
bool Si446x_detachPWM(const radio_unit_t radio);
const ICUConfig *Si446x_startPWM(const radio_unit_t radio, palcallback_t cb);
void Si446x_stopPWM(const radio_unit_t radio);
uint8_t Si446x_readCCA(const radio_unit_t radio);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -155,68 +155,6 @@ AFSKDemodDriver AFSKD1;
/* Decoder local functions. */
/*===========================================================================*/
/**
* @brief Enables PWM stream from radio.
* @post The ICU is configured and started.
* @post The ports and timers for CCA input are configured.
*
* @param[in] myDriver pointer to a @p AFSKDemodDriver structure
*
* @api
*/
/* TODO: Move this into rxpwm.c ?? */
void pktEnablePWM(AFSKDemodDriver *myDriver) {
chDbgAssert(myDriver->icudriver != NULL, "no ICU driver");
/* Set callback for squelch events. */
palSetLineCallback(LINE_CCA, (palcallback_t)pktRadioCCAInput,
myDriver->icudriver);
pktICUStart(myDriver->icudriver);
/* Enabling events on both edges of CCA.*/
palEnableLineEvent(LINE_CCA, PAL_EVENT_MODE_BOTH_EDGES);
myDriver->icustate = PKT_PWM_READY;
}
/**
* @brief Disables PWM stream from 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.
*
* @param[in] myDriver pointer to a @p AFSKDemodDriver structure
* @api
*/
/* TODO: Move this into rxpwm.c ?? */
void pktDisablePWM(AFSKDemodDriver *myDriver) {
chDbgAssert(myDriver->icudriver != NULL, "no ICU driver");
chSysLock();
/* Close the PWM stream. */
pktClosePWMChannelI(myDriver->icudriver, EVT_NONE, PWM_TERM_DECODE_STOP);
/* Stop ICU capture. */
icuStopCaptureI(myDriver->icudriver);
/* Stop any timeouts in ICU handling. */
pktStopAllICUTimersI(myDriver->icudriver);
/* Disable CCA port event. */
palDisableLineEventI(LINE_CCA);
myDriver->icustate = PKT_PWM_STOP;
/* Reschedule is required to avoid a "priority order violation". */
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Check the symbol timing.
*
@ -228,7 +166,7 @@ void pktDisablePWM(AFSKDemodDriver *myDriver) {
*
* @api
*/
bool pktCheckAFSKSymbolTime(AFSKDemodDriver *myDriver) {
static bool pktCheckAFSKSymbolTime(AFSKDemodDriver *myDriver) {
/*
* Each decoder filter is setup at init with a sample source.
* This is set in the filter control structure.
@ -261,7 +199,7 @@ bool pktCheckAFSKSymbolTime(AFSKDemodDriver *myDriver) {
*
* @api
*/
void pktUpdateAFSKSymbolPLL(AFSKDemodDriver *myDriver) {
static void pktUpdateAFSKSymbolPLL(AFSKDemodDriver *myDriver) {
/*
* Increment PLL timing.
*/
@ -288,52 +226,6 @@ void pktUpdateAFSKSymbolPLL(AFSKDemodDriver *myDriver) {
return;
}
/**
* @brief Processes PWM into a decimated time line for AFSK decoding.
* @notes The decimated entries are filtered through a BPF.
*
* @param[in] myDriver pointer to a @p AFSKDemodDriver structure
*
* @return status of operations.
* @retval true no error occurred so decimation can continue at next data.
* @retval false an error occurred and decimation should be aborted.
*
* @api
*/
bool pktProcessAFSK(AFSKDemodDriver *myDriver, min_pwmcnt_t current_tone[]) {
/* Start working on new input data now. */
uint8_t i = 0;
for(i = 0; i < (sizeof(min_pwm_counts_t) / sizeof(min_pwmcnt_t)); i++) {
myDriver->decimation_accumulator += current_tone[i];
while(myDriver->decimation_accumulator >= 0) {
/*
* The decoder will process a converted binary sample.
* The PWM binary is converted to a q31 +/- sample value.
* The sample is passed to pre-filtering (i.e. BPF) as its next input.
*/
(void)pktAddAFSKFilterSample(myDriver, !(i & 1));
/*
* Process the sample at the output side of the pre-filter.
* The filter returns true if its output is now valid.
*/
if(pktProcessAFSKFilteredSample(myDriver)) {
/* Filters are ready so decoding can commence. */
if(pktCheckAFSKSymbolTime(myDriver)) {
/* A symbol is ready to decode. */
if(!pktDecodeAFSKSymbol(myDriver))
/* Unable to store character - buffer full. */
return false;
}
pktUpdateAFSKSymbolPLL(myDriver);
}
myDriver->decimation_accumulator -= myDriver->decimation_size;
} /* End while. Accumulator has underflowed. */
} /* End for. */
return true;
}
/**
* @brief Add a sample to the decoder filter input.
* @notes The decimated entries are filtered through a BPF.
@ -343,7 +235,7 @@ bool pktProcessAFSK(AFSKDemodDriver *myDriver, min_pwmcnt_t current_tone[]) {
*
* @api
*/
void pktAddAFSKFilterSample(AFSKDemodDriver *myDriver, bit_t binary) {
static void pktAddAFSKFilterSample(AFSKDemodDriver *myDriver, bit_t binary) {
switch(AFSK_DECODE_TYPE) {
case AFSK_DSP_QCORR_DECODE: {
(void)push_qcorr_sample(myDriver, binary);
@ -373,7 +265,7 @@ void pktAddAFSKFilterSample(AFSKDemodDriver *myDriver, bit_t binary) {
*
* @api
*/
bool pktProcessAFSKFilteredSample(AFSKDemodDriver *myDriver) {
static bool pktProcessAFSKFilteredSample(AFSKDemodDriver *myDriver) {
/*
* Each decoder filter is setup at init with a sample source.
* This is set in the filter control structure.
@ -413,7 +305,7 @@ bool pktProcessAFSKFilteredSample(AFSKDemodDriver *myDriver) {
*
* @api
*/
bool pktDecodeAFSKSymbol(AFSKDemodDriver *myDriver) {
static bool pktDecodeAFSKSymbol(AFSKDemodDriver *myDriver) {
/*
* Called when a symbol timeline is ready.
* Called from normal thread level.
@ -445,6 +337,52 @@ bool pktDecodeAFSKSymbol(AFSKDemodDriver *myDriver) {
return pktExtractHDLCfromAFSK(myDriver);
} /* End function. */
/**
* @brief Processes PWM into a decimated time line for AFSK decoding.
* @notes The decimated entries are filtered through a BPF.
*
* @param[in] myDriver pointer to a @p AFSKDemodDriver structure
*
* @return status of operations.
* @retval true no error occurred so decimation can continue at next data.
* @retval false an error occurred and decimation should be aborted.
*
* @api
*/
static bool pktProcessAFSK(AFSKDemodDriver *myDriver, min_pwmcnt_t current_tone[]) {
/* Start working on new input data now. */
uint8_t i = 0;
for(i = 0; i < (sizeof(min_pwm_counts_t) / sizeof(min_pwmcnt_t)); i++) {
myDriver->decimation_accumulator += current_tone[i];
while(myDriver->decimation_accumulator >= 0) {
/*
* The decoder will process a converted binary sample.
* The PWM binary is converted to a q31 +/- sample value.
* The sample is passed to pre-filtering (i.e. BPF) as its next input.
*/
(void)pktAddAFSKFilterSample(myDriver, !(i & 1));
/*
* Process the sample at the output side of the pre-filter.
* The filter returns true if its output is now valid.
*/
if(pktProcessAFSKFilteredSample(myDriver)) {
/* Filters are ready so decoding can commence. */
if(pktCheckAFSKSymbolTime(myDriver)) {
/* A symbol is ready to decode. */
if(!pktDecodeAFSKSymbol(myDriver))
/* Unable to store character - buffer full. */
return false;
}
pktUpdateAFSKSymbolPLL(myDriver);
}
myDriver->decimation_accumulator -= myDriver->decimation_size;
} /* End while. Accumulator has underflowed. */
} /* End for. */
return true;
}
/**
* @brief Reset the AFSK decoder and filter.
* @notes Called at completion of packet reception.
@ -454,7 +392,7 @@ bool pktDecodeAFSKSymbol(AFSKDemodDriver *myDriver) {
*
* @api
*/
void pktResetAFSKDecoder(AFSKDemodDriver *myDriver) {
static void pktResetAFSKDecoder(AFSKDemodDriver *myDriver) {
/*
* Called when a decode stream has completed.
* Called from normal thread level.
@ -582,7 +520,7 @@ AFSKDemodDriver *pktCreateAFSKDecoder(packet_svc_t *pktHandler) {
myDriver->active_demod_object = NULL;
/* Attach and initialize the ICU PWM system. */
myDriver->icudriver = pktAttachICU(pktHandler->radio);
myDriver->icudriver = pktAttachRadio(pktHandler->radio);
/* Set the link from ICU driver to AFSK demod driver. */
myDriver->icudriver->link = myDriver;
@ -651,11 +589,13 @@ void pktReleaseAFSKDecoder(AFSKDemodDriver *myDriver) {
chDbgAssert(myDriver->the_pwm_fifo != NULL, "no CCA FIFO");
chDbgAssert(myDriver->icudriver != NULL, "no ICU driver");
/* Stop PWM queue. */
pktDisablePWM(myDriver);
radio_unit_t radio = myDriver->packet_handler->radio;
/* Detach ICU from this AFSK driver. */
pktDetachICU(myDriver->icudriver);
/* Stop PWM queue. */
pktDisableRadioPWM(radio);
/* Detach radio from this AFSK driver. */
pktDetachRadio(radio);
/* Release the PWM FIFO. */
chFactoryReleaseObjectsFIFO(myDriver->the_pwm_fifo);
@ -710,6 +650,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
*/
AFSKDemodDriver *myDriver = arg;
packet_svc_t *myHandler = myDriver->packet_handler;
radio_unit_t radio = myHandler->radio;
/* No active packet object. */
myHandler->active_packet_object = NULL;
@ -750,7 +691,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
eventmask_t evt = chEvtWaitAnyTimeout(DEC_COMMAND_START,
TIME_MS2I(DECODER_WAIT_TIME));
if(evt) {
pktEnablePWM(myDriver);
pktEnableRadioPWM(radio);
myDriver->decoder_state = DECODER_RESET;
pktAddEventFlags(myDriver, DEC_START_EXEC);
break;
@ -781,7 +722,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
*/
eventmask_t evt = chEvtGetAndClearEvents(DEC_COMMAND_STOP);
if(evt) {
pktDisablePWM(myDriver);
pktDisableRadioPWM(radio);
myDriver->decoder_state = DECODER_WAIT;
pktAddEventFlags(myDriver, DEC_STOP_EXEC);
break;

Wyświetl plik

@ -276,6 +276,10 @@ typedef struct AFSK_data {
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
static inline void pktResyncAFSKDecoder(AFSKDemodDriver *myDriver) {
packet_svc_t *myHandler = myDriver->packet_handler;
myDriver->frame_state = FRAME_OPEN;
@ -293,17 +297,8 @@ extern AFSKDemodDriver AFSKD1;
#ifdef __cplusplus
extern "C" {
#endif
void pktAddAFSKFilterSample(AFSKDemodDriver *myDriver, bit_t binary);
bool pktProcessAFSKFilteredSample(AFSKDemodDriver *myDriver);
bool pktDecodeAFSKSymbol(AFSKDemodDriver *myDriver);
bool pktExtractHDLCfromAFSK(AFSKDemodDriver *myDriver);
bool pktProcessAFSK(AFSKDemodDriver *myDriver, min_pwmcnt_t current_tone[]);
AFSKDemodDriver *pktCreateAFSKDecoder(packet_svc_t *pktDriver);
bool pktCheckAFSKSymbolTime(AFSKDemodDriver *myDriver);
void pktUpdateAFSKSymbolPLL(AFSKDemodDriver *myDriver);
void pktReleaseAFSKDecoder(AFSKDemodDriver *myDriver);
void pktResetAFSKDecoder(AFSKDemodDriver *myDriver);
void pktDisablePWM(AFSKDemodDriver *myDriver);
void pktAFSKDecoder(void *arg);
#ifdef __cplusplus
}
@ -311,7 +306,7 @@ extern "C" {
/*
* Test of flow graph and protocol diagrams.
* TODO: Remove or update.
* TODO: Remove or implement.
*/
/**

Wyświetl plik

@ -38,30 +38,6 @@
/* Module exported variables. */
/*===========================================================================*/
/* ICU configuration.
* TODO: Work out where to put this and manage assigning ICU.
* There could be multiple radios so there needs to be an assignment method.
*/
const ICUConfig pwm_icucfg = {
ICU_INPUT_ACTIVE_HIGH,
ICU_COUNT_FREQUENCY, /* ICU clock frequency. */
#if defined(LINE_PWM_MIRROR)
pktRadioICUWidth, /* ICU width callback. */
#else
NULL, /* ICU width callback. */
#endif
pktRadioICUPeriod, /* ICU period callback. */
PktRadioICUOverflow, /* ICU overflow callback. */
#if PWM_TIMER_CHANNEL == 0
ICU_CHANNEL_1, /* Timer channel 0. */
#elif PWM_TIMER_CHANNEL == 1
ICU_CHANNEL_2, /* Timer channel 1. */
#elif
#error PWM_CHANNEL undefined or incorrectly defined
#endif
0
};
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
@ -74,20 +50,13 @@ const ICUConfig pwm_icucfg = {
/* Module local functions. */
/*===========================================================================*/
THD_FUNCTION(pktPWMispatcher, arg) {
(void)arg;
} /* End thread. */
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Initialises and assigns ICU to a Radio.
* @post The ICU is configured and started for a specified radio.
* @brief Attaches decoder to radio hardware according radio config.
* @post The PWM ICU is configured and started for a specified radio.
* @post The ports and timers for CCA input are configured.
*
* @param[in] radio_id radio being started.
@ -96,39 +65,22 @@ THD_FUNCTION(pktPWMispatcher, arg) {
*
* @api
*/
ICUDriver *pktAttachICU(radio_unit_t radio) {
/* For now there is only one radio and a fixed ICU association.
* TODO: Implement Radio <-> ICU association code and data structure.
*/
//(void)radio_id;
ICUDriver *pktAttachRadio(const radio_unit_t radio) {
/*
* Initialize the RX_DATA capture ICU.
* Initialize the association between the radio and the PWM IO.
*/
ICUDriver *myICU = pktLLDradioAttachPWM(radio);
chDbgAssert(myICU != NULL, "no ICU driver");
/* Set the ICU as declared in portab.h. */
ICUDriver *myICU = &PWM_ICU;
icuObjectInit(myICU);
/* The RX_DATA input is routed to ICU timer.
* Set in portab.c
*/
(void)pktSetLineModeICU(radio);
/* If using PWM mirror to output to a diagnostic port. */
pktSetGPIOlineMode(LINE_PWM_MIRROR, PAL_MODE_OUTPUT_PUSHPULL);
/* Initialise the timers. */
/* Initialise the ICU PWM timers. */
chVTObjectInit(&myICU->cca_timer);
chVTObjectInit(&myICU->icu_timer);
chVTObjectInit(&myICU->pwm_timer);
/**
* Set up GPIO port where the NIRQ from the radio is connected.
* The NIRQ line is configured in the radio to output the CCA condition.
*/
pktSetGPIOlineMode(LINE_CCA, PAL_MODE_INPUT_PULLUP);
/* TODO: Implement LLD call to setup indicator LEDs specific to radio. */
/* Setup the squelch LED. */
pktSetGPIOlineMode(LINE_SQUELCH_LED, PAL_MODE_OUTPUT_PUSHPULL);
pktWriteGPIOline(LINE_SQUELCH_LED, PAL_LOW);
@ -141,27 +93,41 @@ ICUDriver *pktAttachICU(radio_unit_t radio) {
pktSetGPIOlineMode(LINE_NO_FIFO_LED, PAL_MODE_OUTPUT_PUSHPULL);
pktWriteGPIOline(LINE_NO_FIFO_LED, PAL_LOW);
/* If using PWM mirror to output to a diagnostic port. */
pktSetGPIOlineMode(LINE_PWM_MIRROR, PAL_MODE_OUTPUT_PUSHPULL);
return myICU;
}
/**
* @brief Detaches the Radio ICU channel.
* @post The ICU is stopped.
* @brief Detaches the Radio from the PWM handlers.
* @post The PWM ICU is stopped.
* @post The GPIO for CCA input is disabled.
* @post The GPIO for LED indicators are disabled.
*
* @param[in] myICU pointer to a @p ICUDriver structure
* @param[in] radio radio attached to this PWM handler
*
* @api
*/
void pktDetachICU(ICUDriver *myICU) {
void pktDetachRadio(const radio_unit_t radio) {
packet_svc_t *myHandler = pktGetServiceObject(radio);
AFSKDemodDriver *myDemod = (AFSKDemodDriver *)myHandler->link_controller;
chDbgAssert(myDemod != NULL, "no demod linked");
chDbgAssert(myICU->link != NULL, "no ICU driver");
/*
* Stop the ICU.
*/
icuStop(myICU);
icuStop(myDemod->icudriver);
/*
* Detach the radio from the PWM handlers.
*/
pktLLDradioDetachPWM(radio);
myDemod->icudriver = NULL;
/* TODO: Implement LLD call to release indicator LEDs specific to radio. */
/* Disable the squelch LED. */
pktUnsetGPIOlineMode(LINE_SQUELCH_LED);
@ -172,7 +138,77 @@ void pktDetachICU(ICUDriver *myICU) {
pktUnsetGPIOlineMode(LINE_NO_FIFO_LED);
/* If using PWM mirror disable diagnostic port. */
pktUnsetGPIOlineMode(PAL_MODE_OUTPUT_PUSHPULL);
pktUnsetGPIOlineMode(LINE_PWM_MIRROR);
}
/**
* @brief Enables PWM stream from radio.
* @post The ICU is configured and started.
* @post The ports and timers for CCA input are configured.
*
* @param[in] radio radio attached to this PWM handler
*
* @api
*/
void pktEnableRadioPWM(const radio_unit_t radio) {
packet_svc_t *myHandler = pktGetServiceObject(radio);
AFSKDemodDriver *myDemod = (AFSKDemodDriver *)myHandler->link_controller;
chDbgAssert(myDemod->icudriver != NULL, "no ICU driver");
/* Enable IO can callbacks. */
const ICUConfig *icucfg = pktLLDradioStartPWM(radio,
(palcallback_t)pktRadioCCAInput);
/* palSetLineCallback(LINE_CCA, (palcallback_t)pktRadioCCAInput,
myDemod->icudriver);*/
//pktICUStart(myDemod->icudriver);
icuStart(myDemod->icudriver, icucfg);
myDemod->icustate = PKT_PWM_READY;
}
/**
* @brief Disables PWM stream from 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.
*
* @param[in] radio radio attached to this PWM handler
*
* @api
*/
void pktDisableRadioPWM(const radio_unit_t radio) {
packet_svc_t *myHandler = pktGetServiceObject(radio);
AFSKDemodDriver *myDemod = (AFSKDemodDriver *)myHandler->link_controller;
chDbgAssert(myDemod->icudriver != NULL, "no ICU driver");
/* Disable CCA line event. */
//palDisableLineEvent(LINE_CCA);
pktLLDradioStopPWM(radio);
/* Stop ICU capture. */
icuStopCapture(myDemod->icudriver);
chSysLock();
/* Stop any timeouts in ICU PWM handling. */
pktStopAllICUtimersI(myDemod->icudriver);
/* Close the PWM stream. */
pktClosePWMchannelI(myDemod->icudriver, EVT_NONE, PWM_TERM_DECODE_STOP);
myDemod->icustate = PKT_PWM_STOP;
/*
* Reschedule is required to avoid a "priority order violation".
* TODO: Investigate the iclass time used. Might be systick related? */
chSchRescheduleS();
chSysUnlock();
}
/**
@ -183,9 +219,9 @@ void pktDetachICU(ICUDriver *myICU) {
*
* @api
*/
void pktICUStart(ICUDriver *myICU) {
/*void pktICUStart(ICUDriver *myICU) {
icuStart(myICU, &pwm_icucfg);
}
}*/
/**
* @brief Terminates the PWM stream from the ICU.
@ -198,7 +234,7 @@ void pktICUStart(ICUDriver *myICU) {
*
* @api
*/
void pktClosePWMChannelI(ICUDriver *myICU, eventflags_t evt, pwm_code_t reason) {
void pktClosePWMchannelI(ICUDriver *myICU, eventflags_t evt, pwm_code_t reason) {
/* Stop posting data and write end marker. */
AFSKDemodDriver *myDemod = myICU->link;
packet_svc_t *myHandler = myDemod->packet_handler;
@ -281,7 +317,7 @@ void pktOpenPWMChannelI(ICUDriver *myICU, eventflags_t evt) {
* Shouldn't happen unless CCA has not triggered an EXTI trailing edge.
* For now just flag that an error condition happened.
*/
pktClosePWMChannelI(myICU, EVT_PWM_FIFO_REMNANT, PWM_TERM_QUEUE_ERR);
pktClosePWMchannelI(myICU, EVT_PWM_FIFO_REMNANT, PWM_TERM_QUEUE_ERR);
return;
}
/* Normal CCA handling. */
@ -448,9 +484,9 @@ void pktICUInactivityTimeout(ICUDriver *myICU) {
*
* @param[in] myICU pointer to a @p ICUDriver structure
*
* @api
* @iclass
*/
void pktStopAllICUTimersI(ICUDriver *myICU) {
void pktStopAllICUtimersI(ICUDriver *myICU) {
chVTResetI(&myICU->icu_timer);
chVTResetI(&myICU->cca_timer);
chVTResetI(&myICU->pwm_timer);
@ -469,7 +505,7 @@ void pktPWMInactivityTimeout(ICUDriver *myICU) {
chSysLockFromISR();
AFSKDemodDriver *myDemod = myICU->link;
if(myDemod->active_radio_object != NULL) {
pktClosePWMChannelI(myICU, EVT_PWM_NO_DATA, PWM_TERM_NO_DATA);
pktClosePWMchannelI(myICU, EVT_PWM_NO_DATA, PWM_TERM_NO_DATA);
}
chSysUnlockFromISR();
}
@ -486,8 +522,9 @@ void pktRadioCCALeadTimer(ICUDriver *myICU) {
chSysLockFromISR();
AFSKDemodDriver *myDemod = myICU->link;
packet_svc_t *myHandler = myDemod->packet_handler;
uint8_t cca = pktLLDradioReadCCA(myHandler->radio);
/* CCA de-glitch timer expired. */
switch(palReadLine(LINE_CCA)) {
switch(cca) {
case PAL_LOW: {
/*
* CAA has dropped so it is a spike.
@ -519,8 +556,9 @@ void pktRadioCCATrailTimer(ICUDriver *myICU) {
chSysLockFromISR();
AFSKDemodDriver *myDemod = myICU->link;
packet_svc_t *myHandler = myDemod->packet_handler;
uint8_t cca = pktLLDradioReadCCA(myHandler->radio);
/* CCA de-glitch timer for trailing edge expired. */
switch(palReadLine(LINE_CCA)) {
switch(cca) {
case PAL_LOW: {
/*
* The decoder operates asynchronously to and usually slower than PWM.
@ -530,7 +568,7 @@ void pktRadioCCATrailTimer(ICUDriver *myICU) {
* This caters for the case where the decoder terminates stream processing first.
* This may happen if noise produces a long string of data.
*/
pktClosePWMChannelI(myICU, EVT_NONE, PWM_TERM_CCA_CLOSE);
pktClosePWMchannelI(myICU, EVT_NONE, PWM_TERM_CCA_CLOSE);
break;
}
@ -547,10 +585,11 @@ void pktRadioCCATrailTimer(ICUDriver *myICU) {
/**
* @brief GPIO callback when CCA edge transitions.
* @notes Both edges are de-glitched by the CCA timer.
* @notes Called from ISR level.
*
* @param[in] myICU pointer to a @p ICUDriver structure
*
* @api
* @isr
*/
void pktRadioCCAInput(ICUDriver *myICU) {
chSysLockFromISR();
@ -560,8 +599,10 @@ void pktRadioCCAInput(ICUDriver *myICU) {
chSysUnlockFromISR();
return;
}
packet_svc_t *myHandler = myDemod->packet_handler;
uint8_t cca = pktLLDradioReadCCA(myHandler->radio);
/* CCA changed. */
switch(palReadLine(LINE_CCA)) {
switch(cca) {
case PAL_LOW: {
if(myDemod->icustate == PKT_PWM_ACTIVE) {
/* CCA trailing edge glitch handling.
@ -650,7 +691,7 @@ void pktRadioICUPeriod(ICUDriver *myICU) {
*
*/
if((myDemod->active_radio_object->status & STA_AFSK_DECODE_DONE) != 0) {
pktClosePWMChannelI(myICU, EVT_NONE, PWM_ACK_DECODE_END);
pktClosePWMchannelI(myICU, EVT_NONE, PWM_ACK_DECODE_END);
chSysUnlockFromISR();
return;
}
@ -661,7 +702,7 @@ void pktRadioICUPeriod(ICUDriver *myICU) {
* Close the PWM stream and wait for next radio CCA.
*/
if((myDemod->active_radio_object->status & STA_AFSK_DECODE_RESET) != 0) {
pktClosePWMChannelI(myICU, EVT_NONE, PWM_ACK_DECODE_ERROR);
pktClosePWMchannelI(myICU, EVT_NONE, PWM_ACK_DECODE_ERROR);
chSysUnlockFromISR();
return;
}
@ -670,7 +711,7 @@ void pktRadioICUPeriod(ICUDriver *myICU) {
* Check if impulse ICU value is zero and thus invalid.
*/
if(icuGetWidthX(myICU) == 0) {
pktClosePWMChannelI(myICU, EVT_NONE, PWM_TERM_ICU_ZERO);
pktClosePWMchannelI(myICU, EVT_NONE, PWM_TERM_ICU_ZERO);
chSysUnlockFromISR();
return;
}
@ -728,7 +769,7 @@ void pktRadioICUPeriod(ICUDriver *myICU) {
* Close channel and write in-band message indicating queue full.
*/
pktWriteGPIOline(LINE_OVERFLOW_LED, PAL_HIGH);
pktClosePWMChannelI(myICU, EVT_PWM_QUEUE_FULL, PWM_TERM_QUEUE_FULL);
pktClosePWMchannelI(myICU, EVT_PWM_QUEUE_FULL, PWM_TERM_QUEUE_FULL);
}
chSysUnlockFromISR();
return;
@ -743,14 +784,14 @@ void pktRadioICUPeriod(ICUDriver *myICU) {
*
* @api
*/
void PktRadioICUOverflow(ICUDriver *myICU) {
void pktRadioICUOverflow(ICUDriver *myICU) {
chSysLockFromISR();
AFSKDemodDriver *myDemod = myICU->link;
/* packet_svc_t *myHandler = myDemod->packet_handler;
pktAddEventFlagsI(myHandler, EVT_ICU_OVERFLOW);*/
if(myDemod->active_radio_object != NULL) {
/* Close the channel and stop ICU notifications. */
pktClosePWMChannelI(myICU, EVT_NONE, PWM_TERM_ICU_OVERFLOW);
pktClosePWMchannelI(myICU, EVT_NONE, PWM_TERM_ICU_OVERFLOW);
} else {
/* Just stop the ICU notification. */
icuDisableNotificationsI(myICU);

Wyświetl plik

@ -275,17 +275,18 @@ static inline msg_t pktWritePWMQueueI(input_queue_t *queue,
#ifdef __cplusplus
extern "C" {
#endif
ICUDriver *pktAttachICU(radio_unit_t radio_id);
void pktDetachICU(ICUDriver *myICU);
void pktICUStart(ICUDriver *myICU);
ICUDriver *pktAttachRadio(const radio_unit_t radio_id);
void pktEnableRadioPWM(const radio_unit_t radio);
void pktDisableRadioPWM(const radio_unit_t radio);
void pktDetachRadio(const radio_unit_t radio_id);
void pktRadioICUWidth(ICUDriver *myICU);
void pktRadioICUPeriod(ICUDriver *myICU);
void PktRadioICUOverflow(ICUDriver *myICU);
void pktRadioICUOverflow(ICUDriver *myICU);
void pktRadioCCAInput(ICUDriver *myICU);
void pktStopAllICUTimersI(ICUDriver *myICU);
void pktStopAllICUtimersI(ICUDriver *myICU);
void pktSleepICUI(ICUDriver *myICU);
msg_t pktQueuePWMDataI(ICUDriver *myICU);
void pktClosePWMChannelI(ICUDriver *myICU, eventflags_t evt,
void pktClosePWMchannelI(ICUDriver *myICU, eventflags_t evt,
pwm_code_t reason);
void pktICUInactivityTimeout(ICUDriver *myICU);
void pktPWMInactivityTimeout(ICUDriver *myICU);

Wyświetl plik

@ -633,14 +633,22 @@ void pktReleaseRadio(const radio_unit_t radio) {
}
/**
* Return pointer to radio object array.
* @brief Return pointer to radio object array for this board.
*
* @param[in] radio radio unit ID.
*
* @api
*/
const radio_config_t *pktGetRadioList(void) {
return radio_list;
}
/**
* Get number of radios for this board type.
* @brief Return number of radios for this board.
*
* @return Number of radios.
*
* @api
*/
uint8_t pktGetNumRadios(void) {
uint8_t i = 0;
@ -648,8 +656,15 @@ uint8_t pktGetNumRadios(void) {
return --i;
}
/*
/**
* @brief Text rendering of frequency code or absolute frequency.
*
* @param[in] buf Pointer to charcater buffer.
* @param[in] size Size of buffer.
*
* @return Number of characters added to buffer.
*
* @api
*/
int pktDisplayFrequencyCode(const radio_freq_t code, char *buf, size_t size) {
char* str = NULL;
@ -1004,7 +1019,6 @@ bool pktLLDradioResumeReceive(const radio_unit_t radio) {
*/
void pktLLDradioCaptureRSSI(const radio_unit_t radio) {
packet_svc_t *handler = pktGetServiceObject(radio);
//chDbgAssert(handler != NULL, "invalid radio ID");
handler->rx_stength = Si446x_getCurrentRSSI(radio);
}
@ -1056,4 +1070,65 @@ void pktLLDradioStopDecoder(const radio_unit_t radio) {
pktStopDecoder(radio);
}
/**
*
*/
ICUDriver *pktLLDradioAttachPWM(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
return Si446x_attachPWM(radio);
}
/**
*
*/
void pktLLDradioDetachPWM(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
(void)radio;
}
/**
*
*/
const ICUConfig *pktLLDradioStartPWM(const radio_unit_t radio,
palcallback_t cb) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only type at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
return Si446x_startPWM(radio, cb);
}
/**
*
*/
void pktLLDradioStopPWM(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
Si446x_stopPWM(radio);
}
/**
*
*/
uint8_t pktLLDradioReadCCA(const radio_unit_t radio) {
/*
* TODO: Implement as VMT inside radio driver (Si446x is only one at present).
* - Lookup radio type from radio ID.
* - Then call VMT dispatcher inside radio driver.
*/
return Si446x_readCCA(radio);
}
/** @} */

Wyświetl plik

@ -122,6 +122,8 @@ struct radioTask {
/* External declarations. */
/*===========================================================================*/
extern const ICUConfig pwm_icucfg;
#ifdef __cplusplus
extern "C" {
#endif
@ -136,7 +138,8 @@ extern "C" {
radio_task_cb_t cb);
void pktScheduleThreadRelease(const radio_unit_t radio,
thread_t *thread);
msg_t pktAcquireRadio(const radio_unit_t radio, sysinterval_t timeout);
msg_t pktAcquireRadio(const radio_unit_t radio,
sysinterval_t timeout);
void pktReleaseRadio(const radio_unit_t radio);
const radio_config_t *pktGetRadioList(void);
uint8_t pktGetNumRadios(void);
@ -162,10 +165,17 @@ extern "C" {
void pktLLDradioStopDecoder(const radio_unit_t radio);
void pktLLDradioSendComplete(radio_task_object_t *rto,
thread_t *thread);
ICUDriver *pktLLDradioAttachPWM(const radio_unit_t radio);
void pktLLDradioDetachPWM(const radio_unit_t radio);
const ICUConfig *pktLLDradioStartPWM(const radio_unit_t radio,
palcallback_t cb);
void pktLLDradioStopPWM(const radio_unit_t radio);
void pktStartDecoder(const radio_unit_t radio);
void pktStopDecoder(const radio_unit_t radio);
int pktDisplayFrequencyCode(radio_freq_t code, char *buf, size_t size);
int pktDisplayFrequencyCode(radio_freq_t code, char *buf,
size_t size);
const radio_config_t *pktGetRadioData(radio_unit_t radio);
uint8_t pktLLDradioReadCCA(const radio_unit_t radio);
#ifdef __cplusplus
}
#endif