#include "pios.h" #ifdef PIOS_INCLUDE_RCVR #include enum pios_rcvr_dev_magic { PIOS_RCVR_DEV_MAGIC = 0x99aabbcc, }; struct pios_rcvr_dev { enum pios_rcvr_dev_magic magic; uint32_t lower_id; const struct pios_rcvr_driver *driver; }; static bool PIOS_RCVR_validate(struct pios_rcvr_dev *rcvr_dev) { return rcvr_dev->magic == PIOS_RCVR_DEV_MAGIC; } #if defined(PIOS_INCLUDE_FREERTOS) static struct pios_rcvr_dev *PIOS_RCVR_alloc(void) { struct pios_rcvr_dev *rcvr_dev; rcvr_dev = (struct pios_rcvr_dev *)pvPortMalloc(sizeof(*rcvr_dev)); if (!rcvr_dev) { return NULL; } rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC; return rcvr_dev; } #else static struct pios_rcvr_dev pios_rcvr_devs[PIOS_RCVR_MAX_DEVS]; static uint8_t pios_rcvr_num_devs; static struct pios_rcvr_dev *PIOS_RCVR_alloc(void) { struct pios_rcvr_dev *rcvr_dev; if (pios_rcvr_num_devs >= PIOS_RCVR_MAX_DEVS) { return NULL; } rcvr_dev = &pios_rcvr_devs[pios_rcvr_num_devs++]; rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC; return rcvr_dev; } #endif /* if defined(PIOS_INCLUDE_FREERTOS) */ /** * Initialises RCVR layer * \param[out] handle * \param[in] driver * \param[in] id * \return < 0 if initialisation failed */ int32_t PIOS_RCVR_Init(uint32_t *rcvr_id, const struct pios_rcvr_driver *driver, uint32_t lower_id) { PIOS_DEBUG_Assert(rcvr_id); PIOS_DEBUG_Assert(driver); struct pios_rcvr_dev *rcvr_dev; rcvr_dev = (struct pios_rcvr_dev *)PIOS_RCVR_alloc(); if (!rcvr_dev) { goto out_fail; } rcvr_dev->driver = driver; rcvr_dev->lower_id = lower_id; *rcvr_id = (uint32_t)rcvr_dev; return 0; out_fail: return -1; } /** * @brief Reads an input channel from the appropriate driver * @param[in] rcvr_id driver to read from * @param[in] channel channel to read * @returns Unitless input value * @retval PIOS_RCVR_TIMEOUT indicates a failsafe or timeout from that channel * @retval PIOS_RCVR_INVALID invalid channel for this driver (usually out of range supported) * @retval PIOS_RCVR_NODRIVER driver was not initialized */ int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel) { // Publicly facing API uses channel 1 for first channel if (channel == 0) { return PIOS_RCVR_INVALID; } else { channel--; } if (rcvr_id == 0) { return PIOS_RCVR_NODRIVER; } struct pios_rcvr_dev *rcvr_dev = (struct pios_rcvr_dev *)rcvr_id; if (!PIOS_RCVR_validate(rcvr_dev)) { /* Undefined RCVR port for this board (see pios_board.c) */ PIOS_Assert(0); } PIOS_DEBUG_Assert(rcvr_dev->driver->read); return rcvr_dev->driver->read(rcvr_dev->lower_id, channel); } /** * @brief Get a semaphore that signals when a new sample is available. * @param[in] rcvr_id driver to read from * @param[in] channel channel to read * @returns The semaphore, or NULL if not supported. */ xSemaphoreHandle PIOS_RCVR_GetSemaphore(uint32_t rcvr_id, uint8_t channel) { // Publicly facing API uses channel 1 for first channel if (channel == 0) { return NULL; } else { channel--; } if (rcvr_id == 0) { return NULL; } struct pios_rcvr_dev *rcvr_dev = (struct pios_rcvr_dev *)rcvr_id; if (!PIOS_RCVR_validate(rcvr_dev)) { /* Undefined RCVR port for this board (see pios_board.c) */ PIOS_Assert(0); } if (rcvr_dev->driver->get_semaphore) { return rcvr_dev->driver->get_semaphore(rcvr_dev->lower_id, channel); } return NULL; } #endif /* PIOS_INCLUDE_RCVR */ /** * @} * @} */