Line data Source code
1 : #include "LR2021.h"
2 :
3 : #include "../LR11x0/LR_common.h"
4 : #include "LR2021_registers.h"
5 :
6 : #include <string.h>
7 : #include <math.h>
8 :
9 : #if !RADIOLIB_EXCLUDE_LR2021
10 :
11 0 : int16_t LR2021::readRadioRxFifo(uint8_t* data, size_t len) {
12 : // FIFO read is just a single transaction sent without the status code
13 0 : this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_0;
14 0 : int16_t state = this->mod->SPIreadStream(RADIOLIB_LR2021_CMD_READ_RX_FIFO, data, len, true, false);
15 0 : this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_16;
16 0 : return(state);
17 : }
18 :
19 0 : int16_t LR2021::writeRadioTxFifo(const uint8_t* data, size_t len) {
20 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_WRITE_TX_FIFO, true, const_cast<uint8_t*>(data), len, NULL, 0));
21 : }
22 :
23 0 : int16_t LR2021::writeRegMem32(uint32_t addr, const uint32_t* data, size_t len) {
24 : // check maximum size
25 0 : if(len > (RADIOLIB_LRXXXX_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
26 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
27 : }
28 0 : return(this->writeCommon(RADIOLIB_LR2021_CMD_WRITE_REG_MEM_32, addr, data, len, false));
29 : }
30 :
31 0 : int16_t LR2021::writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data) {
32 : uint8_t buff[11] = {
33 0 : (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF),
34 0 : (uint8_t)((mask >> 24) & 0xFF), (uint8_t)((mask >> 16) & 0xFF), (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF),
35 0 : (uint8_t)((data >> 24) & 0xFF), (uint8_t)((data >> 16) & 0xFF), (uint8_t)((data >> 8) & 0xFF), (uint8_t)(data & 0xFF),
36 0 : };
37 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_WRITE_REG_MEM_MASK_32, true, buff, sizeof(buff)));
38 : }
39 :
40 0 : int16_t LR2021::readRegMem32(uint32_t addr, uint32_t* data, size_t len) {
41 : // check maximum size
42 0 : if(len > (RADIOLIB_LRXXXX_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
43 0 : return(RADIOLIB_ERR_SPI_CMD_INVALID);
44 : }
45 :
46 : // the request contains the address and length
47 : uint8_t reqBuff[4] = {
48 0 : (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF),
49 : (uint8_t)(addr & 0xFF), (uint8_t)len,
50 0 : };
51 :
52 : // build buffers - later we need to ensure endians are correct,
53 : // so there is probably no way to do this without copying buffers and iterating
54 : #if RADIOLIB_STATIC_ONLY
55 : uint8_t rplBuff[RADIOLIB_LRXXXX_SPI_MAX_READ_WRITE_LEN];
56 : #else
57 0 : uint8_t* rplBuff = new uint8_t[len*sizeof(uint32_t)];
58 : #endif
59 :
60 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_READ_REG_MEM_32, false, rplBuff, len*sizeof(uint32_t), reqBuff, sizeof(reqBuff));
61 :
62 : // convert endians
63 0 : if(data && (state == RADIOLIB_ERR_NONE)) {
64 0 : for(size_t i = 0; i < len; i++) {
65 0 : data[i] = ((uint32_t)rplBuff[2 + i*sizeof(uint32_t)] << 24) | ((uint32_t)rplBuff[3 + i*sizeof(uint32_t)] << 16) | ((uint32_t)rplBuff[4 + i*sizeof(uint32_t)] << 8) | (uint32_t)rplBuff[5 + i*sizeof(uint32_t)];
66 : }
67 : }
68 :
69 : #if !RADIOLIB_STATIC_ONLY
70 0 : delete[] rplBuff;
71 : #endif
72 :
73 0 : return(state);
74 : }
75 :
76 0 : int16_t LR2021::setFs(void) {
77 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_FS, true, NULL, 0));
78 : }
79 :
80 0 : int16_t LR2021::setAdditionalRegToRetain(uint8_t slot, uint32_t addr) {
81 : uint8_t buff[] = {
82 0 : slot, (uint8_t)((addr >> 16) & 0xFF),
83 0 : (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF),
84 0 : };
85 :
86 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_ADDITIONAL_REG_TO_RETAIN, true, buff, sizeof(buff)));
87 : }
88 :
89 1 : int16_t LR2021::setRx(uint32_t timeout) {
90 : uint8_t buff[] = {
91 1 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
92 1 : };
93 2 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_RX, true, buff, sizeof(buff)));
94 : }
95 :
96 0 : int16_t LR2021::setTx(uint32_t timeout) {
97 : uint8_t buff[] = {
98 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
99 0 : };
100 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_TX, true, buff, sizeof(buff)));
101 : }
102 :
103 0 : int16_t LR2021::setRxTxFallbackMode(uint8_t mode) {
104 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_RX_TX_FALLBACK_MODE, true, &mode, sizeof(mode)));
105 : }
106 :
107 0 : int16_t LR2021::setRxDutyCycle(uint32_t rxMaxTime, uint32_t cycleTime, uint8_t cfg) {
108 : uint8_t buff[] = {
109 0 : (uint8_t)((rxMaxTime >> 16) & 0xFF), (uint8_t)((rxMaxTime >> 8) & 0xFF), (uint8_t)(rxMaxTime & 0xFF),
110 0 : (uint8_t)((cycleTime >> 16) & 0xFF), (uint8_t)((cycleTime >> 8) & 0xFF), (uint8_t)(cycleTime & 0xFF),
111 : cfg
112 0 : };
113 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_RX_DUTY_CYCLE, true, buff, sizeof(buff)));
114 : }
115 :
116 0 : int16_t LR2021::autoTxRx(uint32_t delay, uint8_t mode, uint32_t timeout) {
117 : uint8_t buff[] = {
118 0 : (uint8_t)((delay >> 16) & 0xFF), (uint8_t)((delay >> 8) & 0xFF), (uint8_t)(delay & 0xFF), mode,
119 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
120 0 : };
121 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_AUTO_RX_TX, true, buff, sizeof(buff)));
122 : }
123 :
124 1 : int16_t LR2021::getRxPktLength(uint16_t* len) {
125 1 : uint8_t buff[2] = { 0 };
126 1 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_RX_PKT_LENGTH, false, buff, sizeof(buff));
127 1 : if(len) { *len = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
128 1 : return(state);
129 : }
130 :
131 0 : int16_t LR2021::resetRxStats(void) {
132 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_RESET_RX_STATS, true, NULL, 0));
133 : }
134 :
135 0 : int16_t LR2021::setDefaultRxTxTimeout(uint32_t rxTimeout, uint32_t txTimeout) {
136 : uint8_t buff[] = {
137 0 : (uint8_t)((rxTimeout >> 16) & 0xFF), (uint8_t)((rxTimeout >> 8) & 0xFF), (uint8_t)(rxTimeout & 0xFF),
138 0 : (uint8_t)((txTimeout >> 16) & 0xFF), (uint8_t)((txTimeout >> 8) & 0xFF), (uint8_t)(txTimeout & 0xFF),
139 0 : };
140 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_DEFAULT_RX_TX_TIMEOUT, true, buff, sizeof(buff)));
141 : }
142 :
143 0 : int16_t LR2021::setRegMode(uint8_t simoUsage, const uint8_t rampTimes[4]) {
144 : uint8_t buff[] = { simoUsage,
145 0 : rampTimes[RADIOLIB_LR2021_REG_MODE_RAMP_INDEX_RC2RU], rampTimes[RADIOLIB_LR2021_REG_MODE_RAMP_INDEX_TX2RU],
146 0 : rampTimes[RADIOLIB_LR2021_REG_MODE_RAMP_INDEX_RU2RC], rampTimes[RADIOLIB_LR2021_REG_MODE_RAMP_INDEX_RAMP_DOWN],
147 0 : };
148 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_REG_MODE, true, buff, sizeof(buff)));
149 : }
150 :
151 0 : int16_t LR2021::calibrate(uint8_t blocks) {
152 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CALIBRATE, true, &blocks, sizeof(blocks)));
153 : }
154 :
155 0 : int16_t LR2021::calibrateFrontEnd(const uint16_t freq[3]) {
156 : uint8_t buff[] = {
157 0 : (uint8_t)((freq[0] >> 8) & 0xFF), (uint8_t)(freq[0] & 0xFF),
158 0 : (uint8_t)((freq[1] >> 8) & 0xFF), (uint8_t)(freq[1] & 0xFF),
159 0 : (uint8_t)((freq[2] >> 8) & 0xFF), (uint8_t)(freq[2] & 0xFF),
160 0 : };
161 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CALIB_FRONT_END, true, buff, sizeof(buff)));
162 : }
163 :
164 0 : int16_t LR2021::getVbat(uint8_t resolution, uint16_t* vbat) {
165 0 : uint8_t reqBuff[] = { (uint8_t)(RADIOLIB_LR2021_VBAT_FORMAT_MV | ((RADIOLIB_LR2021_MEAS_RESOLUTION_OFFSET + resolution) & 0x07)) };
166 0 : uint8_t rplBuff[2] = { 0 };
167 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_V_BAT, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
168 0 : if(vbat) { *vbat = ((uint16_t)(rplBuff[0]) << 8) | (uint16_t)rplBuff[1]; }
169 0 : return(state);
170 : }
171 :
172 0 : int16_t LR2021::getTemp(uint8_t source, uint8_t resolution, float* temp) {
173 0 : uint8_t reqBuff[] = { (uint8_t)((source & 0x30) | RADIOLIB_LR2021_TEMP_FORMAT_DEG_C | ((RADIOLIB_LR2021_MEAS_RESOLUTION_OFFSET + resolution) & 0x07)) };
174 0 : uint8_t rplBuff[2] = { 0 };
175 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_TEMP, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
176 0 : if(temp) {
177 0 : uint16_t raw = ((uint16_t)(rplBuff[0]) << 8) | (uint16_t)rplBuff[1];
178 0 : *temp = (float)raw/320.0f;
179 : }
180 0 : return(state);
181 : }
182 :
183 0 : int16_t LR2021::setEolConfig(bool enable, uint8_t trim) {
184 0 : uint8_t buff[] = { (uint8_t)((trim & 0x06) | (uint8_t)enable) };
185 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_EOL_CONFIG, true, buff, sizeof(buff)));
186 : }
187 :
188 1 : int16_t LR2021::getRandomNumber(uint32_t* rnd) {
189 1 : uint8_t buff[4] = { 0 };
190 1 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_RANDOM_NUMBER, false, buff, sizeof(buff));
191 1 : if(rnd) { *rnd = ((uint32_t)(buff[0]) << 24) | ((uint32_t)(buff[1]) << 16) | ((uint32_t)(buff[2]) << 8) | (uint32_t)buff[3]; }
192 1 : return(state);
193 : }
194 :
195 0 : int16_t LR2021::getVersion(uint8_t* major, uint8_t* minor) {
196 0 : uint8_t buff[2] = { 0 };
197 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_VERSION, false, buff, sizeof(buff));
198 0 : if(major) { *major = buff[0]; }
199 0 : if(minor) { *minor = buff[1]; }
200 0 : return(state);
201 : }
202 :
203 0 : int16_t LR2021::clearErrors(void) {
204 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CLEAR_ERRORS, true, NULL, 0));
205 : }
206 :
207 0 : int16_t LR2021::getErrors(uint16_t* err) {
208 0 : uint8_t buff[2] = { 0 };
209 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_ERRORS, false, buff, sizeof(buff));
210 0 : if(err) { *err = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
211 0 : return(state);
212 : }
213 :
214 0 : int16_t LR2021::setDioFunction(uint8_t dio, uint8_t func, uint8_t pullDrive) {
215 0 : uint8_t buff[] = { dio, (uint8_t)((func & 0xF0) | (pullDrive & 0x0F)) };
216 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_DIO_FUNCTION, true, buff, sizeof(buff)));
217 : }
218 :
219 0 : int16_t LR2021::setDioRfSwitchConfig(uint8_t dio, uint8_t func) {
220 0 : uint8_t buff[] = { dio, func };
221 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_DIO_RF_SWITCH_CONFIG, true, buff, sizeof(buff)));
222 : }
223 :
224 1 : int16_t LR2021::setDioIrqConfig(uint8_t dio, uint32_t irq) {
225 : uint8_t buff[] = { dio,
226 1 : (uint8_t)((irq >> 24) & 0xFF), (uint8_t)((irq >> 16) & 0xFF),
227 1 : (uint8_t)((irq >> 8) & 0xFF), (uint8_t)(irq & 0xFF),
228 1 : };
229 2 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_DIO_IRQ_CONFIG, true, buff, sizeof(buff)));
230 : }
231 :
232 2 : int16_t LR2021::clearIrqState(uint32_t irq) {
233 2 : return(this->setU32(RADIOLIB_LR2021_CMD_CLEAR_IRQ, irq));
234 : }
235 :
236 0 : int16_t LR2021::getAndClearIrqStatus(uint32_t* irq) {
237 0 : uint8_t buff[4] = { 0 };
238 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_AND_CLEAR_IRQ_STATUS, false, buff, sizeof(buff));
239 0 : if(irq) { *irq = ((uint32_t)(buff[0]) << 24) | ((uint32_t)(buff[1]) << 16) | ((uint32_t)(buff[2]) << 8) |(uint32_t)buff[3]; }
240 0 : return(state);
241 : }
242 :
243 0 : int16_t LR2021::configFifoIrq(uint8_t rxFifoIrq, uint8_t txFifoIrq, uint8_t rxHighThreshold, uint8_t txHighThreshold) {
244 0 : uint8_t buff[] = { rxFifoIrq, txFifoIrq, rxHighThreshold, txHighThreshold };
245 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CONFIG_FIFO_IRQ, true, buff, sizeof(buff)));
246 : }
247 :
248 0 : int16_t LR2021::getFifoIrqFlags(uint8_t* rxFifoFlags, uint8_t* txFifoFlags) {
249 0 : uint8_t buff[2] = { 0 };
250 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_FIFO_IRQ_FLAGS, false, buff, sizeof(buff));
251 0 : if(rxFifoFlags) { *rxFifoFlags = buff[0]; }
252 0 : if(txFifoFlags) { *txFifoFlags = buff[1]; }
253 0 : return(state);
254 : }
255 :
256 0 : int16_t LR2021::clearFifoIrqFlags(uint8_t rxFifoFlags, uint8_t txFifoFlags) {
257 0 : uint8_t buff[] = { rxFifoFlags, txFifoFlags };
258 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CLEAR_FIFO_IRQ_FLAGS, true, buff, sizeof(buff)));
259 : }
260 :
261 0 : int16_t LR2021::getAndClearFifoIrqFlags(uint8_t* rxFifoFlags, uint8_t* txFifoFlags) {
262 0 : uint8_t buff[2] = { 0 };
263 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_AND_CLEAR_FIFO_IRQ_FLAGS, false, buff, sizeof(buff));
264 0 : if(rxFifoFlags) { *rxFifoFlags = buff[0]; }
265 0 : if(txFifoFlags) { *txFifoFlags = buff[1]; }
266 0 : return(state);
267 : }
268 :
269 0 : int16_t LR2021::getRxFifoLevel(uint16_t* level) {
270 0 : uint8_t buff[2] = { 0 };
271 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_RX_FIFO_LEVEL, false, buff, sizeof(buff));
272 0 : if(level) { *level = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
273 0 : return(state);
274 : }
275 :
276 0 : int16_t LR2021::getTxFifoLevel(uint16_t* level) {
277 0 : uint8_t buff[2] = { 0 };
278 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_TX_FIFO_LEVEL, false, buff, sizeof(buff));
279 0 : if(level) { *level = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
280 0 : return(state);
281 : }
282 :
283 0 : int16_t LR2021::clearRxFifo(void) {
284 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CLEAR_RX_FIFO, true, NULL, 0));
285 : }
286 :
287 0 : int16_t LR2021::clearTxFifo(void) {
288 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CLEAR_TX_FIFO, true, NULL, 0));
289 : }
290 :
291 0 : int16_t LR2021::configLfClock(uint8_t cfg) {
292 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CONFIG_LF_CLOCK, true, &cfg, sizeof(cfg)));
293 : }
294 :
295 0 : int16_t LR2021::configClkOutputs(uint8_t scaling) {
296 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_CONFIG_CLK_OUTPUTS, true, &scaling, sizeof(scaling)));
297 : }
298 :
299 0 : int16_t LR2021::setTcxoMode(uint8_t tune, uint32_t startTime) {
300 0 : uint8_t buff[] = { (uint8_t)(tune & 0x07),
301 0 : (uint8_t)((startTime >> 24) & 0xFF), (uint8_t)((startTime >> 16) & 0xFF),
302 0 : (uint8_t)((startTime >> 8) & 0xFF), (uint8_t)(startTime & 0xFF),
303 0 : };
304 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_TCXO_MODE, true, buff, sizeof(buff)));
305 : }
306 :
307 0 : int16_t LR2021::setXoscCpTrim(uint8_t xta, uint8_t xtb, uint8_t startTime) {
308 0 : uint8_t buff[] = { (uint8_t)(xta & 0x3F), (uint8_t)(xtb & 0x3F), startTime };
309 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_XOSC_CP_TRIM, true, buff, sizeof(buff)));
310 : }
311 :
312 0 : int16_t LR2021::activatePram(void) {
313 0 : uint8_t buff[] = { RADIOLIB_LR2021_CMD_NOP };
314 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_ACTIVATE_PRAM, true, buff, sizeof(buff)));
315 : }
316 :
317 0 : int16_t LR2021::checkPramLoaded(bool* loaded) {
318 0 : uint32_t val = 0;
319 0 : int16_t state = this->readRegMem32(RADIOLIB_LR2021_PRAM_ADDR_LOADED, &val, 1);
320 0 : if(loaded) { *loaded = (val == RADIOLIB_LR2021_PRAM_LOADED_MAGIC); }
321 0 : return(state);
322 : }
323 :
324 0 : int16_t LR2021::getPramVersion(uint16_t* version) {
325 0 : uint32_t val = 0;
326 0 : int16_t state = this->readRegMem32(RADIOLIB_LR2021_PRAM_ADDR_VERSION, &val, 1);
327 0 : if(version) { *version = ((val >>8) & 0xFFFF); }
328 0 : return(state);
329 : }
330 :
331 : #endif
|