1 /*
2 * Copyright (c) 2021 Fabio Baltieri
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8
9 #include "sx126x_common.h"
10
11 #include <stm32wlxx_ll_exti.h>
12 #include <stm32wlxx_ll_pwr.h>
13 #include <stm32wlxx_ll_rcc.h>
14
15 #include <zephyr/logging/log.h>
16 #include <zephyr/irq.h>
17 LOG_MODULE_DECLARE(sx126x, CONFIG_LORA_LOG_LEVEL);
18
19 static const enum {
20 RFO_LP,
21 RFO_HP,
22 } pa_output = DT_INST_STRING_UPPER_TOKEN(0, power_amplifier_output);
23
sx126x_reset(struct sx126x_data * dev_data)24 void sx126x_reset(struct sx126x_data *dev_data)
25 {
26 LL_RCC_RF_EnableReset();
27 k_sleep(K_MSEC(20));
28 LL_RCC_RF_DisableReset();
29 k_sleep(K_MSEC(10));
30 }
31
sx126x_is_busy(struct sx126x_data * dev_data)32 bool sx126x_is_busy(struct sx126x_data *dev_data)
33 {
34 return LL_PWR_IsActiveFlag_RFBUSYS();
35 }
36
sx126x_get_dio1_pin_state(struct sx126x_data * dev_data)37 uint32_t sx126x_get_dio1_pin_state(struct sx126x_data *dev_data)
38 {
39 return 0;
40 }
41
sx126x_dio1_irq_enable(struct sx126x_data * dev_data)42 void sx126x_dio1_irq_enable(struct sx126x_data *dev_data)
43 {
44 NVIC_ClearPendingIRQ(DT_INST_IRQN(0));
45 irq_enable(DT_INST_IRQN(0));
46 }
47
sx126x_dio1_irq_disable(struct sx126x_data * dev_data)48 void sx126x_dio1_irq_disable(struct sx126x_data *dev_data)
49 {
50 irq_disable(DT_INST_IRQN(0));
51 }
52
sx126x_set_tx_params(int8_t power,RadioRampTimes_t ramp_time)53 void sx126x_set_tx_params(int8_t power, RadioRampTimes_t ramp_time)
54 {
55 uint8_t buf[2];
56
57 if (pa_output == RFO_LP) {
58 const int8_t max_power = DT_INST_PROP(0, rfo_lp_max_power);
59
60 if (power > max_power) {
61 power = max_power;
62 }
63 if (max_power == 15) {
64 SX126xSetPaConfig(0x07, 0x00, 0x01, 0x01);
65 power = 14 - (max_power - power);
66 } else if (max_power == 10) {
67 SX126xSetPaConfig(0x01, 0x00, 0x01, 0x01);
68 power = 13 - (max_power - power);
69 } else { /* default +14 dBm */
70 SX126xSetPaConfig(0x04, 0x00, 0x01, 0x01);
71 power = 14 - (max_power - power);
72 }
73 if (power < -17) {
74 power = -17;
75 }
76
77 /* PA overcurrent protection limit 60 mA */
78 SX126xWriteRegister(REG_OCP, 0x18);
79 } else { /* RFO_HP */
80 /* Better Resistance of the RFO High Power Tx to Antenna
81 * Mismatch, see STM32WL Erratasheet
82 */
83 SX126xWriteRegister(REG_TX_CLAMP_CFG,
84 SX126xReadRegister(REG_TX_CLAMP_CFG)
85 | (0x0F << 1));
86
87 const int8_t max_power = DT_INST_PROP(0, rfo_hp_max_power);
88
89 if (power > max_power) {
90 power = max_power;
91 }
92 if (max_power == 20) {
93 SX126xSetPaConfig(0x03, 0x05, 0x00, 0x01);
94 power = 22 - (max_power - power);
95 } else if (max_power == 17) {
96 SX126xSetPaConfig(0x02, 0x03, 0x00, 0x01);
97 power = 22 - (max_power - power);
98 } else if (max_power == 14) {
99 SX126xSetPaConfig(0x02, 0x02, 0x00, 0x01);
100 power = 14 - (max_power - power);
101 } else { /* default +22 dBm */
102 SX126xSetPaConfig(0x04, 0x07, 0x00, 0x01);
103 power = 22 - (max_power - power);
104 }
105 if (power < -9) {
106 power = -9;
107 }
108
109 /* PA overcurrent protection limit 140 mA */
110 SX126xWriteRegister(REG_OCP, 0x38);
111 }
112
113 buf[0] = power;
114 buf[1] = (uint8_t)ramp_time;
115 SX126xWriteCommand(RADIO_SET_TXPARAMS, buf, 2);
116 }
117
radio_isr(const struct device * dev)118 static void radio_isr(const struct device *dev)
119 {
120 struct sx126x_data *dev_data = dev->data;
121
122 irq_disable(DT_INST_IRQN(0));
123 k_work_submit(&dev_data->dio1_irq_work);
124 }
125
sx126x_variant_init(const struct device * dev)126 int sx126x_variant_init(const struct device *dev)
127 {
128 IRQ_CONNECT(DT_INST_IRQN(0),
129 DT_INST_IRQ(0, priority),
130 radio_isr, DEVICE_DT_INST_GET(0), 0);
131 LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_44);
132 irq_enable(DT_INST_IRQN(0));
133
134 return 0;
135 }
136