Skip to content

Commit 038378c

Browse files
committed
Add initial library source
1 parent e4f8b51 commit 038378c

File tree

2 files changed

+308
-0
lines changed

2 files changed

+308
-0
lines changed

src/LoRa.cpp

+260
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
#include <LoRa.h>
2+
3+
// registers
4+
#define REG_FIFO 0x00
5+
#define REG_OP_MODE 0x01
6+
#define REG_FRF_MSB 0x06
7+
#define REG_FRF_MID 0x07
8+
#define REG_FRF_LSB 0x08
9+
#define REG_FIFO_ADDR_PTR 0x0d
10+
#define REG_FIFO_TX_BASE_ADDR 0x0e
11+
#define REG_FIFO_RX_BASE_ADDR 0x0f
12+
#define REG_FIFO_RX_CURRENT_ADDR 0x10
13+
#define REG_IRQ_FLAGS 0x12
14+
#define REG_RX_NB_BYTES 0x13
15+
#define REG_PKT_RSSI_VALUE 0x1a
16+
#define REG_PAYLOAD_LENGTH 0x22
17+
#define REG_VERSION 0x42
18+
19+
// modes
20+
#define MODE_LONG_RANGE_MODE 0x80
21+
#define MODE_SLEEP 0x00
22+
#define MODE_STDBY 0x01
23+
#define MODE_TX 0x03
24+
#define MODE_RX_SINGLE 0x06
25+
26+
// IRQ masks
27+
#define IRQ_TX_DONE_MASK 0x08
28+
#define IRQ_RX_DONE_MASK 0x40
29+
30+
#define MAX_PKT_LENGTH 255
31+
32+
LoRaClass::LoRaClass() :
33+
_spiSettings(10E6, MSBFIRST, SPI_MODE0),
34+
_ss(10), _reset(9),
35+
_packetIndex(0)
36+
{
37+
}
38+
39+
int LoRaClass::begin(long frequency)
40+
{
41+
// setup pins
42+
pinMode(_ss, OUTPUT);
43+
pinMode(_reset, OUTPUT);
44+
45+
// perform reset
46+
digitalWrite(_reset, LOW);
47+
delay(10);
48+
digitalWrite(_reset, HIGH);
49+
delay(10);
50+
51+
// set SS high
52+
digitalWrite(_ss, HIGH);
53+
54+
// start SPI
55+
SPI.begin();
56+
57+
// check version
58+
uint8_t version = readRegister(REG_VERSION);
59+
if (version != 0x12) {
60+
return 0;
61+
}
62+
63+
// put in sleep mode
64+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
65+
66+
// set frequency
67+
uint64_t frf = ((uint64_t)frequency << 19) / 32000000;
68+
writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
69+
writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
70+
writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
71+
72+
// set base addresses
73+
writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
74+
writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
75+
76+
// put in standby mode
77+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
78+
79+
return 1;
80+
}
81+
82+
void LoRaClass::end()
83+
{
84+
// put in sleep mode
85+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
86+
87+
// stop SPI
88+
SPI.end();
89+
}
90+
91+
int LoRaClass::beginPacket()
92+
{
93+
// put in standby mode
94+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
95+
96+
// reset FIFO address and paload length
97+
writeRegister(REG_FIFO_ADDR_PTR, 0);
98+
writeRegister(REG_PAYLOAD_LENGTH, 0);
99+
100+
return 1;
101+
}
102+
103+
int LoRaClass::endPacket()
104+
{
105+
// put in TX mode
106+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
107+
108+
// wait for TX done
109+
while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0);
110+
111+
// clear IRQ's
112+
writeRegister(REG_IRQ_FLAGS, 0xff);
113+
114+
return 1;
115+
}
116+
117+
int LoRaClass::parsePacket()
118+
{
119+
int packetLength = 0;
120+
int irqFlags = readRegister(REG_IRQ_FLAGS);
121+
122+
// clear IRQ's
123+
writeRegister(REG_IRQ_FLAGS, 0xff);
124+
125+
if (irqFlags & IRQ_RX_DONE_MASK) {
126+
// received a packet
127+
_packetIndex = 0;
128+
129+
// read packet length
130+
packetLength = readRegister(REG_RX_NB_BYTES);
131+
132+
// set FIFO address to current RX address
133+
writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
134+
135+
// put in standby mode
136+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
137+
} else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
138+
// not currently in RX mode
139+
140+
// reset FIFO address
141+
writeRegister(REG_FIFO_ADDR_PTR, 0);
142+
143+
// put in single RX mode
144+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
145+
}
146+
147+
return packetLength;
148+
}
149+
150+
int LoRaClass::packetRSSI()
151+
{
152+
return (readRegister(REG_PKT_RSSI_VALUE) - 164);
153+
}
154+
155+
size_t LoRaClass::write(uint8_t byte)
156+
{
157+
return write(&byte, sizeof(byte));
158+
}
159+
160+
size_t LoRaClass::write(const uint8_t *buffer, size_t size)
161+
{
162+
int currentLength = readRegister(REG_PAYLOAD_LENGTH);
163+
164+
// check size
165+
if ((currentLength + size) > MAX_PKT_LENGTH) {
166+
size = MAX_PKT_LENGTH - currentLength;
167+
}
168+
169+
// write data
170+
for (size_t i = 0; i < size; i++) {
171+
writeRegister(REG_FIFO, buffer[i]);
172+
}
173+
174+
// update length
175+
writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
176+
177+
return size;
178+
}
179+
180+
int LoRaClass::available()
181+
{
182+
return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
183+
}
184+
185+
int LoRaClass::read()
186+
{
187+
if (!available()) {
188+
return -1;
189+
}
190+
191+
_packetIndex++;
192+
193+
return readRegister(REG_FIFO);
194+
}
195+
196+
int LoRaClass::peek()
197+
{
198+
if (!available()) {
199+
return -1;
200+
}
201+
202+
// store current FIFO address
203+
int currentAddress = readRegister(REG_FIFO_ADDR_PTR);
204+
205+
// read
206+
uint8_t b = readRegister(REG_FIFO);
207+
208+
// restore FIFO address
209+
writeRegister(REG_FIFO_ADDR_PTR, currentAddress);
210+
211+
return b;
212+
}
213+
214+
void LoRaClass::flush()
215+
{
216+
}
217+
218+
void LoRaClass::setPins(int ss, int reset)
219+
{
220+
_ss = ss;
221+
_reset = reset;
222+
}
223+
224+
void LoRaClass::dumpRegisters(Stream& out)
225+
{
226+
for (int i = 0; i < 128; i++) {
227+
out.print("0x");
228+
out.print(i, HEX);
229+
out.print(": 0x");
230+
out.println(readRegister(i), HEX);
231+
}
232+
}
233+
234+
uint8_t LoRaClass::readRegister(uint8_t address)
235+
{
236+
return singleTransfer(address & 0x7f, 0x00);
237+
}
238+
239+
void LoRaClass::writeRegister(uint8_t address, uint8_t value)
240+
{
241+
singleTransfer(address | 0x80, value);
242+
}
243+
244+
uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
245+
{
246+
uint8_t response;
247+
248+
digitalWrite(_ss, LOW);
249+
250+
SPI.beginTransaction(_spiSettings);
251+
SPI.transfer(address);
252+
response = SPI.transfer(value);
253+
SPI.endTransaction();
254+
255+
digitalWrite(_ss, HIGH);
256+
257+
return response;
258+
}
259+
260+
LoRaClass LoRa;

src/LoRa.h

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef LORA_H
2+
#define LORA_H
3+
4+
#include <Arduino.h>
5+
#include <SPI.h>
6+
7+
class LoRaClass : public Stream {
8+
public:
9+
LoRaClass();
10+
11+
int begin(long frequency);
12+
void end();
13+
14+
int beginPacket();
15+
int endPacket();
16+
17+
int parsePacket();
18+
int packetRSSI();
19+
20+
// from Print
21+
virtual size_t write(uint8_t byte);
22+
virtual size_t write(const uint8_t *buffer, size_t size);
23+
24+
// from Stream
25+
virtual int available();
26+
virtual int read();
27+
virtual int peek();
28+
virtual void flush();
29+
30+
void setPins(int ss, int reset);
31+
32+
void dumpRegisters(Stream& out);
33+
34+
private:
35+
uint8_t readRegister(uint8_t address);
36+
void writeRegister(uint8_t address, uint8_t value);
37+
uint8_t singleTransfer(uint8_t address, uint8_t value);
38+
39+
private:
40+
SPISettings _spiSettings;
41+
int _ss;
42+
int _reset;
43+
int _packetIndex;
44+
};
45+
46+
extern LoRaClass LoRa;
47+
48+
#endif

0 commit comments

Comments
 (0)