Line data Source code
1 : #include "LR1120.h"
2 : #include <math.h>
3 :
4 : #if !RADIOLIB_EXCLUDE_LR11X0
5 :
6 2 : LR1120::LR1120(Module* mod) : LR11x0(mod) {
7 2 : chipType = RADIOLIB_LR11X0_DEVICE_LR1120;
8 2 : }
9 :
10 0 : int16_t LR1120::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
11 : // execute common part
12 0 : int16_t state = LR11x0::begin(bw, sf, cr, syncWord, preambleLength, tcxoVoltage, freq > 1000.0f);
13 0 : RADIOLIB_ASSERT(state);
14 :
15 : // configure publicly accessible settings
16 0 : state = setFrequency(freq);
17 0 : RADIOLIB_ASSERT(state);
18 :
19 0 : state = setOutputPower(power);
20 0 : return(state);
21 : }
22 :
23 0 : int16_t LR1120::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
24 : // execute common part
25 0 : int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, preambleLength, tcxoVoltage);
26 0 : RADIOLIB_ASSERT(state);
27 :
28 : // configure publicly accessible settings
29 0 : state = setFrequency(freq);
30 0 : RADIOLIB_ASSERT(state);
31 :
32 0 : state = setOutputPower(power);
33 0 : return(state);
34 : }
35 :
36 0 : int16_t LR1120::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, int8_t power, float tcxoVoltage) {
37 : // execute common part
38 0 : int16_t state = LR11x0::beginLRFHSS(bw, cr, narrowGrid, tcxoVoltage);
39 0 : RADIOLIB_ASSERT(state);
40 :
41 : // configure publicly accessible settings
42 0 : state = setFrequency(freq);
43 0 : RADIOLIB_ASSERT(state);
44 :
45 0 : state = setOutputPower(power);
46 0 : return(state);
47 : }
48 :
49 2 : int16_t LR1120::setFrequency(float freq) {
50 2 : return(this->setFrequency(freq, false));
51 : }
52 :
53 2 : int16_t LR1120::setFrequency(float freq, bool skipCalibration, float band) {
54 : #if RADIOLIB_CHECK_PARAMS
55 2 : if(!(((freq >= 150.0f) && (freq <= 960.0f)) ||
56 2 : ((freq >= 1900.0f) && (freq <= 2200.0f)) ||
57 2 : ((freq >= 2400.0f) && (freq <= 2500.0f)))) {
58 2 : return(RADIOLIB_ERR_INVALID_FREQUENCY);
59 : }
60 : #endif
61 :
62 : // check if we need to recalibrate image
63 : int16_t state;
64 0 : if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG_MHZ)) {
65 0 : state = LR11x0::calibrateImageRejection(freq - band, freq + band);
66 0 : RADIOLIB_ASSERT(state);
67 : }
68 :
69 : // set frequency
70 0 : state = LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f));
71 0 : RADIOLIB_ASSERT(state);
72 0 : this->freqMHz = freq;
73 0 : this->highFreq = (freq > 1000.0f);
74 :
75 : // apply workaround for GFSK
76 0 : return(workaroundGFSK());
77 : }
78 :
79 2 : int16_t LR1120::setOutputPower(int8_t power) {
80 2 : return(this->setOutputPower(power, false));
81 : }
82 :
83 2 : int16_t LR1120::setOutputPower(int8_t power, bool forceHighPower, uint32_t rampTimeUs) {
84 : // check if power value is configurable
85 2 : int16_t state = this->checkOutputPower(power, NULL, forceHighPower);
86 2 : RADIOLIB_ASSERT(state);
87 :
88 : // determine whether to use HP or LP PA and check range accordingly
89 2 : uint8_t paSel = 0;
90 2 : uint8_t paSupply = 0;
91 2 : if(this->highFreq) {
92 0 : paSel = 2;
93 2 : } else if(forceHighPower || (power > 14)) {
94 0 : paSel = 1;
95 0 : paSupply = 1;
96 : }
97 :
98 : // TODO how and when to configure OCP?
99 :
100 : // update PA config and set output power - always use VBAT for high-power PA
101 : // the value returned by LRxxxx class is offset by 3 for LR11x0
102 2 : state = LR11x0::setOutputPower(power, paSel, paSupply, 0x04, 0x07, roundRampTime(rampTimeUs) - 0x03);
103 2 : return(state);
104 : }
105 :
106 2 : int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped) {
107 2 : return(checkOutputPower(power, clipped, false));
108 : }
109 :
110 4 : int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower) {
111 4 : if(this->highFreq) {
112 0 : if(clipped) {
113 0 : *clipped = RADIOLIB_MAX(-18, RADIOLIB_MIN(13, power));
114 : }
115 0 : RADIOLIB_CHECK_RANGE(power, -18, 13, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
116 0 : return(RADIOLIB_ERR_NONE);
117 : }
118 :
119 4 : if(forceHighPower || (power > 14)) {
120 0 : if(clipped) {
121 0 : *clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
122 : }
123 0 : RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
124 :
125 : } else {
126 4 : if(clipped) {
127 0 : *clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
128 : }
129 4 : RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
130 :
131 : }
132 4 : return(RADIOLIB_ERR_NONE);
133 : }
134 :
135 2 : int16_t LR1120::setModem(ModemType_t modem) {
136 2 : switch(modem) {
137 0 : case(ModemType_t::RADIOLIB_MODEM_LORA): {
138 0 : return(this->begin());
139 : } break;
140 0 : case(ModemType_t::RADIOLIB_MODEM_FSK): {
141 0 : return(this->beginGFSK());
142 : } break;
143 0 : case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
144 0 : return(this->beginLRFHSS());
145 : } break;
146 2 : default:
147 2 : return(RADIOLIB_ERR_WRONG_MODEM);
148 : }
149 : return(RADIOLIB_ERR_WRONG_MODEM);
150 : }
151 :
152 : #endif
|