Skip to content

Commit ef76a04

Browse files
authored
Merge pull request #21687 from fabian18/pr/sx126x_tx_power
drivers/sx126x: bind PA config to output power
2 parents bca37a7 + f54c8ff commit ef76a04

File tree

3 files changed

+227
-38
lines changed

3 files changed

+227
-38
lines changed

drivers/include/sx126x.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,17 @@ uint8_t sx126x_get_coding_rate(const sx126x_t *dev);
253253
*/
254254
void sx126x_set_coding_rate(sx126x_t *dev, uint8_t cr);
255255

256+
/**
257+
* @brief Sets the TX power and ramp time
258+
*
259+
* The actual transmission power may be different depending on device capabilities and board design.
260+
*
261+
* @param[in] dev Device descriptor of the driver
262+
* @param[in] power_dbm The TX power in dBm
263+
* @param[in] ramp_time The ramp time
264+
*/
265+
void sx126x_set_tx_power(sx126x_t *dev, int8_t power_dbm, sx126x_ramp_time_t ramp_time);
266+
256267
/**
257268
* @brief Gets the payload length
258269
*

drivers/sx126x/sx126x.c

Lines changed: 215 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,214 @@
4949
#define CONFIG_SX126X_RAMP_TIME_DEFAULT (SX126X_RAMP_10_US)
5050
#endif
5151

52-
const sx126x_pa_cfg_params_t sx1268_pa_cfg = {
53-
.pa_duty_cycle = 0x04,
54-
.hp_max = 0x06,
55-
.device_sel = 0x00,
56-
.pa_lut = 0x01
52+
#if IS_USED(MODULE_SX1268)
53+
/* sx1268 */
54+
const sx126x_pa_cfg_params_t sx1268_pa_cfg[] = {
55+
/* 10 dBm */
56+
{
57+
.pa_duty_cycle = 0x00,
58+
.hp_max = 0x03,
59+
.device_sel = 0x00,
60+
.pa_lut = 0x01
61+
},
62+
/* 14 dBm */
63+
{
64+
.pa_duty_cycle = 0x04,
65+
.hp_max = 0x06,
66+
.device_sel = 0x00,
67+
.pa_lut = 0x01
68+
},
69+
/* 17 dBm */
70+
{
71+
.pa_duty_cycle = 0x02,
72+
.hp_max = 0x03,
73+
.device_sel = 0x00,
74+
.pa_lut = 0x01
75+
},
76+
/* 20 dBm */
77+
{
78+
.pa_duty_cycle = 0x03,
79+
.hp_max = 0x05,
80+
.device_sel = 0x00,
81+
.pa_lut = 0x01
82+
},
83+
/* 22 dBm */
84+
{
85+
.pa_duty_cycle = 0x04,
86+
.hp_max = 0x07,
87+
.device_sel = 0x00,
88+
.pa_lut = 0x01
89+
},
5790
};
91+
#endif
5892

59-
const sx126x_pa_cfg_params_t lpa_cfg = {
60-
.pa_duty_cycle = 0x04,
61-
.hp_max = 0x00,
62-
.device_sel = 0x01,
63-
.pa_lut = 0x01
93+
#if IS_USED(MODULE_SX1261) || IS_USED(MODULE_SX126X_STM32WL)
94+
/* sx1261 */
95+
const sx126x_pa_cfg_params_t lpa_cfg[] = {
96+
/* 10 dBm */
97+
{
98+
.pa_duty_cycle = 0x01,
99+
.hp_max = 0x00,
100+
.device_sel = 0x01,
101+
.pa_lut = 0x01
102+
},
103+
/* 14 dBm */
104+
{
105+
.pa_duty_cycle = 0x04,
106+
.hp_max = 0x00,
107+
.device_sel = 0x01,
108+
.pa_lut = 0x01
109+
},
110+
/* 15 dBm */
111+
{
112+
.pa_duty_cycle = 0x06,
113+
.hp_max = 0x00,
114+
.device_sel = 0x01,
115+
.pa_lut = 0x01
116+
},
64117
};
118+
#endif
65119

66-
const sx126x_pa_cfg_params_t hpa_cfg = {
67-
.pa_duty_cycle = 0x02,
68-
.hp_max = 0x02,
69-
.device_sel = 0x00,
70-
.pa_lut = 0x01
120+
#if IS_USED(MODULE_SX1262) || IS_USED(MODULE_LLCC68) || IS_USED(MODULE_SX126X_STM32WL)
121+
/* sx1262, llcc68 */
122+
const sx126x_pa_cfg_params_t hpa_cfg[] = {
123+
/* 14 dBm */
124+
{
125+
.pa_duty_cycle = 0x02,
126+
.hp_max = 0x02,
127+
.device_sel = 0x00,
128+
.pa_lut = 0x01
129+
},
130+
/* 17 dBm */
131+
{
132+
.pa_duty_cycle = 0x02,
133+
.hp_max = 0x03,
134+
.device_sel = 0x00,
135+
.pa_lut = 0x01
136+
},
137+
/* 20 dBm */
138+
{
139+
.pa_duty_cycle = 0x03,
140+
.hp_max = 0x05,
141+
.device_sel = 0x00,
142+
.pa_lut = 0x01
143+
},
144+
/* 22 dBm */
145+
{
146+
.pa_duty_cycle = 0x04,
147+
.hp_max = 0x07,
148+
.device_sel = 0x00,
149+
.pa_lut = 0x01
150+
}
71151
};
152+
#endif
153+
154+
/* Configure PA optimal settings for maximum output power.
155+
* These values are defined by Semtech in the respective IC datasheet,
156+
* section 13.1.14 SetPaConfig.
157+
* and are optimal for respectively desired TX output power. */
158+
159+
static int8_t _select_pa_cfg(sx126x_t *dev, int8_t tx_power_dbm,
160+
const sx126x_pa_cfg_params_t **pa_cfg)
161+
{
162+
#if IS_USED(MODULE_SX126X_STM32WL)
163+
if (sx126x_is_stm32wl(dev)) {
164+
if (tx_power_dbm <= 10) {
165+
*pa_cfg = &lpa_cfg[0];
166+
return 10;
167+
}
168+
else if (tx_power_dbm <= 14) {
169+
#if IS_USED(MODULE_SX126X_RF_SWITCH)
170+
/* Only lora-e5 and nucleo-wl55jc are using this module
171+
I think the parameter was introduced because 14dbm can be
172+
achieved with both LPA and HPA settings. */
173+
if (dev->params->tx_pa_mode == SX126X_RF_MODE_TX_LPA) {
174+
*pa_cfg = &lpa_cfg[1];
175+
}
176+
else {
177+
*pa_cfg = &hpa_cfg[0];
178+
}
179+
#else
180+
*pa_cfg = &hpa_cfg[0];
181+
return 14;
182+
#endif
183+
}
184+
else if (tx_power_dbm <= 17) {
185+
*pa_cfg = &hpa_cfg[1];
186+
return 17;
187+
}
188+
else if (tx_power_dbm <= 20) {
189+
*pa_cfg = &hpa_cfg[2];
190+
return 20;
191+
}
192+
else {
193+
*pa_cfg = &hpa_cfg[3];
194+
return 22;
195+
}
196+
}
197+
#endif
198+
#if IS_USED(MODULE_SX1261)
199+
if (sx126x_is_sx1261(dev)) {
200+
if (tx_power_dbm <= 10) {
201+
*pa_cfg = &lpa_cfg[0];
202+
return 10;
203+
}
204+
else if (tx_power_dbm <= 14) {
205+
*pa_cfg = &lpa_cfg[1];
206+
return 14;
207+
}
208+
else {
209+
*pa_cfg = &lpa_cfg[2];
210+
return 15;
211+
}
212+
}
213+
#endif
214+
#if IS_USED(MODULE_SX1262) || IS_USED(MODULE_LLCC68)
215+
if (sx126x_is_sx1262(dev) || sx126x_is_llcc68(dev)) {
216+
if (tx_power_dbm <= 14) {
217+
*pa_cfg = &hpa_cfg[0];
218+
return 14;
219+
}
220+
else if (tx_power_dbm <= 17) {
221+
*pa_cfg = &hpa_cfg[1];
222+
return 17;
223+
}
224+
else if (tx_power_dbm <= 20) {
225+
*pa_cfg = &hpa_cfg[2];
226+
return 20;
227+
}
228+
else {
229+
*pa_cfg = &hpa_cfg[3];
230+
return 22;
231+
}
232+
}
233+
#endif
234+
#if IS_USED(MODULE_SX1268)
235+
if (sx126x_is_sx1268(dev)) {
236+
if (tx_power_dbm <= 10) {
237+
*pa_cfg = &sx1268_pa_cfg[0];
238+
return 10;
239+
}
240+
else if (tx_power_dbm <= 14) {
241+
*pa_cfg = &sx1268_pa_cfg[1];
242+
return 14;
243+
}
244+
else if (tx_power_dbm <= 17) {
245+
*pa_cfg = &sx1268_pa_cfg[2];
246+
return 17;
247+
}
248+
else if (tx_power_dbm <= 20) {
249+
*pa_cfg = &sx1268_pa_cfg[3];
250+
return 20;
251+
}
252+
else {
253+
*pa_cfg = &sx1268_pa_cfg[4];
254+
return 22;
255+
}
256+
}
257+
#endif
258+
return -1; /* should not be return if any available driver is used */
259+
}
72260

73261
void sx126x_setup(sx126x_t *dev, const sx126x_params_t *params, uint8_t index)
74262
{
@@ -102,28 +290,7 @@ static void sx126x_init_default_config(sx126x_t *dev)
102290
/* packet type must be set first */
103291
sx126x_set_pkt_type(dev, SX126X_PKT_TYPE_LORA);
104292
sx126x_set_channel(dev, CONFIG_SX126X_CHANNEL_DEFAULT);
105-
106-
/* Configure PA optimal settings for maximum output power
107-
* Values used here comes from the datasheet, section 13.1.14 SetPaConfig
108-
* and are optimal for a TX output power of 14dBm.
109-
*/
110-
if (sx126x_is_llcc68(dev) || sx126x_is_sx1262(dev)) {
111-
sx126x_set_pa_cfg(dev, &hpa_cfg);
112-
}
113-
else if (sx126x_is_sx1268(dev)) {
114-
sx126x_set_pa_cfg(dev, &sx1268_pa_cfg);
115-
}
116-
else if (sx126x_is_sx1261(dev)) {
117-
sx126x_set_pa_cfg(dev, &lpa_cfg);
118-
}
119-
#if IS_USED(MODULE_SX126X_RF_SWITCH)
120-
if (dev->params->tx_pa_mode == SX126X_RF_MODE_TX_LPA){
121-
sx126x_set_pa_cfg(dev, &lpa_cfg);
122-
} else {
123-
sx126x_set_pa_cfg(dev, &hpa_cfg);
124-
}
125-
#endif
126-
sx126x_set_tx_params(dev, CONFIG_SX126X_TX_POWER_DEFAULT, CONFIG_SX126X_RAMP_TIME_DEFAULT);
293+
sx126x_set_tx_power(dev, CONFIG_SX126X_TX_POWER_DEFAULT, CONFIG_SX126X_RAMP_TIME_DEFAULT);
127294

128295
dev->mod_params.bw = (sx126x_lora_bw_t)(CONFIG_LORA_BW_DEFAULT + SX126X_LORA_BW_125);
129296
dev->mod_params.sf = (sx126x_lora_sf_t)CONFIG_LORA_SF_DEFAULT;
@@ -314,6 +481,17 @@ void sx126x_set_coding_rate(sx126x_t *dev, uint8_t cr)
314481
sx126x_set_lora_mod_params(dev, &dev->mod_params);
315482
}
316483

484+
void sx126x_set_tx_power(sx126x_t *dev, int8_t power_dbm, sx126x_ramp_time_t ramp_time)
485+
{
486+
DEBUG("[sx126x]: sx126x_set_tx_power %ddBm\n", power_dbm);
487+
const sx126x_pa_cfg_params_t *pa_cfg;
488+
int8_t pow = _select_pa_cfg(dev, power_dbm, &pa_cfg);
489+
if (pow > 0) {
490+
sx126x_set_pa_cfg(dev, pa_cfg);
491+
sx126x_set_tx_params(dev, pow, ramp_time);
492+
}
493+
}
494+
317495
uint8_t sx126x_get_lora_payload_length(const sx126x_t *dev)
318496
{
319497
DEBUG("[sx126x]: sx126x_get_lora_payload_length \n");

drivers/sx126x/sx126x_netdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
441441
res = -EINVAL;
442442
break;
443443
}
444-
sx126x_set_tx_params(dev, power, SX126X_RAMP_10_US);
444+
sx126x_set_tx_power(dev, power, SX126X_RAMP_10_US);
445445
return sizeof(int16_t);
446446

447447
case NETOPT_FIXED_HEADER:

0 commit comments

Comments
 (0)