Line data Source code
1 : #include "SX1278.h"
2 : #include <math.h>
3 : #if !RADIOLIB_EXCLUDE_SX127X
4 :
5 3 : SX1278::SX1278(Module* mod) : SX127x(mod) {
6 :
7 3 : }
8 :
9 0 : int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
10 : // execute common part
11 0 : const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
12 0 : int16_t state = SX127x::begin(versions, 3, syncWord, preambleLength);
13 0 : RADIOLIB_ASSERT(state);
14 :
15 : // configure publicly accessible settings
16 0 : state = setBandwidth(bw);
17 0 : RADIOLIB_ASSERT(state);
18 :
19 0 : state = setFrequency(freq);
20 0 : RADIOLIB_ASSERT(state);
21 :
22 0 : state = setSpreadingFactor(sf);
23 0 : RADIOLIB_ASSERT(state);
24 :
25 0 : state = setCodingRate(cr);
26 0 : RADIOLIB_ASSERT(state);
27 :
28 0 : state = setOutputPower(power);
29 0 : RADIOLIB_ASSERT(state);
30 :
31 0 : state = setGain(gain);
32 0 : RADIOLIB_ASSERT(state);
33 :
34 : // set publicly accessible settings that are not a part of begin method
35 0 : state = setCRC(true);
36 0 : RADIOLIB_ASSERT(state);
37 :
38 0 : return(state);
39 : }
40 :
41 0 : int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
42 : // execute common part
43 0 : const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
44 0 : int16_t state = SX127x::beginFSK(versions, 3, freqDev, rxBw, preambleLength, enableOOK);
45 0 : RADIOLIB_ASSERT(state);
46 :
47 : // configure settings not accessible by API
48 0 : state = configFSK();
49 0 : RADIOLIB_ASSERT(state);
50 :
51 : // configure publicly accessible settings
52 0 : state = setFrequency(freq);
53 0 : RADIOLIB_ASSERT(state);
54 :
55 0 : state = setBitRate(br);
56 0 : RADIOLIB_ASSERT(state);
57 :
58 0 : state = setOutputPower(power);
59 0 : RADIOLIB_ASSERT(state);
60 :
61 0 : if(enableOOK) {
62 0 : state = setDataShapingOOK(RADIOLIB_SHAPING_NONE);
63 0 : RADIOLIB_ASSERT(state);
64 : } else {
65 0 : state = setDataShaping(RADIOLIB_SHAPING_NONE);
66 0 : RADIOLIB_ASSERT(state);
67 : }
68 :
69 : // set publicly accessible settings that are not a part of begin method
70 0 : state = setCRC(true);
71 0 : RADIOLIB_ASSERT(state);
72 :
73 0 : return(state);
74 : }
75 :
76 0 : void SX1278::reset() {
77 0 : Module* mod = this->getMod();
78 0 : mod->hal->pinMode(mod->getRst(), mod->hal->GpioModeOutput);
79 0 : mod->hal->digitalWrite(mod->getRst(), mod->hal->GpioLevelLow);
80 0 : mod->hal->delay(1);
81 0 : mod->hal->digitalWrite(mod->getRst(), mod->hal->GpioLevelHigh);
82 0 : mod->hal->delay(5);
83 0 : }
84 :
85 1 : int16_t SX1278::setFrequency(float freq) {
86 1 : RADIOLIB_CHECK_RANGE(freq, 137.0f, 525.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
87 :
88 : // set frequency and if successful, save the new setting
89 0 : int16_t state = SX127x::setFrequencyRaw(freq);
90 0 : if(state == RADIOLIB_ERR_NONE) {
91 0 : SX127x::frequency = freq;
92 : }
93 0 : return(state);
94 : }
95 :
96 0 : int16_t SX1278::setBandwidth(float bw) {
97 : // check active modem
98 0 : if(getActiveModem() != RADIOLIB_SX127X_LORA) {
99 0 : return(RADIOLIB_ERR_WRONG_MODEM);
100 : }
101 :
102 : uint8_t newBandwidth;
103 :
104 : // check allowed bandwidth values
105 0 : if(fabsf(bw - 7.8f) <= 0.001f) {
106 0 : newBandwidth = RADIOLIB_SX1278_BW_7_80_KHZ;
107 0 : } else if(fabsf(bw - 10.4f) <= 0.001f) {
108 0 : newBandwidth = RADIOLIB_SX1278_BW_10_40_KHZ;
109 0 : } else if(fabsf(bw - 15.6f) <= 0.001f) {
110 0 : newBandwidth = RADIOLIB_SX1278_BW_15_60_KHZ;
111 0 : } else if(fabsf(bw - 20.8f) <= 0.001f) {
112 0 : newBandwidth = RADIOLIB_SX1278_BW_20_80_KHZ;
113 0 : } else if(fabsf(bw - 31.25f) <= 0.001f) {
114 0 : newBandwidth = RADIOLIB_SX1278_BW_31_25_KHZ;
115 0 : } else if(fabsf(bw - 41.7f) <= 0.001f) {
116 0 : newBandwidth = RADIOLIB_SX1278_BW_41_70_KHZ;
117 0 : } else if(fabsf(bw - 62.5f) <= 0.001f) {
118 0 : newBandwidth = RADIOLIB_SX1278_BW_62_50_KHZ;
119 0 : } else if(fabsf(bw - 125.0f) <= 0.001f) {
120 0 : newBandwidth = RADIOLIB_SX1278_BW_125_00_KHZ;
121 0 : } else if(fabsf(bw - 250.0f) <= 0.001f) {
122 0 : newBandwidth = RADIOLIB_SX1278_BW_250_00_KHZ;
123 0 : } else if(fabsf(bw - 500.0f) <= 0.001f) {
124 0 : newBandwidth = RADIOLIB_SX1278_BW_500_00_KHZ;
125 : } else {
126 0 : return(RADIOLIB_ERR_INVALID_BANDWIDTH);
127 : }
128 :
129 : // set bandwidth and if successful, save the new setting
130 0 : int16_t state = SX1278::setBandwidthRaw(newBandwidth);
131 0 : if(state == RADIOLIB_ERR_NONE) {
132 0 : SX127x::bandwidth = bw;
133 :
134 : // calculate symbol length and set low data rate optimization, if auto-configuration is enabled
135 0 : if(this->ldroAuto) {
136 0 : float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
137 0 : Module* mod = this->getMod();
138 0 : if(symbolLength >= 16.0f) {
139 0 : this->ldroEnabled = true;
140 0 : state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
141 : } else {
142 0 : this->ldroEnabled = false;
143 0 : state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3);
144 : }
145 : }
146 : }
147 0 : return(state);
148 : }
149 :
150 2 : int16_t SX1278::setSpreadingFactor(uint8_t sf) {
151 : // check active modem
152 2 : if(getActiveModem() != RADIOLIB_SX127X_LORA) {
153 0 : return(RADIOLIB_ERR_WRONG_MODEM);
154 : }
155 :
156 : uint8_t newSpreadingFactor;
157 :
158 : // check allowed spreading factor values
159 2 : switch(sf) {
160 0 : case 6:
161 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_6;
162 0 : break;
163 0 : case 7:
164 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_7;
165 0 : break;
166 0 : case 8:
167 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_8;
168 0 : break;
169 0 : case 9:
170 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_9;
171 0 : break;
172 0 : case 10:
173 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_10;
174 0 : break;
175 0 : case 11:
176 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_11;
177 0 : break;
178 0 : case 12:
179 0 : newSpreadingFactor = RADIOLIB_SX127X_SF_12;
180 0 : break;
181 2 : default:
182 2 : return(RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
183 : }
184 :
185 : // set spreading factor and if successful, save the new setting
186 0 : int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor);
187 0 : if(state == RADIOLIB_ERR_NONE) {
188 0 : SX127x::spreadingFactor = sf;
189 :
190 : // calculate symbol length and set low data rate optimization, if auto-configuration is enabled
191 0 : if(this->ldroAuto) {
192 0 : float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
193 0 : Module* mod = this->getMod();
194 0 : if(symbolLength >= 16.0f) {
195 0 : state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
196 : } else {
197 0 : state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3);
198 : }
199 : }
200 : }
201 0 : return(state);
202 : }
203 :
204 0 : int16_t SX1278::setCodingRate(uint8_t cr) {
205 : // check active modem
206 0 : if(getActiveModem() != RADIOLIB_SX127X_LORA) {
207 0 : return(RADIOLIB_ERR_WRONG_MODEM);
208 : }
209 :
210 : uint8_t newCodingRate;
211 :
212 : // check allowed coding rate values
213 0 : switch(cr) {
214 0 : case 4:
215 0 : newCodingRate = RADIOLIB_SX1278_CR_4_4;
216 0 : break;
217 0 : case 5:
218 0 : newCodingRate = RADIOLIB_SX1278_CR_4_5;
219 0 : break;
220 0 : case 6:
221 0 : newCodingRate = RADIOLIB_SX1278_CR_4_6;
222 0 : break;
223 0 : case 7:
224 0 : newCodingRate = RADIOLIB_SX1278_CR_4_7;
225 0 : break;
226 0 : case 8:
227 0 : newCodingRate = RADIOLIB_SX1278_CR_4_8;
228 0 : break;
229 0 : default:
230 0 : return(RADIOLIB_ERR_INVALID_CODING_RATE);
231 : }
232 :
233 : // set coding rate and if successful, save the new setting
234 0 : int16_t state = SX1278::setCodingRateRaw(newCodingRate);
235 0 : if(state == RADIOLIB_ERR_NONE) {
236 0 : SX127x::codingRate = cr;
237 : }
238 0 : return(state);
239 : }
240 :
241 3 : int16_t SX1278::setBitRate(float br) {
242 3 : return(SX127x::setBitRateCommon(br, RADIOLIB_SX1278_REG_BIT_RATE_FRAC));
243 : }
244 :
245 2 : int16_t SX1278::setDataRate(DataRate_t dr, ModemType_t modem) {
246 : // get the current modem
247 : ModemType_t currentModem;
248 2 : int16_t state = this->getModem(¤tModem);
249 2 : RADIOLIB_ASSERT(state);
250 :
251 : // switch over if the requested modem is different
252 2 : if(modem != RADIOLIB_MODEM_NONE && modem != currentModem) {
253 0 : state = this->standby();
254 0 : RADIOLIB_ASSERT(state);
255 0 : state = this->setModem(modem);
256 0 : RADIOLIB_ASSERT(state);
257 : }
258 :
259 2 : if(modem == RADIOLIB_MODEM_NONE) {
260 2 : modem = currentModem;
261 : }
262 :
263 : // select interpretation based on modem
264 2 : if(modem == RADIOLIB_MODEM_FSK) {
265 : // set the bit rate
266 0 : state = this->setBitRate(dr.fsk.bitRate);
267 0 : RADIOLIB_ASSERT(state);
268 :
269 : // set the frequency deviation
270 0 : state = this->setFrequencyDeviation(dr.fsk.freqDev);
271 :
272 2 : } else if(modem == RADIOLIB_MODEM_LORA) {
273 : // set the spreading factor
274 2 : state = this->setSpreadingFactor(dr.lora.spreadingFactor);
275 2 : RADIOLIB_ASSERT(state);
276 :
277 : // set the bandwidth
278 0 : state = this->setBandwidth(dr.lora.bandwidth);
279 0 : RADIOLIB_ASSERT(state);
280 :
281 : // set the coding rate
282 0 : state = this->setCodingRate(dr.lora.codingRate);
283 : }
284 :
285 0 : return(state);
286 : }
287 :
288 2 : int16_t SX1278::checkDataRate(DataRate_t dr, ModemType_t modem) {
289 2 : int16_t state = RADIOLIB_ERR_UNKNOWN;
290 :
291 : // retrieve modem if not supplied
292 2 : if(modem == RADIOLIB_MODEM_NONE) {
293 2 : state = this->getModem(&modem);
294 2 : RADIOLIB_ASSERT(state);
295 : }
296 :
297 : // select interpretation based on modem
298 2 : if(modem == RADIOLIB_MODEM_FSK) {
299 0 : RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
300 0 : if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0f <= 250.0f) && (dr.fsk.freqDev <= 200.0f))) {
301 0 : return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
302 : }
303 0 : return(RADIOLIB_ERR_NONE);
304 :
305 2 : } else if(modem == RADIOLIB_MODEM_LORA) {
306 2 : RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 6, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
307 0 : RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 0.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
308 0 : RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
309 0 : return(RADIOLIB_ERR_NONE);
310 :
311 : }
312 :
313 0 : return(state);
314 : }
315 :
316 3 : int16_t SX1278::setOutputPower(int8_t power) {
317 3 : return(this->setOutputPower(power, false));
318 : }
319 :
320 3 : int16_t SX1278::setOutputPower(int8_t power, bool forceRfo) {
321 : // check if power value is configurable
322 3 : bool useRfo = (power < 2) || forceRfo;
323 3 : int16_t state = checkOutputPower(power, NULL, useRfo);
324 3 : RADIOLIB_ASSERT(state);
325 :
326 : // set mode to standby
327 3 : state = SX127x::standby();
328 3 : Module* mod = this->getMod();
329 :
330 3 : if(useRfo) {
331 3 : uint8_t paCfg = 0;
332 3 : if(power < 0) {
333 : // low power mode RFO output
334 0 : paCfg = RADIOLIB_SX1278_LOW_POWER | (power + 3);
335 : } else {
336 : // high power mode RFO output
337 3 : paCfg = RADIOLIB_SX1278_MAX_POWER | power;
338 : }
339 :
340 3 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_RFO, 7, 7);
341 3 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, paCfg, 6, 0);
342 3 : state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0);
343 :
344 : } else {
345 0 : if(power != 20) {
346 : // power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST
347 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7);
348 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX1278_MAX_POWER | (power - 2), 6, 0);
349 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0);
350 :
351 : } else {
352 : // power is 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control
353 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7);
354 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX1278_MAX_POWER | 0x0F, 6, 0);
355 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_ON, 2, 0);
356 :
357 : }
358 : }
359 :
360 3 : return(state);
361 : }
362 :
363 3 : int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped) {
364 3 : return(checkOutputPower(power, clipped, false));
365 : }
366 :
367 6 : int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped, bool useRfo) {
368 : // check allowed power range
369 6 : if(useRfo) {
370 : // RFO output
371 3 : if(clipped) {
372 0 : *clipped = RADIOLIB_MAX(-4, RADIOLIB_MIN(15, power));
373 : }
374 3 : RADIOLIB_CHECK_RANGE(power, -4, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
375 : } else {
376 : // PA_BOOST output, check high-power operation
377 3 : if(clipped) {
378 0 : if(power != 20) {
379 0 : *clipped = RADIOLIB_MAX(2, RADIOLIB_MIN(17, power));
380 : } else {
381 0 : *clipped = 20;
382 : }
383 : }
384 3 : if(power != 20) {
385 3 : RADIOLIB_CHECK_RANGE(power, 2, 17, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
386 : }
387 : }
388 3 : return(RADIOLIB_ERR_NONE);
389 : }
390 :
391 0 : int16_t SX1278::setGain(uint8_t gain) {
392 : // check allowed range
393 0 : if(gain > 6) {
394 0 : return(RADIOLIB_ERR_INVALID_GAIN);
395 : }
396 :
397 : // set mode to standby
398 0 : int16_t state = SX127x::standby();
399 0 : Module* mod = this->getMod();
400 :
401 : // get modem
402 0 : int16_t modem = getActiveModem();
403 0 : if(modem == RADIOLIB_SX127X_LORA){
404 : // set gain
405 0 : if(gain == 0) {
406 : // gain set to 0, enable AGC loop
407 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_AGC_AUTO_ON, 2, 2);
408 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, RADIOLIB_SX127X_LNA_BOOST_ON, 1, 0);
409 : } else {
410 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_AGC_AUTO_OFF, 2, 2);
411 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON);
412 : }
413 :
414 0 : } else if(modem == RADIOLIB_SX127X_FSK_OOK) {
415 : // set gain
416 0 : if(gain == 0) {
417 : // gain set to 0, enable AGC loop
418 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX127X_AGC_AUTO_ON, 3, 3);
419 : } else {
420 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX1278_AGC_AUTO_OFF, 3, 3);
421 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON);
422 : }
423 :
424 : }
425 :
426 0 : return(state);
427 : }
428 :
429 3 : int16_t SX1278::setDataShaping(uint8_t sh) {
430 : // check active modem
431 3 : if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) {
432 3 : return(RADIOLIB_ERR_WRONG_MODEM);
433 : }
434 :
435 : // check modulation
436 0 : if(SX127x::ookEnabled) {
437 : // we're in OOK mode, the only thing we can do is disable
438 0 : if(sh == RADIOLIB_SHAPING_NONE) {
439 0 : return(setDataShapingOOK(0));
440 : }
441 :
442 0 : return(RADIOLIB_ERR_INVALID_MODULATION);
443 : }
444 :
445 : // set mode to standby
446 0 : int16_t state = SX127x::standby();
447 0 : RADIOLIB_ASSERT(state);
448 :
449 : // set data shaping
450 0 : Module* mod = this->getMod();
451 0 : switch(sh) {
452 0 : case RADIOLIB_SHAPING_NONE:
453 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_NO_SHAPING, 6, 5));
454 0 : case RADIOLIB_SHAPING_0_3:
455 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_0_3, 6, 5));
456 0 : case RADIOLIB_SHAPING_0_5:
457 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_0_5, 6, 5));
458 0 : case RADIOLIB_SHAPING_1_0:
459 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_1_0, 6, 5));
460 0 : default:
461 0 : return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
462 : }
463 : }
464 :
465 0 : int16_t SX1278::setDataShapingOOK(uint8_t sh) {
466 : // check active modem
467 0 : if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) {
468 0 : return(RADIOLIB_ERR_WRONG_MODEM);
469 : }
470 :
471 : // check modulation
472 0 : if(!SX127x::ookEnabled) {
473 0 : return(RADIOLIB_ERR_INVALID_MODULATION);
474 : }
475 :
476 : // set mode to standby
477 0 : int16_t state = SX127x::standby();
478 :
479 : // set data shaping
480 0 : Module* mod = this->getMod();
481 0 : switch(sh) {
482 0 : case 0:
483 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_NO_SHAPING, 6, 5);
484 0 : break;
485 0 : case 1:
486 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_OOK_FILTER_BR, 6, 5);
487 0 : break;
488 0 : case 2:
489 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_OOK_FILTER_2BR, 6, 5);
490 0 : break;
491 0 : default:
492 0 : return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
493 : }
494 :
495 0 : return(state);
496 : }
497 :
498 3 : float SX1278::getRSSI() {
499 3 : return(SX1278::getRSSI(true, false));
500 : }
501 :
502 3 : float SX1278::getRSSI(bool packet, bool skipReceive) {
503 3 : int16_t offset = -157;
504 3 : if(frequency < 868.0f) {
505 3 : offset = -164;
506 : }
507 3 : return(SX127x::getRSSI(packet, skipReceive, offset));
508 : }
509 :
510 0 : int16_t SX1278::setCRC(bool enable, bool mode) {
511 0 : Module* mod = this->getMod();
512 0 : if(getActiveModem() == RADIOLIB_SX127X_LORA) {
513 : // set LoRa CRC
514 0 : SX127x::crcEnabled = enable;
515 0 : if(enable) {
516 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1278_RX_CRC_MODE_ON, 2, 2));
517 : } else {
518 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1278_RX_CRC_MODE_OFF, 2, 2));
519 : }
520 : } else {
521 : // set FSK CRC
522 0 : int16_t state = RADIOLIB_ERR_NONE;
523 0 : if(enable) {
524 0 : state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_ON, 4, 4);
525 : } else {
526 0 : state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_OFF, 4, 4);
527 : }
528 0 : RADIOLIB_ASSERT(state);
529 :
530 : // set FSK CRC mode
531 0 : if(mode) {
532 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_IBM, 0, 0));
533 : } else {
534 0 : return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_CCITT, 0, 0));
535 : }
536 : }
537 : }
538 :
539 0 : int16_t SX1278::forceLDRO(bool enable) {
540 0 : if(getActiveModem() != RADIOLIB_SX127X_LORA) {
541 0 : return(RADIOLIB_ERR_WRONG_MODEM);
542 : }
543 :
544 0 : Module* mod = this->getMod();
545 0 : this->ldroAuto = false;
546 0 : this->ldroEnabled = enable;
547 0 : if(enable) {
548 0 : return(mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3));
549 : } else {
550 0 : return(mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3));
551 : }
552 : }
553 :
554 0 : int16_t SX1278::autoLDRO() {
555 0 : if(getActiveModem() != RADIOLIB_SX127X_LORA) {
556 0 : return(RADIOLIB_ERR_WRONG_MODEM);
557 : }
558 :
559 0 : this->ldroAuto = true;
560 0 : return(RADIOLIB_ERR_NONE);
561 : }
562 :
563 0 : int16_t SX1278::implicitHeader(size_t len) {
564 0 : this->implicitHdr = true;
565 0 : return(setHeaderType(RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, len));
566 : }
567 :
568 0 : int16_t SX1278::explicitHeader() {
569 0 : this->implicitHdr = false;
570 0 : return(setHeaderType(RADIOLIB_SX1278_HEADER_EXPL_MODE, 0));
571 : }
572 :
573 0 : int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) {
574 : // set mode to standby
575 0 : int16_t state = SX127x::standby();
576 :
577 : // write register
578 0 : Module* mod = this->getMod();
579 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newBandwidth, 7, 4);
580 0 : return(state);
581 : }
582 :
583 0 : int16_t SX1278::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
584 : // set mode to standby
585 0 : int16_t state = SX127x::standby();
586 :
587 : // write registers
588 0 : Module* mod = this->getMod();
589 0 : if(newSpreadingFactor == RADIOLIB_SX127X_SF_6) {
590 0 : this->implicitHdr = true;
591 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, 0);
592 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX127X_SF_6 | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
593 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
594 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_6);
595 : } else {
596 0 : this->implicitHdr = false;
597 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_EXPL_MODE, 0, 0);
598 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
599 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
600 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_7_12);
601 : }
602 0 : return(state);
603 : }
604 :
605 0 : int16_t SX1278::setCodingRateRaw(uint8_t newCodingRate) {
606 : // set mode to standby
607 0 : int16_t state = SX127x::standby();
608 :
609 : // write register
610 0 : Module* mod = this->getMod();
611 0 : state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newCodingRate, 3, 1);
612 0 : return(state);
613 : }
614 :
615 0 : int16_t SX1278::configFSK() {
616 : // configure common registers
617 0 : int16_t state = SX127x::configFSK();
618 0 : RADIOLIB_ASSERT(state);
619 :
620 : // set fast PLL hop
621 0 : Module* mod = this->getMod();
622 0 : state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PLL_HOP, RADIOLIB_SX127X_FAST_HOP_ON, 7, 7);
623 0 : return(state);
624 : }
625 :
626 0 : void SX1278::errataFix(bool rx) {
627 : // only apply in LoRa mode
628 0 : if(getActiveModem() != RADIOLIB_SX127X_LORA) {
629 0 : return;
630 : }
631 :
632 : // sensitivity optimization for 500kHz bandwidth
633 : // see SX1276/77/78 Errata, section 2.1 for details
634 0 : Module* mod = this->getMod();
635 0 : if(fabsf(SX127x::bandwidth - 500.0f) <= 0.001f) {
636 0 : if((frequency >= 862.0f) && (frequency <= 1020.0f)) {
637 0 : mod->SPIwriteRegister(0x36, 0x02);
638 0 : mod->SPIwriteRegister(0x3a, 0x64);
639 0 : } else if((frequency >= 410.0f) && (frequency <= 525.0f)) {
640 0 : mod->SPIwriteRegister(0x36, 0x02);
641 0 : mod->SPIwriteRegister(0x3a, 0x7F);
642 : }
643 : }
644 :
645 : // mitigation of receiver spurious response
646 : // see SX1276/77/78 Errata, section 2.3 for details
647 :
648 : // figure out what we need to set
649 0 : uint8_t fixedRegs[3] = { 0x00, 0x00, 0x00 };
650 0 : float rxFreq = frequency;
651 0 : if(fabsf(SX127x::bandwidth - 7.8f) <= 0.001f) {
652 0 : fixedRegs[0] = 0b00000000;
653 0 : fixedRegs[1] = 0x48;
654 0 : fixedRegs[2] = 0x00;
655 0 : rxFreq += 0.00781f;
656 0 : } else if(fabsf(SX127x::bandwidth - 10.4f) <= 0.001f) {
657 0 : fixedRegs[0] = 0b00000000;
658 0 : fixedRegs[1] = 0x44;
659 0 : fixedRegs[2] = 0x00;
660 0 : rxFreq += 0.01042f;
661 0 : } else if(fabsf(SX127x::bandwidth - 15.6f) <= 0.001f) {
662 0 : fixedRegs[0] = 0b00000000;
663 0 : fixedRegs[1] = 0x44;
664 0 : fixedRegs[2] = 0x00;
665 0 : rxFreq += 0.01562f;
666 0 : } else if(fabsf(SX127x::bandwidth - 20.8f) <= 0.001f) {
667 0 : fixedRegs[0] = 0b00000000;
668 0 : fixedRegs[1] = 0x44;
669 0 : fixedRegs[2] = 0x00;
670 0 : rxFreq += 0.02083f;
671 0 : } else if(fabsf(SX127x::bandwidth - 31.25f) <= 0.001f) {
672 0 : fixedRegs[0] = 0b00000000;
673 0 : fixedRegs[1] = 0x44;
674 0 : fixedRegs[2] = 0x00;
675 0 : rxFreq += 0.03125f;
676 0 : } else if(fabsf(SX127x::bandwidth - 41.7f) <= 0.001f) {
677 0 : fixedRegs[0] = 0b00000000;
678 0 : fixedRegs[1] = 0x44;
679 0 : fixedRegs[2] = 0x00;
680 0 : rxFreq += 0.04167f;
681 0 : } else if(fabsf(SX127x::bandwidth - 62.5f) <= 0.001f) {
682 0 : fixedRegs[0] = 0b00000000;
683 0 : fixedRegs[1] = 0x40;
684 0 : fixedRegs[2] = 0x00;
685 0 : } else if(fabsf(SX127x::bandwidth - 125.0f) <= 0.001f) {
686 0 : fixedRegs[0] = 0b00000000;
687 0 : fixedRegs[1] = 0x40;
688 0 : fixedRegs[2] = 0x00;
689 0 : } else if(fabsf(SX127x::bandwidth - 250.0f) <= 0.001f) {
690 0 : fixedRegs[0] = 0b00000000;
691 0 : fixedRegs[1] = 0x40;
692 0 : fixedRegs[2] = 0x00;
693 0 : } else if(fabsf(SX127x::bandwidth - 500.0f) <= 0.001f) {
694 0 : fixedRegs[0] = 0b10000000;
695 0 : fixedRegs[1] = mod->SPIreadRegister(0x2F);
696 0 : fixedRegs[2] = mod->SPIreadRegister(0x30);
697 : } else {
698 0 : return;
699 : }
700 :
701 : // first, go to standby
702 0 : standby();
703 :
704 : // shift the freqency up when receiving, or restore the original when transmitting
705 0 : if(rx) {
706 0 : SX127x::setFrequencyRaw(rxFreq);
707 : } else {
708 0 : SX127x::setFrequencyRaw(frequency);
709 : }
710 :
711 : // finally, apply errata fixes
712 0 : mod->SPIsetRegValue(0x31, fixedRegs[0], 7, 7);
713 0 : mod->SPIsetRegValue(0x2F, fixedRegs[1]);
714 0 : mod->SPIsetRegValue(0x30, fixedRegs[2]);
715 : }
716 :
717 1 : int16_t SX1278::setModem(ModemType_t modem) {
718 1 : switch(modem) {
719 0 : case(ModemType_t::RADIOLIB_MODEM_LORA): {
720 0 : return(this->begin());
721 : } break;
722 0 : case(ModemType_t::RADIOLIB_MODEM_FSK): {
723 0 : return(this->beginFSK());
724 : } break;
725 1 : default:
726 1 : return(RADIOLIB_ERR_WRONG_MODEM);
727 : }
728 : }
729 :
730 : #endif
|