Driver library for SX1272/SX1276 transceivers

Dependents:   LORA_RX LORA_TX WindConcentrator hid_test ... more

/media/uploads/dudmuck/lora.png

Driver library for SX1272 and SX1276 radio transceivers.

This device uses CSS modulation to provide much improved link budget. The RF hardware is same as in FSK devices, just with added LoRa spread-spectrum modem.

This library provides functions to configure radio chip and transmit & receive packets.

Using This Library

Library function service_radio() must be called continuously from main loop, to service interrupts from radio.

/media/uploads/dudmuck/sx1272rf1_connector_300.jpg

Board Specific implementation

FunctionPointer for rf_switch callback allows the program to implement control of RF switch unique to their board. Example options are:

  • SKY13373 for external power amplifier implementation. Requires two DigitalOut pins.
  • SKY13350 using PA_BOOST. requires two DigitalOut pins.
  • PE4259-63: controlled directly by radio chip, no software function needed. However, in the case of SX1276MB1xAS, the RXTX pin on IO2 should be driven by this callback function when R16 is installed (without R15) on this shield board.

Some configurations may need to force the use of RFO or PA_BOOST, or a board could offer both options. The rf_switch function pointer callback should support the implementation choice on the board.

further reading

Committer:
dudmuck
Date:
Wed Apr 30 22:49:43 2014 +0000
Revision:
2:fdae76e1215e
Child:
3:3bf2515b1eed
separated LoRa code from FSK code from common code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 2:fdae76e1215e 1 #include "sx127x_lora.h"
dudmuck 2:fdae76e1215e 2
dudmuck 2:fdae76e1215e 3 /* SX127x driver
dudmuck 2:fdae76e1215e 4 * Copyright (c) 2013 Semtech
dudmuck 2:fdae76e1215e 5 *
dudmuck 2:fdae76e1215e 6 * Licensed under the Apache License, Version 2.0 (the "License");
dudmuck 2:fdae76e1215e 7 * you may not use this file except in compliance with the License.
dudmuck 2:fdae76e1215e 8 * You may obtain a copy of the License at
dudmuck 2:fdae76e1215e 9 *
dudmuck 2:fdae76e1215e 10 * http://www.apache.org/licenses/LICENSE-2.0
dudmuck 2:fdae76e1215e 11 *
dudmuck 2:fdae76e1215e 12 * Unless required by applicable law or agreed to in writing, software
dudmuck 2:fdae76e1215e 13 * distributed under the License is distributed on an "AS IS" BASIS,
dudmuck 2:fdae76e1215e 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dudmuck 2:fdae76e1215e 15 * See the License for the specific language governing permissions and
dudmuck 2:fdae76e1215e 16 * limitations under the License.
dudmuck 2:fdae76e1215e 17 */
dudmuck 2:fdae76e1215e 18
dudmuck 2:fdae76e1215e 19 //SX127x_lora::SX127x_lora(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName dio_0, PinName dio_1, PinName fem_ctx, PinName fem_cps) : SX127x(mosi, miso, sclk, cs, rst, dio_0, dio_1, fem_ctx, fem_cps)
dudmuck 2:fdae76e1215e 20 SX127x_lora::SX127x_lora(SX127x r) : m_xcvr(r)
dudmuck 2:fdae76e1215e 21 {
dudmuck 2:fdae76e1215e 22 RegModemConfig.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG);
dudmuck 2:fdae76e1215e 23 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2);
dudmuck 2:fdae76e1215e 24 RegTest31.octet = m_xcvr.read_reg(REG_LR_TEST31);
dudmuck 2:fdae76e1215e 25
dudmuck 2:fdae76e1215e 26 // CRC for TX is disabled by default
dudmuck 2:fdae76e1215e 27 setRxPayloadCrcOn(true);
dudmuck 2:fdae76e1215e 28 }
dudmuck 2:fdae76e1215e 29
dudmuck 2:fdae76e1215e 30 SX127x_lora::~SX127x_lora()
dudmuck 2:fdae76e1215e 31 {
dudmuck 2:fdae76e1215e 32 }
dudmuck 2:fdae76e1215e 33
dudmuck 2:fdae76e1215e 34 void SX127x_lora::write_fifo(uint8_t len)
dudmuck 2:fdae76e1215e 35 {
dudmuck 2:fdae76e1215e 36 int i;
dudmuck 2:fdae76e1215e 37
dudmuck 2:fdae76e1215e 38 m_xcvr.m_cs = 0;
dudmuck 2:fdae76e1215e 39 m_xcvr.m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio
dudmuck 2:fdae76e1215e 40
dudmuck 2:fdae76e1215e 41 for (i = 0; i < len; i++) {
dudmuck 2:fdae76e1215e 42 m_xcvr.m_spi.write(m_xcvr.tx_buf[i]);
dudmuck 2:fdae76e1215e 43 }
dudmuck 2:fdae76e1215e 44 m_xcvr.m_cs = 1;
dudmuck 2:fdae76e1215e 45 }
dudmuck 2:fdae76e1215e 46
dudmuck 2:fdae76e1215e 47 void SX127x_lora::read_fifo(uint8_t len)
dudmuck 2:fdae76e1215e 48 {
dudmuck 2:fdae76e1215e 49 int i;
dudmuck 2:fdae76e1215e 50
dudmuck 2:fdae76e1215e 51 m_xcvr.m_cs = 0;
dudmuck 2:fdae76e1215e 52 m_xcvr.m_spi.write(REG_FIFO); // bit7 is low for reading from radio
dudmuck 2:fdae76e1215e 53 for (i = 0; i < len; i++) {
dudmuck 2:fdae76e1215e 54 m_xcvr.rx_buf[i] = m_xcvr.m_spi.write(0);
dudmuck 2:fdae76e1215e 55 }
dudmuck 2:fdae76e1215e 56 m_xcvr.m_cs = 1;
dudmuck 2:fdae76e1215e 57 }
dudmuck 2:fdae76e1215e 58
dudmuck 2:fdae76e1215e 59 void SX127x_lora::enable()
dudmuck 2:fdae76e1215e 60 {
dudmuck 2:fdae76e1215e 61 m_xcvr.set_opmode(RF_OPMODE_SLEEP);
dudmuck 2:fdae76e1215e 62
dudmuck 2:fdae76e1215e 63 m_xcvr.RegOpMode.bits.LongRangeMode = 1;
dudmuck 2:fdae76e1215e 64 m_xcvr.write_reg(REG_OPMODE, m_xcvr.RegOpMode.octet);
dudmuck 2:fdae76e1215e 65
dudmuck 2:fdae76e1215e 66 /*RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 2:fdae76e1215e 67 printf("setloraon:%02x\r\n", RegOpMode.octet);*/
dudmuck 2:fdae76e1215e 68
dudmuck 2:fdae76e1215e 69
dudmuck 2:fdae76e1215e 70 /* // RxDone RxTimeout FhssChangeChannel CadDone
dudmuck 2:fdae76e1215e 71 SX1272LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
dudmuck 2:fdae76e1215e 72 // CadDetected ModeReady
dudmuck 2:fdae76e1215e 73 SX1272LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;
dudmuck 2:fdae76e1215e 74 SX1272WriteBuffer( REG_LR_DIOMAPPING1, &SX1272LR->RegDioMapping1, 2 );*/
dudmuck 2:fdae76e1215e 75 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 2:fdae76e1215e 76 m_xcvr.RegDioMapping1.bits.Dio1Mapping = 0;
dudmuck 2:fdae76e1215e 77 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 78
dudmuck 2:fdae76e1215e 79 // todo: read LoRa regsiters
dudmuck 2:fdae76e1215e 80 //SX1272ReadBuffer( REG_LR_OPMODE, SX1272Regs + 1, 0x70 - 1 );
dudmuck 2:fdae76e1215e 81
dudmuck 2:fdae76e1215e 82 m_xcvr.set_opmode(RF_OPMODE_STANDBY);
dudmuck 2:fdae76e1215e 83 }
dudmuck 2:fdae76e1215e 84
dudmuck 2:fdae76e1215e 85 uint8_t SX127x_lora::getCodingRate(bool from_rx)
dudmuck 2:fdae76e1215e 86 {
dudmuck 2:fdae76e1215e 87 if (from_rx) {
dudmuck 2:fdae76e1215e 88 // expected RegModemStatus was read on RxDone interrupt
dudmuck 2:fdae76e1215e 89 return RegModemStatus.bits.RxCodingRate;
dudmuck 2:fdae76e1215e 90 } else { // transmitted coding rate...
dudmuck 2:fdae76e1215e 91 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 92 return RegModemConfig.sx1276bits.CodingRate;
dudmuck 2:fdae76e1215e 93 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 94 return RegModemConfig.sx1272bits.CodingRate;
dudmuck 2:fdae76e1215e 95 else
dudmuck 2:fdae76e1215e 96 return 0;
dudmuck 2:fdae76e1215e 97 }
dudmuck 2:fdae76e1215e 98 }
dudmuck 2:fdae76e1215e 99
dudmuck 2:fdae76e1215e 100
dudmuck 2:fdae76e1215e 101
dudmuck 2:fdae76e1215e 102 void SX127x_lora::setCodingRate(uint8_t cr)
dudmuck 2:fdae76e1215e 103 {
dudmuck 2:fdae76e1215e 104 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 105 return;
dudmuck 2:fdae76e1215e 106
dudmuck 2:fdae76e1215e 107 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 108 RegModemConfig.sx1276bits.CodingRate = cr;
dudmuck 2:fdae76e1215e 109 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 110 RegModemConfig.sx1272bits.CodingRate = cr;
dudmuck 2:fdae76e1215e 111 else
dudmuck 2:fdae76e1215e 112 return;
dudmuck 2:fdae76e1215e 113
dudmuck 2:fdae76e1215e 114 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 115 }
dudmuck 2:fdae76e1215e 116
dudmuck 2:fdae76e1215e 117
dudmuck 2:fdae76e1215e 118
dudmuck 2:fdae76e1215e 119 bool SX127x_lora::getHeaderMode(void)
dudmuck 2:fdae76e1215e 120 {
dudmuck 2:fdae76e1215e 121 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 122 return RegModemConfig.sx1276bits.ImplicitHeaderModeOn;
dudmuck 2:fdae76e1215e 123 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 124 return RegModemConfig.sx1272bits.ImplicitHeaderModeOn;
dudmuck 2:fdae76e1215e 125 else
dudmuck 2:fdae76e1215e 126 return false;
dudmuck 2:fdae76e1215e 127 }
dudmuck 2:fdae76e1215e 128
dudmuck 2:fdae76e1215e 129 void SX127x_lora::setHeaderMode(bool hm)
dudmuck 2:fdae76e1215e 130 {
dudmuck 2:fdae76e1215e 131 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 132 RegModemConfig.sx1276bits.ImplicitHeaderModeOn = hm;
dudmuck 2:fdae76e1215e 133 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 134 RegModemConfig.sx1272bits.ImplicitHeaderModeOn = hm;
dudmuck 2:fdae76e1215e 135 else
dudmuck 2:fdae76e1215e 136 return;
dudmuck 2:fdae76e1215e 137
dudmuck 2:fdae76e1215e 138 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 139 }
dudmuck 2:fdae76e1215e 140
dudmuck 2:fdae76e1215e 141
dudmuck 2:fdae76e1215e 142 uint8_t SX127x_lora::getBw(void)
dudmuck 2:fdae76e1215e 143 {
dudmuck 2:fdae76e1215e 144 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 145 return RegModemConfig.sx1276bits.Bw;
dudmuck 2:fdae76e1215e 146 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 147 return RegModemConfig.sx1272bits.Bw;
dudmuck 2:fdae76e1215e 148 else
dudmuck 2:fdae76e1215e 149 return 0;
dudmuck 2:fdae76e1215e 150 }
dudmuck 2:fdae76e1215e 151
dudmuck 2:fdae76e1215e 152 void SX127x_lora::setBw(uint8_t bw)
dudmuck 2:fdae76e1215e 153 {
dudmuck 2:fdae76e1215e 154 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 155 return;
dudmuck 2:fdae76e1215e 156
dudmuck 2:fdae76e1215e 157 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 158 RegModemConfig.sx1276bits.Bw = bw;
dudmuck 2:fdae76e1215e 159 else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 160 RegModemConfig.sx1272bits.Bw = bw;
dudmuck 2:fdae76e1215e 161 if (RegModemConfig2.sx1272bits.SpreadingFactor > 10)
dudmuck 2:fdae76e1215e 162 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 163 else
dudmuck 2:fdae76e1215e 164 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 165 } else
dudmuck 2:fdae76e1215e 166 return;
dudmuck 2:fdae76e1215e 167
dudmuck 2:fdae76e1215e 168 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 169 }
dudmuck 2:fdae76e1215e 170
dudmuck 2:fdae76e1215e 171
dudmuck 2:fdae76e1215e 172
dudmuck 2:fdae76e1215e 173 uint8_t SX127x_lora::getSf(void)
dudmuck 2:fdae76e1215e 174 {
dudmuck 2:fdae76e1215e 175 // spreading factor same between sx127[26]
dudmuck 2:fdae76e1215e 176 return RegModemConfig2.sx1276bits.SpreadingFactor;
dudmuck 2:fdae76e1215e 177 }
dudmuck 2:fdae76e1215e 178
dudmuck 2:fdae76e1215e 179 void SX127x_lora::set_nb_trig_peaks(int n)
dudmuck 2:fdae76e1215e 180 {
dudmuck 2:fdae76e1215e 181 RegTest31.bits.detect_trig_same_peaks_nb = n;
dudmuck 2:fdae76e1215e 182 m_xcvr.write_reg(REG_LR_TEST31, RegTest31.octet);
dudmuck 2:fdae76e1215e 183 }
dudmuck 2:fdae76e1215e 184
dudmuck 2:fdae76e1215e 185
dudmuck 2:fdae76e1215e 186 void SX127x_lora::setSf(uint8_t sf)
dudmuck 2:fdae76e1215e 187 {
dudmuck 2:fdae76e1215e 188 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 189 return;
dudmuck 2:fdae76e1215e 190
dudmuck 2:fdae76e1215e 191 // false detections vs missed detections tradeoff
dudmuck 2:fdae76e1215e 192 switch (sf) {
dudmuck 2:fdae76e1215e 193 case 6:
dudmuck 2:fdae76e1215e 194 set_nb_trig_peaks(3);
dudmuck 2:fdae76e1215e 195 break;
dudmuck 2:fdae76e1215e 196 case 7:
dudmuck 2:fdae76e1215e 197 set_nb_trig_peaks(4);
dudmuck 2:fdae76e1215e 198 break;
dudmuck 2:fdae76e1215e 199 default:
dudmuck 2:fdae76e1215e 200 set_nb_trig_peaks(5);
dudmuck 2:fdae76e1215e 201 break;
dudmuck 2:fdae76e1215e 202 }
dudmuck 2:fdae76e1215e 203
dudmuck 2:fdae76e1215e 204 // write register at 0x37 with value 0xc if at SF6
dudmuck 2:fdae76e1215e 205 if (sf < 7)
dudmuck 2:fdae76e1215e 206 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c);
dudmuck 2:fdae76e1215e 207 else
dudmuck 2:fdae76e1215e 208 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a);
dudmuck 2:fdae76e1215e 209
dudmuck 2:fdae76e1215e 210 RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26]
dudmuck 2:fdae76e1215e 211 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 212
dudmuck 2:fdae76e1215e 213 if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 214 if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12
dudmuck 2:fdae76e1215e 215 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 216 else
dudmuck 2:fdae76e1215e 217 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 218 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 219 } else if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 220 if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12
dudmuck 2:fdae76e1215e 221 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 222 else
dudmuck 2:fdae76e1215e 223 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 224 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 2:fdae76e1215e 225 }
dudmuck 2:fdae76e1215e 226 }
dudmuck 2:fdae76e1215e 227
dudmuck 2:fdae76e1215e 228
dudmuck 2:fdae76e1215e 229
dudmuck 2:fdae76e1215e 230 bool SX127x_lora::getRxPayloadCrcOn(void)
dudmuck 2:fdae76e1215e 231 {
dudmuck 2:fdae76e1215e 232 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 233 return RegModemConfig2.sx1276bits.RxPayloadCrcOn;
dudmuck 2:fdae76e1215e 234 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 235 return RegModemConfig.sx1272bits.RxPayloadCrcOn;
dudmuck 2:fdae76e1215e 236 else
dudmuck 2:fdae76e1215e 237 return 0;
dudmuck 2:fdae76e1215e 238 }
dudmuck 2:fdae76e1215e 239
dudmuck 2:fdae76e1215e 240
dudmuck 2:fdae76e1215e 241 void SX127x_lora::setRxPayloadCrcOn(bool on)
dudmuck 2:fdae76e1215e 242 {
dudmuck 2:fdae76e1215e 243 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 244 RegModemConfig2.sx1276bits.RxPayloadCrcOn = on;
dudmuck 2:fdae76e1215e 245 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 246 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 247 RegModemConfig.sx1272bits.RxPayloadCrcOn = on;
dudmuck 2:fdae76e1215e 248 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 249 }
dudmuck 2:fdae76e1215e 250 }
dudmuck 2:fdae76e1215e 251
dudmuck 2:fdae76e1215e 252
dudmuck 2:fdae76e1215e 253
dudmuck 2:fdae76e1215e 254 bool SX127x_lora::getAgcAutoOn(void)
dudmuck 2:fdae76e1215e 255 {
dudmuck 2:fdae76e1215e 256 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 257 RegModemConfig3.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG3);
dudmuck 2:fdae76e1215e 258 return RegModemConfig3.sx1276bits.AgcAutoOn;
dudmuck 2:fdae76e1215e 259 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 260 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2);
dudmuck 2:fdae76e1215e 261 return RegModemConfig2.sx1272bits.AgcAutoOn;
dudmuck 2:fdae76e1215e 262 } else
dudmuck 2:fdae76e1215e 263 return 0;
dudmuck 2:fdae76e1215e 264 }
dudmuck 2:fdae76e1215e 265
dudmuck 2:fdae76e1215e 266 void SX127x_lora::setAgcAutoOn(bool on)
dudmuck 2:fdae76e1215e 267 {
dudmuck 2:fdae76e1215e 268 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 269 RegModemConfig3.sx1276bits.AgcAutoOn = on;
dudmuck 2:fdae76e1215e 270 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 2:fdae76e1215e 271 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 272 RegModemConfig2.sx1272bits.AgcAutoOn = on;
dudmuck 2:fdae76e1215e 273 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 274 }
dudmuck 2:fdae76e1215e 275
dudmuck 2:fdae76e1215e 276 }
dudmuck 2:fdae76e1215e 277
dudmuck 2:fdae76e1215e 278
dudmuck 2:fdae76e1215e 279
dudmuck 2:fdae76e1215e 280 void SX127x_lora::start_tx(uint8_t len)
dudmuck 2:fdae76e1215e 281 {
dudmuck 2:fdae76e1215e 282 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 283 // PA_BOOST on LF, RFO on HF
dudmuck 2:fdae76e1215e 284 if (m_xcvr.HF) {
dudmuck 2:fdae76e1215e 285 if (m_xcvr.RegPaConfig.bits.PaSelect) {
dudmuck 2:fdae76e1215e 286 m_xcvr.RegPaConfig.bits.PaSelect = 0;
dudmuck 2:fdae76e1215e 287 m_xcvr.write_reg(REG_PACONFIG, m_xcvr.RegPaConfig.octet);
dudmuck 2:fdae76e1215e 288 }
dudmuck 2:fdae76e1215e 289 } else { // LF...
dudmuck 2:fdae76e1215e 290 if (!m_xcvr.RegPaConfig.bits.PaSelect) {
dudmuck 2:fdae76e1215e 291 m_xcvr.RegPaConfig.bits.PaSelect = 1;
dudmuck 2:fdae76e1215e 292 m_xcvr.write_reg(REG_PACONFIG, m_xcvr.RegPaConfig.octet);
dudmuck 2:fdae76e1215e 293 }
dudmuck 2:fdae76e1215e 294 }
dudmuck 2:fdae76e1215e 295 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 296 // always PA_BOOST
dudmuck 2:fdae76e1215e 297 if (!m_xcvr.RegPaConfig.bits.PaSelect) {
dudmuck 2:fdae76e1215e 298 m_xcvr.RegPaConfig.bits.PaSelect = 1;
dudmuck 2:fdae76e1215e 299 m_xcvr.write_reg(REG_PACONFIG, m_xcvr.RegPaConfig.octet);
dudmuck 2:fdae76e1215e 300 }
dudmuck 2:fdae76e1215e 301 }
dudmuck 2:fdae76e1215e 302
dudmuck 2:fdae76e1215e 303
dudmuck 2:fdae76e1215e 304 // DIO0 to TxDone
dudmuck 2:fdae76e1215e 305 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 1) {
dudmuck 2:fdae76e1215e 306 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 2:fdae76e1215e 307 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 308 }
dudmuck 2:fdae76e1215e 309
dudmuck 2:fdae76e1215e 310 // set FifoPtrAddr to FifoTxPtrBase
dudmuck 2:fdae76e1215e 311 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFOTXBASEADDR));
dudmuck 2:fdae76e1215e 312
dudmuck 2:fdae76e1215e 313 // write PayloadLength bytes to fifo
dudmuck 2:fdae76e1215e 314 write_fifo(len);
dudmuck 2:fdae76e1215e 315
dudmuck 2:fdae76e1215e 316 if (m_xcvr.HF)
dudmuck 2:fdae76e1215e 317 m_xcvr.femctx = 1;
dudmuck 2:fdae76e1215e 318 else
dudmuck 2:fdae76e1215e 319 m_xcvr.femcps = 0;
dudmuck 2:fdae76e1215e 320
dudmuck 2:fdae76e1215e 321 // radio doesnt provide FhssChangeChannel with channel=0 for TX
dudmuck 2:fdae76e1215e 322 if (RegHopPeriod > 0)
dudmuck 2:fdae76e1215e 323 m_xcvr.write_reg_u24(REG_FRFMSB, m_xcvr.frfs[0]);
dudmuck 2:fdae76e1215e 324
dudmuck 2:fdae76e1215e 325 m_xcvr.set_opmode(RF_OPMODE_TRANSMITTER);
dudmuck 2:fdae76e1215e 326 }
dudmuck 2:fdae76e1215e 327
dudmuck 2:fdae76e1215e 328 void SX127x_lora::start_rx()
dudmuck 2:fdae76e1215e 329 {
dudmuck 2:fdae76e1215e 330 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 331 return;
dudmuck 2:fdae76e1215e 332
dudmuck 2:fdae76e1215e 333 if (m_xcvr.HF)
dudmuck 2:fdae76e1215e 334 m_xcvr.femctx = 0;
dudmuck 2:fdae76e1215e 335 else
dudmuck 2:fdae76e1215e 336 m_xcvr.femcps = 1;
dudmuck 2:fdae76e1215e 337
dudmuck 2:fdae76e1215e 338 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 0) {
dudmuck 2:fdae76e1215e 339 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 2:fdae76e1215e 340 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 341 }
dudmuck 2:fdae76e1215e 342
dudmuck 2:fdae76e1215e 343 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXBASEADDR));
dudmuck 2:fdae76e1215e 344
dudmuck 2:fdae76e1215e 345 // shouldn't be necessary, radio should provide FhssChangeChannel with channel=0 for RX
dudmuck 2:fdae76e1215e 346 if (RegHopPeriod > 0)
dudmuck 2:fdae76e1215e 347 m_xcvr.write_reg_u24(REG_FRFMSB, m_xcvr.frfs[0]);
dudmuck 2:fdae76e1215e 348
dudmuck 2:fdae76e1215e 349 m_xcvr.set_opmode(RF_OPMODE_RECEIVER);
dudmuck 2:fdae76e1215e 350 }
dudmuck 2:fdae76e1215e 351
dudmuck 2:fdae76e1215e 352 float SX127x_lora::get_pkt_rssi()
dudmuck 2:fdae76e1215e 353 {
dudmuck 2:fdae76e1215e 354 /* TODO: calculating with pktSNR to give meaningful result below noise floor */
dudmuck 2:fdae76e1215e 355 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 356 return RegPktRssiValue - 137;
dudmuck 2:fdae76e1215e 357 else
dudmuck 2:fdae76e1215e 358 return RegPktRssiValue - 125;
dudmuck 2:fdae76e1215e 359 }
dudmuck 2:fdae76e1215e 360
dudmuck 2:fdae76e1215e 361 service_action_e SX127x_lora::service()
dudmuck 2:fdae76e1215e 362 {
dudmuck 2:fdae76e1215e 363 if (m_xcvr.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) {
dudmuck 2:fdae76e1215e 364 if (poll_vh) {
dudmuck 2:fdae76e1215e 365 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS);
dudmuck 2:fdae76e1215e 366 if (RegIrqFlags.bits.ValidHeader) {
dudmuck 2:fdae76e1215e 367 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 368 RegIrqFlags.bits.ValidHeader = 1;
dudmuck 2:fdae76e1215e 369 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 370 printf("VH\r\n");
dudmuck 2:fdae76e1215e 371 }
dudmuck 2:fdae76e1215e 372 }
dudmuck 2:fdae76e1215e 373 }
dudmuck 2:fdae76e1215e 374
dudmuck 2:fdae76e1215e 375 // FhssChangeChannel
dudmuck 2:fdae76e1215e 376 if (m_xcvr.RegDioMapping1.bits.Dio1Mapping == 1) {
dudmuck 2:fdae76e1215e 377 if (m_xcvr.dio1) {
dudmuck 2:fdae76e1215e 378 RegHopChannel.octet = m_xcvr.read_reg(REG_LR_HOPCHANNEL);
dudmuck 2:fdae76e1215e 379 m_xcvr.write_reg_u24(REG_FRFMSB, m_xcvr.frfs[RegHopChannel.bits.FhssPresentChannel]);
dudmuck 2:fdae76e1215e 380 printf("hopch:%d\r\n", RegHopChannel.bits.FhssPresentChannel);
dudmuck 2:fdae76e1215e 381 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 382 RegIrqFlags.bits.FhssChangeChannel = 1;
dudmuck 2:fdae76e1215e 383 m_xcvr. write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 384
dudmuck 2:fdae76e1215e 385 }
dudmuck 2:fdae76e1215e 386 }
dudmuck 2:fdae76e1215e 387
dudmuck 2:fdae76e1215e 388 if (m_xcvr.dio0 == 0)
dudmuck 2:fdae76e1215e 389 return SERVICE_NONE;
dudmuck 2:fdae76e1215e 390
dudmuck 2:fdae76e1215e 391 switch (m_xcvr.RegDioMapping1.bits.Dio0Mapping) {
dudmuck 2:fdae76e1215e 392 case 0: // RxDone
dudmuck 2:fdae76e1215e 393 /* user checks for CRC error in IrqFlags */
dudmuck 2:fdae76e1215e 394 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS); // save flags
dudmuck 2:fdae76e1215e 395 RegHopChannel.octet = m_xcvr.read_reg(REG_LR_HOPCHANNEL);
dudmuck 2:fdae76e1215e 396 if (RegIrqFlags.bits.FhssChangeChannel) {
dudmuck 2:fdae76e1215e 397 m_xcvr.write_reg_u24(REG_FRFMSB, m_xcvr.frfs[RegHopChannel.bits.FhssPresentChannel]);
dudmuck 2:fdae76e1215e 398 }
dudmuck 2:fdae76e1215e 399 //printf("[%02x]", RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 400 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio
dudmuck 2:fdae76e1215e 401
dudmuck 2:fdae76e1215e 402 /* any register of interest on received packet is read(saved) here */
dudmuck 2:fdae76e1215e 403 RegModemStatus.octet = m_xcvr.read_reg(REG_LR_MODEMSTAT);
dudmuck 2:fdae76e1215e 404 RegPktSnrValue = m_xcvr.read_reg(REG_LR_PKTSNRVALUE);
dudmuck 2:fdae76e1215e 405 RegPktRssiValue = m_xcvr.read_reg(REG_LR_PKTRSSIVALUE);
dudmuck 2:fdae76e1215e 406 RegRxNbBytes = m_xcvr.read_reg(REG_LR_RXNBBYTES);
dudmuck 2:fdae76e1215e 407
dudmuck 2:fdae76e1215e 408 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXCURRENTADDR));
dudmuck 2:fdae76e1215e 409 read_fifo(RegRxNbBytes);
dudmuck 2:fdae76e1215e 410 return SERVICE_READ_FIFO;
dudmuck 2:fdae76e1215e 411 case 1: // TxDone
dudmuck 2:fdae76e1215e 412 if (m_xcvr.HF)
dudmuck 2:fdae76e1215e 413 m_xcvr.femctx = 0;
dudmuck 2:fdae76e1215e 414 else
dudmuck 2:fdae76e1215e 415 m_xcvr.femcps = 1;
dudmuck 2:fdae76e1215e 416
dudmuck 2:fdae76e1215e 417 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 418 RegIrqFlags.bits.TxDone = 1;
dudmuck 2:fdae76e1215e 419 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 420 return SERVICE_TX_DONE;
dudmuck 2:fdae76e1215e 421 } // ...switch (RegDioMapping1.bits.Dio0Mapping)
dudmuck 2:fdae76e1215e 422
dudmuck 2:fdae76e1215e 423 return SERVICE_ERROR;
dudmuck 2:fdae76e1215e 424 }