From 240d219b97357f789cd0cba02e8cadc8b486509e Mon Sep 17 00:00:00 2001 From: Wojciech Domski Date: Wed, 21 Oct 2020 20:20:39 +0200 Subject: [PATCH] Updated documentation Updated documentation of the driver. Updated readme file. Separate hardware layer in SX1278_hw files. --- README.md | 28 ++++- driver/SX1278.c | 121 +++++-------------- driver/SX1278.h | 295 +++++++++++++++++++++++++++++++++++++-------- driver/SX1278_hw.c | 60 +++++++++ driver/SX1278_hw.h | 95 +++++++++++++++ 5 files changed, 461 insertions(+), 138 deletions(-) create mode 100644 driver/SX1278_hw.c create mode 100644 driver/SX1278_hw.h diff --git a/README.md b/README.md index 8516f89..e6d355d 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,36 @@ The initial work was based on DORJI.COM sample code and [SX1278_LoRa](https://gi The driver was written in **C**. It has a hardware abstraction layer for easy porting to others MCUs. Also the hardware functions are defined as *__weak* so there is no need to change the driver files themselves. -The driver is using HAL to communicate between STM32 SPI periperal and LoRa module. +The driver is using HAL to communicate between STM32 SPI peripheral and LoRa module. # Example There is also an example available at [SX1278-example repository](https://github.com/wdomski/SX1278-example). -The example project was prepared for STM32F1 MCU in SW4STM32. +The example project was initially prepared for STM32F1 MCU in SW4STM32. +Consult the *README* file in the above repository which development +board is currently supported. + +# Documentation + +The driver is quite simple to use and now requires even lower entry +level. After collecting some feedback from my blog readers I decided +to include some more features including automatic frequency setting. +Previously, it was done by manually calculating values which +should be written to the LoRa module's registers. Now, the frequency +can be set during initialization by passing an argument to the +function. + +Since the driver is rather small the documentation (at least the +most common parts) will be included here. + +## Hardware layer + +The driver can be easily ported to a different platform with +minimum effort. Only the hardware dependant functions ought to be +modified. The hardware dependant parts can be find in +**SX1278_hw.c** and **SX1278_hw.h**. + +## Logic layer # Final remarks diff --git a/driver/SX1278.c b/driver/SX1278.c index b8a8def..78ee703 100644 --- a/driver/SX1278.c +++ b/driver/SX1278.c @@ -9,65 +9,7 @@ #include "SX1278.h" #include -#include "gpio.h" -#include "spi.h" - -////////////////////////////////// -// logic -////////////////////////////////// - -__weak void SX1278_hw_init(SX1278_hw_t * hw) { - SX1278_hw_SetNSS(hw, 1); - HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_SET); -} - -__weak void SX1278_hw_SetNSS(SX1278_hw_t * hw, int value) { - HAL_GPIO_WritePin(hw->nss.port, hw->nss.pin, - (value == 1) ? GPIO_PIN_SET : GPIO_PIN_RESET); -} - -__weak void SX1278_hw_Reset(SX1278_hw_t * hw) { - SX1278_hw_SetNSS(hw, 1); - HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_RESET); - - SX1278_hw_DelayMs(1); - - HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_SET); - - SX1278_hw_DelayMs(100); -} - -__weak void SX1278_hw_SPICommand(SX1278_hw_t * hw, uint8_t cmd) { - SX1278_hw_SetNSS(hw, 0); - HAL_SPI_Transmit(hw->spi, &cmd, 1, 1000); - while (HAL_SPI_GetState(hw->spi) != HAL_SPI_STATE_READY) - ; -} - -__weak uint8_t SX1278_hw_SPIReadByte(SX1278_hw_t * hw) { - uint8_t txByte = 0x00; - uint8_t rxByte = 0x00; - - SX1278_hw_SetNSS(hw, 0); - HAL_SPI_TransmitReceive(hw->spi, &txByte, &rxByte, 1, 1000); - while (HAL_SPI_GetState(hw->spi) != HAL_SPI_STATE_READY) - ; - return rxByte; -} - -__weak void SX1278_hw_DelayMs(uint32_t msec) { - HAL_Delay(msec); -} - -__weak int SX1278_hw_GetDIO0(SX1278_hw_t * hw) { - return (HAL_GPIO_ReadPin(hw->dio0.port, hw->dio0.pin) == GPIO_PIN_SET); -} - -////////////////////////////////// -// logic -////////////////////////////////// - -uint8_t SX1278_SPIRead(SX1278_t * module, uint8_t addr) { +uint8_t SX1278_SPIRead(SX1278_t *module, uint8_t addr) { uint8_t tmp; SX1278_hw_SPICommand(module->hw, addr); tmp = SX1278_hw_SPIReadByte(module->hw); @@ -75,14 +17,14 @@ uint8_t SX1278_SPIRead(SX1278_t * module, uint8_t addr) { return tmp; } -void SX1278_SPIWrite(SX1278_t * module, uint8_t addr, uint8_t cmd) { +void SX1278_SPIWrite(SX1278_t *module, uint8_t addr, uint8_t cmd) { SX1278_hw_SetNSS(module->hw, 0); SX1278_hw_SPICommand(module->hw, addr | 0x80); SX1278_hw_SPICommand(module->hw, cmd); SX1278_hw_SetNSS(module->hw, 1); } -void SX1278_SPIBurstRead(SX1278_t * module, uint8_t addr, uint8_t * rxBuf, +void SX1278_SPIBurstRead(SX1278_t *module, uint8_t addr, uint8_t *rxBuf, uint8_t length) { uint8_t i; if (length <= 1) { @@ -97,7 +39,7 @@ void SX1278_SPIBurstRead(SX1278_t * module, uint8_t addr, uint8_t * rxBuf, } } -void SX1278_SPIBurstWrite(SX1278_t * module, uint8_t addr, uint8_t * txBuf, +void SX1278_SPIBurstWrite(SX1278_t *module, uint8_t addr, uint8_t *txBuf, uint8_t length) { unsigned char i; if (length <= 1) { @@ -112,7 +54,7 @@ void SX1278_SPIBurstWrite(SX1278_t * module, uint8_t addr, uint8_t * txBuf, } } -void SX1278_config(SX1278_t * module) { +void SX1278_config(SX1278_t *module) { SX1278_sleep(module); //Change modem mode Must in Sleep mode SX1278_hw_DelayMs(15); @@ -133,16 +75,16 @@ void SX1278_config(SX1278_t * module) { SX1278_SPIWrite(module, LR_RegOcp, 0x0B); //RegOcp,Close Ocp SX1278_SPIWrite(module, LR_RegLna, 0x23); //RegLNA,High & LNA Enable - if (SX1278_SpreadFactor[module->LoRa_Rate] == 6) { //SFactor=6 + if (SX1278_SpreadFactor[module->LoRa_SF] == 6) { //SFactor=6 uint8_t tmp; SX1278_SPIWrite(module, LR_RegModemConfig1, - ((SX1278_LoRaBandwidth[module->LoRa_BW] << 4) + (SX1278_CodingRate[module->LoRa_CR] << 1) - + 0x01)); //Implicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04) + ((SX1278_LoRaBandwidth[module->LoRa_BW] << 4) + + (SX1278_CodingRate[module->LoRa_CR] << 1) + 0x01)); //Implicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04) SX1278_SPIWrite(module, LR_RegModemConfig2, - ((SX1278_SpreadFactor[module->LoRa_Rate] << 4) + ((SX1278_SpreadFactor[module->LoRa_SF] << 4) + (SX1278_CRC_Sum[module->LoRa_CRC_sum] << 2) + 0x03)); tmp = SX1278_SPIRead(module, 0x31); @@ -153,12 +95,12 @@ void SX1278_config(SX1278_t * module) { } else { SX1278_SPIWrite(module, LR_RegModemConfig1, - ((SX1278_LoRaBandwidth[module->LoRa_BW] << 4) + (SX1278_CodingRate[module->LoRa_CR] << 1) - + 0x00)); //Explicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04) + ((SX1278_LoRaBandwidth[module->LoRa_BW] << 4) + + (SX1278_CodingRate[module->LoRa_CR] << 1) + 0x00)); //Explicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04) SX1278_SPIWrite(module, LR_RegModemConfig2, - ((SX1278_SpreadFactor[module->LoRa_Rate] << 4) + ((SX1278_SpreadFactor[module->LoRa_SF] << 4) + (SX1278_CRC_Sum[module->LoRa_CRC_sum] << 2) + 0x00)); //SFactor & LNA gain set by the internal AGC loop } @@ -171,25 +113,25 @@ void SX1278_config(SX1278_t * module) { SX1278_standby(module); //Entry standby mode } -void SX1278_standby(SX1278_t * module) { +void SX1278_standby(SX1278_t *module) { SX1278_SPIWrite(module, LR_RegOpMode, 0x09); module->status = STANDBY; } -void SX1278_sleep(SX1278_t * module) { +void SX1278_sleep(SX1278_t *module) { SX1278_SPIWrite(module, LR_RegOpMode, 0x08); module->status = SLEEP; } -void SX1278_entryLoRa(SX1278_t * module) { +void SX1278_entryLoRa(SX1278_t *module) { SX1278_SPIWrite(module, LR_RegOpMode, 0x88); } -void SX1278_clearLoRaIrq(SX1278_t * module) { +void SX1278_clearLoRaIrq(SX1278_t *module) { SX1278_SPIWrite(module, LR_RegIrqFlags, 0xFF); } -int SX1278_LoRaEntryRx(SX1278_t * module, uint8_t length, uint32_t timeout) { +int SX1278_LoRaEntryRx(SX1278_t *module, uint8_t length, uint32_t timeout) { uint8_t addr; module->packetLength = length; @@ -221,7 +163,7 @@ int SX1278_LoRaEntryRx(SX1278_t * module, uint8_t length, uint32_t timeout) { } } -uint8_t SX1278_LoRaRxPacket(SX1278_t * module) { +uint8_t SX1278_LoRaRxPacket(SX1278_t *module) { unsigned char addr; unsigned char packet_size; @@ -231,7 +173,7 @@ uint8_t SX1278_LoRaRxPacket(SX1278_t * module) { addr = SX1278_SPIRead(module, LR_RegFifoRxCurrentaddr); //last packet addr SX1278_SPIWrite(module, LR_RegFifoAddrPtr, addr); //RxBaseAddr -> FiFoAddrPtr - if (module->LoRa_Rate == SX1278_LORA_SF_6) { //When SpreadFactor is six,will used Implicit Header mode(Excluding internal packet length) + if (module->LoRa_SF == SX1278_LORA_SF_6) { //When SpreadFactor is six,will used Implicit Header mode(Excluding internal packet length) packet_size = module->packetLength; } else { packet_size = SX1278_SPIRead(module, LR_RegRxNbBytes); //Number for received bytes @@ -244,7 +186,7 @@ uint8_t SX1278_LoRaRxPacket(SX1278_t * module) { return module->readBytes; } -int SX1278_LoRaEntryTx(SX1278_t * module, uint8_t length, uint32_t timeout) { +int SX1278_LoRaEntryTx(SX1278_t *module, uint8_t length, uint32_t timeout) { uint8_t addr; uint8_t temp; @@ -275,7 +217,7 @@ int SX1278_LoRaEntryTx(SX1278_t * module, uint8_t length, uint32_t timeout) { } } -int SX1278_LoRaTxPacket(SX1278_t * module, uint8_t * txBuffer, uint8_t length, +int SX1278_LoRaTxPacket(SX1278_t *module, uint8_t *txBuffer, uint8_t length, uint32_t timeout) { SX1278_SPIBurstWrite(module, 0x00, txBuffer, length); SX1278_SPIWrite(module, LR_RegOpMode, 0x8b); //Tx Mode @@ -296,12 +238,13 @@ int SX1278_LoRaTxPacket(SX1278_t * module, uint8_t * txBuffer, uint8_t length, } } -void SX1278_init(SX1278_t * module, uint64_t frequency, uint8_t power, - uint8_t LoRa_Rate, uint8_t LoRa_BW, uint8_t LoRa_CR, uint8_t LoRa_CRC_sum, uint8_t packetLength) { +void SX1278_init(SX1278_t *module, uint64_t frequency, uint8_t power, + uint8_t LoRa_SF, uint8_t LoRa_BW, uint8_t LoRa_CR, + uint8_t LoRa_CRC_sum, uint8_t packetLength) { SX1278_hw_init(module->hw); module->frequency = frequency; module->power = power; - module->LoRa_Rate = LoRa_Rate; + module->LoRa_SF = LoRa_SF; module->LoRa_BW = LoRa_BW; module->LoRa_CR = LoRa_CR; module->LoRa_CRC_sum = LoRa_CRC_sum; @@ -309,7 +252,7 @@ void SX1278_init(SX1278_t * module, uint64_t frequency, uint8_t power, SX1278_config(module); } -int SX1278_transmit(SX1278_t * module, uint8_t * txBuf, uint8_t length, +int SX1278_transmit(SX1278_t *module, uint8_t *txBuf, uint8_t length, uint32_t timeout) { if (SX1278_LoRaEntryTx(module, length, timeout)) { return SX1278_LoRaTxPacket(module, txBuf, length, timeout); @@ -317,15 +260,15 @@ int SX1278_transmit(SX1278_t * module, uint8_t * txBuf, uint8_t length, return 0; } -int SX1278_receive(SX1278_t * module, uint8_t length, uint32_t timeout) { +int SX1278_receive(SX1278_t *module, uint8_t length, uint32_t timeout) { return SX1278_LoRaEntryRx(module, length, timeout); } -uint8_t SX1278_available(SX1278_t * module) { +uint8_t SX1278_available(SX1278_t *module) { return SX1278_LoRaRxPacket(module); } -uint8_t SX1278_read(SX1278_t * module, uint8_t * rxBuf, uint8_t length) { +uint8_t SX1278_read(SX1278_t *module, uint8_t *rxBuf, uint8_t length) { if (length != module->readBytes) length = module->readBytes; memcpy(rxBuf, module->rxBuffer, length); @@ -334,16 +277,16 @@ uint8_t SX1278_read(SX1278_t * module, uint8_t * rxBuf, uint8_t length) { return length; } -uint8_t SX1278_RSSI_LoRa(SX1278_t * module) { +uint8_t SX1278_RSSI_LoRa(SX1278_t *module) { uint32_t temp = 10; temp = SX1278_SPIRead(module, LR_RegRssiValue); //Read RegRssiValue, Rssi value temp = temp + 127 - 137; //127:Max RSSI, 137:RSSI offset return (uint8_t) temp; } -uint8_t SX1278_RSSI(SX1278_t * module) { +uint8_t SX1278_RSSI(SX1278_t *module) { uint8_t temp = 0xff; - temp = SX1278_SPIRead(module, 0x11); + temp = SX1278_SPIRead(module, RegRssiValue); temp = 127 - (temp >> 1); //127:Max RSSI return temp; } diff --git a/driver/SX1278.h b/driver/SX1278.h index 789b2d2..b04fbe7 100644 --- a/driver/SX1278.h +++ b/driver/SX1278.h @@ -12,6 +12,8 @@ #include #include +#include "SX1278_hw.h" + #define SX1278_MAX_PACKET 256 #define SX1278_DEFAULT_TIMEOUT 3000 @@ -195,36 +197,24 @@ static const uint8_t SX1278_LoRaBandwidth[10] = { 0, // 7.8KHz, #define SX1278_LORA_CR_4_7 2 #define SX1278_LORA_CR_4_8 3 -static const uint8_t SX1278_CodingRate[4] = { 0x01, 0x02, 0x03, 0x04}; +static const uint8_t SX1278_CodingRate[4] = { 0x01, 0x02, 0x03, 0x04 }; //CRC Enable #define SX1278_LORA_CRC_EN 0 #define SX1278_LORA_CRC_DIS 1 -static const uint8_t SX1278_CRC_Sum[2] = { 0x01, 0x00}; +static const uint8_t SX1278_CRC_Sum[2] = { 0x01, 0x00 }; typedef enum _SX1278_STATUS { SLEEP, STANDBY, TX, RX } SX1278_Status_t; typedef struct { - int pin; - void * port; -} SX1278_hw_dio_t; - -typedef struct { - SX1278_hw_dio_t reset; - SX1278_hw_dio_t dio0; - SX1278_hw_dio_t nss; - void * spi; -} SX1278_hw_t; - -typedef struct { - SX1278_hw_t * hw; + SX1278_hw_t *hw; uint64_t frequency; uint8_t power; - uint8_t LoRa_Rate; + uint8_t LoRa_SF; uint8_t LoRa_BW; uint8_t LoRa_CR; uint8_t LoRa_CRC_sum; @@ -236,48 +226,259 @@ typedef struct { uint8_t readBytes; } SX1278_t; -//hardware -void SX1278_hw_init(SX1278_hw_t * hw); -void SX1278_hw_SetNSS(SX1278_hw_t * hw, int value); -void SX1278_hw_Reset(SX1278_hw_t * hw); -void SX1278_hw_SPICommand(SX1278_hw_t * hw, uint8_t cmd); -uint8_t SX1278_hw_SPIReadByte(SX1278_hw_t * hw); -void SX1278_hw_DelayMs(uint32_t msec); -int SX1278_hw_GetDIO0(SX1278_hw_t * hw); +/** + * \brief Read byte from LoRa module + * + * Reads data from LoRa module from given address. + * + * \param[in] module Pointer to LoRa structure + * \param[in] addr Address from which data will be read + * + * \return Read data + */ +uint8_t SX1278_SPIRead(SX1278_t *module, uint8_t addr); -//logic +/** + * \brief Write byte to LoRa module + * + * Writes data to LoRa module under given address. + * + * \param[in] module Pointer to LoRa structure + * \param[in] addr Address under which data will be written + * \param[in] cmd Data to write + */ +void SX1278_SPIWrite(SX1278_t *module, uint8_t addr, uint8_t cmd); -uint8_t SX1278_SPIRead(SX1278_t * module, uint8_t addr); -void SX1278_SPIWrite(SX1278_t * module, uint8_t addr, uint8_t cmd); -void SX1278_SPIBurstRead(SX1278_t * module, uint8_t addr, uint8_t * rxBuf, +/** + * \brief Read data from LoRa module + * + * Reads data from LoRa module from given address. + * + * \param[in] module Pointer to LoRa structure + * \param[in] addr Address from which data will be read + * \param[out] rxBuf Pointer to store read data + * \param[in] length Number of bytes to read + */ +void SX1278_SPIBurstRead(SX1278_t *module, uint8_t addr, uint8_t *rxBuf, uint8_t length); -void SX1278_SPIBurstWrite(SX1278_t * module, uint8_t addr, uint8_t * txBuf, + +/** + * \brief Write data to LoRa module + * + * Writes data to LoRa module under given address. + * + * \param[in] module Pointer to LoRa structure + * \param[in] addr Address under which data will be written + * \param[in] txBuf Pointer to data + * \param[in] length Number of bytes to write + */ +void SX1278_SPIBurstWrite(SX1278_t *module, uint8_t addr, uint8_t *txBuf, uint8_t length); -void SX1278_DIO0_InterruptHandler(SX1278_t * module); -void SX1278_config(SX1278_t * module); +/** + * \brief Configure LoRa module + * + * Configure LoRa module according to parameters stored in + * module structure. + * + * \param[in] module Pointer to LoRa structure + */ +void SX1278_config(SX1278_t *module); -void SX1278_entryLoRa(SX1278_t * module); -void SX1278_clearLoRaIrq(SX1278_t * module); -int SX1278_LoRaEntryRx(SX1278_t * module, uint8_t length, uint32_t timeout); -uint8_t SX1278_LoRaRxPacket(SX1278_t * module); -int SX1278_LoRaEntryTx(SX1278_t * module, uint8_t length, uint32_t timeout); -int SX1278_LoRaTxPacket(SX1278_t * module, uint8_t * txBuf, uint8_t length, +/** + * \brief Entry LoRa mode + * + * Module supports different operation mode. + * To use LoRa operation mode one has to enter this + * particular mode to transmit and receive data + * using LoRa. + * + * \param[in] module Pointer to LoRa structure + */ +void SX1278_entryLoRa(SX1278_t *module); + +/** + * \brief Clear IRQ + * + * Clears interrupt flags. + * + * \param[in] module Pointer to LoRa structure + */ +void SX1278_clearLoRaIrq(SX1278_t *module); + +/** + * \brief Entry reception mode + * + * Entry reception mode + * + * \param[in] module Pointer to LoRa structure + * \param[in] length Length of message to be received + * \param[in] timeout Timeout in [ms] + * + * \return 1 if entering reception mode + * 0 if timeout was exceeded + */ +int SX1278_LoRaEntryRx(SX1278_t *module, uint8_t length, uint32_t timeout); + +/** + * \brief Read data + * + * Read data and store it in module's RX buffer + * + * \param[in] module Pointer to LoRa structure + * + * \return returns number of read bytes + */ +uint8_t SX1278_LoRaRxPacket(SX1278_t *module); + +/** + * \brief Entry transmitter mode + * + * Entry transmitter mode + * + * \param[in] module Pointer to LoRa structure + * \param[in] length Length of message to be sent + * \param[in] timeout Timeout in [ms] + * + * \return 1 if entering reception mode + * 0 if timeout was exceeded + */ +int SX1278_LoRaEntryTx(SX1278_t *module, uint8_t length, uint32_t timeout); + +/** + * \brief Send data + * + * Transmit data + * + * \param[in] module Pointer to LoRa structure + * \param[in] txBuf Data buffer with data to be sent + * \param[in] length Length of message to be sent + * \param[in] timeout Timeout in [ms] + * + * \return 1 if entering reception mode + * 0 if timeout was exceeded + */ +int SX1278_LoRaTxPacket(SX1278_t *module, uint8_t *txBuf, uint8_t length, uint32_t timeout); -void SX1278_init(SX1278_t * module, uint64_t frequency, uint8_t power, - uint8_t LoRa_Rate, uint8_t LoRa_BW, uint8_t LoRa_CR, uint8_t LoRa_CRC_sum, uint8_t packetLength); +/** + * \brief Initialize LoRa module + * + * Initialize LoRa module and initialize LoRa structure. + * + * \param[in] module Pointer to LoRa structure + * \param[in] frequency Frequency in [Hz] + * \param[in] power Power level, accepts SX1278_POWER_* + * \param[in] LoRa_SF LoRa spread rate, accepts SX1278_LORA_SF_* + * \param[in] LoRa_BW LoRa bandwidth, accepts SX1278_LORA_BW_* + * \param[in] LoRa_CR LoRa coding rate, accepts SX1278_LORA_CR_* + * \param[in] LoRa_CRC_sum Hardware CRC check, SX1278_LORA_CRC_EN or + * SX1278_LORA_CRC_DIS + * \param[in] packetLength Package length, no more than 256 bytes + */ +void SX1278_init(SX1278_t *module, uint64_t frequency, uint8_t power, + uint8_t LoRa_SF, uint8_t LoRa_BW, uint8_t LoRa_CR, + uint8_t LoRa_CRC_sum, uint8_t packetLength); -int SX1278_transmit(SX1278_t * module, uint8_t * txBuf, uint8_t length, +/** + * \brief Entry transmitter mode and send data + * + * Entry transmitter mode and send data. + * Combination of SX1278_LoRaEntryTx() and SX1278_LoRaTxPacket(). + * + * \param[in] module Pointer to LoRa structure + * \param[in] txBuf Data buffer with data to be sent + * \param[in] length Length of message to be sent + * \param[in] timeout Timeout in [ms] + * + * \return 1 if entered TX mode and sent data + * 0 if timeout was exceeded + */ +int SX1278_transmit(SX1278_t *module, uint8_t *txBuf, uint8_t length, uint32_t timeout); -int SX1278_(SX1278_t * module, uint8_t length, uint32_t timeoutT); -uint8_t SX1278_available(SX1278_t * module); -uint8_t SX1278_read(SX1278_t * module, uint8_t * rxBuf, uint8_t length); -uint8_t SX1278_RSSI_LoRa(SX1278_t * module); -uint8_t SX1278_RSSI(SX1278_t * module); +/** + * \brief Entry reception mode + * + * Same as SX1278_LoRaEntryRx() + * + * \param[in] module Pointer to LoRa structure + * \param[in] length Length of message to be received + * \param[in] timeout Timeout in [ms] + * + * \return 1 if entering reception mode + * 0 if timeout was exceeded + */ +int SX1278_receive(SX1278_t *module, uint8_t length, uint32_t timeout); -void SX1278_standby(SX1278_t * module); -void SX1278_sleep(SX1278_t * module); +/** + * \brief Returns number of received data + * + * Returns the number of received data which are + * held in internal buffer. + * Same as SX1278_LoRaRxPacket(). + * + * \param[in] module Pointer to LoRa structure + * + * \return returns number of read bytes + */ +uint8_t SX1278_available(SX1278_t *module); + +/** + * \brief Read received data to buffer + * + * Reads data from internal buffer to external + * buffer. Reads exactly number of bytes which are stored in + * internal buffer. + * + * \param[in] module Pointer to LoRa structure + * \param[out] rxBuf External buffer to store data. + * External buffer is terminated with '\0' + * character + * \param[in] length Length of message to be received + * + * \return returns number of read bytes + */ +uint8_t SX1278_read(SX1278_t *module, uint8_t *rxBuf, uint8_t length); + +/** + * \brief Returns RSSI (LoRa) + * + * Returns RSSI in LoRa mode. + * + * \param[in] module Pointer to LoRa structure + * + * \return RSSI value + */ +uint8_t SX1278_RSSI_LoRa(SX1278_t *module); + +/** + * \brief Returns RSSI + * + * Returns RSSI (general mode). + * + * \param[in] module Pointer to LoRa structure + * + * \return RSSI value + */ +uint8_t SX1278_RSSI(SX1278_t *module); + +/** + * \brief Enter standby mode + * + * Enters standby mode. + * + * \param[in] module Pointer to LoRa structure + */ +void SX1278_standby(SX1278_t *module); + +/** + * \brief Enter sleep mode + * + * Enters sleep mode. + * + * \param[in] module Pointer to LoRa structure + */ +void SX1278_sleep(SX1278_t *module); #endif diff --git a/driver/SX1278_hw.c b/driver/SX1278_hw.c new file mode 100644 index 0000000..181fc3b --- /dev/null +++ b/driver/SX1278_hw.c @@ -0,0 +1,60 @@ +/** + * Author Wojciech Domski + * www: www.Domski.pl + * + * Hardware layer for SX1278 LoRa module + */ + +#include "SX1278_hw.h" +#include + +#include "gpio.h" +#include "spi.h" + +__weak void SX1278_hw_init(SX1278_hw_t *hw) { + SX1278_hw_SetNSS(hw, 1); + HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_SET); +} + +__weak void SX1278_hw_SetNSS(SX1278_hw_t *hw, int value) { + HAL_GPIO_WritePin(hw->nss.port, hw->nss.pin, + (value == 1) ? GPIO_PIN_SET : GPIO_PIN_RESET); +} + +__weak void SX1278_hw_Reset(SX1278_hw_t *hw) { + SX1278_hw_SetNSS(hw, 1); + HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_RESET); + + SX1278_hw_DelayMs(1); + + HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_SET); + + SX1278_hw_DelayMs(100); +} + +__weak void SX1278_hw_SPICommand(SX1278_hw_t *hw, uint8_t cmd) { + SX1278_hw_SetNSS(hw, 0); + HAL_SPI_Transmit(hw->spi, &cmd, 1, 1000); + while (HAL_SPI_GetState(hw->spi) != HAL_SPI_STATE_READY) + ; +} + +__weak uint8_t SX1278_hw_SPIReadByte(SX1278_hw_t *hw) { + uint8_t txByte = 0x00; + uint8_t rxByte = 0x00; + + SX1278_hw_SetNSS(hw, 0); + HAL_SPI_TransmitReceive(hw->spi, &txByte, &rxByte, 1, 1000); + while (HAL_SPI_GetState(hw->spi) != HAL_SPI_STATE_READY) + ; + return rxByte; +} + +__weak void SX1278_hw_DelayMs(uint32_t msec) { + HAL_Delay(msec); +} + +__weak int SX1278_hw_GetDIO0(SX1278_hw_t *hw) { + return (HAL_GPIO_ReadPin(hw->dio0.port, hw->dio0.pin) == GPIO_PIN_SET); +} + diff --git a/driver/SX1278_hw.h b/driver/SX1278_hw.h new file mode 100644 index 0000000..16142ca --- /dev/null +++ b/driver/SX1278_hw.h @@ -0,0 +1,95 @@ +/** + * Author Wojciech Domski + * www: www.Domski.pl + * + * Hardware layer for SX1278 LoRa module + */ + +#ifndef __SX1278_HW_HEADER +#define __SX1278_HW_HEADER + +#include + +typedef struct { + int pin; + void *port; +} SX1278_hw_dio_t; + +typedef struct { + SX1278_hw_dio_t reset; + SX1278_hw_dio_t dio0; + SX1278_hw_dio_t nss; + void *spi; +} SX1278_hw_t; + +/** + * \brief Initialize hardware layer + * + * Clears NSS and resets LoRa module. + * + * \param[in] hw Pointer to hardware structure + */ +void SX1278_hw_init(SX1278_hw_t *hw); + +/** + * \brief Control NSS + * + * Clears and sets NSS according to passed value. + * + * \param[in] hw Pointer to hardware structure. + * \param[in] value 1 sets NSS high, other value sets NSS low. + */ +void SX1278_hw_SetNSS(SX1278_hw_t *hw, int value); + +/** + * \brief Resets LoRa module + * + * Resets LoRa module. + * + * \param[in] hw Pointer to hardware structure + */ +void SX1278_hw_Reset(SX1278_hw_t *hw); + +/** + * \brief Send command via SPI. + * + * Send single byte via SPI interface. + * + * \param[in] hw Pointer to hardware structure + * \param[in] cmd Command + */ +void SX1278_hw_SPICommand(SX1278_hw_t *hw, uint8_t cmd); + +/** + * \brief Reads data via SPI + * + * Reads data via SPI interface. + * + * \param[in] hw Pointer to hardware structure + * + * \return Read value + */ +uint8_t SX1278_hw_SPIReadByte(SX1278_hw_t *hw); + +/** + * \brief ms delay + * + * Milisecond delay. + * + * \param[in] msec Number of milliseconds to wait + */ +void SX1278_hw_DelayMs(uint32_t msec); + +/** + * \brief Reads DIO0 state + * + * Reads LoRa DIO0 state using GPIO. + * + * \param[in] hw Pointer to hardware structure + * + * \return 0 if DIO0 low, 1 if DIO high + */ +int SX1278_hw_GetDIO0(SX1278_hw_t *hw); + +#endif +