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:
Fri May 02 23:35:30 2014 +0000
Revision:
4:d987ac2836bf
Parent:
3:3bf2515b1eed
Child:
6:5d94ee847016
Child:
7:927a05f84ede
fixed FSK AFC

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