commit
67b4916137
3 changed files with 454 additions and 0 deletions
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* sx127x.h |
||||
* |
||||
* Created on: Mar 4, 2023 |
||||
* Author: Daniel Peter Chokola |
||||
*/ |
||||
|
||||
#ifndef SX127X_INC_SX127X_H_ |
||||
#define SX127X_INC_SX127X_H_ |
||||
|
||||
/* Includes */ |
||||
#include <stdint.h> |
||||
#include "spi.h" |
||||
|
||||
/* Definitions */ |
||||
|
||||
/* Data Structures */ |
||||
typedef struct sx127x_s { |
||||
SPI_HandleTypeDef *hspi; |
||||
GPIO_TypeDef *port; |
||||
uint16_t pin; |
||||
union __attribute__((packed, aligned(1))) sx127x_ver_u { |
||||
uint8_t byte; |
||||
struct __attribute__((packed, aligned(1))) sx127x_ver_s { |
||||
uint8_t maskrev:4; |
||||
uint8_t fullrev:4; |
||||
} field; |
||||
} ver; |
||||
} sx127x_t; |
||||
|
||||
/* Function Prototypes */ |
||||
int32_t sx127x_init(sx127x_t *sx127x, SPI_HandleTypeDef *hspi, GPIO_TypeDef *port, uint16_t pin); |
||||
int32_t sx127x_tx(sx127x_t *sx127x, uint8_t *buf, uint16_t len); |
||||
int32_t sx127x_rx(sx127x_t *sx127x, uint8_t *buf); |
||||
|
||||
#endif /* SX127X_INC_SX127X_H_ */ |
@ -0,0 +1,404 @@
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* sx127x.c |
||||
* |
||||
* Created on: Mar 4, 2023 |
||||
* Author: Daniel Peter Chokola |
||||
*/ |
||||
|
||||
/* Includes */ |
||||
#include "sx127x.h" |
||||
#include "spi.h" |
||||
#include "util.h" |
||||
|
||||
/* Definitions */ |
||||
/* Common Registers */ |
||||
#define SX127X_REG_FIFO (0x00) /* Default: 0x00 */ |
||||
#define SX127X_REG_OPMODE (0x01) /* Default: 0x01 */ |
||||
#define SX127X_REG_FRFMSB (0x06) /* Default: 0x6C */ |
||||
#define SX127X_REG_FRFMID (0x07) /* Default: 0x80 */ |
||||
#define SX127X_REG_FRFLSB (0x08) /* Default: 0x00 */ |
||||
#define SX127X_REG_PACONFIG (0x09) /* Default: 0x4F */ |
||||
#define SX127X_REG_PARAMP (0x0A) /* Default: 0x09 */ |
||||
#define SX127X_REG_OCP (0x0B) /* Default: 0x2B */ |
||||
#define SX127X_REG_LNA (0x0C) /* Default: 0x20 */ |
||||
#define SX127X_REG_LOWBAT (0x3D) /* Default: 0x02 */ |
||||
#define SX127X_REG_IRQFLAGS1 (0x3E) /* Default: 0x80 */ |
||||
#define SX127X_REG_IRQFLAGS2 (0x3F) /* Default: 0x40 */ |
||||
#define SX127X_REG_DIOMAPPING1 (0x40) /* Default: 0x00 */ |
||||
#define SX127X_REG_DIOMAPPING2 (0x41) /* Default: 0x00 */ |
||||
#define SX127X_REG_VERSION (0x42) /* Default: 0x12 */ |
||||
#define SX127X_REG_TCXO (0x4B) /* Default: 0x09 */ |
||||
#define SX127X_REG_PADAC (0x4D) /* Default: 0x84 */ |
||||
#define SX127X_REG_FORMERTEMP (0x5B) /* Default: - */ |
||||
#define SX127X_REG_AGCREF (0x61) /* Default: 0x13 */ |
||||
#define SX127X_REG_AGCTHRESH1 (0x62) /* Default: 0x0E */ |
||||
#define SX127X_REG_AGCTHRESH2 (0x63) /* Default: 0x5B */ |
||||
#define SX127X_REG_AGCTHRESH3 (0x64) /* Default: 0xDB */ |
||||
#define SX127X_REG_PLL (0x70) /* Default: 0xD0 */ |
||||
/* FSK Registers */ |
||||
#define SX127X_REG_BITRATEMSB (0x02) /* Default: 0x1A */ |
||||
#define SX127X_REG_BITRATELSB (0x03) /* Default: 0x0B */ |
||||
#define SX127X_REG_FDEVMSB (0x04) /* Default: 0x00 */ |
||||
#define SX127X_REG_FDEVLSB (0x05) /* Default: 0x52 */ |
||||
#define SX127X_REG_RXCONFIG (0x0D) /* Default: 0x08 (POR), 0x0E (FSK) */ |
||||
#define SX127X_REG_RSSICONFIG (0x0E) /* Default: 0x02 */ |
||||
#define SX127X_REG_RSSICOLLISION (0x0F) /* Default: 0x0A */ |
||||
#define SX127X_REG_RSSITHRESH (0x10) /* Default: 0xFF */ |
||||
#define SX127X_REG_RXBW (0x12) /* Default: 0x15 */ |
||||
#define SX127X_REG_AFCBW (0x13) /* Default: 0x0B */ |
||||
#define SX127X_REG_OOKPEAK (0x14) /* Default: 0x28 */ |
||||
#define SX127X_REG_OOKFIX (0x15) /* Default: 0x0C */ |
||||
#define SX127X_REG_OOKAVG (0x16) /* Default: 0x12 */ |
||||
#define SX127X_REG_ERVED17 (0x17) /* Default: 0x47 */ |
||||
#define SX127X_REG_ERVED18 (0x18) /* Default: 0x32 */ |
||||
#define SX127X_REG_ERVED19 (0x19) /* Default: 0x3E */ |
||||
#define SX127X_REG_AFCFEI (0x1A) /* Default: 0x00 */ |
||||
#define SX127X_REG_AFCMSB (0x1B) /* Default: 0x00 (POR), n/a (FSK) */ |
||||
#define SX127X_REG_AFCLSB (0x1C) /* Default: 0x00 (POR), n/a (FSK) */ |
||||
#define SX127X_REG_PREAMBLEDETECT (0x1F) /* Default: 0x40 (POR), 0xAA (FSK) */ |
||||
#define SX127X_REG_RXTIMEOUT1 (0x20) /* Default: 0x00 */ |
||||
#define SX127X_REG_RXTIMEOUT2 (0x21) /* Default: 0x00 */ |
||||
#define SX127X_REG_RXTIMEOUT3 (0x22) /* Default: 0x00 */ |
||||
#define SX127X_REG_RXDELAY (0x23) /* Default: 0x00 */ |
||||
#define SX127X_REG_OSC (0x24) /* Default: 0x05 (POR), 0x07 (FSK) */ |
||||
#define SX127X_REG_SYNCCONFIG (0x27) /* Default: 0x93 */ |
||||
#define SX127X_REG_SYNCVALUE1 (0x28) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE2 (0x29) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE3 (0x2A) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE4 (0x2B) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE5 (0x2C) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE6 (0x2D) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE7 (0x2E) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_SYNCVALUE8 (0x2F) /* Default: 0x55 (POR), 0x01 (FSK) */ |
||||
#define SX127X_REG_PACKETCONFIG1 (0x30) /* Default: 0x90 */ |
||||
#define SX127X_REG_PACKETCONFIG2 (0x31) /* Default: 0x40 */ |
||||
#define SX127X_REG_NODEADRS (0x33) /* Default: 0x00 */ |
||||
#define SX127X_REG_BROADCASTADRS (0x34) /* Default: 0x00 */ |
||||
#define SX127X_REG_FIFOTHRESH (0x35) /* Default: 0x0F (POR), 0x1F (FSK) */ |
||||
#define SX127X_REG_SEQCONFIG1 (0x36) /* Default: 0x00 */ |
||||
#define SX127X_REG_SEQCONFIG2 (0x37) /* Default: 0x00 */ |
||||
#define SX127X_REG_TIMERRESOL (0x38) /* Default: 0x00 */ |
||||
#define SX127X_REG_TIMER1COEF (0x39) /* Default: 0xF5 (POR), 0x12 (FSK) */ |
||||
#define SX127X_REG_TIMER2COEF (0x3A) /* Default: 0x20 */ |
||||
#define SX127X_REG_IMAGECAL (0x3B) /* Default: 0x82 (POR), 0x02 (FSK) */ |
||||
#define SX127X_REG_TEMP (0x3C) /* Default: - */ |
||||
#define SX127X_REG_PLLHOP (0x44) /* Default: 0x2D */ |
||||
#define SX127X_REG_BITRATEFRAC (0x5D) /* Default: 0x00 */ |
||||
/* LoRa Registers */ |
||||
#define SX127X_REG_FIFOADDRPTR (0x0D) /* Default: 0x08 */ |
||||
#define SX127X_REG_FIFOTXBASEADDR (0x0E) /* Default: 0x02 */ |
||||
#define SX127X_REG_FIFORXBASEADDR (0x0F) /* Default: 0x0A */ |
||||
#define SX127X_REG_FIFORXCURRENTADDR (0x10) /* Default: 0xFF */ |
||||
#define SX127X_REG_IRQFLAGSMASK (0x11) /* Default: n/a */ |
||||
#define SX127X_REG_IRQFLAGS (0x12) /* Default: 0x15 */ |
||||
#define SX127X_REG_RXNBBYTES (0x13) /* Default: 0x0B */ |
||||
#define SX127X_REG_RXHEADERCNTVALUEMSB (0x14) /* Default: 0x28 */ |
||||
#define SX127X_REG_RXHEADERCNTVALUELSB (0x15) /* Default: 0x0C */ |
||||
#define SX127X_REG_RXPACKETCNTVALUEMSB (0x16) /* Default: 0x12 */ |
||||
#define SX127X_REG_RXPACKETCNTVALUELSB (0x17) /* Default: 0x47 */ |
||||
#define SX127X_REG_MODEMSTAT (0x18) /* Default: 0x32 */ |
||||
#define SX127X_REG_PKTSNRVALUE (0x19) /* Default: 0x3E */ |
||||
#define SX127X_REG_PKTRSSIVALUE (0x1A) /* Default: 0x00 */ |
||||
#define SX127X_REG_RSSIVALUE (0x1B) /* Default: 0x00 */ |
||||
#define SX127X_REG_HOPCHANNEL (0x1C) /* Default: 0x00 */ |
||||
#define SX127X_REG_MODEMCONFIG1 (0x1D) /* Default: 0x00 */ |
||||
#define SX127X_REG_MODEMCONFIG2 (0x1E) /* Default: 0x00 */ |
||||
#define SX127X_REG_SYMBTIMEOUTLSB (0x1F) /* Default: 0x40 */ |
||||
#define SX127X_REG_PREAMBLEMSB (0x20) /* Default: 0x00 */ |
||||
#define SX127X_REG_PREAMBLELSB (0x21) /* Default: 0x00 */ |
||||
#define SX127X_REG_PAYLOADLENGTH (0x22) /* Default: 0x00 */ |
||||
#define SX127X_REG_MAXPAYLOADLENGTH (0x23) /* Default: 0x00 */ |
||||
#define SX127X_REG_HOPPERIOD (0x24) /* Default: 0x05 */ |
||||
#define SX127X_REG_FIFORXBYTEADDR (0x25) /* Default: 0x00 */ |
||||
#define SX127X_REG_MODEMCONFIG3 (0x26) /* Default: 0x03 */ |
||||
#define SX127X_REG_FEIMSB (0x28) /* Default: 0x55 */ |
||||
#define SX127X_REG_FEIMID (0x29) /* Default: 0x55 */ |
||||
#define SX127X_REG_FEILSB (0x2A) /* Default: 0x55 */ |
||||
#define SX127X_REG_RSSIWIDEBAND (0x2C) /* Default: 0x55 */ |
||||
#define SX127X_REG_IFFREQ1 (0x2F) /* Default: 0x55 */ |
||||
#define SX127X_REG_IFFREQ2 (0x30) /* Default: 0x90 */ |
||||
#define SX127X_REG_DETECTOPTIMIZE (0x31) /* Default: 0x40 */ |
||||
#define SX127X_REG_INVERTIQ (0x33) /* Default: 0x00 */ |
||||
#define SX127X_REG_HIGHBWOPTIMIZE1 (0x36) /* Default: 0x00 */ |
||||
#define SX127X_REG_DETECTIONTHRESHOLD (0x37) /* Default: 0x00 */ |
||||
#define SX127X_REG_SYNCWORD (0x39) /* Default: 0xF5 */ |
||||
#define SX127X_REG_HIGHBWOPTIMIZE2 (0x3A) /* Default: 0x20 */ |
||||
#define SX127X_REG_INVERTIQ2 (0x3B) /* Default: 0x82 */ |
||||
/* SX127x Operational Modes */ |
||||
#define SX127X_OPMODE_LRFSK (0x00) /* FSK/OOK Mode */ |
||||
#define SX127X_OPMODE_LRLORA (0x80) /* LoRa Mode */ |
||||
#define SX127X_OPMODE_SHLORA (0x00) /* Access LoRa registers page 0x0D:0x3F */ |
||||
#define SX127X_OPMODE_SHFSK (0x40) /* Access FSK Registers page (in LoRa mode) 0x0D:0x3F */ |
||||
#define SX127X_OPMODE_LFOFF (0x00) /* High Frequency Mode (access to HF test registers) */ |
||||
#define SX127X_OPMODE_LFON (0x08) /* Low Frequency Mode (access to LF test registers) */ |
||||
#define SX127X_OPMODE_SLEEP (0x00) /* Sleep Mode */ |
||||
#define SX127X_OPMODE_STDBY (0x01) /* Standby Mode */ |
||||
#define SX127X_OPMODE_FSTX (0x02) /* Frequency synthesis TX */ |
||||
#define SX127X_OPMODE_TX (0x03) /* Transmit */ |
||||
#define SX127X_OPMODE_FSRX (0x04) /* Frequency synthesis RX */ |
||||
#define SX127X_OPMODE_RXCONTINUOUS (0x05) /* Receive continuous */ |
||||
#define SX127X_OPMODE_RXSINGLE (0x06) /* receive single */ |
||||
#define SX127X_OPMODE_CAD (0x07) /* Channel activity detection */ |
||||
/* SX127x IRQ1 Flags (FSK/OOK) */ |
||||
#define SX127X_IRQFLAGS1_MODEREADY (0x80) |
||||
#define SX127X_IRQFLAGS1_RXREADY (0x40) |
||||
#define SX127X_IRQFLAGS1_TXREADY (0x20) |
||||
#define SX127X_IRQFLAGS1_PLLLOCK (0x10) |
||||
#define SX127X_IRQFLAGS1_RSSI (0x08) |
||||
#define SX127X_IRQFLAGS1_TIMEOUT (0x04) |
||||
#define SX127X_IRQFLAGS1_PREAMBLEDETECT (0x02) |
||||
#define SX127X_IRQFLAGS1_SYNCADDRMATCH (0x01) |
||||
/* SX127x IRQ2 Flags (FSK/OOK) */ |
||||
#define SX127X_IRQFLAGS2_FIFOFULL (0x80) |
||||
#define SX127X_IRQFLAGS2_FIFOEMPTY (0x40) |
||||
#define SX127X_IRQFLAGS2_FIFOLEVEL (0x20) |
||||
#define SX127X_IRQFLAGS2_FIFOOVERRUN (0x10) |
||||
#define SX127X_IRQFLAGS2_PACKETSENT (0x08) |
||||
#define SX127X_IRQFLAGS2_PAYLOADREADY (0x04) |
||||
#define SX127X_IRQFLAGS2_CRCOK (0x02) |
||||
#define SX127X_IRQFLAGS2_LOWBAT (0x01) |
||||
/* SX127x IRQ Flags (LoRa) */ |
||||
#define SX127X_IRQFLAGS_RXTIMEOUT (0x80) |
||||
#define SX127X_IRQFLAGS_RXDONE (0x40) |
||||
#define SX127X_IRQFLAGS_PAYLOADCRCERROR (0x20) |
||||
#define SX127X_IRQFLAGS_VALIDHEADER (0x10) |
||||
#define SX127X_IRQFLAGS_TXDONE (0x08) |
||||
#define SX127X_IRQFLAGS_CADDONE (0x04) |
||||
#define SX127X_IRQFLAGS_FHSSCHANGECHAN (0x02) |
||||
#define SX127X_IRQFLAGS_CADDETECTED (0x01) |
||||
/* SX127x Modem Configuration Fields */ |
||||
#define SX127X_MDMCFG1_BW_7K8 (0x00) /* 0000 → 7.8 kHz */ |
||||
#define SX127X_MDMCFG1_BW_10K4 (0x10) /* 0001 → 10.4 kHz */ |
||||
#define SX127X_MDMCFG1_BW_15K6 (0x20) /* 0010 → 15.6 kHz */ |
||||
#define SX127X_MDMCFG1_BW_20K8 (0x30) /* 0011 → 20.8kHz */ |
||||
#define SX127X_MDMCFG1_BW_31K2 (0x40) /* 0100 → 31.25 kHz */ |
||||
#define SX127X_MDMCFG1_BW_41K7 (0x50) /* 0101 → 41.7 kHz */ |
||||
#define SX127X_MDMCFG1_BW_62K5 (0x60) /* 0110 → 62.5 kHz */ |
||||
#define SX127X_MDMCFG1_BW_125K (0x70) /* 0111 → 125 kHz */ |
||||
#define SX127X_MDMCFG1_BW_250K (0x80) /* 1000 → 250 kHz */ |
||||
#define SX127X_MDMCFG1_BW_500K (0x90) /* 1001 → 500 kHz */ |
||||
#define SX127X_MDMCFG1_RATE_4_5 (0x02) /* 001 → 4/5 */ |
||||
#define SX127X_MDMCFG1_RATE_4_6 (0x04) /* 010 → 4/6 */ |
||||
#define SX127X_MDMCFG1_RATE_4_7 (0x06) /* 011 → 4/7 */ |
||||
#define SX127X_MDMCFG1_RATE_4_8 (0x08) /* 100 → 4/8 */ |
||||
#define SX127X_MDMCFG1_HDR_EXPLICIT (0x00) /* Explicit Header Mode */ |
||||
#define SX127X_MDMCFG1_HDR_IMPLICIT (0x01) /* Implicit Header Mode */ |
||||
#define SX127X_MDMCFG2_SF_64 (0x60) /* 64 chips / symbol */ |
||||
#define SX127X_MDMCFG2_SF_128 (0x70) /* 128 chips / symbol */ |
||||
#define SX127X_MDMCFG2_SF_256 (0x80) /* 256 chips / symbol */ |
||||
#define SX127X_MDMCFG2_SF_512 (0x90) /* 512 chips / symbol */ |
||||
#define SX127X_MDMCFG2_SF_1024 (0xA0) /* 1024 chips / symbol */ |
||||
#define SX127X_MDMCFG2_SF_2048 (0xB0) /* 2048 chips / symbol */ |
||||
#define SX127X_MDMCFG2_SF_4096 (0xC0) /* 4096 chips / symbol */ |
||||
#define SX127X_MDMCFG2_NORMAL (0x00) /* normal mode, a single packet is sent */ |
||||
#define SX127X_MDMCFG2_CONTINUOUS (0x08) /* continuous mode, send multiple packets across the FIFO (used for spectral analysis) */ |
||||
#define SX127X_MDMCFG2_CRC_OFF (0x00) /* CRC disable */ |
||||
#define SX127X_MDMCFG2_CRC_ON (0x04) /* CRC enable */ |
||||
#define SX127X_MDMCFG3_LDR_DISABLE (0x00) /* Disabled */ |
||||
#define SX127X_MDMCFG3_LDR_ENABLE (0x08) /* Enabled; mandated for when the symbol length exceeds 16ms */ |
||||
#define SX127X_MDMCFG3_GAIN_FIXED (0x00) /* LNA gain set by register LnaGain */ |
||||
#define SX127X_MDMCFG3_GAIN_AUTO (0x04) /* LNA gain set by the internal AGC loop */ |
||||
/* SX127x LNA Gain Settings */ |
||||
#define SX127X_LNA_BOOSTHF_ON (0x03) |
||||
#define SX127X_LNA_BOOSTHF_OFF (0x00) |
||||
#define SX127X_LNA_BOOSTLF_OFF (0x00) |
||||
#define SX127X_LNA_GAIN_MASK (0xe0) |
||||
/* SX127x SPI Register Masks */ |
||||
#define SX127X_WRITE_MASK (0x80) |
||||
#define SX127X_READ_MASK (0x7f) |
||||
/* Convenience Macros */ |
||||
#define WREG(x) ((x) | SX127X_WRITE_MASK) |
||||
#define RREG(x) ((x) & SX127X_READ_MASK) |
||||
#define CS_ASSERT() do { sx127x->port->BSRR = sx127x->pin << 16; } while(0) |
||||
#define CS_DEASSERT() do { sx127x->port->BSRR = sx127x->pin; } while(0) |
||||
|
||||
/* Private Variables */ |
||||
|
||||
/* Function Prototypes */ |
||||
static int32_t sx127x_writebyte(sx127x_t *sx127x, uint8_t reg, uint8_t byte); |
||||
static int32_t sx127x_readbyte(sx127x_t *sx127x, uint8_t reg, uint8_t *byte); |
||||
|
||||
/* Function Definitions */ |
||||
int32_t sx127x_init(sx127x_t *sx127x, SPI_HandleTypeDef *hspi, GPIO_TypeDef *port, uint16_t pin) |
||||
{ |
||||
uint8_t opmode; |
||||
|
||||
return_val_if_fail(sx127x, -1); |
||||
return_val_if_fail(hspi, -1); |
||||
|
||||
sx127x->hspi = hspi; |
||||
sx127x->port = port; |
||||
sx127x->pin = pin; |
||||
|
||||
/* query chip ID */ |
||||
return_val_if_fail(sx127x_readbyte(sx127x, SX127X_REG_VERSION, &sx127x->ver.byte) == 0, -1); |
||||
|
||||
/* put the device into sleep mode */ |
||||
opmode = SX127X_OPMODE_LRLORA | SX127X_OPMODE_SLEEP; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_OPMODE, opmode) == 0, -1); |
||||
/* set FIFO base addresses */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FIFOTXBASEADDR, 0) == 0, -1); |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FIFORXBASEADDR, 0) == 0, -1); |
||||
/* set bandwidth, default coding rate */ |
||||
opmode = SX127X_MDMCFG1_BW_125K | SX127X_MDMCFG1_RATE_4_5 | SX127X_MDMCFG1_HDR_EXPLICIT; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG1, opmode) == 0, -1); |
||||
/* set spreading factor & CRC on */ |
||||
opmode = SX127X_MDMCFG2_SF_128 | SX127X_MDMCFG2_NORMAL | SX127X_MDMCFG2_CRC_ON; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG2, opmode) == 0, -1); |
||||
/* set LNA boost */ |
||||
opmode = SX127X_LNA_BOOSTHF_ON; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_LNA, opmode) == 0, -1); |
||||
/* turn on the AGC */ |
||||
opmode = SX127X_MDMCFG3_LDR_ENABLE | SX127X_MDMCFG3_GAIN_AUTO; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG3, opmode) == 0, -1); |
||||
/* set Tx power */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_PACONFIG, 0x87) == 0, -1); |
||||
/* set frequency */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FRFMSB, 0x6c) == 0, -1); |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FRFMID, 0x4f) == 0, -1); |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FRFLSB, 0xf9) == 0, -1); |
||||
/* put the device into LoRa mode and standby */ |
||||
opmode = SX127X_OPMODE_LRLORA | SX127X_OPMODE_SHLORA | SX127X_OPMODE_LFON | SX127X_OPMODE_STDBY; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_OPMODE, opmode) == 0, -1); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int32_t sx127x_tx(sx127x_t *sx127x, uint8_t *buf, uint16_t len) |
||||
{ |
||||
uint16_t i; |
||||
uint8_t tmp; |
||||
|
||||
/*
|
||||
* FIFO can be prefilled in Sleep/Standby but must be refilled “on-the-fly” during Tx with the rest of the payload. |
||||
* 1) Pre-fill FIFO (in Sleep/Standby first or directly in Tx mode) until FifoThreshold or FifoFull is set |
||||
* 2) In Tx, wait for FifoThreshold or FifoEmpty to be set (i.e. FIFO is nearly empty) |
||||
* 3) Write bytes into the FIFO until FifoThreshold or FifoFull is set. |
||||
* 4) Continue to step 2 until the entire message has been written to the FIFO (PacketSent will fire when the last bit of the |
||||
* packet has been sent). |
||||
*/ |
||||
/* set explicit packet mode */ |
||||
return_val_if_fail(sx127x_readbyte(sx127x, SX127X_REG_MODEMCONFIG1, &tmp) == 0, -1); |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG1, tmp & ~SX127X_MDMCFG1_HDR_IMPLICIT) == 0, -1); |
||||
/* reset FIFO address pointer */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FIFOADDRPTR, 0) == 0, -1); |
||||
/* clear payload length */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_PAYLOADLENGTH, 0) == 0, -1); |
||||
/* send data */ |
||||
for(i = 0; i < len; i++) |
||||
{ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FIFO, buf[i]) == 0, -1); |
||||
} |
||||
/* set payload length */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_PAYLOADLENGTH, len) == 0, -1); |
||||
/* put the device in transmit mode */ |
||||
tmp = SX127X_OPMODE_LRLORA | SX127X_OPMODE_SHLORA | SX127X_OPMODE_LFON | SX127X_OPMODE_TX; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_OPMODE, tmp) == 0, -1); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int32_t sx127x_rx(sx127x_t *sx127x, uint8_t *buf) |
||||
{ |
||||
uint16_t i; |
||||
uint8_t irq; |
||||
uint8_t tmp; |
||||
uint8_t len; |
||||
uint8_t ptr; |
||||
|
||||
/*
|
||||
* In continuous mode the received packet processing sequence is given below. |
||||
* 1 Whilst in Sleep or Standby mode select RXCONT mode. |
||||
* 2 Upon reception of a valid header CRC the RxDone interrupt is set. The radio remains in RXCONT mode waiting for the next RX LoRa packet. |
||||
* 3 The PayloadCrcError flag should be checked for packet integrity. |
||||
* 4 If packet has been correctly received the FIFO data buffer can be read (see below). |
||||
* 5 The reception process (steps 2 - 4) can be repeated or receiver operating mode exited as desired. |
||||
*/ |
||||
/* set explicit packet mode */ |
||||
return_val_if_fail(sx127x_readbyte(sx127x, SX127X_REG_MODEMCONFIG1, &tmp) == 0, -1); |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG1, tmp & ~SX127X_MDMCFG1_HDR_IMPLICIT) == 0, -1); |
||||
/* put the device in continuous receive mode */ |
||||
tmp = SX127X_OPMODE_LRLORA | SX127X_OPMODE_SHLORA | SX127X_OPMODE_LFON | SX127X_OPMODE_RXCONTINUOUS; |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_OPMODE, tmp) == 0, -1); |
||||
/* wait for RxDone interrupt */ |
||||
do |
||||
{ |
||||
return_val_if_fail(sx127x_readbyte(sx127x, SX127X_REG_IRQFLAGS, &irq) == 0, -1); |
||||
} |
||||
while(!(irq & SX127X_IRQFLAGS_RXDONE)); |
||||
/*
|
||||
* In order to retrieve received data from FIFO the user must ensure that |
||||
* ValidHeader, PayloadCrcError, RxDone and RxTimeout interrupts in the |
||||
* status register RegIrqFlags are not asserted to ensure that packet |
||||
* reception has terminated successfully (i.e. no flags should be set). In |
||||
* case of errors the steps below should be skipped and the packet |
||||
* discarded. In order to retrieve valid received data from the FIFO the |
||||
* user must: |
||||
* * RegRxNbBytes Indicates the number of bytes that have been received |
||||
* thus far. |
||||
* * RegFifoAddrPtr is a dynamic pointer that indicates precisely where the |
||||
* Lora modem received data has been written up to. |
||||
* * Set RegFifoAddrPtr to RegFifoRxCurrentAddr. This sets the FIFO pointer |
||||
* to the location of the last packet received in the FIFO. The payload |
||||
* can then be extracted by reading the register RegFifo, RegRxNbBytes |
||||
* times. |
||||
* * Alternatively, it is possible to manually point to the location of the |
||||
* last packet received, from the start of the current packet, by setting |
||||
* RegFifoAddrPtr to RegFifoRxByteAddr minus RegRxNbBytes. The payload |
||||
* bytes can then be read from the FIFO by reading the RegFifo address |
||||
* RegRxNbBytes times. |
||||
*/ |
||||
/* clear interrupt flags */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_IRQFLAGS, irq) == 0, -1); |
||||
/* check for errors */ |
||||
return_val_if_fail( (irq & SX127X_IRQFLAGS_VALIDHEADER) && |
||||
!(irq & SX127X_IRQFLAGS_PAYLOADCRCERROR) && |
||||
!(irq & SX127X_IRQFLAGS_RXTIMEOUT), -1); |
||||
/* get number of received bytes */ |
||||
tmp = RREG(SX127X_REG_RXNBBYTES); |
||||
return_val_if_fail(sx127x_readbyte(sx127x, tmp, &len) == 0, -1); |
||||
/* get location of payload from RegFifoRxCurrentAddr */ |
||||
tmp = RREG(SX127X_REG_FIFORXCURRENTADDR); |
||||
return_val_if_fail(sx127x_readbyte(sx127x, tmp, &ptr) == 0, -1); |
||||
/* set FIFO pointer to RegFifoRxCurrentAddr */ |
||||
tmp = WREG(SX127X_REG_FIFOADDRPTR); |
||||
return_val_if_fail(sx127x_writebyte(sx127x, tmp, ptr) == 0, -1); |
||||
/* extract the payload */ |
||||
tmp = RREG(SX127X_REG_FIFO); |
||||
for(i = 0; i < len; i++) |
||||
{ |
||||
return_val_if_fail(sx127x_readbyte(sx127x, tmp, &(buf[i])) == 0, -1); |
||||
} |
||||
/* reset FIFO address pointer */ |
||||
return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_FIFOADDRPTR, 0) == 0, -1); |
||||
|
||||
return len; |
||||
} |
||||
|
||||
static int32_t sx127x_writebyte(sx127x_t *sx127x, uint8_t reg, uint8_t byte) |
||||
{ |
||||
uint8_t txdata[2] = { WREG(reg), byte }; |
||||
HAL_StatusTypeDef res; |
||||
|
||||
CS_ASSERT(); |
||||
res = HAL_SPI_Transmit(sx127x->hspi, &(txdata[0]), 2, 10); |
||||
CS_DEASSERT(); |
||||
return_val_if_fail(res == HAL_OK, -1); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int32_t sx127x_readbyte(sx127x_t *sx127x, uint8_t reg, uint8_t *byte) |
||||
{ |
||||
uint8_t txdata[2] = { RREG(reg), 0x00 }; |
||||
uint8_t rxdata[2]; |
||||
HAL_StatusTypeDef res; |
||||
|
||||
CS_ASSERT(); |
||||
res = HAL_SPI_TransmitReceive(sx127x->hspi, &(txdata[0]), &(rxdata[0]), 2, 10); |
||||
CS_DEASSERT(); |
||||
return_val_if_fail(res == HAL_OK, -1); |
||||
*byte = rxdata[1]; |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
# SX127x |
||||
## Introduction |
||||
This library implements support for the [SX1276/77/78/79](https://www.semtech.com/products/wireless-rf/lora-connect/sx1276) transceivers in LoRa mode. It is written for the STM32 HAL, but a low-level, platform agnostic library is planned. |
||||
|
||||
## Usage |
||||
Clone this repository, or add it as a submodule, to your STM32 project under the Drivers/ directory. |
||||
|
||||
Example: |
||||
``` |
||||
#include "sx127x.h" |
||||
sx127x_t sx127x; |
||||
sx127x_init(&sx127x, &hspi1, SPI1_CS_GPIO_Port, SPI1_CS_Pin); |
||||
sx127x_tx(&sx127x, (uint8_t *) "Hello, world!\r\n", 15); |
||||
``` |
Loading…
Reference in new issue