kopia lustrzana https://github.com/DL7AD/pecanpico10
WIP on abstraction layer for radio LLD.
rodzic
5b06fd76ef
commit
bf655b6d54
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
/** @} */
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue