Line data Source code
1 : #include "SX1280.h"
2 : #include <string.h>
3 : #if !RADIOLIB_EXCLUDE_SX128X
4 :
5 2 : SX1280::SX1280(Module* mod) : SX1281(mod) {
6 2 : chipType = RADIOLIB_SX1280_CHIP_TYPE;
7 2 : }
8 :
9 0 : int16_t SX1280::range(bool master, uint32_t addr, uint16_t calTable[3][6]) {
10 : // start ranging
11 0 : int16_t state = startRanging(master, addr, calTable);
12 0 : RADIOLIB_ASSERT(state);
13 :
14 : // wait until ranging is finished
15 0 : Module* mod = this->getMod();
16 0 : RadioLibTime_t start = mod->hal->millis();
17 0 : while(!mod->hal->digitalRead(mod->getIrq())) {
18 0 : mod->hal->yield();
19 0 : if(mod->hal->millis() - start > 10000) {
20 0 : (void)finishRanging();
21 0 : return(RADIOLIB_ERR_RANGING_TIMEOUT);
22 : }
23 : }
24 :
25 0 : return(finishRanging());
26 : }
27 :
28 0 : int16_t SX1280::startRanging(bool master, uint32_t addr, const uint16_t calTable[3][6]) {
29 : // check active modem
30 0 : uint8_t modem = getPacketType();
31 0 : if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) {
32 0 : return(RADIOLIB_ERR_WRONG_MODEM);
33 : }
34 :
35 : // set mode to standby
36 0 : int16_t state = standby();
37 0 : RADIOLIB_ASSERT(state);
38 :
39 : // ensure modem is set to ranging
40 0 : if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
41 0 : state = setPacketType(RADIOLIB_SX128X_PACKET_TYPE_RANGING);
42 0 : RADIOLIB_ASSERT(state);
43 : }
44 :
45 : // set modulation parameters
46 0 : state = setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRateLoRa);
47 0 : RADIOLIB_ASSERT(state);
48 :
49 : // set packet parameters
50 0 : state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa);
51 0 : RADIOLIB_ASSERT(state);
52 :
53 : // check all address bits
54 0 : if(!master) {
55 : uint8_t regValue;
56 0 : state = readRegister(RADIOLIB_SX128X_REG_SLAVE_RANGING_ADDRESS_WIDTH, ®Value, 1);
57 0 : RADIOLIB_ASSERT(state);
58 0 : regValue &= 0b00111111;
59 0 : regValue |= 0b11000000;
60 0 : state = writeRegister(RADIOLIB_SX128X_REG_SLAVE_RANGING_ADDRESS_WIDTH, ®Value, 1);
61 0 : RADIOLIB_ASSERT(state);
62 : }
63 :
64 : // set remaining parameter values
65 0 : uint32_t addrReg = RADIOLIB_SX128X_REG_SLAVE_RANGING_ADDRESS_BYTE_3;
66 0 : uint32_t irqMask = RADIOLIB_SX128X_IRQ_RANGING_SLAVE_RESP_DONE | RADIOLIB_SX128X_IRQ_RANGING_SLAVE_REQ_DISCARD;
67 0 : uint32_t irqDio1 = RADIOLIB_SX128X_IRQ_RANGING_SLAVE_RESP_DONE;
68 0 : if(master) {
69 0 : addrReg = RADIOLIB_SX128X_REG_MASTER_RANGING_ADDRESS_BYTE_3;
70 0 : irqMask = RADIOLIB_SX128X_IRQ_RANGING_MASTER_RES_VALID | RADIOLIB_SX128X_IRQ_RANGING_MASTER_TIMEOUT;
71 0 : irqDio1 = RADIOLIB_SX128X_IRQ_RANGING_MASTER_RES_VALID;
72 : }
73 :
74 : // set ranging address
75 0 : const uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
76 0 : state = writeRegister(addrReg, addrBuff, 4);
77 0 : RADIOLIB_ASSERT(state);
78 :
79 : // set DIO mapping
80 0 : state = setDioIrqParams(irqMask, irqDio1);
81 0 : RADIOLIB_ASSERT(state);
82 :
83 : // this is the default calibration from AN1200.29
84 0 : uint16_t calTbl[3][6] = {
85 : { 10299, 10271, 10244, 10242, 10230, 10246 },
86 : { 11486, 11474, 11453, 11426, 11417, 11401 },
87 : { 13308, 13493, 13528, 13515, 13430, 13376 }
88 : };
89 :
90 : // check if user provided some custom calibration
91 0 : if(calTable != NULL) {
92 0 : memcpy(calTbl, calTable, sizeof(calTbl));
93 : }
94 :
95 : // set calibration values
96 0 : uint8_t index = (this->spreadingFactor >> 4) - 5;
97 0 : uint16_t val = 0;
98 0 : switch(this->bandwidth) {
99 0 : case(RADIOLIB_SX128X_LORA_BW_406_25):
100 0 : val = calTbl[0][index];
101 0 : break;
102 0 : case(RADIOLIB_SX128X_LORA_BW_812_50):
103 0 : val = calTbl[1][index];
104 0 : break;
105 0 : case(RADIOLIB_SX128X_LORA_BW_1625_00):
106 0 : val = calTbl[2][index];
107 0 : break;
108 0 : default:
109 0 : return(RADIOLIB_ERR_INVALID_BANDWIDTH);
110 : }
111 0 : const uint8_t calBuff[] = { (uint8_t)((val >> 8) & 0xFF), (uint8_t)(val & 0xFF) };
112 0 : state = writeRegister(RADIOLIB_SX128X_REG_RANGING_CALIBRATION_MSB, calBuff, 2);
113 0 : RADIOLIB_ASSERT(state);
114 :
115 : // set role and start ranging
116 0 : if(master) {
117 0 : state = setRangingRole(RADIOLIB_SX128X_RANGING_ROLE_MASTER);
118 0 : RADIOLIB_ASSERT(state);
119 :
120 0 : state = setTx(RADIOLIB_SX128X_TX_TIMEOUT_NONE);
121 0 : RADIOLIB_ASSERT(state);
122 :
123 : } else {
124 0 : state = setRangingRole(RADIOLIB_SX128X_RANGING_ROLE_SLAVE);
125 0 : RADIOLIB_ASSERT(state);
126 :
127 0 : state = setRx(RADIOLIB_SX128X_RX_TIMEOUT_INF);
128 0 : RADIOLIB_ASSERT(state);
129 :
130 : }
131 :
132 0 : return(state);
133 : }
134 :
135 0 : int16_t SX1280::finishRanging() {
136 : // start by clearing interrupt flags
137 0 : int16_t state = clearIrqStatus();
138 0 : RADIOLIB_ASSERT(state);
139 :
140 : // set mode to standby
141 0 : state = standby();
142 0 : RADIOLIB_ASSERT(state);
143 :
144 : // restore back to LoRa communication
145 : // config sets up the bare minimum
146 0 : state = config(RADIOLIB_SX128X_PACKET_TYPE_LORA);
147 0 : RADIOLIB_ASSERT(state);
148 :
149 : // restore modulation and packet parameters and we're done
150 0 : state = setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRateLoRa);
151 0 : RADIOLIB_ASSERT(state);
152 0 : return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa));
153 : }
154 :
155 0 : int32_t SX1280::getRangingResultRaw() {
156 0 : return(getRangingResultCommon(false));
157 : }
158 :
159 0 : float SX1280::getRangingResult() {
160 0 : int32_t raw = getRangingResultCommon(false);
161 0 : return((float)raw * 150.0f / (4.096f * this->bandwidthKhz));
162 : }
163 :
164 0 : int32_t SX1280::getRangingResultCommon(bool filtered) {
165 : // set mode to standby XOSC
166 0 : int16_t state = standby(RADIOLIB_SX128X_STANDBY_XOSC);
167 0 : RADIOLIB_ASSERT(state);
168 :
169 : // enable clock
170 0 : uint8_t data[3] = { 0 };
171 0 : state = readRegister(RADIOLIB_SX128X_REG_RANGING_LORA_CLOCK_ENABLE, data, 1);
172 0 : RADIOLIB_ASSERT(state);
173 :
174 0 : data[0] |= (1 << 1);
175 0 : state = writeRegister(RADIOLIB_SX128X_REG_RANGING_LORA_CLOCK_ENABLE, data, 1);
176 0 : RADIOLIB_ASSERT(state);
177 :
178 : // set result type filtered/raw
179 : // TODO: at the moment, filtered values do not work and just return huge numbers
180 : // the datasheet also isn't exactly clear on how to use the filtering
181 : // (when to reset, when are samples added etc.)
182 0 : state = readRegister(RADIOLIB_SX128X_REG_RANGING_TYPE, data, 1);
183 0 : RADIOLIB_ASSERT(state);
184 :
185 0 : data[0] &= 0xCF;
186 0 : data[0] |= ((uint8_t)filtered << 4);
187 0 : state = writeRegister(RADIOLIB_SX128X_REG_RANGING_TYPE, data, 1);
188 0 : RADIOLIB_ASSERT(state);
189 :
190 : // read the register values
191 0 : state = readRegister(RADIOLIB_SX128X_REG_RANGING_RESULT_MSB, data, 3);
192 0 : RADIOLIB_ASSERT(state);
193 :
194 : // set mode to standby RC
195 0 : state = standby();
196 0 : RADIOLIB_ASSERT(state);
197 :
198 : // shifting everything by 8 bits more to the left will convert the result to signed number
199 0 : int32_t raw = ((((int32_t)data[0]) << 24) | (((int32_t)data[1]) << 16) | (((int32_t)data[2]) << 8)) >> 8;
200 0 : return(raw);
201 : }
202 :
203 : #endif
|