Driver library for SX1272/SX1276 transceivers
Fork of SX127x by
sx127x.cpp@0:27aa8733f85d, 2014-03-26 (annotated)
- Committer:
- dudmuck
- Date:
- Wed Mar 26 00:56:09 2014 +0000
- Revision:
- 0:27aa8733f85d
- Child:
- 1:7dc60eb4c7ec
initial commit of library driver for SX1272/SX1276
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dudmuck | 0:27aa8733f85d | 1 | #include "sx127x.h" |
dudmuck | 0:27aa8733f85d | 2 | |
dudmuck | 0:27aa8733f85d | 3 | /* SX127x driver |
dudmuck | 0:27aa8733f85d | 4 | * Copyright (c) 2013 Semtech |
dudmuck | 0:27aa8733f85d | 5 | * |
dudmuck | 0:27aa8733f85d | 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
dudmuck | 0:27aa8733f85d | 7 | * you may not use this file except in compliance with the License. |
dudmuck | 0:27aa8733f85d | 8 | * You may obtain a copy of the License at |
dudmuck | 0:27aa8733f85d | 9 | * |
dudmuck | 0:27aa8733f85d | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
dudmuck | 0:27aa8733f85d | 11 | * |
dudmuck | 0:27aa8733f85d | 12 | * Unless required by applicable law or agreed to in writing, software |
dudmuck | 0:27aa8733f85d | 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
dudmuck | 0:27aa8733f85d | 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
dudmuck | 0:27aa8733f85d | 15 | * See the License for the specific language governing permissions and |
dudmuck | 0:27aa8733f85d | 16 | * limitations under the License. |
dudmuck | 0:27aa8733f85d | 17 | */ |
dudmuck | 0:27aa8733f85d | 18 | |
dudmuck | 0:27aa8733f85d | 19 | SX127x::SX127x(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName dio_0, PinName dio_1, PinName fem_ctx, PinName fem_cps) : |
dudmuck | 0:27aa8733f85d | 20 | m_spi(mosi, miso, sclk), m_cs(cs), reset_pin(rst), dio0(dio_0), dio1(dio_1), femctx(fem_ctx), femcps(fem_cps) |
dudmuck | 0:27aa8733f85d | 21 | { |
dudmuck | 0:27aa8733f85d | 22 | reset_pin.input(); |
dudmuck | 0:27aa8733f85d | 23 | m_cs = 1; |
dudmuck | 0:27aa8733f85d | 24 | m_spi.format(8, 0); |
dudmuck | 0:27aa8733f85d | 25 | m_spi.frequency(1000000); |
dudmuck | 0:27aa8733f85d | 26 | |
dudmuck | 0:27aa8733f85d | 27 | init(); |
dudmuck | 0:27aa8733f85d | 28 | } |
dudmuck | 0:27aa8733f85d | 29 | |
dudmuck | 0:27aa8733f85d | 30 | SX127x::~SX127x() |
dudmuck | 0:27aa8733f85d | 31 | { |
dudmuck | 0:27aa8733f85d | 32 | set_opmode(RF_OPMODE_SLEEP); |
dudmuck | 0:27aa8733f85d | 33 | } |
dudmuck | 0:27aa8733f85d | 34 | |
dudmuck | 0:27aa8733f85d | 35 | void SX127x::init() |
dudmuck | 0:27aa8733f85d | 36 | { |
dudmuck | 0:27aa8733f85d | 37 | type = SX_NONE; |
dudmuck | 0:27aa8733f85d | 38 | |
dudmuck | 0:27aa8733f85d | 39 | RegOpMode.octet = read_reg(REG_OPMODE); |
dudmuck | 0:27aa8733f85d | 40 | RegPaConfig.octet = read_reg(REG_PACONFIG); |
dudmuck | 0:27aa8733f85d | 41 | RegLna.octet = read_reg(REG_LNA); |
dudmuck | 0:27aa8733f85d | 42 | RegDioMapping1.octet = read_reg(REG_DIOMAPPING1); |
dudmuck | 0:27aa8733f85d | 43 | RegDioMapping2.octet = read_reg(REG_DIOMAPPING2); |
dudmuck | 0:27aa8733f85d | 44 | |
dudmuck | 0:27aa8733f85d | 45 | if (!RegOpMode.bits.LongRangeMode) { |
dudmuck | 0:27aa8733f85d | 46 | if (RegOpMode.bits.Mode != RF_OPMODE_SLEEP) |
dudmuck | 0:27aa8733f85d | 47 | set_opmode(RF_OPMODE_SLEEP); |
dudmuck | 0:27aa8733f85d | 48 | RegOpMode.bits.LongRangeMode = 1; |
dudmuck | 0:27aa8733f85d | 49 | write_reg(REG_OPMODE, RegOpMode.octet); |
dudmuck | 0:27aa8733f85d | 50 | } |
dudmuck | 0:27aa8733f85d | 51 | |
dudmuck | 0:27aa8733f85d | 52 | RegModemConfig.octet = read_reg(REG_LR_MODEMCONFIG); |
dudmuck | 0:27aa8733f85d | 53 | RegModemConfig2.octet = read_reg(REG_LR_MODEMCONFIG2); |
dudmuck | 0:27aa8733f85d | 54 | RegTest31.octet = read_reg(REG_LR_TEST31); |
dudmuck | 0:27aa8733f85d | 55 | |
dudmuck | 0:27aa8733f85d | 56 | get_type(); |
dudmuck | 0:27aa8733f85d | 57 | |
dudmuck | 0:27aa8733f85d | 58 | // turn on PA BOOST, eval boards are wired for this connection |
dudmuck | 0:27aa8733f85d | 59 | RegPaConfig.bits.PaSelect = 1; |
dudmuck | 0:27aa8733f85d | 60 | write_reg(REG_PACONFIG, RegPaConfig.octet); |
dudmuck | 0:27aa8733f85d | 61 | |
dudmuck | 0:27aa8733f85d | 62 | // CRC for TX is disabled by default |
dudmuck | 0:27aa8733f85d | 63 | setRxPayloadCrcOn(true); |
dudmuck | 0:27aa8733f85d | 64 | } |
dudmuck | 0:27aa8733f85d | 65 | |
dudmuck | 0:27aa8733f85d | 66 | void SX127x::get_type() |
dudmuck | 0:27aa8733f85d | 67 | { |
dudmuck | 0:27aa8733f85d | 68 | RegOpMode.octet = read_reg(REG_OPMODE); |
dudmuck | 0:27aa8733f85d | 69 | if (RegOpMode.sx1276LORAbits.LowFrequencyModeOn) |
dudmuck | 0:27aa8733f85d | 70 | type = SX1276; |
dudmuck | 0:27aa8733f85d | 71 | else { |
dudmuck | 0:27aa8733f85d | 72 | RegOpMode.sx1276LORAbits.LowFrequencyModeOn = 1; |
dudmuck | 0:27aa8733f85d | 73 | write_reg(REG_OPMODE, RegOpMode.octet); |
dudmuck | 0:27aa8733f85d | 74 | RegOpMode.octet = read_reg(REG_OPMODE); |
dudmuck | 0:27aa8733f85d | 75 | if (RegOpMode.sx1276LORAbits.LowFrequencyModeOn) |
dudmuck | 0:27aa8733f85d | 76 | type = SX1276; |
dudmuck | 0:27aa8733f85d | 77 | else |
dudmuck | 0:27aa8733f85d | 78 | type = SX1272; |
dudmuck | 0:27aa8733f85d | 79 | } |
dudmuck | 0:27aa8733f85d | 80 | } |
dudmuck | 0:27aa8733f85d | 81 | uint8_t SX127x::read_reg(uint8_t addr) |
dudmuck | 0:27aa8733f85d | 82 | { |
dudmuck | 0:27aa8733f85d | 83 | uint8_t ret; |
dudmuck | 0:27aa8733f85d | 84 | // Select the device by seting chip select low |
dudmuck | 0:27aa8733f85d | 85 | m_cs = 0; |
dudmuck | 0:27aa8733f85d | 86 | |
dudmuck | 0:27aa8733f85d | 87 | m_spi.write(addr); // bit7 is low for reading from radio |
dudmuck | 0:27aa8733f85d | 88 | |
dudmuck | 0:27aa8733f85d | 89 | // Send a dummy byte to receive the contents of register |
dudmuck | 0:27aa8733f85d | 90 | ret = m_spi.write(0x00); |
dudmuck | 0:27aa8733f85d | 91 | |
dudmuck | 0:27aa8733f85d | 92 | // Deselect the device |
dudmuck | 0:27aa8733f85d | 93 | m_cs = 1; |
dudmuck | 0:27aa8733f85d | 94 | |
dudmuck | 0:27aa8733f85d | 95 | return ret; |
dudmuck | 0:27aa8733f85d | 96 | } |
dudmuck | 0:27aa8733f85d | 97 | |
dudmuck | 0:27aa8733f85d | 98 | uint16_t SX127x::read_u16(uint8_t addr) |
dudmuck | 0:27aa8733f85d | 99 | { |
dudmuck | 0:27aa8733f85d | 100 | uint16_t ret; |
dudmuck | 0:27aa8733f85d | 101 | // Select the device by seting chip select low |
dudmuck | 0:27aa8733f85d | 102 | m_cs = 0; |
dudmuck | 0:27aa8733f85d | 103 | |
dudmuck | 0:27aa8733f85d | 104 | m_spi.write(addr); // bit7 is low for reading from radio |
dudmuck | 0:27aa8733f85d | 105 | |
dudmuck | 0:27aa8733f85d | 106 | // Send a dummy byte to receive the contents of register |
dudmuck | 0:27aa8733f85d | 107 | ret = m_spi.write(0x00); |
dudmuck | 0:27aa8733f85d | 108 | ret <<= 8; |
dudmuck | 0:27aa8733f85d | 109 | ret += m_spi.write(0x00); |
dudmuck | 0:27aa8733f85d | 110 | |
dudmuck | 0:27aa8733f85d | 111 | // Deselect the device |
dudmuck | 0:27aa8733f85d | 112 | m_cs = 1; |
dudmuck | 0:27aa8733f85d | 113 | |
dudmuck | 0:27aa8733f85d | 114 | return ret; |
dudmuck | 0:27aa8733f85d | 115 | } |
dudmuck | 0:27aa8733f85d | 116 | |
dudmuck | 0:27aa8733f85d | 117 | void SX127x::write_reg_u24(uint8_t addr, uint32_t data) |
dudmuck | 0:27aa8733f85d | 118 | { |
dudmuck | 0:27aa8733f85d | 119 | m_cs = 0; // Select the device by seting chip select low |
dudmuck | 0:27aa8733f85d | 120 | |
dudmuck | 0:27aa8733f85d | 121 | m_spi.write(addr | 0x80); // bit7 is high for writing to radio |
dudmuck | 0:27aa8733f85d | 122 | m_spi.write((data >> 16) & 0xff); |
dudmuck | 0:27aa8733f85d | 123 | m_spi.write((data >> 8) & 0xff); |
dudmuck | 0:27aa8733f85d | 124 | m_spi.write(data & 0xff); |
dudmuck | 0:27aa8733f85d | 125 | |
dudmuck | 0:27aa8733f85d | 126 | m_cs = 1; // Deselect the device |
dudmuck | 0:27aa8733f85d | 127 | |
dudmuck | 0:27aa8733f85d | 128 | if (addr == REG_FRFMSB) { |
dudmuck | 0:27aa8733f85d | 129 | if (data < 0x8340000) // < 525MHz |
dudmuck | 0:27aa8733f85d | 130 | HF = false; |
dudmuck | 0:27aa8733f85d | 131 | else |
dudmuck | 0:27aa8733f85d | 132 | HF = true; |
dudmuck | 0:27aa8733f85d | 133 | } |
dudmuck | 0:27aa8733f85d | 134 | } |
dudmuck | 0:27aa8733f85d | 135 | |
dudmuck | 0:27aa8733f85d | 136 | void SX127x::write_reg(uint8_t addr, uint8_t data) |
dudmuck | 0:27aa8733f85d | 137 | { |
dudmuck | 0:27aa8733f85d | 138 | m_cs = 0; // Select the device by seting chip select low |
dudmuck | 0:27aa8733f85d | 139 | |
dudmuck | 0:27aa8733f85d | 140 | m_spi.write(addr | 0x80); // bit7 is high for writing to radio |
dudmuck | 0:27aa8733f85d | 141 | m_spi.write(data); |
dudmuck | 0:27aa8733f85d | 142 | |
dudmuck | 0:27aa8733f85d | 143 | m_cs = 1; // Deselect the device |
dudmuck | 0:27aa8733f85d | 144 | } |
dudmuck | 0:27aa8733f85d | 145 | |
dudmuck | 0:27aa8733f85d | 146 | void SX127x::lora_write_fifo(uint8_t len) |
dudmuck | 0:27aa8733f85d | 147 | { |
dudmuck | 0:27aa8733f85d | 148 | int i; |
dudmuck | 0:27aa8733f85d | 149 | |
dudmuck | 0:27aa8733f85d | 150 | m_cs = 0; |
dudmuck | 0:27aa8733f85d | 151 | m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio |
dudmuck | 0:27aa8733f85d | 152 | for (i = 0; i < len; i++) { |
dudmuck | 0:27aa8733f85d | 153 | m_spi.write(tx_buf[i]); |
dudmuck | 0:27aa8733f85d | 154 | } |
dudmuck | 0:27aa8733f85d | 155 | m_cs = 1; |
dudmuck | 0:27aa8733f85d | 156 | } |
dudmuck | 0:27aa8733f85d | 157 | |
dudmuck | 0:27aa8733f85d | 158 | void SX127x::lora_read_fifo(uint8_t len) |
dudmuck | 0:27aa8733f85d | 159 | { |
dudmuck | 0:27aa8733f85d | 160 | int i; |
dudmuck | 0:27aa8733f85d | 161 | |
dudmuck | 0:27aa8733f85d | 162 | m_cs = 0; |
dudmuck | 0:27aa8733f85d | 163 | m_spi.write(REG_FIFO); // bit7 is low for reading from radio |
dudmuck | 0:27aa8733f85d | 164 | for (i = 0; i < len; i++) { |
dudmuck | 0:27aa8733f85d | 165 | rx_buf[i] = m_spi.write(0); |
dudmuck | 0:27aa8733f85d | 166 | } |
dudmuck | 0:27aa8733f85d | 167 | m_cs = 1; |
dudmuck | 0:27aa8733f85d | 168 | } |
dudmuck | 0:27aa8733f85d | 169 | |
dudmuck | 0:27aa8733f85d | 170 | void SX127x::set_opmode(chip_mode_e mode) |
dudmuck | 0:27aa8733f85d | 171 | { |
dudmuck | 0:27aa8733f85d | 172 | RegOpMode.bits.Mode = mode; |
dudmuck | 0:27aa8733f85d | 173 | write_reg(REG_OPMODE, RegOpMode.octet); |
dudmuck | 0:27aa8733f85d | 174 | } |
dudmuck | 0:27aa8733f85d | 175 | |
dudmuck | 0:27aa8733f85d | 176 | void SX127x::set_frf_MHz( float MHz ) |
dudmuck | 0:27aa8733f85d | 177 | { |
dudmuck | 0:27aa8733f85d | 178 | uint32_t frf; |
dudmuck | 0:27aa8733f85d | 179 | |
dudmuck | 0:27aa8733f85d | 180 | frf = MHz / FREQ_STEP_MHZ; |
dudmuck | 0:27aa8733f85d | 181 | write_reg_u24(REG_FRFMSB, frf); |
dudmuck | 0:27aa8733f85d | 182 | |
dudmuck | 0:27aa8733f85d | 183 | if (MHz < 525) |
dudmuck | 0:27aa8733f85d | 184 | HF = false; |
dudmuck | 0:27aa8733f85d | 185 | else |
dudmuck | 0:27aa8733f85d | 186 | HF = true; |
dudmuck | 0:27aa8733f85d | 187 | } |
dudmuck | 0:27aa8733f85d | 188 | |
dudmuck | 0:27aa8733f85d | 189 | float SX127x::get_frf_MHz(void) |
dudmuck | 0:27aa8733f85d | 190 | { |
dudmuck | 0:27aa8733f85d | 191 | uint32_t frf; |
dudmuck | 0:27aa8733f85d | 192 | uint8_t lsb, mid, msb; |
dudmuck | 0:27aa8733f85d | 193 | float MHz; |
dudmuck | 0:27aa8733f85d | 194 | |
dudmuck | 0:27aa8733f85d | 195 | msb = read_reg(REG_FRFMSB); |
dudmuck | 0:27aa8733f85d | 196 | mid = read_reg(REG_FRFMID); |
dudmuck | 0:27aa8733f85d | 197 | lsb = read_reg(REG_FRFLSB); |
dudmuck | 0:27aa8733f85d | 198 | frf = msb; |
dudmuck | 0:27aa8733f85d | 199 | frf <<= 8; |
dudmuck | 0:27aa8733f85d | 200 | frf += mid; |
dudmuck | 0:27aa8733f85d | 201 | frf <<= 8; |
dudmuck | 0:27aa8733f85d | 202 | frf += lsb; |
dudmuck | 0:27aa8733f85d | 203 | |
dudmuck | 0:27aa8733f85d | 204 | MHz = frf * FREQ_STEP_MHZ; |
dudmuck | 0:27aa8733f85d | 205 | |
dudmuck | 0:27aa8733f85d | 206 | if (MHz < 525) |
dudmuck | 0:27aa8733f85d | 207 | HF = false; |
dudmuck | 0:27aa8733f85d | 208 | else |
dudmuck | 0:27aa8733f85d | 209 | HF = true; |
dudmuck | 0:27aa8733f85d | 210 | |
dudmuck | 0:27aa8733f85d | 211 | return MHz; |
dudmuck | 0:27aa8733f85d | 212 | } |
dudmuck | 0:27aa8733f85d | 213 | |
dudmuck | 0:27aa8733f85d | 214 | uint8_t SX127x::getCodingRate(bool from_rx) |
dudmuck | 0:27aa8733f85d | 215 | { |
dudmuck | 0:27aa8733f85d | 216 | if (from_rx) { |
dudmuck | 0:27aa8733f85d | 217 | // expected RegModemStatus was read on RxDone interrupt |
dudmuck | 0:27aa8733f85d | 218 | return RegModemStatus.bits.RxCodingRate; |
dudmuck | 0:27aa8733f85d | 219 | } else { // transmitted coding rate... |
dudmuck | 0:27aa8733f85d | 220 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 221 | return RegModemConfig.sx1276bits.CodingRate; |
dudmuck | 0:27aa8733f85d | 222 | else if (type == SX1272) |
dudmuck | 0:27aa8733f85d | 223 | return RegModemConfig.sx1272bits.CodingRate; |
dudmuck | 0:27aa8733f85d | 224 | else |
dudmuck | 0:27aa8733f85d | 225 | return 0; |
dudmuck | 0:27aa8733f85d | 226 | } |
dudmuck | 0:27aa8733f85d | 227 | } |
dudmuck | 0:27aa8733f85d | 228 | |
dudmuck | 0:27aa8733f85d | 229 | void SX127x::setCodingRate(uint8_t cr) |
dudmuck | 0:27aa8733f85d | 230 | { |
dudmuck | 0:27aa8733f85d | 231 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 232 | RegModemConfig.sx1276bits.CodingRate = cr; |
dudmuck | 0:27aa8733f85d | 233 | else if (type == SX1272) |
dudmuck | 0:27aa8733f85d | 234 | RegModemConfig.sx1272bits.CodingRate = cr; |
dudmuck | 0:27aa8733f85d | 235 | else |
dudmuck | 0:27aa8733f85d | 236 | return; |
dudmuck | 0:27aa8733f85d | 237 | |
dudmuck | 0:27aa8733f85d | 238 | write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); |
dudmuck | 0:27aa8733f85d | 239 | } |
dudmuck | 0:27aa8733f85d | 240 | |
dudmuck | 0:27aa8733f85d | 241 | bool SX127x::getHeaderMode(void) |
dudmuck | 0:27aa8733f85d | 242 | { |
dudmuck | 0:27aa8733f85d | 243 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 244 | return RegModemConfig.sx1276bits.ImplicitHeaderModeOn; |
dudmuck | 0:27aa8733f85d | 245 | else if (type == SX1272) |
dudmuck | 0:27aa8733f85d | 246 | return RegModemConfig.sx1272bits.ImplicitHeaderModeOn; |
dudmuck | 0:27aa8733f85d | 247 | else |
dudmuck | 0:27aa8733f85d | 248 | return false; |
dudmuck | 0:27aa8733f85d | 249 | } |
dudmuck | 0:27aa8733f85d | 250 | |
dudmuck | 0:27aa8733f85d | 251 | void SX127x::setHeaderMode(bool hm) |
dudmuck | 0:27aa8733f85d | 252 | { |
dudmuck | 0:27aa8733f85d | 253 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 254 | RegModemConfig.sx1276bits.ImplicitHeaderModeOn = hm; |
dudmuck | 0:27aa8733f85d | 255 | else if (type == SX1272) |
dudmuck | 0:27aa8733f85d | 256 | RegModemConfig.sx1272bits.ImplicitHeaderModeOn = hm; |
dudmuck | 0:27aa8733f85d | 257 | else |
dudmuck | 0:27aa8733f85d | 258 | return; |
dudmuck | 0:27aa8733f85d | 259 | |
dudmuck | 0:27aa8733f85d | 260 | write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); |
dudmuck | 0:27aa8733f85d | 261 | } |
dudmuck | 0:27aa8733f85d | 262 | |
dudmuck | 0:27aa8733f85d | 263 | uint8_t SX127x::getBw(void) |
dudmuck | 0:27aa8733f85d | 264 | { |
dudmuck | 0:27aa8733f85d | 265 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 266 | return RegModemConfig.sx1276bits.Bw; |
dudmuck | 0:27aa8733f85d | 267 | else if (type == SX1272) |
dudmuck | 0:27aa8733f85d | 268 | return RegModemConfig.sx1272bits.Bw; |
dudmuck | 0:27aa8733f85d | 269 | else |
dudmuck | 0:27aa8733f85d | 270 | return 0; |
dudmuck | 0:27aa8733f85d | 271 | } |
dudmuck | 0:27aa8733f85d | 272 | |
dudmuck | 0:27aa8733f85d | 273 | void SX127x::setBw(uint8_t bw) |
dudmuck | 0:27aa8733f85d | 274 | { |
dudmuck | 0:27aa8733f85d | 275 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 276 | RegModemConfig.sx1276bits.Bw = bw; |
dudmuck | 0:27aa8733f85d | 277 | else if (type == SX1272) { |
dudmuck | 0:27aa8733f85d | 278 | RegModemConfig.sx1272bits.Bw = bw; |
dudmuck | 0:27aa8733f85d | 279 | if (RegModemConfig2.sx1272bits.SpreadingFactor > 10) |
dudmuck | 0:27aa8733f85d | 280 | RegModemConfig.sx1272bits.LowDataRateOptimize = 1; |
dudmuck | 0:27aa8733f85d | 281 | else |
dudmuck | 0:27aa8733f85d | 282 | RegModemConfig.sx1272bits.LowDataRateOptimize = 0; |
dudmuck | 0:27aa8733f85d | 283 | } else |
dudmuck | 0:27aa8733f85d | 284 | return; |
dudmuck | 0:27aa8733f85d | 285 | |
dudmuck | 0:27aa8733f85d | 286 | write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); |
dudmuck | 0:27aa8733f85d | 287 | } |
dudmuck | 0:27aa8733f85d | 288 | |
dudmuck | 0:27aa8733f85d | 289 | uint8_t SX127x::getSf(void) |
dudmuck | 0:27aa8733f85d | 290 | { |
dudmuck | 0:27aa8733f85d | 291 | // spreading factor same between sx127[26] |
dudmuck | 0:27aa8733f85d | 292 | return RegModemConfig2.sx1276bits.SpreadingFactor; |
dudmuck | 0:27aa8733f85d | 293 | } |
dudmuck | 0:27aa8733f85d | 294 | |
dudmuck | 0:27aa8733f85d | 295 | void SX127x::set_nb_trig_peaks(int n) |
dudmuck | 0:27aa8733f85d | 296 | { |
dudmuck | 0:27aa8733f85d | 297 | RegTest31.bits.detect_trig_same_peaks_nb = n; |
dudmuck | 0:27aa8733f85d | 298 | write_reg(REG_LR_TEST31, RegTest31.octet); |
dudmuck | 0:27aa8733f85d | 299 | } |
dudmuck | 0:27aa8733f85d | 300 | |
dudmuck | 0:27aa8733f85d | 301 | void SX127x::setSf(uint8_t sf) |
dudmuck | 0:27aa8733f85d | 302 | { |
dudmuck | 0:27aa8733f85d | 303 | // false detections vs missed detections tradeoff |
dudmuck | 0:27aa8733f85d | 304 | switch (sf) { |
dudmuck | 0:27aa8733f85d | 305 | case 6: |
dudmuck | 0:27aa8733f85d | 306 | set_nb_trig_peaks(3); |
dudmuck | 0:27aa8733f85d | 307 | break; |
dudmuck | 0:27aa8733f85d | 308 | case 7: |
dudmuck | 0:27aa8733f85d | 309 | set_nb_trig_peaks(4); |
dudmuck | 0:27aa8733f85d | 310 | break; |
dudmuck | 0:27aa8733f85d | 311 | default: |
dudmuck | 0:27aa8733f85d | 312 | set_nb_trig_peaks(5); |
dudmuck | 0:27aa8733f85d | 313 | break; |
dudmuck | 0:27aa8733f85d | 314 | } |
dudmuck | 0:27aa8733f85d | 315 | |
dudmuck | 0:27aa8733f85d | 316 | // write register at 0x37 with value 0xc if at SF6 |
dudmuck | 0:27aa8733f85d | 317 | if (sf < 7) |
dudmuck | 0:27aa8733f85d | 318 | write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c); |
dudmuck | 0:27aa8733f85d | 319 | else |
dudmuck | 0:27aa8733f85d | 320 | write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a); |
dudmuck | 0:27aa8733f85d | 321 | |
dudmuck | 0:27aa8733f85d | 322 | RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26] |
dudmuck | 0:27aa8733f85d | 323 | write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet); |
dudmuck | 0:27aa8733f85d | 324 | |
dudmuck | 0:27aa8733f85d | 325 | if (type == SX1272) { |
dudmuck | 0:27aa8733f85d | 326 | if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12 |
dudmuck | 0:27aa8733f85d | 327 | RegModemConfig.sx1272bits.LowDataRateOptimize = 1; |
dudmuck | 0:27aa8733f85d | 328 | else |
dudmuck | 0:27aa8733f85d | 329 | RegModemConfig.sx1272bits.LowDataRateOptimize = 0; |
dudmuck | 0:27aa8733f85d | 330 | write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); |
dudmuck | 0:27aa8733f85d | 331 | } else if (type == SX1276) { |
dudmuck | 0:27aa8733f85d | 332 | if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12 |
dudmuck | 0:27aa8733f85d | 333 | RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; |
dudmuck | 0:27aa8733f85d | 334 | else |
dudmuck | 0:27aa8733f85d | 335 | RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; |
dudmuck | 0:27aa8733f85d | 336 | write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet); |
dudmuck | 0:27aa8733f85d | 337 | } |
dudmuck | 0:27aa8733f85d | 338 | } |
dudmuck | 0:27aa8733f85d | 339 | |
dudmuck | 0:27aa8733f85d | 340 | bool SX127x::getRxPayloadCrcOn(void) |
dudmuck | 0:27aa8733f85d | 341 | { |
dudmuck | 0:27aa8733f85d | 342 | if (type == SX1276) |
dudmuck | 0:27aa8733f85d | 343 | return RegModemConfig2.sx1276bits.RxPayloadCrcOn; |
dudmuck | 0:27aa8733f85d | 344 | else if (type == SX1272) |
dudmuck | 0:27aa8733f85d | 345 | return RegModemConfig.sx1272bits.RxPayloadCrcOn; |
dudmuck | 0:27aa8733f85d | 346 | else |
dudmuck | 0:27aa8733f85d | 347 | return 0; |
dudmuck | 0:27aa8733f85d | 348 | } |
dudmuck | 0:27aa8733f85d | 349 | |
dudmuck | 0:27aa8733f85d | 350 | void SX127x::setRxPayloadCrcOn(bool on) |
dudmuck | 0:27aa8733f85d | 351 | { |
dudmuck | 0:27aa8733f85d | 352 | if (type == SX1276) { |
dudmuck | 0:27aa8733f85d | 353 | RegModemConfig2.sx1276bits.RxPayloadCrcOn = on; |
dudmuck | 0:27aa8733f85d | 354 | write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet); |
dudmuck | 0:27aa8733f85d | 355 | } else if (type == SX1272) { |
dudmuck | 0:27aa8733f85d | 356 | RegModemConfig.sx1272bits.RxPayloadCrcOn = on; |
dudmuck | 0:27aa8733f85d | 357 | write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); |
dudmuck | 0:27aa8733f85d | 358 | } |
dudmuck | 0:27aa8733f85d | 359 | } |
dudmuck | 0:27aa8733f85d | 360 | |
dudmuck | 0:27aa8733f85d | 361 | bool SX127x::getAgcAutoOn(void) |
dudmuck | 0:27aa8733f85d | 362 | { |
dudmuck | 0:27aa8733f85d | 363 | if (type == SX1276) { |
dudmuck | 0:27aa8733f85d | 364 | RegModemConfig3.octet = read_reg(REG_LR_MODEMCONFIG3); |
dudmuck | 0:27aa8733f85d | 365 | return RegModemConfig3.sx1276bits.AgcAutoOn; |
dudmuck | 0:27aa8733f85d | 366 | } else if (type == SX1272) { |
dudmuck | 0:27aa8733f85d | 367 | RegModemConfig2.octet = read_reg(REG_LR_MODEMCONFIG2); |
dudmuck | 0:27aa8733f85d | 368 | return RegModemConfig2.sx1272bits.AgcAutoOn; |
dudmuck | 0:27aa8733f85d | 369 | } else |
dudmuck | 0:27aa8733f85d | 370 | return 0; |
dudmuck | 0:27aa8733f85d | 371 | } |
dudmuck | 0:27aa8733f85d | 372 | |
dudmuck | 0:27aa8733f85d | 373 | void SX127x::setAgcAutoOn(bool on) |
dudmuck | 0:27aa8733f85d | 374 | { |
dudmuck | 0:27aa8733f85d | 375 | if (type == SX1276) { |
dudmuck | 0:27aa8733f85d | 376 | RegModemConfig3.sx1276bits.AgcAutoOn = on; |
dudmuck | 0:27aa8733f85d | 377 | write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet); |
dudmuck | 0:27aa8733f85d | 378 | } else if (type == SX1272) { |
dudmuck | 0:27aa8733f85d | 379 | RegModemConfig2.sx1272bits.AgcAutoOn = on; |
dudmuck | 0:27aa8733f85d | 380 | write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet); |
dudmuck | 0:27aa8733f85d | 381 | } |
dudmuck | 0:27aa8733f85d | 382 | |
dudmuck | 0:27aa8733f85d | 383 | } |
dudmuck | 0:27aa8733f85d | 384 | |
dudmuck | 0:27aa8733f85d | 385 | void SX127x::lora_start_tx(uint8_t len) |
dudmuck | 0:27aa8733f85d | 386 | { |
dudmuck | 0:27aa8733f85d | 387 | if (type == SX1276) { |
dudmuck | 0:27aa8733f85d | 388 | // PA_BOOST on LF, RFO on HF |
dudmuck | 0:27aa8733f85d | 389 | if (HF) { |
dudmuck | 0:27aa8733f85d | 390 | if (RegPaConfig.bits.PaSelect) { |
dudmuck | 0:27aa8733f85d | 391 | RegPaConfig.bits.PaSelect = 0; |
dudmuck | 0:27aa8733f85d | 392 | write_reg(REG_PACONFIG, RegPaConfig.octet); |
dudmuck | 0:27aa8733f85d | 393 | } |
dudmuck | 0:27aa8733f85d | 394 | } else { // LF... |
dudmuck | 0:27aa8733f85d | 395 | if (!RegPaConfig.bits.PaSelect) { |
dudmuck | 0:27aa8733f85d | 396 | RegPaConfig.bits.PaSelect = 1; |
dudmuck | 0:27aa8733f85d | 397 | write_reg(REG_PACONFIG, RegPaConfig.octet); |
dudmuck | 0:27aa8733f85d | 398 | } |
dudmuck | 0:27aa8733f85d | 399 | } |
dudmuck | 0:27aa8733f85d | 400 | } else if (type == SX1272) { |
dudmuck | 0:27aa8733f85d | 401 | // always PA_BOOST |
dudmuck | 0:27aa8733f85d | 402 | if (!RegPaConfig.bits.PaSelect) { |
dudmuck | 0:27aa8733f85d | 403 | RegPaConfig.bits.PaSelect = 1; |
dudmuck | 0:27aa8733f85d | 404 | write_reg(REG_PACONFIG, RegPaConfig.octet); |
dudmuck | 0:27aa8733f85d | 405 | } |
dudmuck | 0:27aa8733f85d | 406 | } |
dudmuck | 0:27aa8733f85d | 407 | |
dudmuck | 0:27aa8733f85d | 408 | |
dudmuck | 0:27aa8733f85d | 409 | // DIO0 to TxDone |
dudmuck | 0:27aa8733f85d | 410 | if (RegDioMapping1.bits.Dio0Mapping != 1) { |
dudmuck | 0:27aa8733f85d | 411 | RegDioMapping1.bits.Dio0Mapping = 1; |
dudmuck | 0:27aa8733f85d | 412 | write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); |
dudmuck | 0:27aa8733f85d | 413 | } |
dudmuck | 0:27aa8733f85d | 414 | |
dudmuck | 0:27aa8733f85d | 415 | // set FifoPtrAddr to FifoTxPtrBase |
dudmuck | 0:27aa8733f85d | 416 | write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFOTXBASEADDR)); |
dudmuck | 0:27aa8733f85d | 417 | |
dudmuck | 0:27aa8733f85d | 418 | // write PayloadLength bytes to fifo |
dudmuck | 0:27aa8733f85d | 419 | lora_write_fifo(len); |
dudmuck | 0:27aa8733f85d | 420 | |
dudmuck | 0:27aa8733f85d | 421 | if (HF) |
dudmuck | 0:27aa8733f85d | 422 | femctx = 1; |
dudmuck | 0:27aa8733f85d | 423 | else |
dudmuck | 0:27aa8733f85d | 424 | femcps = 0; |
dudmuck | 0:27aa8733f85d | 425 | |
dudmuck | 0:27aa8733f85d | 426 | // radio doesnt provide FhssChangeChannel with channel=0 for TX |
dudmuck | 0:27aa8733f85d | 427 | if (RegHopPeriod > 0) |
dudmuck | 0:27aa8733f85d | 428 | write_reg_u24(REG_FRFMSB, frfs[0]); |
dudmuck | 0:27aa8733f85d | 429 | |
dudmuck | 0:27aa8733f85d | 430 | set_opmode(RF_OPMODE_TRANSMITTER); |
dudmuck | 0:27aa8733f85d | 431 | } |
dudmuck | 0:27aa8733f85d | 432 | |
dudmuck | 0:27aa8733f85d | 433 | |
dudmuck | 0:27aa8733f85d | 434 | |
dudmuck | 0:27aa8733f85d | 435 | void SX127x::lora_start_rx() |
dudmuck | 0:27aa8733f85d | 436 | { |
dudmuck | 0:27aa8733f85d | 437 | if (HF) |
dudmuck | 0:27aa8733f85d | 438 | femctx = 0; |
dudmuck | 0:27aa8733f85d | 439 | else |
dudmuck | 0:27aa8733f85d | 440 | femcps = 1; |
dudmuck | 0:27aa8733f85d | 441 | |
dudmuck | 0:27aa8733f85d | 442 | if (RegDioMapping1.bits.Dio0Mapping != 0) { |
dudmuck | 0:27aa8733f85d | 443 | RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone |
dudmuck | 0:27aa8733f85d | 444 | write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); |
dudmuck | 0:27aa8733f85d | 445 | } |
dudmuck | 0:27aa8733f85d | 446 | |
dudmuck | 0:27aa8733f85d | 447 | write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFORXBASEADDR)); |
dudmuck | 0:27aa8733f85d | 448 | |
dudmuck | 0:27aa8733f85d | 449 | // shouldn't be necessary, radio should provide FhssChangeChannel with channel=0 for RX |
dudmuck | 0:27aa8733f85d | 450 | if (RegHopPeriod > 0) |
dudmuck | 0:27aa8733f85d | 451 | write_reg_u24(REG_FRFMSB, frfs[0]); |
dudmuck | 0:27aa8733f85d | 452 | |
dudmuck | 0:27aa8733f85d | 453 | set_opmode(RF_OPMODE_RECEIVER); |
dudmuck | 0:27aa8733f85d | 454 | } |
dudmuck | 0:27aa8733f85d | 455 | |
dudmuck | 0:27aa8733f85d | 456 | |
dudmuck | 0:27aa8733f85d | 457 | void SX127x::hw_reset() |
dudmuck | 0:27aa8733f85d | 458 | { |
dudmuck | 0:27aa8733f85d | 459 | /* only a french-swiss design would have hi-Z deassert */ |
dudmuck | 0:27aa8733f85d | 460 | reset_pin.output(); |
dudmuck | 0:27aa8733f85d | 461 | reset_pin.write(1); |
dudmuck | 0:27aa8733f85d | 462 | wait(0.05); |
dudmuck | 0:27aa8733f85d | 463 | reset_pin.input(); |
dudmuck | 0:27aa8733f85d | 464 | wait(0.05); |
dudmuck | 0:27aa8733f85d | 465 | } |
dudmuck | 0:27aa8733f85d | 466 | |
dudmuck | 0:27aa8733f85d | 467 | service_action_e SX127x::service() |
dudmuck | 0:27aa8733f85d | 468 | { |
dudmuck | 0:27aa8733f85d | 469 | |
dudmuck | 0:27aa8733f85d | 470 | if (RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) { |
dudmuck | 0:27aa8733f85d | 471 | if (poll_vh) { |
dudmuck | 0:27aa8733f85d | 472 | RegIrqFlags.octet = read_reg(REG_LR_IRQFLAGS); |
dudmuck | 0:27aa8733f85d | 473 | if (RegIrqFlags.bits.ValidHeader) { |
dudmuck | 0:27aa8733f85d | 474 | RegIrqFlags.octet = 0; |
dudmuck | 0:27aa8733f85d | 475 | RegIrqFlags.bits.ValidHeader = 1; |
dudmuck | 0:27aa8733f85d | 476 | write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); |
dudmuck | 0:27aa8733f85d | 477 | printf("VH\r\n"); |
dudmuck | 0:27aa8733f85d | 478 | } |
dudmuck | 0:27aa8733f85d | 479 | } |
dudmuck | 0:27aa8733f85d | 480 | } |
dudmuck | 0:27aa8733f85d | 481 | |
dudmuck | 0:27aa8733f85d | 482 | // FhssChangeChannel |
dudmuck | 0:27aa8733f85d | 483 | if (RegDioMapping1.bits.Dio1Mapping == 1) { |
dudmuck | 0:27aa8733f85d | 484 | if (dio1) { |
dudmuck | 0:27aa8733f85d | 485 | RegHopChannel.octet = read_reg(REG_LR_HOPCHANNEL); |
dudmuck | 0:27aa8733f85d | 486 | write_reg_u24(REG_FRFMSB, frfs[RegHopChannel.bits.FhssPresentChannel]); |
dudmuck | 0:27aa8733f85d | 487 | printf("hopch:%d\r\n", RegHopChannel.bits.FhssPresentChannel); |
dudmuck | 0:27aa8733f85d | 488 | RegIrqFlags.octet = 0; |
dudmuck | 0:27aa8733f85d | 489 | RegIrqFlags.bits.FhssChangeChannel = 1; |
dudmuck | 0:27aa8733f85d | 490 | write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); |
dudmuck | 0:27aa8733f85d | 491 | |
dudmuck | 0:27aa8733f85d | 492 | } |
dudmuck | 0:27aa8733f85d | 493 | } |
dudmuck | 0:27aa8733f85d | 494 | |
dudmuck | 0:27aa8733f85d | 495 | if (dio0 == 0) |
dudmuck | 0:27aa8733f85d | 496 | return SERVICE_NONE; |
dudmuck | 0:27aa8733f85d | 497 | |
dudmuck | 0:27aa8733f85d | 498 | switch (RegDioMapping1.bits.Dio0Mapping) { |
dudmuck | 0:27aa8733f85d | 499 | case 0: // RxDone |
dudmuck | 0:27aa8733f85d | 500 | /* user checks for CRC error in IrqFlags */ |
dudmuck | 0:27aa8733f85d | 501 | RegIrqFlags.octet = read_reg(REG_LR_IRQFLAGS); // save flags |
dudmuck | 0:27aa8733f85d | 502 | RegHopChannel.octet = read_reg(REG_LR_HOPCHANNEL); |
dudmuck | 0:27aa8733f85d | 503 | if (RegIrqFlags.bits.FhssChangeChannel) { |
dudmuck | 0:27aa8733f85d | 504 | write_reg_u24(REG_FRFMSB, frfs[RegHopChannel.bits.FhssPresentChannel]); |
dudmuck | 0:27aa8733f85d | 505 | } |
dudmuck | 0:27aa8733f85d | 506 | //printf("[%02x]", RegIrqFlags.octet); |
dudmuck | 0:27aa8733f85d | 507 | write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio |
dudmuck | 0:27aa8733f85d | 508 | |
dudmuck | 0:27aa8733f85d | 509 | /* any register of interest on received packet is read(saved) here */ |
dudmuck | 0:27aa8733f85d | 510 | RegModemStatus.octet = read_reg(REG_LR_MODEMSTAT); |
dudmuck | 0:27aa8733f85d | 511 | RegPktSnrValue = read_reg(REG_LR_PKTSNRVALUE); |
dudmuck | 0:27aa8733f85d | 512 | RegPktRssiValue = read_reg(REG_LR_PKTRSSIVALUE); |
dudmuck | 0:27aa8733f85d | 513 | RegRxNbBytes = read_reg(REG_LR_RXNBBYTES); |
dudmuck | 0:27aa8733f85d | 514 | |
dudmuck | 0:27aa8733f85d | 515 | write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFORXCURRENTADDR)); |
dudmuck | 0:27aa8733f85d | 516 | lora_read_fifo(RegRxNbBytes); |
dudmuck | 0:27aa8733f85d | 517 | return SERVICE_READ_FIFO; |
dudmuck | 0:27aa8733f85d | 518 | case 1: // TxDone |
dudmuck | 0:27aa8733f85d | 519 | if (HF) |
dudmuck | 0:27aa8733f85d | 520 | femctx = 0; |
dudmuck | 0:27aa8733f85d | 521 | else |
dudmuck | 0:27aa8733f85d | 522 | femcps = 1; |
dudmuck | 0:27aa8733f85d | 523 | |
dudmuck | 0:27aa8733f85d | 524 | RegIrqFlags.octet = 0; |
dudmuck | 0:27aa8733f85d | 525 | RegIrqFlags.bits.TxDone = 1; |
dudmuck | 0:27aa8733f85d | 526 | write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); |
dudmuck | 0:27aa8733f85d | 527 | return SERVICE_TX_DONE; |
dudmuck | 0:27aa8733f85d | 528 | } // ...switch (RegDioMapping1.bits.Dio0Mapping) |
dudmuck | 0:27aa8733f85d | 529 | |
dudmuck | 0:27aa8733f85d | 530 | return SERVICE_ERROR; |
dudmuck | 0:27aa8733f85d | 531 | } |