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::setLoRaModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro) {
11 : // calculate symbol length and enable low data rate optimization, if auto-configuration is enabled
12 0 : if(this->ldroAuto) {
13 0 : uint64_t symbolLengthUs = ((uint64_t)1000000 * ((uint64_t)1 << this->spreadingFactor)) / (uint64_t)this->bandwidthHz;
14 : // LDRO on SX128x seems to be working differently to sub-GHz LoRa, as it is always needed for SF > 10
15 : // if SX128x bandwidth is being used at 2.4 GHz, we use this approach instead of the symbol time to preserve compatibility
16 0 : bool sx128xLdro = this->highFreq && ((bw >= RADIOLIB_LR2021_LORA_BW_203) || (bw <= RADIOLIB_LR2021_LORA_BW_812)) && (sf > 10);
17 0 : if((symbolLengthUs >= 16000) || sx128xLdro) {
18 0 : this->ldrOptimize = RADIOLIB_LR2021_LORA_LDRO_ENABLED;
19 : } else {
20 0 : this->ldrOptimize = RADIOLIB_LR2021_LORA_LDRO_DISABLED;
21 : }
22 : } else {
23 0 : this->ldrOptimize = ldro;
24 : }
25 :
26 0 : uint8_t buff[] = { (uint8_t)(((sf & 0x0F) << 4) | (bw & 0x0F)), (uint8_t)(((cr & 0x0F) << 4) | this->ldrOptimize) };
27 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_MODULATION_PARAMS, true, buff, sizeof(buff));
28 0 : if (state == RADIOLIB_ERR_NONE) {
29 0 : state = this->setDCDCworkaround();
30 : }
31 0 : return(state);
32 : }
33 :
34 0 : int16_t LR2021::setLoRaPacketParams(uint16_t preambleLen, uint8_t hdrType, uint8_t payloadLen, uint8_t crcType, uint8_t invertIQ) {
35 : uint8_t buff[] = {
36 0 : (uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF), payloadLen,
37 0 : (uint8_t)(((hdrType & 0x01) << 2) | ((crcType & 0x01) << 1) | (invertIQ & 0x01)),
38 0 : };
39 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_PACKET_PARAMS, true, buff, sizeof(buff)));
40 : }
41 :
42 0 : int16_t LR2021::setLoRaSynchTimeout(uint16_t numSymbols) {
43 0 : bool mantissa = false;
44 0 : uint8_t val = 0;
45 0 : if(numSymbols <= 0xFF) {
46 0 : val = numSymbols;
47 : } else {
48 0 : uint16_t mant = numSymbols >> 1;
49 0 : uint8_t exp = 0;
50 0 : while(mant > 31) {
51 0 : mant = (mant + 3) >> 2;
52 0 : exp++;
53 : }
54 0 : mantissa = true;
55 0 : val = (mant << 3) + exp;
56 : }
57 0 : uint8_t buff[2] = { val, (uint8_t)mantissa };
58 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_SYNCH_TIMEOUT, true, buff, sizeof(buff)));
59 : }
60 :
61 0 : int16_t LR2021::setLoRaSyncword(uint8_t syncword) {
62 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_SYNCWORD, true, &syncword, sizeof(syncword)));
63 : }
64 :
65 0 : int16_t LR2021::setLoRaSideDetConfig(uint8_t* configs, size_t numSideDets) {
66 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_SIDE_DET_CONFIG, true, configs, numSideDets));
67 : }
68 :
69 0 : int16_t LR2021::setLoRaSideDetSyncword(uint8_t* syncwords, size_t numSideDets) {
70 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_SIDE_DET_SYNCWORD, true, syncwords, numSideDets));
71 : }
72 :
73 0 : int16_t LR2021::setLoRaCadParams(uint8_t numSymbols, bool preambleOnly, uint8_t pnrDelta, uint8_t cadExitMode, uint32_t timeout, uint8_t detPeak) {
74 : uint8_t buff[] = {
75 0 : numSymbols, (uint8_t)(((uint8_t)preambleOnly << 4) | (pnrDelta & 0x0F)), cadExitMode,
76 0 : (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
77 0 : (uint8_t)(detPeak & 0x7F)
78 0 : };
79 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_CAD_PARAMS, true, buff, sizeof(buff)));
80 : }
81 :
82 0 : int16_t LR2021::setLoRaCad(void) {
83 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_CAD, true, NULL, 0));
84 : }
85 :
86 0 : int16_t LR2021::getLoRaRxStats(uint16_t* pktRxTotal, uint16_t* pktCrcError, uint16_t* headerCrcError, uint16_t* falseSynch) {
87 0 : uint8_t buff[8] = { 0 };
88 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_LORA_RX_STATS, false, buff, sizeof(buff));
89 0 : if(pktRxTotal) { *pktRxTotal = ((uint16_t)(buff[0]) << 8) | (uint16_t)buff[1]; }
90 0 : if(pktCrcError) { *pktCrcError = ((uint16_t)(buff[2]) << 8) | (uint16_t)buff[3]; }
91 0 : if(headerCrcError) { *headerCrcError = ((uint16_t)(buff[4]) << 8) | (uint16_t)buff[5]; }
92 0 : if(falseSynch) { *falseSynch = ((uint16_t)(buff[6]) << 8) | (uint16_t)buff[7]; }
93 0 : return(state);
94 : }
95 :
96 0 : int16_t LR2021::getLoRaPacketStatus(uint8_t* cr, bool* crc, uint8_t* packetLen, float* snrPacket, float* rssiPacket, float* rssiSignalPacket, uint8_t* detector, int32_t* freqError) {
97 0 : uint8_t buff[9] = { 0 };
98 0 : int16_t state = this->SPIcommand(RADIOLIB_LR2021_CMD_GET_LORA_PACKET_STATUS, false, buff, sizeof(buff));
99 : uint32_t raw;
100 0 : if(crc) { *crc = (buff[0] & 0x10) >> 4; }
101 0 : if(cr) { *cr = buff[0] & 0x0F; }
102 0 : if(packetLen) { *packetLen = buff[1]; }
103 0 : if(snrPacket) { *snrPacket = (float)((int8_t)buff[2]) * 0.25f; }
104 0 : if(rssiPacket) {
105 0 : raw = (uint16_t)buff[3] << 1;
106 0 : raw |= (buff[5] & 0x02) >> 1;
107 0 : *rssiPacket = (float)raw * -0.5f;
108 : }
109 0 : if(rssiSignalPacket) {
110 0 : raw = (uint16_t)buff[4] << 1;
111 0 : raw |= buff[5] & 0x01;
112 0 : *rssiSignalPacket = (float)raw * -0.5f;
113 : }
114 0 : if(detector) {
115 0 : uint8_t det = (buff[5] >> 2) & 0x0F;
116 0 : if(det == 0x01) { *detector = 0; }
117 0 : else if(det == 0x02) { *detector = 1; }
118 0 : else if(det == 0x04) { *detector = 2; }
119 0 : else if(det == 0x08) { *detector = 3; }
120 : }
121 0 : if(freqError) {
122 0 : raw = (uint32_t)buff[6] << 16;
123 0 : raw |= (uint32_t)buff[7] << 8;
124 0 : raw |= buff[8];
125 0 : *freqError = (int32_t)((raw ^ 0x800000UL) - 0x800000UL);
126 : }
127 0 : return(state);
128 : }
129 :
130 0 : int16_t LR2021::setLoRaAddress(uint8_t addrLen, uint8_t addrPos, const uint8_t* addr) {
131 0 : if(addrLen > 8) { return(RADIOLIB_ERR_UNKNOWN); }
132 0 : uint8_t buff[9] = { (uint8_t)(((addrLen & 0x0F) << 4) | (addrPos & 0x0F)) };
133 0 : memcpy(&buff[1], addr, addrLen);
134 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_ADDRESS, true, buff, sizeof(buff)));
135 : }
136 :
137 0 : int16_t LR2021::setLoRaHopping(uint8_t hopCtrl, uint16_t hopPeriod, const uint32_t* freqHops, size_t numFreqHops) {
138 0 : if(numFreqHops > 40) { return(RADIOLIB_ERR_UNKNOWN); }
139 0 : uint8_t buff[2 + 160] = { (uint8_t)(hopCtrl | ((hopPeriod & 0xF00) >> 8)), (uint8_t)(hopPeriod & 0xFF) };
140 0 : for(uint8_t i = 0; i < numFreqHops; i++) {
141 0 : buff[i + 2] = (freqHops[i] >> 24) & 0xFF;
142 0 : buff[i + 3] = (freqHops[i] >> 16) & 0xFF;
143 0 : buff[i + 4] = (freqHops[i] >> 8) & 0xFF;
144 0 : buff[i + 5] = freqHops[i] & 0xFF;
145 : }
146 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_HOPPING, true, buff, sizeof(buff)));
147 : }
148 :
149 0 : int16_t LR2021::setLoRaTxSync(uint8_t function, uint8_t dioNum) {
150 0 : uint8_t buff[] = { (uint8_t)(function | (dioNum & 0x3F)) };
151 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_TX_SYNC, true, buff, sizeof(buff)));
152 : }
153 :
154 0 : int16_t LR2021::setLoRaSideDetCad(const uint8_t* pnrDelta, const uint8_t* detPeak, size_t numSideDets) {
155 0 : uint8_t buff[6] = { 0 };
156 0 : for(size_t i = 0; i < numSideDets; i++) {
157 0 : if(i >= 3) { return(RADIOLIB_ERR_UNKNOWN); }
158 0 : buff[2*i] = pnrDelta[i] & 0x0F;
159 0 : buff[2*i + 1] = detPeak[i] & 0x7F;
160 : }
161 0 : return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_LORA_SIDE_DET_CAD, true, buff, 2*numSideDets));
162 : }
163 :
164 : #endif
|