123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- /**
- * Author Wojciech Domski <Wojciech.Domski@gmail.com>
- * www: www.Domski.pl
- *
- * work based on DORJI.COM sample code and
- * https://github.com/realspinner/SX1276_LoRa
- */
-
- #include "SX1276.h"
- #include <string.h>
-
-
- //////////////////////////////////
- // logic
- //////////////////////////////////
-
- __weak void SX1276_hw_init(SX1276_hw_t * hw) {
- SX1276_hw_SetNSS(hw, 1);
- HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_SET);
- }
-
- __weak void SX1276_hw_SetNSS(SX1276_hw_t * hw, int value) {
- HAL_GPIO_WritePin(hw->nss.port, hw->nss.pin,
- (value == 1) ? GPIO_PIN_SET : GPIO_PIN_RESET);
- }
-
- __weak void SX1276_hw_Reset(SX1276_hw_t * hw) {
- SX1276_hw_SetNSS(hw, 1);
- HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_RESET);
-
- SX1276_hw_DelayMs(1);
-
- HAL_GPIO_WritePin(hw->reset.port, hw->reset.pin, GPIO_PIN_SET);
-
- SX1276_hw_DelayMs(100);
- }
-
- #if 0 // PYJ.2019.04.01_BEGIN --
- __weak void SX1276_hw_SPICommand(SX1276_hw_t * hw, uint8_t cmd) {
- SX1276_hw_SetNSS(hw, 0);
- HAL_SPI_Transmit(hw->spi, &cmd, 1, 1000);
- while (HAL_SPI_GetState(hw->spi) != HAL_SPI_STATE_READY)
- ;
- }
- #endif // PYJ.2019.04.01_END --
- void SX1276_hw_SPICommand(SX1276_hw_t * hw, uint8_t cmd) {
- SX1276_hw_SetNSS(hw, 0);
- BLUECELL_SPI_Transmit(cmd);
- }
-
- #if 0 // PYJ.2019.04.01_BEGIN --
- __weak uint8_t SX1276_hw_SPIReadByte(SX1276_hw_t * hw) {
- uint8_t txByte = 0x00;
- uint8_t rxByte = 0x00;
-
- SX1276_hw_SetNSS(hw, 0);
- HAL_SPI_TransmitReceive(hw->spi, &txByte, &rxByte, 1, 1000);
- return rxByte;
- }
- #endif // PYJ.2019.04.01_END --
- uint8_t SX1276_hw_SPIReadByte(SX1276_hw_t * hw) {
- //uint8_t txByte = 0x00;
- uint8_t rxByte = 0x00;
-
- SX1276_hw_SetNSS(hw, 0);
- // HAL_SPI_TransmitReceive(hw->spi, &txByte, &rxByte, 1, 1000);
- rxByte = SpiRead();
- return rxByte;
- }
-
- __weak void SX1276_hw_DelayMs(uint32_t msec) {
- HAL_Delay(msec);
- }
-
- __weak int SX1276_hw_GetDIO0(SX1276_hw_t * hw) {
- return (HAL_GPIO_ReadPin(hw->dio0.port, hw->dio0.pin) == GPIO_PIN_SET);
- }
-
- //////////////////////////////////
- // logic
- //////////////////////////////////
-
- uint8_t SX1276_SPIRead(SX1276_t * module, uint8_t addr) {
- uint8_t tmp;
- SX1276_hw_SPICommand(module->hw, addr);
- tmp = SX1276_hw_SPIReadByte(module->hw);
- SX1276_hw_SetNSS(module->hw, 1);
- return tmp;
- }
- uint8_t SX1276_SPIIDRead(SX1276_t * module, uint8_t addr) {
- uint8_t tmp;
- SX1276_hw_SPICommand(module->hw, addr);
- tmp = SX1276_hw_SPIReadByte(module->hw);
- SX1276_hw_SetNSS(module->hw, 1);
- return tmp;
- }
-
- void SX1276_SPIWrite(SX1276_t * module, uint8_t addr, uint8_t cmd) {
- SX1276_hw_SetNSS(module->hw, 0);
- SX1276_hw_SPICommand(module->hw, addr | 0x80);
- SX1276_hw_SPICommand(module->hw, cmd);
- // SPIGPIOTxRx(addr | 0x80,cmd);
-
- SX1276_hw_SetNSS(module->hw, 1);
- }
-
- void SX1276_SPIBurstRead(SX1276_t * module, uint8_t addr, uint8_t* rxBuf,
- uint8_t length) {
- uint8_t i;
- if (length <= 1) {
- return;
- } else {
- SX1276_hw_SetNSS(module->hw, 0);
- SX1276_hw_SPICommand(module->hw, addr);
- //printf("Test Data:");
- for (i = 0; i < length; i++) {
- rxBuf[i] = SX1276_hw_SPIReadByte(module->hw);
- //printf("%02x ",rxBuf[i]);
- }
- //printf("\n");
- SX1276_hw_SetNSS(module->hw, 1);
- }
- }
-
- void SX1276_SPIBurstWrite(SX1276_t * module, uint8_t addr, uint8_t* txBuf,
- uint8_t length) {
- uint8_t i;
- if (length <= 1) {
- return;
- } else {
- SX1276_hw_SetNSS(module->hw, 0);
- SX1276_hw_SPICommand(module->hw, addr | 0x80);
- // printf("Test Data:");
- for (i = 0; i < length; i++) {
- SX1276_hw_SPICommand(module->hw, txBuf[i]);
- // printf("%02x ",txBuf[i]);
- }
- // printf("\n");
- SX1276_hw_SetNSS(module->hw, 1);
- }
- }
- /*
- RegPaConfig - 0x09
- PaSelect Mode Power Range Pout Formula
- 0 PA_HF or PA_LF on RFO_HF or RFO_LF -4 to +15dBm Pout=Pmax-(15-OutputPower), Pmax=10.8+0.6*MaxPower [dBm]
- 1 PA_HP on PA_BOOST, any frequency +2 to +17dBm Pout=17-(15-OutputPower) [dBm]
- PA_LF option doesn't seem to transmit anything. Not connected on these boards, perhaps?
- Use only PA_BOOST mode.
-
- PA_LF Pmax
- Pout 0 1 2 3 4 5 6 7
- 0 -4.2 -3.6 -3 -2.4 -1.8 -1.2 -0.6 0
- 1 -3.2 -2.6 -2 -1.4 -0.8 -0.2 0.4 1
- 2 -2.2 -1.6 -1 -0.4 0.2 0.8 1.4 2
- 3 -1.2 -0.6 0 0.6 1.2 1.8 2.4 3
- 4 -0.2 0.4 1 1.6 2.2 2.8 3.4 4
- 5 0.8 1.4 2 2.6 3.2 3.8 4.4 5
- 6 1.8 2.4 3 3.6 4.2 4.8 5.4 6
- 7 2.8 3.4 4 4.6 5.2 5.8 6.4 7
- 8 3.8 4.4 5 5.6 6.2 6.8 7.4 8
- 9 4.8 5.4 6 6.6 7.2 7.8 8.4 9
- 10 5.8 6.4 7 7.6 8.2 8.8 9.4 10
- 11 6.8 7.4 8 8.6 9.2 9.8 10.4 11
- 12 7.8 8.4 9 9.6 10.2 10.8 11.4 12
- 13 8.8 9.4 10 10.6 11.2 11.8 12.4 13
- 14 9.8 10.4 11 11.6 12.2 12.8 13.4 14
- 15 10.8 11.4 12 12.6 13.2 13.8 14.4 15 [dBm]
-
- PA_BOOST
- Pout OutputPower
- 0 2 dBm
- 1 3 dBm
- 2 4 dBm
- 3 5 dBm
- 4 6 dBm
- 5 7 dBm
- 6 8 dBm
- 7 9 dBm
- 8 10 dBm
- 9 11 dBm
- 10 12 dBm
- 11 13 dBm
- 12 14 dBm
- 13 15 dBm
- 14 16 dBm
- 15 17 dBm
-
- PaSelect
- 0 RFO pin. Maximum power of +14 dBm
- 1 PA_BOOST pin. Maximum power of +20 dBm
- MaxPower
- Select max output power: Pmax=10.8+0.6*MaxPower [dBm]
- OutputPower
- Pout=Pmax-(15-OutputPower) if PaSelect = 0 (RFO pins)
- Pout=17-(15-OutputPower) if PaSelect = 1 (PA_BOOST pin)
- PA_HF and PA_LF are high efficiency amplifiers capable of yielding RF power programmable in 1 dB steps
- from -4 to +14dBm directly into a 50 ohm load with low current consumption. PA_LF covers the lower bands
- (up to 525 MHz), whilst PA_HF will cover the upper bands (from 860 MHz).
- PA_HP (High Power), connected to the PA_BOOST pin, covers all frequency bands that the chip addresses.
- It permits continuous operation at up to +17 dBm and duty cycled operation at up to +20dBm.
- RegOcp - 0x0B
- OcpTrim IMAX Imax Formula
- 0 to 15 45 to 120 mA 45 + 5*OcpTrim [mA]
- 16 to 27 130 to 240 mA -30 + 10*OcpTrim [mA]
- 27+ 240 mA 240 mA
-
- The power amplifiers of RFM95/96/97/98(W) are protected against current over supply in adverse RF load
- conditions by the over current protection block. The current limiter value is controlled by the OcpTrim
- bits in RegOcp.
- Imax sets a limit on the current drain of the Power Amplifier only, hence the maximum current drain of the
- RFM96/77/78 is equal to Imax + IFS.
- Default 100mA changed to 240mA.
- */
-
- void SX1276_set_power(SX1276_t * module)
- {
- // SX1276_SPIWrite(LR_RegPaConfig, (PaSelect << 7) | ((MaxPower & 0x07) << 4) | (OutputPower & 0x0F));
- SX1276_SPIWrite(module,LR_RegPaConfig, (module->LoRa_Pa_boost << 7) | ((0x07) << 4) | (module->power & 0x0F));
- //RFO -> 0 ~ 15 / PA_BOOST -> 2 ~ 17
- }
- void SX1276_defaultConfig(SX1276_t * module) {
- SX1276_config(module, module->frequency, module->power, module->LoRa_Rate,
- module->LoRa_BW,module->LoRa_Lna,module->LoRa_Pa_boost);
- }
-
- void SX1276_config(SX1276_t * module, uint8_t frequency, uint8_t power,
- uint8_t LoRa_Rate, uint8_t LoRa_BW,uint8_t LoRa_Lna,uint8_t LoRa_PaBoost) {
- SX1276_sleep(module); //Change modem mode Must in Sleep mode
- SX1276_hw_DelayMs(15);
-
- SX1276_entryLoRa(module);
- //SX1276_SPIWrite(module, 0x5904); //?? Change digital regulator form 1.6V to 1.47V: see errata note
-
- SX1276_SPIBurstWrite(module, LR_RegFrMsb,
- (uint8_t*) SX1276_Frequency[frequency], 3); //setting frequency parameter
-
- //setting base parameter
- SX1276_SPIWrite(module, LR_RegPaConfig, SX1276_Power[power]); //Setting output power parameter
-
- SX1276_SPIWrite(module, LR_RegOcp, 0x0B); //RegOcp,Close Ocp
- // SX1276_SPIWrite(module, LR_RegLna, 0x20); //RegLNA,High & LNA Enable
- SX1276_set_power(module);
-
- SX1276_SPIWrite(module, LR_RegLna, LoRa_Lna); //RegLNA,High & LNA Enable
-
- if (SX1276_SpreadFactor[LoRa_Rate] == 6) { //SFactor=6
- uint8_t tmp;
- SX1276_SPIWrite(module,
- LR_RegModemConfig1,
- ((SX1276_LoRaBandwidth[LoRa_BW] << 4) + (SX1276_CR << 1) + 0x01)); //Implicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04)
-
- SX1276_SPIWrite(module,LR_RegModemConfig2,((SX1276_SpreadFactor[LoRa_Rate] << 4) + (SX1276_CRC << 2) + 0x03));
-
- tmp = SX1276_SPIRead(module, 0x31);
- tmp &= 0xF8;
- tmp |= 0x05;
- SX1276_SPIWrite(module, 0x31, tmp);
- SX1276_SPIWrite(module, 0x37, 0x0C);
- } else {
- SX1276_SPIWrite(module,
- LR_RegModemConfig1,
- ((SX1276_LoRaBandwidth[LoRa_BW] << 4) + (SX1276_CR << 1) + 0x00)); //Explicit Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7(0x03), 4/8(0x04)
-
- SX1276_SPIWrite(module,
- LR_RegModemConfig2,
- ((SX1276_SpreadFactor[LoRa_Rate] << 4) + (SX1276_CRC << 2)
- + 0x03)); //SFactor & LNA gain set by the internal AGC loop
- }
-
- SX1276_SPIWrite(module, LR_RegSymbTimeoutLsb, 0xFF); //RegSymbTimeoutLsb Timeout = 0x3FF(Max)
- SX1276_SPIWrite(module, LR_RegPreambleMsb, 0x00); //RegPreambleMsb
- SX1276_SPIWrite(module, LR_RegPreambleLsb, 12); //RegPreambleLsb 8+4=12byte Preamble
- SX1276_SPIWrite(module, REG_LR_DIOMAPPING2, 0x01); //RegDioMapping2 DIO5=00, DIO4=01
- module->readBytes = 0;
- SX1276_standby(module); //Entry standby mode
- }
-
- void SX1276_standby(SX1276_t * module) {
- // SX1276_SPIWrite(module, LR_RegOpMode, 0x09);
- SX1276_SPIWrite(module, LR_RegOpMode, 0x01);
-
- module->status = STANDBY;
- }
-
- void SX1276_sleep(SX1276_t * module) {
- // SX1276_SPIWrite(module, LR_RegOpMode, 0x08);
- SX1276_SPIWrite(module, LR_RegOpMode, 0x80);
-
- module->status = SLEEP;
- }
-
- void SX1276_entryLoRa(SX1276_t * module) {
- // SX1276_SPIWrite(module, LR_RegOpMode, 0x88);
- SX1276_SPIWrite(module, LR_RegOpMode, 0x80);
- }
-
- void SX1276_clearLoRaIrq(SX1276_t * module) {
- SX1276_SPIWrite(module, LR_RegIrqFlags, 0xFF);
- }
-
- int SX1276_LoRaEntryRx(SX1276_t * module, uint8_t length, uint32_t timeout) {
- uint8_t addr;
-
- module->packetLength = length;
-
- SX1276_defaultConfig(module); //Setting base parameter
- SX1276_SPIWrite(module, REG_LR_PADAC, 0x84); //Normal and RX
- SX1276_SPIWrite(module, LR_RegHopPeriod, 0xFF); //No FHSS
- SX1276_SPIWrite(module, REG_LR_DIOMAPPING1, 0x01);//DIO=00,DIO1=00,DIO2=00, DIO3=01
- SX1276_SPIWrite(module, LR_RegIrqFlagsMask, 0x3F);//Open RxDone interrupt & Timeout
- SX1276_clearLoRaIrq(module);
- SX1276_SPIWrite(module, LR_RegPayloadLength, length);//Payload Length 21byte(this register must difine when the data long of one byte in SF is 6)
- addr = SX1276_SPIRead(module, LR_RegFifoRxBaseAddr); //Read RxBaseAddr
- SX1276_SPIWrite(module, LR_RegFifoAddrPtr, addr); //RxBaseAddr->FiFoAddrPtr
- SX1276_SPIWrite(module, LR_RegOpMode, 0x85); //Mode//Low Frequency Mode
- //SX1276_SPIWrite(module, LR_RegOpMode,0x05); //Continuous Rx Mode //High Frequency Mode
- module->readBytes = 0;
-
- while (1) {
- if ((SX1276_SPIRead(module, LR_RegModemStat) & 0x04) == 0x04) { //Rx-on going RegModemStat
- module->status = RX;
- return 1;
- }
- if (--timeout == 0) {
- printf(
"Function : %s Line : %d \n",__func__,__LINE__);
- NVIC_SystemReset();
- SX1276_hw_Reset(module->hw);
- SX1276_defaultConfig(module);
- return 0;
- }
- SX1276_hw_DelayMs(1);
- }
- }
-
- uint8_t SX1276_LoRaRxPacket(SX1276_t * module) {
- unsigned char addr;
- unsigned char packet_size;
-
- if (SX1276_hw_GetDIO0(module->hw)) {
- memset(module->rxBuffer, 0x00, SX1276_MAX_PACKET);
-
- addr = SX1276_SPIRead(module, LR_RegFifoRxCurrentaddr); //last packet addr
- SX1276_SPIWrite(module, LR_RegFifoAddrPtr, addr); //RxBaseAddr -> FiFoAddrPtr
-
- if (module->LoRa_Rate == SX1276_LORA_SF_6) { //When SpreadFactor is six,will used Implicit Header mode(Excluding internal packet length)
- packet_size = module->packetLength;
- } else {
- packet_size = SX1276_SPIRead(module, LR_RegRxNbBytes); //Number for received bytes
- }
-
- SX1276_SPIBurstRead(module, 0x00, module->rxBuffer, packet_size);
- module->readBytes = packet_size;
- SX1276_clearLoRaIrq(module);
- }
- return module->readBytes;
- }
-
-
-
-
- int SX1276_LoRaEntryTx(SX1276_t * module, uint8_t length, uint32_t timeout) {
- uint8_t addr;
- uint8_t temp;
-
- module->packetLength = length;
-
- SX1276_defaultConfig(module); //setting base parameter
- SX1276_SPIWrite(module, REG_LR_PADAC, 0x87); //Tx for 20dBm
- SX1276_SPIWrite(module, LR_RegHopPeriod, 0x00); //RegHopPeriod NO FHSS
- SX1276_SPIWrite(module, REG_LR_DIOMAPPING1, 0x41); //DIO0=01, DIO1=00,DIO2=00, DIO3=01
- SX1276_clearLoRaIrq(module);
- SX1276_SPIWrite(module, LR_RegIrqFlagsMask, 0xF7); //Open TxDone interrupt
- SX1276_SPIWrite(module, LR_RegPayloadLength, length); //RegPayloadLength 21byte
- addr = SX1276_SPIRead(module, LR_RegFifoTxBaseAddr); //RegFiFoTxBaseAddr
- SX1276_SPIWrite(module, LR_RegFifoAddrPtr, addr); //RegFifoAddrPtr
-
- while (1) {
- temp = SX1276_SPIRead(module, LR_RegPayloadLength);
- if (temp == length) {
- module->status = TX;
- return 1;
- }
-
- if (--timeout == 0) {
- printf(
"Function : %s Line : %d \n",__func__,__LINE__);
- NVIC_SystemReset();
- SX1276_hw_Reset(module->hw);
- SX1276_defaultConfig(module);
- return 0;
- }
- }
- }
-
- int SX1276_LoRaTxPacket(SX1276_t * module, uint8_t* txBuffer, uint8_t length,
- uint32_t timeout) {
- SX1276_SPIBurstWrite(module, 0x00, txBuffer, length);
- // SX1276_SPIWrite(module, LR_RegOpMode, 0x8b); //Tx Mode
- SX1276_SPIWrite(module, LR_RegOpMode, 0x83); //Tx Mode
-
- while (1) {
- if (SX1276_hw_GetDIO0(module->hw)) { //if(Get_NIRQ()) //Packet send over
- SX1276_SPIRead(module, LR_RegIrqFlags);
- SX1276_clearLoRaIrq(module); //Clear irq
- SX1276_standby(module); //Entry Standby mode
- return 1;
- }
-
- if (--timeout == 0) {
- printf(
"Function : %s Line : %d \n",__func__,__LINE__);
- NVIC_SystemReset();
- SX1276_hw_Reset(module->hw);
- SX1276_defaultConfig(module);
- return 0;
- }
- SX1276_hw_DelayMs(1);
- }
- }
-
- void SX1276_begin(SX1276_t * module, uint8_t frequency, uint8_t power,
- uint8_t LoRa_Rate, uint8_t LoRa_BW, uint8_t packetLength,uint8_t LoRa_Lna,uint8_t LoRa_PaBoost) {
- SX1276_hw_init(module->hw);
- module->frequency = frequency;
- module->power = power;
- module->LoRa_Rate = LoRa_Rate;
- module->LoRa_BW = LoRa_BW;
- module->packetLength = packetLength;
- module->LoRa_Lna = LoRa_Lna;
- module->LoRa_Pa_boost = LoRa_PaBoost;
- SX1276_defaultConfig(module);
- }
-
- int SX1276_transmit(SX1276_t * module, uint8_t* txBuf, uint8_t length,
- uint32_t timeout) {
- if (SX1276_LoRaEntryTx(module, length, timeout)) {
- return SX1276_LoRaTxPacket(module, txBuf, length, timeout);
- }
- return 0;
- }
-
- int SX1276_receive(SX1276_t * module, uint8_t length, uint32_t timeout) {
- return SX1276_LoRaEntryRx(module, length, timeout);
- }
-
- uint8_t SX1276_available(SX1276_t * module) {
- return SX1276_LoRaRxPacket(module);
- }
-
- uint8_t SX1276_read(SX1276_t * module, uint8_t* rxBuf, uint8_t length) {
- if (length != module->readBytes)
- length = module->readBytes;
- memcpy(rxBuf, module->rxBuffer, length);
- rxBuf[length] = '\0';
- module->readBytes = 0;
- return length;
- }
-
- uint8_t SX1276_RSSI_LoRa(SX1276_t * module) {
- uint32_t temp = 10;
- temp = SX1276_SPIRead(module, LR_RegRssiValue); //Read RegRssiValue, Rssi value
- temp = temp + 127 - 137; //127:Max RSSI, 137:RSSI offset
- return (uint8_t) temp;
- }
-
- uint8_t SX1276_RSSI(SX1276_t * module) {
- uint8_t temp = 0xff;
- temp = SX1276_SPIRead(module, RegRssiValue);
- temp = 127 - (temp >> 1); //127:Max RSSI
- return temp;
- }
-
|