1
0
mirror of https://github.com/sandeepmistry/arduino-LoRa.git synced 2025-04-19 13:02:14 +03:00
arduino-LoRa/src/LoRa.cpp
2016-08-21 12:22:38 -04:00

268 lines
5.4 KiB
C++

#include <LoRa.h>
// registers
#define REG_FIFO 0x00
#define REG_OP_MODE 0x01
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
#define REG_PA_CONFIG 0x09
#define REG_FIFO_ADDR_PTR 0x0d
#define REG_FIFO_TX_BASE_ADDR 0x0e
#define REG_FIFO_RX_BASE_ADDR 0x0f
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS 0x12
#define REG_RX_NB_BYTES 0x13
#define REG_PKT_RSSI_VALUE 0x1a
#define REG_PAYLOAD_LENGTH 0x22
#define REG_VERSION 0x42
// modes
#define MODE_LONG_RANGE_MODE 0x80
#define MODE_SLEEP 0x00
#define MODE_STDBY 0x01
#define MODE_TX 0x03
#define MODE_RX_SINGLE 0x06
// PA config
#define PA_BOOST 0x80
// IRQ masks
#define IRQ_TX_DONE_MASK 0x08
#define IRQ_RX_DONE_MASK 0x40
#define MAX_PKT_LENGTH 255
LoRaClass::LoRaClass() :
_spiSettings(10E6, MSBFIRST, SPI_MODE0),
_ss(10), _reset(9),
_packetIndex(0)
{
}
int LoRaClass::begin(long frequency)
{
// setup pins
pinMode(_ss, OUTPUT);
pinMode(_reset, OUTPUT);
// perform reset
digitalWrite(_reset, LOW);
delay(10);
digitalWrite(_reset, HIGH);
delay(10);
// set SS high
digitalWrite(_ss, HIGH);
// start SPI
SPI.begin();
// check version
uint8_t version = readRegister(REG_VERSION);
if (version != 0x12) {
return 0;
}
// put in sleep mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
// set frequency
uint64_t frf = ((uint64_t)frequency << 19) / 32000000;
writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
// set base addresses
writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
// set output power to 17 dBm
writeRegister(REG_PA_CONFIG, PA_BOOST | 0x0f);
// put in standby mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
return 1;
}
void LoRaClass::end()
{
// put in sleep mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
// stop SPI
SPI.end();
}
int LoRaClass::beginPacket()
{
// put in standby mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
// reset FIFO address and paload length
writeRegister(REG_FIFO_ADDR_PTR, 0);
writeRegister(REG_PAYLOAD_LENGTH, 0);
return 1;
}
int LoRaClass::endPacket()
{
// put in TX mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
// wait for TX done
while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0);
// clear IRQ's
writeRegister(REG_IRQ_FLAGS, 0xff);
return 1;
}
int LoRaClass::parsePacket()
{
int packetLength = 0;
int irqFlags = readRegister(REG_IRQ_FLAGS);
// clear IRQ's
writeRegister(REG_IRQ_FLAGS, 0xff);
if (irqFlags & IRQ_RX_DONE_MASK) {
// received a packet
_packetIndex = 0;
// read packet length
packetLength = readRegister(REG_RX_NB_BYTES);
// set FIFO address to current RX address
writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
// put in standby mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
} else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
// not currently in RX mode
// reset FIFO address
writeRegister(REG_FIFO_ADDR_PTR, 0);
// put in single RX mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
}
return packetLength;
}
int LoRaClass::packetRSSI()
{
return (readRegister(REG_PKT_RSSI_VALUE) - 164);
}
size_t LoRaClass::write(uint8_t byte)
{
return write(&byte, sizeof(byte));
}
size_t LoRaClass::write(const uint8_t *buffer, size_t size)
{
int currentLength = readRegister(REG_PAYLOAD_LENGTH);
// check size
if ((currentLength + size) > MAX_PKT_LENGTH) {
size = MAX_PKT_LENGTH - currentLength;
}
// write data
for (size_t i = 0; i < size; i++) {
writeRegister(REG_FIFO, buffer[i]);
}
// update length
writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
return size;
}
int LoRaClass::available()
{
return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
}
int LoRaClass::read()
{
if (!available()) {
return -1;
}
_packetIndex++;
return readRegister(REG_FIFO);
}
int LoRaClass::peek()
{
if (!available()) {
return -1;
}
// store current FIFO address
int currentAddress = readRegister(REG_FIFO_ADDR_PTR);
// read
uint8_t b = readRegister(REG_FIFO);
// restore FIFO address
writeRegister(REG_FIFO_ADDR_PTR, currentAddress);
return b;
}
void LoRaClass::flush()
{
}
void LoRaClass::setPins(int ss, int reset)
{
_ss = ss;
_reset = reset;
}
void LoRaClass::dumpRegisters(Stream& out)
{
for (int i = 0; i < 128; i++) {
out.print("0x");
out.print(i, HEX);
out.print(": 0x");
out.println(readRegister(i), HEX);
}
}
uint8_t LoRaClass::readRegister(uint8_t address)
{
return singleTransfer(address & 0x7f, 0x00);
}
void LoRaClass::writeRegister(uint8_t address, uint8_t value)
{
singleTransfer(address | 0x80, value);
}
uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
{
uint8_t response;
digitalWrite(_ss, LOW);
SPI.beginTransaction(_spiSettings);
SPI.transfer(address);
response = SPI.transfer(value);
SPI.endTransaction();
digitalWrite(_ss, HIGH);
return response;
}
LoRaClass LoRa;