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 paOptTable[32] = {
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 : }
47 :
48 0 : int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
49 : // execute common part
50 0 : int16_t state = SX126x::begin(cr, syncWord, preambleLength, tcxoVoltage, useRegulatorLDO);
51 0 : RADIOLIB_ASSERT(state);
52 :
53 : // configure publicly accessible settings
54 0 : state = setFrequency(freq);
55 0 : RADIOLIB_ASSERT(state);
56 :
57 0 : state = setSpreadingFactor(sf);
58 0 : RADIOLIB_ASSERT(state);
59 :
60 0 : state = setBandwidth(bw);
61 0 : RADIOLIB_ASSERT(state);
62 :
63 0 : state = setOutputPower(power);
64 0 : RADIOLIB_ASSERT(state);
65 :
66 0 : state = SX126x::fixPaClamping();
67 0 : RADIOLIB_ASSERT(state);
68 :
69 0 : return(state);
70 : }
71 :
72 0 : int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
73 : // execute common part
74 0 : int16_t state = SX126x::beginFSK(br, freqDev, rxBw, preambleLength, tcxoVoltage, useRegulatorLDO);
75 0 : RADIOLIB_ASSERT(state);
76 :
77 : // configure publicly accessible settings
78 0 : state = setFrequency(freq);
79 0 : RADIOLIB_ASSERT(state);
80 :
81 0 : state = setOutputPower(power);
82 0 : RADIOLIB_ASSERT(state);
83 :
84 0 : state = SX126x::fixPaClamping();
85 0 : RADIOLIB_ASSERT(state);
86 :
87 0 : return(state);
88 : }
89 :
90 0 : int16_t SX1268::beginBPSK(float freq, float br, int8_t power, float tcxoVoltage, bool useRegulatorLDO) {
91 : // execute common part
92 0 : int16_t state = SX126x::beginBPSK(br, tcxoVoltage, useRegulatorLDO);
93 0 : RADIOLIB_ASSERT(state);
94 :
95 : // configure publicly accessible settings
96 0 : state = setFrequency(freq);
97 0 : RADIOLIB_ASSERT(state);
98 :
99 0 : state = SX126x::fixPaClamping();
100 0 : RADIOLIB_ASSERT(state);
101 :
102 0 : state = setOutputPower(power);
103 0 : RADIOLIB_ASSERT(state);
104 :
105 0 : return(state);
106 : }
107 :
108 0 : int16_t SX1268::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, int8_t power, float tcxoVoltage, bool useRegulatorLDO) {
109 : // execute common part
110 0 : int16_t state = SX126x::beginLRFHSS(bw, cr, narrowGrid, tcxoVoltage, useRegulatorLDO);
111 0 : RADIOLIB_ASSERT(state);
112 :
113 : // configure publicly accessible settings
114 0 : state = setFrequency(freq);
115 0 : RADIOLIB_ASSERT(state);
116 :
117 0 : state = SX126x::fixPaClamping();
118 0 : RADIOLIB_ASSERT(state);
119 :
120 0 : state = setOutputPower(power);
121 0 : RADIOLIB_ASSERT(state);
122 :
123 0 : return(state);
124 : }
125 :
126 1 : int16_t SX1268::setFrequency(float freq) {
127 1 : return(setFrequency(freq, false));
128 : }
129 :
130 : /// \todo integers only (all modules - frequency, data rate, bandwidth etc.)
131 1 : int16_t SX1268::setFrequency(float freq, bool skipCalibration) {
132 1 : RADIOLIB_CHECK_RANGE(freq, 410.0f, 810.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
133 :
134 : // check if we need to recalibrate image
135 0 : if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) {
136 0 : int16_t state = this->calibrateImage(freq);
137 0 : RADIOLIB_ASSERT(state);
138 : }
139 :
140 : // set frequency
141 0 : return(SX126x::setFrequencyRaw(freq));
142 : }
143 :
144 1 : int16_t SX1268::setOutputPower(int8_t power) {
145 1 : return(setOutputPower(power, true));
146 : }
147 :
148 1 : int16_t SX1268::setOutputPower(int8_t power, bool optimize) {
149 : // check if power value is configurable
150 1 : int16_t state = checkOutputPower(power, NULL);
151 1 : RADIOLIB_ASSERT(state);
152 :
153 : // set PA config
154 1 : int8_t paVal = optimize ? paOptTable[power + 9].paVal : power;
155 1 : uint8_t paDutyCycle = optimize ? paOptTable[power + 9].paDutyCycle : 0x04;
156 1 : uint8_t hpMax = optimize ? paOptTable[power + 9].hpMax : 0x07;
157 1 : return(SX126x::setOutputPower(paVal, paDutyCycle, hpMax, RADIOLIB_SX126X_PA_CONFIG_SX1268));
158 : }
159 :
160 2 : int16_t SX1268::checkOutputPower(int8_t power, int8_t* clipped) {
161 2 : if(clipped) {
162 0 : *clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
163 : }
164 2 : RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
165 2 : return(RADIOLIB_ERR_NONE);
166 : }
167 :
168 1 : int16_t SX1268::setModem(ModemType_t modem) {
169 1 : switch(modem) {
170 0 : case(ModemType_t::RADIOLIB_MODEM_LORA): {
171 0 : return(this->begin());
172 : } break;
173 0 : case(ModemType_t::RADIOLIB_MODEM_FSK): {
174 0 : return(this->beginFSK());
175 : } break;
176 0 : case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
177 0 : return(this->beginLRFHSS());
178 : } break;
179 1 : default:
180 1 : return(RADIOLIB_ERR_WRONG_MODEM);
181 : }
182 : }
183 :
184 : #endif
|