Line data Source code
1 : #include "SX1268.h"
2 : #include <math.h>
3 :
4 : #if !RADIOLIB_EXCLUDE_SX126X
5 :
6 : // this is a lookup table for optimized PA configuration
7 : // it was determined by testing in https://github.com/jgromes/RadioLib/issues/1628
8 : // see also https://github.com/radiolib-org/power-tests
9 : static const SX126x::paTableEntry_t paOptimizedTable[RADIOLIB_SX126X_PA_TABLE_LEN] = {
10 : { .paDutyCycle = 2, .hpMax = 1, .paVal = -3 },
11 : { .paDutyCycle = 2, .hpMax = 1, .paVal = -2 },
12 : { .paDutyCycle = 1, .hpMax = 1, .paVal = 0 },
13 : { .paDutyCycle = 4, .hpMax = 1, .paVal = -1 },
14 : { .paDutyCycle = 2, .hpMax = 1, .paVal = 2 },
15 : { .paDutyCycle = 2, .hpMax = 2, .paVal = 0 },
16 : { .paDutyCycle = 2, .hpMax = 2, .paVal = 1 },
17 : { .paDutyCycle = 1, .hpMax = 2, .paVal = 3 },
18 : { .paDutyCycle = 1, .hpMax = 3, .paVal = 3 },
19 : { .paDutyCycle = 1, .hpMax = 2, .paVal = 5 },
20 : { .paDutyCycle = 1, .hpMax = 1, .paVal = 9 },
21 : { .paDutyCycle = 4, .hpMax = 1, .paVal = 8 },
22 : { .paDutyCycle = 2, .hpMax = 2, .paVal = 7 },
23 : { .paDutyCycle = 1, .hpMax = 1, .paVal = 13 },
24 : { .paDutyCycle = 4, .hpMax = 1, .paVal = 11 },
25 : { .paDutyCycle = 1, .hpMax = 1, .paVal = 19 },
26 : { .paDutyCycle = 2, .hpMax = 1, .paVal = 19 },
27 : { .paDutyCycle = 4, .hpMax = 1, .paVal = 17 },
28 : { .paDutyCycle = 1, .hpMax = 6, .paVal = 12 },
29 : { .paDutyCycle = 1, .hpMax = 2, .paVal = 16 },
30 : { .paDutyCycle = 4, .hpMax = 1, .paVal = 22 },
31 : { .paDutyCycle = 2, .hpMax = 2, .paVal = 18 },
32 : { .paDutyCycle = 1, .hpMax = 2, .paVal = 21 },
33 : { .paDutyCycle = 2, .hpMax = 2, .paVal = 21 },
34 : { .paDutyCycle = 3, .hpMax = 2, .paVal = 21 },
35 : { .paDutyCycle = 2, .hpMax = 3, .paVal = 20 },
36 : { .paDutyCycle = 1, .hpMax = 6, .paVal = 20 },
37 : { .paDutyCycle = 1, .hpMax = 5, .paVal = 22 },
38 : { .paDutyCycle = 2, .hpMax = 5, .paVal = 22 },
39 : { .paDutyCycle = 3, .hpMax = 5, .paVal = 22 },
40 : { .paDutyCycle = 3, .hpMax = 7, .paVal = 22 },
41 : { .paDutyCycle = 4, .hpMax = 7, .paVal = 22 },
42 : };
43 :
44 1 : SX1268::SX1268(Module* mod) : SX126x(mod) {
45 1 : chipType = RADIOLIB_SX1268_CHIP_TYPE;
46 1 : this->powerMin = RADIOLIB_SX1268_POUT_MIN;
47 1 : this->powerMax = RADIOLIB_SX1268_POUT_MAX;
48 1 : this->paSteps = this->powerMax - this->powerMin + 1;
49 1 : }
50 :
51 0 : int16_t SX1268::begin(const ConfigLoRa_t& cfg) {
52 0 : int16_t state = SX126x::begin(cfg.codingRate, cfg.syncWord, cfg.preambleLength);
53 0 : RADIOLIB_ASSERT(state);
54 :
55 : // configure publicly accessible settings
56 0 : state = setSpreadingFactor(cfg.spreadingFactor);
57 0 : RADIOLIB_ASSERT(state);
58 :
59 0 : state = setBandwidth(cfg.bandwidth);
60 0 : RADIOLIB_ASSERT(state);
61 :
62 0 : state = setFrequency(cfg.frequency);
63 0 : RADIOLIB_ASSERT(state);
64 :
65 0 : state = SX126x::fixPaClamping();
66 0 : RADIOLIB_ASSERT(state);
67 :
68 0 : state = setOutputPower(cfg.power);
69 0 : RADIOLIB_ASSERT(state);
70 :
71 0 : return(state);
72 : }
73 :
74 0 : int16_t SX1268::beginFSK(const ConfigFSK_t& cfg) {
75 : // execute common part
76 0 : int16_t state = SX126x::beginFSK(cfg.bitRate, cfg.frequencyDeviation, cfg.receiverBandwidth, cfg.preambleLength);
77 0 : RADIOLIB_ASSERT(state);
78 :
79 : // configure publicly accessible settings
80 0 : state = setFrequency(cfg.frequency);
81 0 : RADIOLIB_ASSERT(state);
82 :
83 0 : state = SX126x::fixPaClamping();
84 0 : RADIOLIB_ASSERT(state);
85 :
86 0 : state = setOutputPower(cfg.power);
87 0 : RADIOLIB_ASSERT(state);
88 :
89 0 : return(state);
90 : }
91 :
92 0 : int16_t SX1268::beginBPSK(const ConfigBPSK_t& cfg) {
93 : // execute common part
94 0 : int16_t state = SX126x::beginBPSK(cfg.bitRate);
95 0 : RADIOLIB_ASSERT(state);
96 :
97 : // configure publicly accessible settings
98 0 : state = setFrequency(cfg.frequency);
99 0 : RADIOLIB_ASSERT(state);
100 :
101 0 : state = SX126x::fixPaClamping();
102 0 : RADIOLIB_ASSERT(state);
103 :
104 0 : state = setOutputPower(cfg.power);
105 0 : RADIOLIB_ASSERT(state);
106 :
107 0 : return(state);
108 : }
109 :
110 0 : int16_t SX1268::beginLRFHSS(const ConfigLRFHSS_t& cfg) {
111 : // execute common part
112 0 : int16_t state = SX126x::beginLRFHSS(cfg.bandwidth, cfg.codingRate, cfg.narrowGrid);
113 0 : RADIOLIB_ASSERT(state);
114 :
115 : // configure publicly accessible settings
116 0 : state = setFrequency(cfg.frequency);
117 0 : RADIOLIB_ASSERT(state);
118 :
119 0 : state = SX126x::fixPaClamping();
120 0 : RADIOLIB_ASSERT(state);
121 :
122 0 : state = setOutputPower(cfg.power);
123 0 : RADIOLIB_ASSERT(state);
124 :
125 0 : return(state);
126 : }
127 :
128 1 : int16_t SX1268::setFrequency(uint32_t freq) {
129 1 : return(setFrequency(freq, false));
130 : }
131 :
132 1 : int16_t SX1268::setFrequency(uint32_t freq, bool skipCalibration) {
133 1 : RADIOLIB_CHECK_RANGE(freq, RADIOLIB_UNIT_MEGA(410), RADIOLIB_UNIT_MEGA(810), RADIOLIB_ERR_INVALID_FREQUENCY);
134 :
135 : // check if we need to recalibrate image
136 0 : if(!skipCalibration && (RADIOLIB_ABS_UNSIGNED(freq, this->freqHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) {
137 0 : int16_t state = this->calibrateImage(freq);
138 0 : RADIOLIB_ASSERT(state);
139 : }
140 :
141 : // set frequency
142 0 : return(SX126x::setFrequencyRaw(freq));
143 : }
144 :
145 1 : int16_t SX1268::setOutputPower(int8_t power) {
146 1 : return(setOutputPower(power, true));
147 : }
148 :
149 1 : int16_t SX1268::setOutputPower(int8_t power, bool optimize) {
150 : // apply offset for external PA
151 1 : int8_t pwr = power;
152 1 : int16_t state = this->applyOutputPowerOffset(RADIOLIB_SX1268_POUT_MIN, &power, &pwr);
153 1 : RADIOLIB_ASSERT(state);
154 :
155 : // set PA config
156 1 : SX126x::paTableEntry_t* paTable = this->paOptTable ? this->paOptTable : const_cast<SX126x::paTableEntry_t*>(paOptimizedTable);
157 1 : int8_t paVal = optimize ? paTable[pwr - RADIOLIB_SX1268_POUT_MIN].paVal : pwr;
158 1 : uint8_t paDutyCycle = optimize ? paTable[pwr - RADIOLIB_SX1268_POUT_MIN].paDutyCycle : 0x04;
159 1 : uint8_t hpMax = optimize ? paTable[pwr - RADIOLIB_SX1268_POUT_MIN].hpMax : 0x07;
160 1 : return(SX126x::setOutputPower(paVal, paDutyCycle, hpMax, RADIOLIB_SX126X_PA_CONFIG_SX1268));
161 : }
162 :
163 1 : int16_t SX1268::setModem(ModemType_t modem) {
164 1 : switch(modem) {
165 0 : case(ModemType_t::RADIOLIB_MODEM_LORA): {
166 0 : ConfigLoRa_t cfg;
167 0 : return(this->begin(cfg));
168 : } break;
169 0 : case(ModemType_t::RADIOLIB_MODEM_FSK): {
170 0 : ConfigFSK_t cfg;
171 0 : return(this->beginFSK(cfg));
172 : } break;
173 0 : case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
174 0 : ConfigLRFHSS_t cfg;
175 0 : return(this->beginLRFHSS(cfg));
176 : } break;
177 1 : default:
178 1 : return(RADIOLIB_ERR_WRONG_MODEM);
179 : }
180 : }
181 :
182 : #endif
|