From e4bb52add66a75945db2a2f5c695640705e65e3a Mon Sep 17 00:00:00 2001 From: Daniel He Date: Mon, 26 Feb 2024 16:38:16 -0800 Subject: [PATCH 1/2] Add radio drivers --- radio_sx127x_spi/radio_sx127x_spi.cc | 206 +++++++++++++++++++++++++++ radio_sx127x_spi/radio_sx127x_spi.h | 183 ++++++++++++++++++++++++ 2 files changed, 389 insertions(+) create mode 100644 radio_sx127x_spi/radio_sx127x_spi.cc create mode 100644 radio_sx127x_spi/radio_sx127x_spi.h diff --git a/radio_sx127x_spi/radio_sx127x_spi.cc b/radio_sx127x_spi/radio_sx127x_spi.cc new file mode 100644 index 0000000..acdde69 --- /dev/null +++ b/radio_sx127x_spi/radio_sx127x_spi.cc @@ -0,0 +1,206 @@ +#include "radio_sx127x_spi.h" + +RadioSx127xSpi::RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *rstPort, uint16_t rstPin, GPIO_TypeDef *dio0Port, uint16_t dio0Pin, Mode mode, + RfPort rfPort, int frequency, int transmitPower, RampTime rampTime, Bandwidth bandwidth, CodingRate codingRate, SpreadingFactor spreadingFactor, int preambleLength, + int payloadLength, bool crcEnable) + : _hspi(hspi), + _csPort(csPort), + _csPin(csPin), + _rstPort(rstPort), + _rstPin(rstPin), + _dio0Port(dio0Port), + _dio0Pin(dio0Pin), + _mode(mode), + _rfPort(rfPort), + _frequency(frequency), + _transmitPower(transmitPower), + _rampTime(rampTime), + _bandwidth(bandwidth), + _codingRate(codingRate), + _spreadingFactor(spreadingFactor), + _preambleLength(preambleLength), + _payloadLength(payloadLength), + _crcEnable(crcEnable) {} + +bool RadioSx127xSpi::Reset() { + HAL_GPIO_WritePin(_rstPort, _rstPin, GPIO_PIN_RESET); + HAL_Delay(1); + HAL_GPIO_WritePin(_rstPort, _rstPin, GPIO_PIN_SET); + HAL_Delay(5); + return true; +} + +RadioSx127xSpi::State RadioSx127xSpi::Init() { + _state = IDLE; + + // sleep mode + if (WriteRegister(0x01, 0b00000000) == false) _state = ERROR; + + // LoRa mode, set frequency mode + if (WriteRegister(0x01, 0b10000000 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; + + // set carrier frequency + uint32_t f = (uint64_t)_frequency * 524288ULL / 32000000ULL; + if (WriteRegister(0x06, (uint8_t)(f >> 16)) == false) _state = ERROR; + if (WriteRegister(0x07, (uint8_t)(f >> 8)) == false) _state = ERROR; + if (WriteRegister(0x08, (uint8_t)f) == false) _state = ERROR; + + // use PA_BOOST, set transmit power + if (WriteRegister(0x09, 0b10000000 | (uint8_t)(_transmitPower - 2)) == false) _state = ERROR; + + // set PA ramp time + if (WriteRegister(0x0A, (uint8_t)_rampTime) == false) _state = ERROR; + + // configure over-current protection + if (WriteRegister(0x0B, 0b00111011) == false) _state = ERROR; + + // configure LNA + if (WriteRegister(0x0C, 0b00100000) == false) _state = ERROR; + + // set FIFO TX base address + if (WriteRegister(0x0E, 0x80) == false) _state = ERROR; + + // set FIFO RX base address + if (WriteRegister(0x0F, 0x00) == false) _state = ERROR; + + // set bandwidth, set coding rate, use implicit header mode + if (WriteRegister(0x1D, 0b00000001 | ((uint8_t)_bandwidth << 4) | ((uint8_t)_codingRate << 1)) == false) _state = ERROR; + + // set spreading factor, use non-continuous mode, set CRC + if (WriteRegister(0x0E, ((uint8_t)_spreadingFactor << 4) | ((uint8_t)_crcEnable << 2)) == false) _state = ERROR; + + // set preamble length + if (WriteRegister(0x20, (uint8_t)(_preambleLength >> 8)) == false) _state = ERROR; + if (WriteRegister(0x21, (uint8_t)_preambleLength) == false) _state = ERROR; + + // set payload length + if (WriteRegister(0x22, (uint8_t)_payloadLength) == false) _state = ERROR; + + // if radio is only transmitting, set DIO0 to TxDone IRQ, else DIO0 is RxDone IRQ (default) + if (_mode == TX_ONLY) { + if (WriteRegister(0x40, 0b01000000) == false) _state = ERROR; + } + + // standby mode + if (WriteRegister(0x01, 0b10000001 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; + + return _state; +} + +RadioSx127xSpi::State RadioSx127xSpi::Transmit(const uint8_t *payload) { + if (_mode != TXRX && _mode != TX_ONLY) { + _state = ERROR; + return _state; + } + + switch (_state) { + case IDLE: { + _state = TX; + + // set FIFO address pointer + if (WriteRegister(0x0D, 0x80) == false) _state = ERROR; + + // write payload to FIFO + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); + if (HAL_SPI_Transmit(_hspi, (uint8_t *)(const uint8_t[]){0x80}, 1, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; + if (HAL_SPI_Transmit(_hspi, (uint8_t *)payload, _payloadLength, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); + + // if radio is bidirectional, set DIO0 to TxDone IRQ, else DIO0 should already be in this mode + if (_mode == TXRX) { + if (WriteRegister(0x40, 0b01000000) == false) _state = ERROR; + } + + // start TX + if (WriteRegister(0x01, 0b10000011 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; + + break; + } + + case TX: { + if (HAL_GPIO_ReadPin(_dio0Port, _dio0Pin) == GPIO_PIN_SET) { + _state = IDLE; + + // clear TxDone IRQ + if (WriteRegister(0x12, 0b00001000) == false) _state = ERROR; + } + break; + } + + default: + break; + } + return _state; +} + +RadioSx127xSpi::State RadioSx127xSpi::Receive(uint8_t *payload, int *rssi) { + if (_mode != TXRX && _mode != RX_ONLY) { + _state = ERROR; + return _state; + } + + switch (_state) { + case IDLE: { + _state = RX; + + if (_mode == TXRX) { + // if radio is bidirectional, set DIO0 to RxDone IRQ, else DIO0 should already be in this mode + if (WriteRegister(0x40, 0b00000000) == false) _state = ERROR; + } + + // start RX single + if (WriteRegister(0x01, 0b10000110 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; + + break; + } + + case RX: { + if (HAL_GPIO_ReadPin(_dio0Port, _dio0Pin) == GPIO_PIN_SET) { + _state = IDLE; + + // clear RxDone IRQ + if (WriteRegister(0x12, 0b01000000) == false) _state = ERROR; + } + + // set FIFO address pointer + if (WriteRegister(0x0D, 0x00) == false) _state = ERROR; + + // read payload from FIFO + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); + if (HAL_SPI_Transmit(_hspi, (uint8_t *)(const uint8_t[]){0x00}, 1, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; + if (HAL_SPI_Receive(_hspi, (uint8_t *)payload, _payloadLength, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); + + // read RSSI + uint8_t data; + if (ReadRegister(0x1A, &data) == false) _state = ERROR; + if (_rfPort == HF) { + *rssi = data - 157; + } else if (_rfPort == LF) { + *rssi = data - 164; + } + } + + default: + break; + } + return _state; +} + +bool RadioSx127xSpi::ReadRegister(uint8_t address, uint8_t *data) { + bool status = true; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); + if (HAL_SPI_Transmit(_hspi, &address, 1, SERIAL_TIMEOUT) != HAL_OK) status = false; + if (HAL_SPI_Receive(_hspi, data, 1, SERIAL_TIMEOUT) != HAL_OK) status = false; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); + return status; +} + +bool RadioSx127xSpi::WriteRegister(uint8_t address, uint8_t data) { + bool status = true; + uint8_t payload[2] = {(uint8_t)(address | 0x80), data}; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); + if (HAL_SPI_Transmit(_hspi, payload, 2, SERIAL_TIMEOUT) != HAL_OK) status = false; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); + return status; +} diff --git a/radio_sx127x_spi/radio_sx127x_spi.h b/radio_sx127x_spi/radio_sx127x_spi.h new file mode 100644 index 0000000..50dc34b --- /dev/null +++ b/radio_sx127x_spi/radio_sx127x_spi.h @@ -0,0 +1,183 @@ +#pragma once + +#if defined(STM32F1) +#include "stm32f1xx_hal.h" +#elif defined(STM32F4xx) +#include "stm32f4xx_hal.h" +#endif + +#ifndef SERIAL_TIMEOUT +#define SERIAL_TIMEOUT 10 +#endif + +class RadioSx127xSpi { + public: + enum State { IDLE, TX, RX, ERROR }; + + enum Mode { + // bidirectional + TXRX, + // transmit only + TX_ONLY, + // receive only + RX_ONLY + }; + + enum RfPort { + // high frequency port 779-1020 MHz + HF = 0, + // low frequency port 137-525 MHz + LF = 1 + }; + + enum RampTime { + // 3.4 ms + RT3M4S = 0, + // 2 ms + RT2MS = 1, + // 1 ms + RT1MS = 2, + // 500 us + RT500US = 3, + // 250 us + RT250US = 4, + // 125 us + RT125US = 5, + // 100 us + RT100US = 6, + // 62 us + RT62US = 7, + // 50 us + RT50US = 8, + // 40 us + RT40US = 9, + // 31 us + RT31US = 10, + // 25 us + RT25US = 11, + // 20 us + RT20US = 12, + // 15 us + RT15US = 13, + // 12 us + RT12US = 14, + // 10 us + RT10US = 15 + }; + + enum Bandwidth { + // 7.8 kHz + BW7K8HZ = 0, + // 10.4 kHz + BW10K4HZ = 1, + // 15.6 kHz + BW15K6HZ = 2, + // 20.8 kHz + BW20K8HZ = 3, + // 31.25 kHz + BW31K25HZ = 4, + // 41.7 kHz + BW41K7HZ = 5, + // 62.5 kHz + BW62K5HZ = 6, + // 125 kHz + BW125KHZ = 7, + // 250 kHz + BW250KHZ = 8, + // 500 kHz + BW500KHZ = 9 + }; + + enum CodingRate { + // 4/5 + CR45 = 1, + // 4/6 + CR46 = 2, + // 4/7 + CR47 = 3, + // 4/8 + CR48 = 4 + }; + + enum SpreadingFactor { SF6 = 6, SF7 = 7, SF8 = 8, SF9 = 9, SF10 = 10, SF11 = 11, SF12 = 12 }; + + /** + * @param hspi SPI bus handler + * @param csPort chip select GPIO port + * @param csPin chip select GPIO pin + * @param rstPort reset GPIO port + * @param rstPin reset GPIO pin + * @param dio0Port DIO0 GPIO port + * @param dio0Pin DIO0 GPIO pin + * @param frequency RF center frequency in Hz, valid range 137000000-525000000, 779000000-1020000000 + * @param transmitPower transmit power in dBm, valid range 2-15 + * @param rampTime PA ramp time + * @param bandwidth signal bandwidth + * @param codingRate error coding rate + * @param spreadingFactor spreading factor rate + * @param preambleLength preamble length in symbols, valid range 6-65535 + * @param payloadLength packet length in bytes, valid range 1-255 + * @param crcEnable enable CRC + */ + RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *rstPort, uint16_t rstPin, GPIO_TypeDef *dio0Port, uint16_t dio0Pin, Mode mode, RfPort rfPort, + int frequency, int transmitPower, RampTime rampTime, Bandwidth bandwidth, CodingRate codingRate, SpreadingFactor spreadingFactor, int preambleLength, int payloadLength, + bool crcEnable); + + /** + * @brief Resets radio + * @retval Operation status, true for success + */ + bool Reset(); + + /** + * @brief Initializes and configures radio + * @retval Current state + */ + State Init(); + + /** + * @brief Transmits payload + * @param payload pointer to payload buffer, must be the same length as specified by payloadLength + * @retval Current state, returns to IDLE when transmit complete + */ + State Transmit(const uint8_t *payload); + + /** + * @brief Listens and receives one packet + * @param payload pointer to payload buffer, must be the same length as specified by payloadLength + * @param rssi received signal strength indication, this is an output + * @retval Current state, returns to IDLE when receive complete + */ + State Receive(uint8_t *payload, int *rssi); + + private: + /** + * @retval Operation status, true for success + */ + bool ReadRegister(uint8_t address, uint8_t *data); + + /** + * @retval Operation status, true for success + */ + bool WriteRegister(uint8_t address, uint8_t data); + + SPI_HandleTypeDef *_hspi; + GPIO_TypeDef *_csPort; + uint16_t _csPin; + GPIO_TypeDef *_rstPort; + uint16_t _rstPin; + GPIO_TypeDef *_dio0Port; + uint16_t _dio0Pin; + Mode _mode; + RfPort _rfPort; + int _frequency; + int _transmitPower; + RampTime _rampTime; + Bandwidth _bandwidth; + CodingRate _codingRate; + SpreadingFactor _spreadingFactor; + int _preambleLength; + int _payloadLength; + bool _crcEnable; + State _state; +}; From 7fb4a31dde35bc9b6b2cfc769f7880370b306787 Mon Sep 17 00:00:00 2001 From: Daniel He Date: Tue, 27 Feb 2024 16:02:12 -0800 Subject: [PATCH 2/2] working? radio tx rx drivers --- radio_sx127x_spi/radio_sx127x_spi.cc | 143 ++++++++++++++++----------- radio_sx127x_spi/radio_sx127x_spi.h | 49 ++++----- 2 files changed, 113 insertions(+), 79 deletions(-) diff --git a/radio_sx127x_spi/radio_sx127x_spi.cc b/radio_sx127x_spi/radio_sx127x_spi.cc index acdde69..d9c66a6 100644 --- a/radio_sx127x_spi/radio_sx127x_spi.cc +++ b/radio_sx127x_spi/radio_sx127x_spi.cc @@ -1,16 +1,14 @@ #include "radio_sx127x_spi.h" -RadioSx127xSpi::RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *rstPort, uint16_t rstPin, GPIO_TypeDef *dio0Port, uint16_t dio0Pin, Mode mode, - RfPort rfPort, int frequency, int transmitPower, RampTime rampTime, Bandwidth bandwidth, CodingRate codingRate, SpreadingFactor spreadingFactor, int preambleLength, - int payloadLength, bool crcEnable) +RadioSx127xSpi::RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *rstPort, uint16_t rstPin, uint8_t syncWord, RfPort rfPort, unsigned int frequency, + unsigned int transmitPower, RampTime rampTime, Bandwidth bandwidth, CodingRate codingRate, SpreadingFactor spreadingFactor, unsigned int preambleLength, + unsigned int payloadLength, bool crcEnable, unsigned int txTimeout, unsigned int rxTimeout) : _hspi(hspi), _csPort(csPort), _csPin(csPin), _rstPort(rstPort), _rstPin(rstPin), - _dio0Port(dio0Port), - _dio0Pin(dio0Pin), - _mode(mode), + _syncWord(syncWord), _rfPort(rfPort), _frequency(frequency), _transmitPower(transmitPower), @@ -20,7 +18,9 @@ RadioSx127xSpi::RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, ui _spreadingFactor(spreadingFactor), _preambleLength(preambleLength), _payloadLength(payloadLength), - _crcEnable(crcEnable) {} + _crcEnable(crcEnable), + _txTimeout(txTimeout), + _rxTimeout(rxTimeout) {} bool RadioSx127xSpi::Reset() { HAL_GPIO_WritePin(_rstPort, _rstPin, GPIO_PIN_RESET); @@ -66,8 +66,11 @@ RadioSx127xSpi::State RadioSx127xSpi::Init() { // set bandwidth, set coding rate, use implicit header mode if (WriteRegister(0x1D, 0b00000001 | ((uint8_t)_bandwidth << 4) | ((uint8_t)_codingRate << 1)) == false) _state = ERROR; - // set spreading factor, use non-continuous mode, set CRC - if (WriteRegister(0x0E, ((uint8_t)_spreadingFactor << 4) | ((uint8_t)_crcEnable << 2)) == false) _state = ERROR; + // set spreading factor, use non-continuous mode, set CRC, set RX timeout MSB + if (WriteRegister(0x1E, ((uint8_t)_spreadingFactor << 4) | ((uint8_t)_crcEnable << 2) | ((uint8_t)(0x3 & (_rxTimeout >> 8)))) == false) _state = ERROR; + + // set RX timeout LSB + if (WriteRegister(0x1F, (uint8_t)_rxTimeout) == false) _state = ERROR; // set preamble length if (WriteRegister(0x20, (uint8_t)(_preambleLength >> 8)) == false) _state = ERROR; @@ -76,11 +79,23 @@ RadioSx127xSpi::State RadioSx127xSpi::Init() { // set payload length if (WriteRegister(0x22, (uint8_t)_payloadLength) == false) _state = ERROR; - // if radio is only transmitting, set DIO0 to TxDone IRQ, else DIO0 is RxDone IRQ (default) - if (_mode == TX_ONLY) { - if (WriteRegister(0x40, 0b01000000) == false) _state = ERROR; + if (_spreadingFactor == SF6) { + // LoRa detection optimize + if (WriteRegister(0x31, 0x05) == false) _state = ERROR; + + // LoRa detection threshold + if (WriteRegister(0x37, 0x0C) == false) _state = ERROR; + } else { + // LoRa detection optimize + if (WriteRegister(0x31, 0x03) == false) _state = ERROR; + + // LoRa detection threshold + if (WriteRegister(0x37, 0x0A) == false) _state = ERROR; } + // set sync word + if (WriteRegister(0x39, (uint8_t)_syncWord) == false) _state = ERROR; + // standby mode if (WriteRegister(0x01, 0b10000001 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; @@ -88,11 +103,6 @@ RadioSx127xSpi::State RadioSx127xSpi::Init() { } RadioSx127xSpi::State RadioSx127xSpi::Transmit(const uint8_t *payload) { - if (_mode != TXRX && _mode != TX_ONLY) { - _state = ERROR; - return _state; - } - switch (_state) { case IDLE: { _state = TX; @@ -106,23 +116,25 @@ RadioSx127xSpi::State RadioSx127xSpi::Transmit(const uint8_t *payload) { if (HAL_SPI_Transmit(_hspi, (uint8_t *)payload, _payloadLength, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); - // if radio is bidirectional, set DIO0 to TxDone IRQ, else DIO0 should already be in this mode - if (_mode == TXRX) { - if (WriteRegister(0x40, 0b01000000) == false) _state = ERROR; - } - // start TX if (WriteRegister(0x01, 0b10000011 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; + _txStartTime = HAL_GetTick(); + break; } case TX: { - if (HAL_GPIO_ReadPin(_dio0Port, _dio0Pin) == GPIO_PIN_SET) { - _state = IDLE; + uint8_t irqFlags = 0x00; + if (ReadRegister(0x12, &irqFlags) == false) _state = ERROR; + + if ((irqFlags & 0x08) != 0) { + _state = TX_COMPLETE; // clear TxDone IRQ - if (WriteRegister(0x12, 0b00001000) == false) _state = ERROR; + if (WriteRegister(0x12, 0x08) == false) _state = ERROR; + } else if (HAL_GetTick() - _txStartTime > _txTimeout) { + _state = TX_TIMEOUT; } break; } @@ -134,20 +146,10 @@ RadioSx127xSpi::State RadioSx127xSpi::Transmit(const uint8_t *payload) { } RadioSx127xSpi::State RadioSx127xSpi::Receive(uint8_t *payload, int *rssi) { - if (_mode != TXRX && _mode != RX_ONLY) { - _state = ERROR; - return _state; - } - switch (_state) { case IDLE: { _state = RX; - if (_mode == TXRX) { - // if radio is bidirectional, set DIO0 to RxDone IRQ, else DIO0 should already be in this mode - if (WriteRegister(0x40, 0b00000000) == false) _state = ERROR; - } - // start RX single if (WriteRegister(0x01, 0b10000110 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; @@ -155,30 +157,52 @@ RadioSx127xSpi::State RadioSx127xSpi::Receive(uint8_t *payload, int *rssi) { } case RX: { - if (HAL_GPIO_ReadPin(_dio0Port, _dio0Pin) == GPIO_PIN_SET) { - _state = IDLE; + uint8_t irqFlags = 0x00; + if (ReadRegister(0x12, &irqFlags) == false) _state = ERROR; - // clear RxDone IRQ - if (WriteRegister(0x12, 0b01000000) == false) _state = ERROR; - } + if ((irqFlags & 0x40) != 0) { + _state = RX_COMPLETE; - // set FIFO address pointer - if (WriteRegister(0x0D, 0x00) == false) _state = ERROR; + // standby mode + if (WriteRegister(0x01, 0b10000001 | ((uint8_t)_rfPort << 3)) == false) _state = ERROR; - // read payload from FIFO - HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); - if (HAL_SPI_Transmit(_hspi, (uint8_t *)(const uint8_t[]){0x00}, 1, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; - if (HAL_SPI_Receive(_hspi, (uint8_t *)payload, _payloadLength, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; - HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); - - // read RSSI - uint8_t data; - if (ReadRegister(0x1A, &data) == false) _state = ERROR; - if (_rfPort == HF) { - *rssi = data - 157; - } else if (_rfPort == LF) { - *rssi = data - 164; + // clear RxDone IRQ + if (WriteRegister(0x12, 0x40) == false) _state = ERROR; + + // check valid CRC + if ((irqFlags & 0x20) != 0) { + _state = RX_CRC_ERROR; + + // clear CRC Error IRQ + if (WriteRegister(0x12, 0x20) == false) _state = ERROR; + + break; + } + + // set FIFO address pointer + if (WriteRegister(0x0D, 0x00) == false) _state = ERROR; + + // read payload from FIFO + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); + if (HAL_SPI_Transmit(_hspi, (uint8_t *)(const uint8_t[]){0x00}, 1, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; + if (HAL_SPI_Receive(_hspi, (uint8_t *)payload, _payloadLength, SERIAL_TIMEOUT) != HAL_OK) _state = ERROR; + HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_SET); + + // read RSSI + uint8_t data; + if (ReadRegister(0x1A, &data) == false) _state = ERROR; + if (_rfPort == HF) { + *rssi = data - 157; + } else if (_rfPort == LF) { + *rssi = data - 164; + } + } else if (irqFlags & 0x80) { + _state = RX_TIMEOUT; + + // clear RxTimeout IRQ + if (WriteRegister(0x12, 0x80) == false) _state = ERROR; } + break; } default: @@ -187,6 +211,15 @@ RadioSx127xSpi::State RadioSx127xSpi::Receive(uint8_t *payload, int *rssi) { return _state; } +RadioSx127xSpi::State RadioSx127xSpi::ClearState() { + _state = IDLE; + + // clear all IRQ + if (WriteRegister(0x12, 0xFF) == false) _state = ERROR; + + return _state; +} + bool RadioSx127xSpi::ReadRegister(uint8_t address, uint8_t *data) { bool status = true; HAL_GPIO_WritePin(_csPort, _csPin, GPIO_PIN_RESET); diff --git a/radio_sx127x_spi/radio_sx127x_spi.h b/radio_sx127x_spi/radio_sx127x_spi.h index 50dc34b..a02d371 100644 --- a/radio_sx127x_spi/radio_sx127x_spi.h +++ b/radio_sx127x_spi/radio_sx127x_spi.h @@ -12,16 +12,7 @@ class RadioSx127xSpi { public: - enum State { IDLE, TX, RX, ERROR }; - - enum Mode { - // bidirectional - TXRX, - // transmit only - TX_ONLY, - // receive only - RX_ONLY - }; + enum State { IDLE, TX, TX_COMPLETE, TX_TIMEOUT, RX, RX_COMPLETE, RX_CRC_ERROR, RX_TIMEOUT, ERROR }; enum RfPort { // high frequency port 779-1020 MHz @@ -107,8 +98,8 @@ class RadioSx127xSpi { * @param csPin chip select GPIO pin * @param rstPort reset GPIO port * @param rstPin reset GPIO pin - * @param dio0Port DIO0 GPIO port - * @param dio0Pin DIO0 GPIO pin + * @param syncWord LoRa sync word + * @param rfPort transponder physical RF port * @param frequency RF center frequency in Hz, valid range 137000000-525000000, 779000000-1020000000 * @param transmitPower transmit power in dBm, valid range 2-15 * @param rampTime PA ramp time @@ -118,10 +109,12 @@ class RadioSx127xSpi { * @param preambleLength preamble length in symbols, valid range 6-65535 * @param payloadLength packet length in bytes, valid range 1-255 * @param crcEnable enable CRC + * @param txTimeout TX timeout in milliseconds + * @param rxTimeout RX timeout in number of symbols, valid range 4-1023, timeout in seconds = rxTimeout * (2 ** spreadingFactor) / bandwidth */ - RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *rstPort, uint16_t rstPin, GPIO_TypeDef *dio0Port, uint16_t dio0Pin, Mode mode, RfPort rfPort, - int frequency, int transmitPower, RampTime rampTime, Bandwidth bandwidth, CodingRate codingRate, SpreadingFactor spreadingFactor, int preambleLength, int payloadLength, - bool crcEnable); + RadioSx127xSpi(SPI_HandleTypeDef *hspi, GPIO_TypeDef *csPort, uint16_t csPin, GPIO_TypeDef *rstPort, uint16_t rstPin, uint8_t syncWord, RfPort rfPort, unsigned int frequency, + unsigned int transmitPower, RampTime rampTime, Bandwidth bandwidth, CodingRate codingRate, SpreadingFactor spreadingFactor, unsigned int preambleLength, unsigned int payloadLength, + bool crcEnable, unsigned int txTimeout, unsigned int rxTimeout); /** * @brief Resets radio @@ -138,7 +131,7 @@ class RadioSx127xSpi { /** * @brief Transmits payload * @param payload pointer to payload buffer, must be the same length as specified by payloadLength - * @retval Current state, returns to IDLE when transmit complete + * @retval Current state, state is IDLE when transmit complete */ State Transmit(const uint8_t *payload); @@ -146,10 +139,16 @@ class RadioSx127xSpi { * @brief Listens and receives one packet * @param payload pointer to payload buffer, must be the same length as specified by payloadLength * @param rssi received signal strength indication, this is an output - * @retval Current state, returns to IDLE when receive complete + * @retval Current state, state is RX_COMPLETE when a new valid packet is received, state is IDLE when timeout or CRC error */ State Receive(uint8_t *payload, int *rssi); + /** + * @brief Resets state to IDLE + * @retval Current state + */ + State ClearState(); + private: /** * @retval Operation status, true for success @@ -166,18 +165,20 @@ class RadioSx127xSpi { uint16_t _csPin; GPIO_TypeDef *_rstPort; uint16_t _rstPin; - GPIO_TypeDef *_dio0Port; - uint16_t _dio0Pin; - Mode _mode; + uint8_t _syncWord; RfPort _rfPort; - int _frequency; - int _transmitPower; + unsigned int _frequency; + unsigned int _transmitPower; RampTime _rampTime; Bandwidth _bandwidth; CodingRate _codingRate; SpreadingFactor _spreadingFactor; - int _preambleLength; - int _payloadLength; + unsigned int _preambleLength; + unsigned int _payloadLength; bool _crcEnable; + unsigned int _txTimeout; + unsigned int _rxTimeout; + + uint32_t _txStartTime; State _state; };