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