From b70d37cbdf8b354644c172967e3b59590a459317 Mon Sep 17 00:00:00 2001 From: Daniel Peter Chokola Date: Mon, 6 Mar 2023 21:16:04 -0500 Subject: [PATCH] SX127x can transmit in LoRa mode with some hardcoded settings The code is janky and many settings are hardcoded. Will need to improve robustness, add configuration options to the API, and add receive functionality. --- Core/Src/main.c | 1 + Drivers/SX127x/Inc/sx127x.h | 8 + Drivers/SX127x/Src/sx127x.c | 362 ++++++++++++++++++++++++++++-------- 3 files changed, 294 insertions(+), 77 deletions(-) diff --git a/Core/Src/main.c b/Core/Src/main.c index 20e043b..3c8eb8a 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -97,6 +97,7 @@ int main(void) HAL_GPIO_WritePin(BME280_PWR_GPIO_Port, BME280_PWR_Pin, GPIO_PIN_SET); bme280_init(&bme280, &hspi2, SPI2_CS_GPIO_Port, SPI2_CS_Pin); sx127x_init(&sx127x, &hspi1, SPI1_CS_GPIO_Port, SPI1_CS_Pin); + sx127x_tx(&sx127x, "Hello, world!\r", 14); /* USER CODE END 2 */ /* Infinite loop */ diff --git a/Drivers/SX127x/Inc/sx127x.h b/Drivers/SX127x/Inc/sx127x.h index 9d186ef..1ef2380 100644 --- a/Drivers/SX127x/Inc/sx127x.h +++ b/Drivers/SX127x/Inc/sx127x.h @@ -19,9 +19,17 @@ 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); #endif /* SX127X_INC_SX127X_H_ */ diff --git a/Drivers/SX127x/Src/sx127x.c b/Drivers/SX127x/Src/sx127x.c index 260db12..4ae8eec 100644 --- a/Drivers/SX127x/Src/sx127x.c +++ b/Drivers/SX127x/Src/sx127x.c @@ -11,91 +11,195 @@ #include "util.h" /* Definitions */ -#define SX127X_REG_FIFO (0x00) /* Default: 0x00 */ -#define SX127X_REG_OPMODE (0x01) /* Default: 0x01 */ -#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_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_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_RSSIVALUE (0x11) /* Default: n/a */ -#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_FEIMSB (0x1D) /* Default: 0x00 (POR), n/a (FSK) */ -#define SX127X_REG_FEILSB (0x1E) /* 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_PREAMBLEMSB (0x25) /* Default: 0x00 */ -#define SX127X_REG_PREAMBLELSB (0x26) /* Default: 0x03 */ -#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_PAYLOADLENGTH (0x32) /* Default: 0x40 */ -#define SX127X_REG_NODEADRS (0x33) /* Default: 0x00 */ -#define SX127X_REG_BROADCASTADRS (0x34) /* Default: 0x00 */ -#define SX127X_REG_FIFOTHRESH (0x35) /* Default: 0x1F */ -#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_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_PLLHOP (0x44) /* Default: 0x2D */ -#define SX127X_REG_TCXO (0x4B) /* Default: 0x09 */ -#define SX127X_REG_PADAC (0x4D) /* Default: 0x84 */ -#define SX127X_REG_FORMERTEMP (0x5B) /* Default: - */ -#define SX127X_REG_BITRATEFRAC (0x5D) /* Default: 0x00 */ -#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 */ +/* 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 IRQ Flags (LoRa) */ +#define SX127X_IRQFLAGS_FIFOFULL (0x80) +#define SX127X_IRQFLAGS_FIFOEMPTY (0x40) +#define SX127X_IRQFLAGS_FIFOLEVEL (0x20) +#define SX127X_IRQFLAGS_FIFOOVERRUN (0x10) +#define SX127X_IRQFLAGS_PACKETSENT (0x08) +#define SX127X_IRQFLAGS_PAYLOADREADY (0x04) +#define SX127X_IRQFLAGS_CRCOK (0x02) +#define SX127X_IRQFLAGS_LOWBAT (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 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); @@ -103,5 +207,109 @@ int32_t sx127x_init(sx127x_t *sx127x, SPI_HandleTypeDef *hspi, GPIO_TypeDef *por 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_7K8 | 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_4096 | SX127X_MDMCFG2_NORMAL | SX127X_MDMCFG2_CRC_ON; + return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG2, opmode) == 0, -1); + /* turn on the AGC */ + return_val_if_fail(sx127x_writebyte(sx127x, SX127X_REG_MODEMCONFIG3, SX127X_MDMCFG3_LDR_ENABLE | SX127X_MDMCFG3_GAIN_AUTO) == 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) +{ + HAL_StatusTypeDef res = HAL_OK; + uint16_t i; + uint8_t irq; + 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); + /* + do + { + CS_ASSERT(); + tmp = RREG(SX127X_REG_IRQFLAGS); + res |= HAL_SPI_Transmit(sx127x->hspi, &tmp, 1, 10); + res |= HAL_SPI_Receive(sx127x->hspi, &irq, 1, 10); + CS_DEASSERT(); + } + while(irq & SX127X_IRQFLAGS_FIFOFULL); + */ + } + + return_val_if_fail(res == HAL_OK, -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; +} + +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; }