From 571c83a5220a38abcfcc8fa87c39d27204843c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Tue, 9 Jun 2020 01:26:02 +0200 Subject: [PATCH] sx172x: add library to communicate with semtech SX127x LoRa module --- lib/radio_sx172x.c | 145 ++++++++++++++++++++++++++++++++++++++++ lib/radio_sx172x.h | 161 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 lib/radio_sx172x.c create mode 100644 lib/radio_sx172x.h diff --git a/lib/radio_sx172x.c b/lib/radio_sx172x.c new file mode 100644 index 0000000..48695d3 --- /dev/null +++ b/lib/radio_sx172x.c @@ -0,0 +1,145 @@ +/** library to communication with Semtech SX172x LoRa radio module using SPI + * @file + * @author King Kévin + * @copyright SPDX-License-Identifier: GPL-3.0-or-later + * @date 2020 + * @note peripherals used: SPI @ref radio_sx172x_spi, GPIO @ref radio_sx172x_gpio + * @note the interrupts and corresponding DIO should be handled directly by the user + */ +/* standard libraries */ +#include // standard integer types +#include // general utilities +#include // boolean utilities + +/* STM32 (including CM3) libraries */ +#include // Cortex M3 utilities +#include // real-time control clock library +#include // general purpose input output library +#include // SPI library + +/* own libraries */ +#include "global.h" // common methods +#include "radio_sx172x.h" // own definitions + +/** @defgroup radio_sx172x_spi SPI peripheral used to communicate with the SX172x + * @{ + */ +#define RADIO_SX172X_SPI 2 /**< SPI peripheral */ +/** @} */ + +/** @defgroup radio_sx172x_gpio GPIO used to control the SX172x + * @{ + */ +#define RADIO_SX172X_GPIO_NRESET PB7 /**< reset input (active low) */ +/** @} */ + +bool radio_sx172x_setup(void) +{ + // setup SPI + rcc_periph_clock_enable(RCC_SPI_SCK_PORT(RADIO_SX172X_SPI)); // enable clock for GPIO peripheral for clock signal + gpio_set_mode(SPI_SCK_PORT(RADIO_SX172X_SPI), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, SPI_SCK_PIN(RADIO_SX172X_SPI)); // set SCK as output (clock speed will be negotiated later) + rcc_periph_clock_enable(RCC_SPI_MOSI_PORT(RADIO_SX172X_SPI)); // enable clock for GPIO peripheral for MOSI signal + gpio_set_mode(SPI_MOSI_PORT(RADIO_SX172X_SPI), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, SPI_MOSI_PIN(RADIO_SX172X_SPI)); // set MOSI as output + rcc_periph_clock_enable(RCC_SPI_MISO_PORT(RADIO_SX172X_SPI)); // enable clock for GPIO peripheral for MISO signal + gpio_set_mode(SPI_MISO_PORT(RADIO_SX172X_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SPI_MISO_PIN(RADIO_SX172X_SPI)); // set MISO as input + rcc_periph_clock_enable(RCC_SPI_NSS_PORT(RADIO_SX172X_SPI)); // enable clock for GPIO peripheral for NSS (CS) signal + gpio_set_mode(SPI_NSS_PORT(RADIO_SX172X_SPI), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, SPI_NSS_PIN(RADIO_SX172X_SPI)); // set NSS (CS) as output + rcc_periph_clock_enable(RCC_AFIO); // enable clock for SPI alternate function + rcc_periph_clock_enable(RCC_SPI(RADIO_SX172X_SPI)); // enable clock for SPI peripheral + spi_reset(SPI(RADIO_SX172X_SPI)); // clear SPI values to default + spi_init_master(SPI(RADIO_SX172X_SPI), SPI_CR1_BAUDRATE_FPCLK_DIV_8, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST); // initialise SPI as master, divide clock by 8 (72E6/8 < 10 MHz, max SX172X SCK is 10 MHz, maximum SPI PCLK clock is 72 MHz, depending on which SPI is used), set clock polarity to idle low (not that important), set clock phase to do bit change on falling edge (polarity depends on clock phase), use 8-bit frames , use MSb first + spi_set_full_duplex_mode(SPI(RADIO_SX172X_SPI)); // ensure we are in full duplex mode + spi_enable_software_slave_management(SPI(RADIO_SX172X_SPI)); // control NSS (CS) manually + spi_set_nss_high(SPI(RADIO_SX172X_SPI)); // set NSS high (internally) so we can output + spi_disable_ss_output(SPI(RADIO_SX172X_SPI)); // disable NSS output since we control CS manually + gpio_set(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS high to unselect device + spi_enable(SPI(RADIO_SX172X_SPI)); // enable SPI + // use NRESET pin to read ensure it started + rcc_periph_clock_enable(GPIO_RCC(RADIO_SX172X_GPIO_NRESET)); // enable clock for GPIO port + gpio_set_mode(GPIO_PORT(RADIO_SX172X_GPIO_NRESET), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_PIN(RADIO_SX172X_GPIO_NRESET)); // set GPIO as input + sleep_ms(10); // wait for POR sequence to complete + return (0 != gpio_get(GPIO_PORT(RADIO_SX172X_GPIO_NRESET), GPIO_PIN(RADIO_SX172X_GPIO_NRESET))); // ensure the module has started +} + +void radio_sx172x_release(void) +{ + spi_disable(SPI(RADIO_SX172X_SPI)); + rcc_periph_clock_disable(RCC_SPI(RADIO_SX172X_SPI)); + gpio_set_mode(SPI_NSS_PORT(RADIO_SX172X_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_NSS_PIN(RADIO_SX172X_SPI)); + gpio_set_mode(SPI_MISO_PORT(RADIO_SX172X_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_MISO_PIN(RADIO_SX172X_SPI)); + gpio_set_mode(SPI_MOSI_PORT(RADIO_SX172X_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_MOSI_PIN(RADIO_SX172X_SPI)); + gpio_set_mode(SPI_SCK_PORT(RADIO_SX172X_SPI), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SPI_SCK_PIN(RADIO_SX172X_SPI)); +} + +bool radio_sx172x_reset(void) +{ + gpio_clear(GPIO_PORT(RADIO_SX172X_GPIO_NRESET), GPIO_PIN(RADIO_SX172X_GPIO_NRESET)); // set low to reset device + gpio_set_mode(GPIO_PORT(RADIO_SX172X_GPIO_NRESET), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(RADIO_SX172X_GPIO_NRESET)); // set GPIO as output + sleep_us(200); // set low for at least 100 us (see datasheet section 7.2.2) + gpio_set_mode(GPIO_PORT(RADIO_SX172X_GPIO_NRESET), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_PIN(RADIO_SX172X_GPIO_NRESET)); // set GPIO as input + sleep_ms(6); // wait for at least 5 ms for reset to complete (see datasheet section 7.2.2) + return (0 != gpio_get(GPIO_PORT(RADIO_SX172X_GPIO_NRESET), GPIO_PIN(RADIO_SX172X_GPIO_NRESET))); // ensure the module has started +} + +uint8_t radio_sx172x_read_register(enum radio_sx172x_register_t name) +{ + gpio_clear(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS low to select device + (void)SPI_DR(SPI(RADIO_SX172X_SPI)); // clear RXNE flag (by reading previously received data) + spi_send(SPI(RADIO_SX172X_SPI), name & 0x7f); // send register address (with 7th bit at 0 to read) and any data + spi_read(SPI(RADIO_SX172X_SPI)); // wait for data to be transferred, but discard the received data (clears RXNE go get the next data correctly) + spi_send(SPI(RADIO_SX172X_SPI), 0); // write any data so we can read back data + const uint8_t value = spi_read(SPI(RADIO_SX172X_SPI)); // read data + while ((SPI_SR(SPI(RADIO_SX172X_SPI)) & SPI_SR_BSY)); // wait for SPI to not be busy (communication completed) + gpio_set(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS high to unselect device + return value; +} + +void radio_sx172x_write_register(enum radio_sx172x_register_t name, uint8_t value) +{ + gpio_clear(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS low to select device + spi_send(SPI(RADIO_SX172X_SPI), name | 0x80); // send register address (with 7th bit at 1 to write) and value + spi_send(SPI(RADIO_SX172X_SPI), value); // write value + while ((SPI_SR(SPI(RADIO_SX172X_SPI)) & SPI_SR_BSY)); // wait for SPI to not be busy (communication completed) + gpio_set(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS high to unselect device +} + +void radio_sx172x_read_fifo(uint8_t addr, uint8_t* data, uint8_t length) +{ + if (NULL == data || 0 == length || addr + length > 256) { // sanity check + return; + } + const uint8_t mode = radio_sx172x_read_register(RADIO_SX172X_REG_OP_MODE); // read in which mode we are + if (0 == (mode & 0x7)) { // we are in sleep mode + radio_sx172x_write_register(RADIO_SX172X_REG_OP_MODE, (mode & 0xf8) | 1); // go to standby mode so we can access the FIFO registers + } + radio_sx172x_write_register(RADIO_SX172X_REG_LORA_FIFO_ADDR_PTR, addr); // set address to be read + gpio_clear(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS low to select device + (void)SPI_DR(SPI(RADIO_SX172X_SPI)); // clear RXNE flag (by reading previously received data) + spi_send(SPI(RADIO_SX172X_SPI), RADIO_SX172X_REG_FIFO & 0x7f); // select FIFO register (with 7th bit at 0 to read) + spi_read(SPI(RADIO_SX172X_SPI)); // wait for data to be transferred, but discard the received data (clears RXNE go get the next data correctly) + for (uint8_t i = 0; i < length; i++) { + spi_send(SPI(RADIO_SX172X_SPI), 0); // write any data so we can read back data + data[i] = spi_read(SPI(RADIO_SX172X_SPI)); // read data + } + while ((SPI_SR(SPI(RADIO_SX172X_SPI)) & SPI_SR_BSY)); // wait for SPI to not be busy (communication completed) + gpio_set(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS high to unselect device +} + +void radio_sx172x_write_fifo(uint8_t addr, const uint8_t* data, uint8_t length) +{ + if (NULL == data || 0 == length || addr + length > 256) { // sanity check + return; + } + const uint8_t mode = radio_sx172x_read_register(RADIO_SX172X_REG_OP_MODE); // read in which mode we are + if (0 == (mode & 0x7)) { // we are in sleep mode + radio_sx172x_write_register(RADIO_SX172X_REG_OP_MODE, (mode & 0xf8) | 1); // go to standby mode so we can access the FIFO registers + } + radio_sx172x_write_register(RADIO_SX172X_REG_LORA_FIFO_ADDR_PTR, addr); // set address to be read + gpio_clear(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS low to select device + spi_send(SPI(RADIO_SX172X_SPI), RADIO_SX172X_REG_FIFO | 0x80); // select FIFO register (with 7th bit at 1 to write) + for (uint8_t i = 0; i < length; i++) { + spi_send(SPI(RADIO_SX172X_SPI), data[i]); // write data + } + while ((SPI_SR(SPI(RADIO_SX172X_SPI)) & SPI_SR_BSY)); // wait for SPI to not be busy (communication completed) + gpio_set(SPI_NSS_PORT(RADIO_SX172X_SPI), SPI_NSS_PIN(RADIO_SX172X_SPI)); // set CS high to unselect device +} diff --git a/lib/radio_sx172x.h b/lib/radio_sx172x.h new file mode 100644 index 0000000..7c15699 --- /dev/null +++ b/lib/radio_sx172x.h @@ -0,0 +1,161 @@ +/** library to communication with Semtech SX172x LoRa radio module using SPI + * @file + * @author King Kévin + * @copyright SPDX-License-Identifier: GPL-3.0-or-later + * @date 2020 + * @note peripherals used: SPI @ref radio_sx172x_spi, GPIO @ref radio_sx172x_gpio + * @note the interrupts and corresponding DIO should be handled directly by the user + */ +#pragma once + +/** register addresses */ +enum radio_sx172x_register_t { + RADIO_SX172X_REG_FIFO = 0x00, + RADIO_SX172X_REG_OP_MODE = 0x01, + RADIO_SX172X_REG_FSKOOK_BITRATE_MSB = 0x02, + RADIO_SX172X_REG_FSKOOK_BITRATE_LSB = 0x03, + RADIO_SX172X_REG_FSKOOK_FDEV_MSB = 0x04, + RADIO_SX172X_REG_FSKOOK_FDEV_LSB = 0x05, + RADIO_SX172X_REG_FRF_MSB = 0x06, + RADIO_SX172X_REG_FRF_MID = 0x07, + RADIO_SX172X_REG_FRF_LSB = 0x08, + RADIO_SX172X_REG_PA_CONFIG = 0x09, + RADIO_SX172X_REG_PA_RAMP = 0x0A, + RADIO_SX172X_REG_OCP = 0x0B, + RADIO_SX172X_REG_LNA = 0x0C, + RADIO_SX172X_REG_FSKOOB_RX_CONFIG = 0x0D, + RADIO_SX172X_REG_LORA_FIFO_ADDR_PTR = 0x0D, + RADIO_SX172X_REG_FSKOOB_RSSI_CONFIG = 0x0E, + RADIO_SX172X_REG_LORA_FIFO_TX_BASE_ADDR = 0x0E, + RADIO_SX172X_REG_FSKOOB_RSSI_COLLISION = 0x0F, + RADIO_SX172X_REG_LORA_FIFO_RX_BASE_ADDR = 0x0F, + RADIO_SX172X_REG_FSKOOB_RSSI_THRESH = 0x10, + RADIO_SX172X_REG_LORA_FIFO_RX_CURRENT_ADDR = 0x10, + RADIO_SX172X_REG_FSKOOK_RSSI_VALUE = 0x11, + RADIO_SX172X_REG_LORA_IRQ_FLAGS_MASK = 0x11, + RADIO_SX172X_REG_FSKOOK_RX_BW = 0x12, + RADIO_SX172X_REG_LORA_IRQ_FLAGS = 0x12, + RADIO_SX172X_REG_FSKOOK_AFC_BW = 0x13, + RADIO_SX172X_REG_LORA_RX_NB_BYTES = 0x13, + RADIO_SX172X_REG_FSKOOK_OOK_PEAK = 0x14, + RADIO_SX172X_REG_LORA_RX_HEADER_CNT_VALUE_MSB = 0x14, + RADIO_SX172X_REG_FSKOOK_OOK_FIX = 0x15, + RADIO_SX172X_REG_LORA_RX_HEADER_CNT_VALUE_LSB = 0x15, + RADIO_SX172X_REG_FSKOOK_OOK_AVG = 0x16, + RADIO_SX172X_REG_LORA_RX_PACKET_CNT_VALUE_MSB = 0x16, + RADIO_SX172X_REG_LORA_RX_PACKET_CNT_VALUE_LSB = 0x17, + RADIO_SX172X_REG_LORA_MODEM_STAT = 0x18, + RADIO_SX172X_REG_LORA_PKT_SNR_VALUE = 0x19, + RADIO_SX172X_REG_FSKOOK_AFC_FEI = 0x1A, + RADIO_SX172X_REG_LORA_PKT_RSSI_VALUE = 0x1A, + RADIO_SX172X_REG_FSKOOK_AFC_MSB = 0x1B, + RADIO_SX172X_REG_LORA_RSSI_VALUE = 0x1B, + RADIO_SX172X_REG_FSKOOK_AFC_LSB = 0x1C, + RADIO_SX172X_REG_LORA_HOP_CHANNEL = 0x1C, + RADIO_SX172X_REG_FSKOOK_FEI_MSB = 0x1D, + RADIO_SX172X_REG_LORA_MODEM_CONFIG_1 = 0x1D, + RADIO_SX172X_REG_FSKOOK_FEI_LSB = 0x1E, + RADIO_SX172X_REG_LORA_MODEM_CONFIG_2 = 0x1E, + RADIO_SX172X_REG_FSKOOK_PREAMBLE_DETECT = 0x1F, + RADIO_SX172X_REG_LORA_SYMB_TIMEOUT_LSB = 0x1F, + RADIO_SX172X_REG_FSKOOK_RX_TIMEOUT_1 = 0x20, + RADIO_SX172X_REG_LORA_PREAMBLE_MSB = 0x20, + RADIO_SX172X_REG_FSKOOK_RX_TIMEOUT_2 = 0x21, + RADIO_SX172X_REG_LORA_PREAMBLE_LSB = 0x21, + RADIO_SX172X_REG_FSKOOK_RX_TIMEOUT_3 = 0x22, + RADIO_SX172X_REG_LORA_PAYLOAD_LENGTH = 0x22, + RADIO_SX172X_REG_FSKOOK_RX_DELAY = 0x23, + RADIO_SX172X_REG_LORA_MAX_PAYLOD_LENGTH = 0x23, + RADIO_SX172X_REG_FSKOOK_OSC = 0x24, + RADIO_SX172X_REG_LORA_HOP_PERIOD = 0x24, + RADIO_SX172X_REG_FSKOOK_PREAMBLE_MSB = 0x25, + RADIO_SX172X_REG_LORA_FIFO_RX_BYTE_ADDR = 0x25, + RADIO_SX172X_REG_FSKOOK_PREAMBLE_LSB = 0x26, + RADIO_SX172X_REG_LORA_MODEM_CONFIG_3 = 0x26, + RADIO_SX172X_REG_FSKOOK_SYNC_CONFIG = 0x27, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_1 = 0x28, + RADIO_SX172X_REG_LORA_FEI_MSB = 0x28, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_2 = 0x29, + RADIO_SX172X_REG_LORA_FEI_MID = 0x29, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_3 = 0x2A, + RADIO_SX172X_REG_LORA_FEI_LSB = 0x2A, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_4 = 0x2B, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_5 = 0x2C, + RADIO_SX172X_REG_LORA_RSSI_WIDEBAND = 0x2C, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_6 = 0x2D, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_7 = 0x2E, + RADIO_SX172X_REG_FSKOOK_SYNC_VALUE_8 = 0x2F, + RADIO_SX172X_REG_LORA_IF_FREQ_1 = 0x2F, + RADIO_SX172X_REG_FSKOOK_PACKET_CONFIG_1 = 0x30, + RADIO_SX172X_REG_LORA_IF_FREQ_2 = 0x30, + RADIO_SX172X_REG_FSKOOK_PACKET_CONFIG_2 = 0x31, + RADIO_SX172X_REG_LORA_DETECT_OPTIMIZE = 0x31, + RADIO_SX172X_REG_FSKOOK_PAYLOAD_LENGTH = 0x32, + RADIO_SX172X_REG_FSKOOK_NODE_ADRS = 0x33, + RADIO_SX172X_REG_LORA_INVERT_IQ = 0x33, + RADIO_SX172X_REG_FSKOOK_BROADCAST_ADRS = 0x34, + RADIO_SX172X_REG_FSKOOK_FIFO_THRESH = 0x35, + RADIO_SX172X_REG_FSKOOK_SEQ_CONFIG_1 = 0x36, + RADIO_SX172X_REG_LORA_HIGH_BW_OPTIMIZE_1 = 0x36, + RADIO_SX172X_REG_FSKOOK_SEQ_CONFIG_2 = 0x37, + RADIO_SX172X_REG_LORA_DETECTION_THRESHOLD = 0x37, + RADIO_SX172X_REG_FSKOOK_TIMER_RESOLV = 0x38, + RADIO_SX172X_REG_FSKOOK_TIMER_1_COEF = 0x39, + RADIO_SX172X_REG_LORA_SYNC_WORD = 0x39, + RADIO_SX172X_REG_FSKOOK_TIMER_2_COEF = 0x3A, + RADIO_SX172X_REG_LORA_HIGH_BW_OPTIMIZE_2 = 0x3A, + RADIO_SX172X_REG_FSKOOK_IMAGE_CAL = 0x3B, + RADIO_SX172X_REG_LORA_INVERT_IQ_2 = 0x3B, + RADIO_SX172X_REG_FSKOOK_TEMP = 0x3C, + RADIO_SX172X_REG_FSKOOK_LOW_BAT = 0x3D, + RADIO_SX172X_REG_FSKOOK_IRQ_FLAGS_1 = 0x3E, + RADIO_SX172X_REG_FSKOOK_IRQ_FLAGS_2 = 0x3F, + RADIO_SX172X_REG_DIO_MAPPING_1 = 0x40, + RADIO_SX172X_REG_DIO_MAPPING_2 = 0x41, + RADIO_SX172X_REG_VERSION = 0x42, + RADIO_SX172X_REG_FSKOOK_PLL_HOP = 0x44, + RADIO_SX172X_REG_TCX0 = 0x4B, + RADIO_SX172X_REG_PA_DAC = 0x4D, + RADIO_SX172X_REG_FORMER_TEMP = 0x5B, + RADIO_SX172X_REG_FSKOOK_BIT_RATE_FRAC = 0x5D, + RADIO_SX172X_REG_AGC_REF = 0x61, + RADIO_SX172X_REG_AGC_THRESH_1 = 0x62, + RADIO_SX172X_REG_AGC_THRESH_2 = 0x63, + RADIO_SX172X_REG_AGC_THRESH_3 = 0x64, + RADIO_SX172X_REG_PLL = 0x70, +}; + +/** setup communication to SX172x + * @return if SX172x is ready + */ +bool radio_sx172x_setup(void); +/** release resources and peripherals used by communication */ +void radio_sx172x_release(void); +/** reset SX172x chip + * @return if SX172x is ready + */ +bool radio_sx172x_reset(void); +/** read register from SX172x + * @param[in] name register name to read + * @return register value read + */ +uint8_t radio_sx172x_read_register(enum radio_sx172x_register_t name); +/** write register to SX172x + * @param[in] name register name to write + * @param[in} value register value to write + */ +void radio_sx172x_write_register(enum radio_sx172x_register_t name, uint8_t value); +/** read FIFO data + * @param[in] addr address of the data to be read in the FIFO buffer + * @param[out] data buffer to store read data + * @param[in] length number of byte to read + * @warning puts device in standby mode when in sleep mode + */ +void radio_sx172x_read_fifo(uint8_t addr, uint8_t* data, uint8_t length); +/** write FIFO data + * @param[in] addr address of the data to be written in the FIFO buffer + * @param[out] data data to be written in FIFO buffer + * @param[in] length number of byte to written + * @warning puts device in standby mode when in sleep mode + */ +void radio_sx172x_write_fifo(uint8_t addr, const uint8_t* data, uint8_t length);