1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/include/nrf24l01p_ng.h
Marian Buschsieweke c3500eb6e0
tree wide: fix typos in comments found by codespell
This will not change generated binaries, only the Doxygen output and
source code will have less typos.
2023-05-02 09:52:06 +02:00

480 lines
15 KiB
C

/*
* Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_nrf24l01p_ng NRF24L01+ (NG) 2.4 GHz trasceiver driver
* @ingroup drivers_netdev
*
* This module contains the driver for the NRF24L01+ (NG) 2.4 GHz
* transceiver.
*
* @{
* @file
* @brief Public interface for NRF24L01+ (NG) devices
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*/
#ifndef NRF24L01P_NG_H
#define NRF24L01P_NG_H
#include <stdint.h>
#include "board.h"
#include "kernel_defines.h"
#include "net/gnrc/nettype.h"
#include "net/netdev.h"
#include "periph/gpio.h"
#include "periph/spi.h"
#include "nrf24l01p_ng_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Minimum width of a NRF24L01+ layer-2 address
*/
#define NRF24L01P_NG_MIN_ADDR_WIDTH (3)
/**
* @brief Maximum width of a NRF24L01+ layer-2 address
*/
#define NRF24L01P_NG_MAX_ADDR_WIDTH (5)
/**
* @brief Pass the compiler a definition of NRF24L01P_NG_ADDR_WIDTH to configure
* the layer-2 address width of this transceiver.
*/
#ifndef NRF24L01P_NG_ADDR_WIDTH
#define NRF24L01P_NG_ADDR_WIDTH NRF24L01P_NG_MAX_ADDR_WIDTH
#elif (NRF24L01P_NG_ADDR_WIDTH < NRF24L01P_NG_MIN_ADDR_WIDTH) || \
(NRF24L01P_NG_ADDR_WIDTH > NRF24L01P_NG_MAX_ADDR_WIDTH)
#error "NRF24L01P_NG_ADDR_WIDTH must be within [3, 5]"
#endif
/**
* @brief Agreed layer-2 address to send broadcast frames to
*
* The broadcast address will be assigned to pipe 0.
*/
#define NRF24L01P_NG_BROADCAST_ADDR { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
/**
* @brief Shortcut to access the address of pipe 0
*/
#define NRF24L01P_NG_ADDR_P0(dev) ((dev)->arxaddr.rx_addr_long[NRF24L01P_NG_P0])
/**
* @brief Shortcut to access the address of pipe 1
*/
#define NRF24L01P_NG_ADDR_P1(dev) ((dev)->arxaddr.rx_addr_long[NRF24L01P_NG_P1])
/**
* @brief Shortcut to access the least significant byte of the
* addresses pipe 2, pipe 3, pipe 4 or pipe 5
*
* The other bytes are shared with the address of pipe 1
*/
#define NRF24L01P_NG_ADDR_PX_LSB(dev, pipe) ((dev)->arxaddr.rx_addr_short[(pipe) - 2])
/**
* @brief Struct that holds all active configuration values
*/
typedef struct __attribute__((packed)) {
/**
* @brief padding
*/
uint8_t : 1;
/**
* @brief Current channel
*/
uint8_t cfg_channel : 7;
/**
* @brief padding
*/
uint8_t : 2;
/**
* @brief Current CRC length configuration value
* @see nrf24l01p_ng_crc_t
*/
uint8_t cfg_crc : 2;
/**
* @brief Current tx power configuration value
* @see nrf24l01p_ng_tx_power_t
*/
uint8_t cfg_tx_power : 2;
/**
* @brief Current data rate configuration value
* @see nrf24l01p_ng_rfdr_t
*/
uint8_t cfg_data_rate : 2;
/**
* @brief Current maximum number of retransmissions
*/
uint8_t cfg_max_retr : 4;
/**
* @brief Current retransmission delay configuration value
* @see nrf24l01p_ng_ard_t
*/
uint8_t cfg_retr_delay : 4;
} nrf24l01p_ng_cfg_t;
/**
* @brief Struct of NRF24L01+ initialization parameters
*/
typedef struct {
spi_t spi; /**< SPI bus */
spi_clk_t spi_clk; /**< SPI clock speed */
gpio_t pin_cs; /**< SPI chip select gpio pin */
gpio_t pin_ce; /**< NRF24L01+ chip enable gpio pin */
gpio_t pin_irq; /**< NRF24L01+ IRQ gpio pin */
nrf24l01p_ng_cfg_t config; /**< Current configuration values */
} nrf24l01p_ng_params_t;
/**
* @brief NRF24L01+ device struct
*/
struct nrf24l01p_ng {
netdev_t netdev; /**< Netdev member */
nrf24l01p_ng_params_t params; /**< Parameters */
uint8_t state; /**< Current operation state */
uint8_t idle_state; /**< State to return to after sending */
/**
* @brief Rx addresses
*
* The NRF24L01+ has 6 data pipes.
* Each data pipe has a unique address.
* The address of a pipe can be 3 to 5 bytes long
* but must be equal for all pipes.
* The addresses of pipe 0 and pipe 1 can be arbitrary while the addresses
* of pipe 2 to pipe 5 share the most significant bytes, thus they only
* differ in the least significant byte.
* The least significant byte must be different for all pipes.
*
* Data pipe 0 is also the Tx pipe.
* That means if you want to send a frame, you must assign to pipe 0
* the address of the recipient. After a transmission if you want to
* continue listening on pipe 0, the address of pipe 0 must be restored.
*/
struct {
/**
* @brief Array to access the addresses of pipe 0 and pipe 1 via
* pipe indices @see nrf24l01p_ng_pipe_t
*/
uint8_t rx_addr_long[2][NRF24L01P_NG_ADDR_WIDTH];
/**
* @brief Array to access the addresses of pipe 2, pipe 3,
* pipe 4 and pipe 5 via pipe indices
* @see nrf24l01p_ng_pipe_t
*/
uint8_t rx_addr_short[4];
} arxaddr;
};
/**
* @brief Setup the NRF24L01+ driver, but perform no initialization
*
* @ref netdev_driver_t::init can be used after this call to initialize the
* transceiver.
*
* @param[in] dev NRF24L01+ device handle
* @param[in] params Parameters of the device to setup
* @param[in] index Index of @p params in a global parameter struct array.
* If initialized manually, pass a unique identifier instead.
*
* @retval 0 Device successfully set up
*/
int nrf24l01p_ng_setup(nrf24l01p_ng_t *dev,
const nrf24l01p_ng_params_t *params,
uint8_t index);
/**
* @brief Enable or disable data pipe @p pipe
*
* If @p pipe should be enabled, it is advised to
* set an address in advance.
* @see nrf24l01p_ng_set_rx_addr
* For Enhanced ShockBurst, auto ACK and dynamic
* payload length are enabled
*
* @param[in] dev NRF24L01+ device handle
* @param[in] pipe Pipe index
* @param[in] enable If pipe should be enabled or disabled
*
* @retval 0 Success
* @retval -EINVAL Bad pipe index
*/
int nrf24l01p_ng_set_enable_pipe(nrf24l01p_ng_t *dev, nrf24l01p_ng_pipe_t pipe,
bool enable);
/**
* @brief Query if data pipe @p pipe is enabled
*
* @param[in] dev NRF24L01+ device handle
* @param[in] pipe Pipe index
* @param[out] enable If pipe is enabled or disabled
*
* @retval 0 Success
* @retval -EINVAL Bad pipe index
*/
int nrf24l01p_ng_get_enable_pipe(nrf24l01p_ng_t *dev, nrf24l01p_ng_pipe_t pipe,
bool* enable);
/**
* @brief Configure air data rate
*
* @param[in] dev NRF24L01+ device handle
* @param[in] data_rate Data rate configuration value
*
* @retval 0 Success
* @retval -EINVAL Bad data rate value
* @retval -EAGAIN Current state does not permit changing data rate
*/
int nrf24l01p_ng_set_air_data_rate(nrf24l01p_ng_t *dev,
nrf24l01p_ng_rfdr_t data_rate);
/**
* @brief Get currently configured data rate
*
* @param[in] dev NRF24L01+ device handle
* @param[out] data_rate Configuration data rate value (may be NULL)
*
* @return Data rate in [kbit/s]
*/
uint16_t nrf24l01p_ng_get_air_data_rate(const nrf24l01p_ng_t *dev,
nrf24l01p_ng_rfdr_t *data_rate);
/**
* @brief Configure CRC length
*
* @param[in] dev NRF24L01+ device handle
* @param[in] crc Configuration CRC value
*
* @retval 0 Success
* @retval -EINVAL Bad CRC configuration value
* @retval -ENOTSUP CRC length not supported
* @retval -EAGAIN Current state does not permit changing CRC length
*/
int nrf24l01p_ng_set_crc(nrf24l01p_ng_t *dev, nrf24l01p_ng_crc_t crc);
/**
* @brief Get currently configured CRC length
*
* @param[in] dev NRF24L01+ device handle
* @param[out] crc Configuration crc value (may be NULL)
*
* @return Current CRC length
*/
uint8_t nrf24l01p_ng_get_crc(const nrf24l01p_ng_t *dev,
nrf24l01p_ng_crc_t *crc);
/**
* @brief Configure Tx trasceiver power
*
* @param[in] dev NRf24L01+ device handle
* @param[in] power Configuration Tx power value
*
* @retval 0 Success
* @retval -EINVAL Bad Tx power configuration value
* @retval -EAGAIN Current state does not permit changing Tx power
*/
int nrf24l01p_ng_set_tx_power(nrf24l01p_ng_t *dev,
nrf24l01p_ng_tx_power_t power);
/**
* @brief Get currently configured Tx transceiver power
*
* @param[in] dev NRF24L01+ device handle
* @param[out] power Configuration Tx power value
*
* @return Tx power in [dbm]
*/
int8_t nrf24l01p_ng_get_tx_power(const nrf24l01p_ng_t *dev,
nrf24l01p_ng_tx_power_t *power);
/**
* @brief Set transceiver channel
*
* @param[in] dev NRF24l01+ device handle
* @param[in] channel Channel [0; 15]
*
* @retval 0 Success
* @retval -EINVAL Bad channel
* @retval -EAGAIN Current state does not permit switching channel
*/
int nrf24l01p_ng_set_channel(nrf24l01p_ng_t *dev, uint8_t channel);
/**
* @brief Get currently configured transceiver channel
*
* @param[in] dev NRF24L01+ device handle
*
* @return Transceiver channel
*/
uint8_t nrf24l01p_ng_get_channel(const nrf24l01p_ng_t *dev);
/**
* @brief Set Rx address of a certain data pipe
*
* If you want to set the address of pipe 2, 3, 4 or 5
* you only set the LSB because the other bytes are
* equal to the address of pipe 1.
*
* For pipe 0 and 1 NRF24L01P_NG_ADDR_WIGTH bytes are expected
*
* @param[in] dev NRF24L01+ device handle
* @param[in] addr Rx address
* @param[in] pipe Pipe index
*
* @retval 0 Success
* @retval -EINVAL Bad address length
* @return -EAGAIN Current state does not permit changing Rx address
*/
int nrf24l01p_ng_set_rx_address(nrf24l01p_ng_t *dev, const uint8_t *addr,
nrf24l01p_ng_pipe_t pipe);
/**
* @brief Get current Rx address of a certain data pipe
*
* @p addr must be at least NRF24L01P_NG_ADDR_WIDTH wide.
*
* @param[in] dev NRF24L01+ device handle
* @param[out] addr Rx address
* @param[in] pipe Pipe index
*
* @return Address width
* @retval -EINVAL Bad pipe index
*/
int nrf24l01p_ng_get_rx_address(const nrf24l01p_ng_t *dev, uint8_t *addr,
nrf24l01p_ng_pipe_t pipe);
/**
* @brief Configure maximum number of retransmissions for ESB
*
* @param[in] dev NRF24L01+ device handle
* @param[in] max_rt Number of maximum retransmissions [0; 15]
*
* @retval 0 Success
* @retval -EINVAL Unsupported number of retransmissions
* @retval -EAGAIN Current state does not permit changing
* the maximum number of retransmissions
*/
int nrf24l01p_ng_set_max_retransm(nrf24l01p_ng_t *dev, uint8_t max_rt);
/**
* @brief Get currently configured number of maximum retransmissions for ESB
*
* @param[in] dev NRF24L01+ device handle
*
* @return Maximum number of retransmissions
*/
uint8_t nrf24l01p_ng_get_max_retransm(const nrf24l01p_ng_t *dev);
/**
* @brief Set retransmission delay for ESB
*
* @param[in] dev NRF24L01+ device handle
* @param[in] rt_delay Configuration retransmission delay value
*
* @return 0
* @return -EINVAL Bad retransmission delay value
* @return -EAGAIN Current state does not permit changing
* retransmission delay
*/
int nrf24l01p_ng_set_retransm_delay(nrf24l01p_ng_t *dev,
nrf24l01p_ng_ard_t rt_delay);
/**
* @brief Get retransmission delay for ESB
*
* @param[in] dev NRF24L01+ device handle
* @param[out] rt_delay Configuration retransmission delay value
*
* @return Retransmission delay in [us]
*/
uint16_t nrf24l01p_ng_get_retransm_delay(const nrf24l01p_ng_t *dev,
nrf24l01p_ng_ard_t *rt_delay);
/**
* @brief Put device into
* sleep mode(@ref NRF24L01P_NG_STATE_POWER_DOWN),
* standby mode (@ref NRF24L01P_NG_STATE_STANDBY_1),
* or Rx mode (@ref NRF24L01P_NG_STATE_RX_MODE)
*
* @param[in] dev NRF24L01+ device handle
* @param[in] state State
*
* @return Old state
* @retval -EAGAIN Device is currently not permitted to change state
* @retval -ENOTSUP Device is not permitted to change state to @p state
*/
int nrf24l01p_ng_set_state(nrf24l01p_ng_t *dev, nrf24l01p_ng_state_t state);
/**
* @brief Get current device state
*
* @param[in] dev NRf24L01+ device handle
*
* @return Device state
*/
nrf24l01p_ng_state_t nrf24l01p_ng_get_state(const nrf24l01p_ng_t *dev);
/**
* @brief Retrieve a unique layer-2 address for an nrf24l01p_ng instance
*
* @note This function has __attribute__((weak)) so you can override this, e.g.
* to construct an address. By default @ref luid_get_lb is used.
*
* @param[in] dev The device descriptor of the transceiver
* @param[out] eui Destination to write the address to
*/
void nrf24l01p_ng_eui_get(const netdev_t *dev, uint8_t *eui);
#if IS_USED(MODULE_NRF24L01P_NG_DIAGNOSTICS)
/**
* @brief Get state variable as a string
*
* @param[in] state State
*
* @return @p state as a string
*/
const char *
nrf24l01p_ng_diagnostics_state_to_string(nrf24l01p_ng_state_t state);
/**
* @brief Convert string to state variable
*
* @param[in] sstate State string
*
* @return State variable
*/
nrf24l01p_ng_state_t
nrf24l01p_ng_diagnostics_string_to_state(const char *sstate);
/**
* @brief Print all registers
*
* @param[in] dev NRf24L01+ device handle
*/
void nrf24l01p_ng_print_all_regs(nrf24l01p_ng_t *dev);
/**
* @brief Print device parameters
*
* @param[in] dev NRf24L01+ device handle
*/
void nrf24l01p_ng_print_dev_info(const nrf24l01p_ng_t *dev);
#endif
#ifdef __cplusplus
}
#endif
#endif /* NRF24L01P_NG_H */
/** @} */