#include <SPI.h>
#define SERIAL_SPEED 9600
#define LORA_FREQ 869.525
#define STATE_SLEEP 0
#define STATE_STANDBY 1
#define STATE_FSRX 4
#define STATE_RX 5
#define S_DELAY 10
#define L_DELAY 100
#define RX_BUFFER_LEN 255
#define SX_FREQ "Frequency "
#define SX_VERSION "Chip version "
#define PRINT_MODEM_STAT
#undef PRINT_MODEM_STAT
#define RegFifo 0x00
#define RegOpMode 0x01
#define RegFrMsb 0x06
#define RegFrMid 0x07
#define RegFrLsb 0x08
#define RegFifoRxCurrentAddr 0x10
#define RegFifoAddrPtr 0x0D
#define RegIrqFlagsMask 0x11
#define RegIrqFlags 0x12
#define RegRxNbBytes 0x13
#define RegModemStat 0x18
#define RegPktSnrValue 0x19
#define RegPktRssiValue 0x1A
#define RegRssiValue 0x1B
#define RegHopChannel 0x1C
#define RegModemConfig1 0x1D
#define RegModemConfig2 0x1E
#define RegVersion 0x42
#define SX_OSC_FREQ 32000000
#define SX_RESET 9
#define SX_RESET_DELAY_H 5
#define SX_RESET_DELAY_L 100
#define SPI_SS 10
#define SPI_RW_DELAY 50
uint8_t modemStat;
uint8_t rxBuffer[RX_BUFFER_LEN];
void setup() {
Serial.begin(SERIAL_SPEED);
if (initSX()) {
memset(rxBuffer, 0, RX_BUFFER_LEN);
uint8_t r = readSPI(RegVersion);
Serial.print(F(SX_VERSION));
char strVer[4];
snprintf(strVer, 4, "%1u.%1u", r >> 4 , r & 0x0F);
Serial.println(strVer);
Serial.println();
startLora();
setFreq(LORA_FREQ);
Serial.print(F(SX_FREQ));
Serial.println(LORA_FREQ, DEC);
// Set SF12, CR 4/5, explicit header mode
r = readSPI(RegModemConfig2);
r = r & B11000000;
writeSPI(RegModemConfig2, r);
// Set BW 125 kHz
r = readSPI(RegModemConfig1);
bitSet(r, 6); bitSet(r, 5); bitSet(r, 4);
writeSPI(RegModemConfig1, r);
setState(STATE_FSRX);
delay(L_DELAY);
setState(STATE_RX);
delay(S_DELAY);
#ifdef PRINT_MODEM_STAT
modemStat = readSPI(RegModemStat);
Serial.println();
Serial.print(F("Modem status: "));
Serial.print("\t");
Serial.print(modemStat, BIN);
Serial.println();
#endif
}
}
void loop() {
uint8_t r;
#ifdef PRINT_MODEM_STAT
r = readSPI(RegModemStat);
if (r != modemStat) {
modemStat = r;
Serial.println();
Serial.print(F("Modem status: "));
Serial.print("\t");
Serial.print(r, BIN);
Serial.println();
}
#endif
if (getRxState() == 1) {
r = readFifo(rxBuffer, RX_BUFFER_LEN);
if (r > 0) {
Serial.println();
for (uint8_t i = 0; i < r; i++) {
Serial.print(rxBuffer[i], HEX);
}
Serial.println();
}
clearLoraIrqFlags();
memset(rxBuffer, 0, RX_BUFFER_LEN);
}
}
void setFreq(float f)
{
uint32_t lf = (f * 1000000) / 61.035;
writeSPI(RegFrMsb, (lf >> 16) & 0xff);
writeSPI(RegFrMid, (lf >> 8) & 0xff);
writeSPI(RegFrLsb, lf & 0xff);
}
void setState(uint8_t s) {
uint8_t b = readSPI(RegOpMode);
bitClear(b, 2);
bitClear(b, 1);
bitClear(b, 0);
switch (s) {
case STATE_SLEEP:
{
break;
}
case STATE_STANDBY:
{
bitSet(b, 0);
break;
}
case STATE_FSRX:
{
bitSet(b, 2);
break;
}
case STATE_RX:
{
bitSet(b, 2);
bitSet(b, 0);
break;
}
}
writeSPI(RegOpMode, b);
}
void startLora()
{
setState(STATE_SLEEP);
uint8_t b = readSPI(RegOpMode);
bitSet(b, 7);
writeSPI(RegOpMode, b);
}
uint8_t getLoraIrqFlag(uint8_t v) {
return bitRead(readSPI(RegIrqFlags), v);
}
void clearLoraIrqFlag(uint8_t v) {
uint8_t b = readSPI(RegIrqFlags);
bitSet(b, v);
writeSPI(RegIrqFlags, b);
}
void clearLoraIrqFlags() {
writeSPI(RegIrqFlags, 0xFF);
}
int16_t pktRssiValue() {
return (int16_t) (-164 + readSPI(RegPktRssiValue));
}
int16_t rssiValue() {
return (int16_t) (-164 + readSPI(RegRssiValue));
}
uint8_t lastPktSnrValue()
{
return (readSPI(RegPktSnrValue) >> 2);
}
int8_t getRxState() {
uint8_t b = readSPI(RegIrqFlags);
if (bitRead(b, 6)) {
return 1; // packet rx
}
if (bitRead(b, 7)) {
return -1; // timeout
}
return 0;
}
void discardFifo()
{
uint8_t b = readSPI(RegFifoRxCurrentAddr);
writeSPI(RegFifoAddrPtr, b);
uint8_t n = readSPI(RegRxNbBytes);
writeSPI(RegFifoAddrPtr, 0);
for (b = 0; b < n; b++) {
readSPI(RegFifo);
}
}
uint8_t readFifo(uint8_t buf[], uint8_t buf_len)
{
uint8_t l = 0;
writeSPI(RegFifoAddrPtr, readSPI(RegFifoRxCurrentAddr));
uint8_t n = readSPI(RegRxNbBytes);
if (buf_len < n) {
l = buf_len;
}
else {
l = n;
}
uint8_t i;
for(i = 0; i < l; i++) {
buf[i] = readSPI(RegFifo);
}
uint8_t cnt = n - buf_len;
if (cnt > 0) {
for (i = 0; i < cnt; i++) {
readSPI(RegFifo);
}
}
return l;
}
// Parse LoRa class B device beacon (RX2) downlink message
// https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5038744/
void parseLoraMsg(uint8_t rxPacket[]) {
uint16_t i;
Serial.println(F("PHYPayload MHDR:"));
Serial.print(F("MType: "));
Serial.print((rxPacket[0] & B11100000) >> 5);
Serial.print("\t");
Serial.print(F("RFU: "));
Serial.print((rxPacket[0] & B00011100) >> 2);
Serial.print("\t");
Serial.print(F("Major: "));
Serial.println(rxPacket[0] & B00000011);
Serial.println(F("MACPayload FHDR: "));
Serial.print(F("DevAddr: "));
for (i = 1; i < 5; i++) {
Serial.print(rxPacket[i]);
}
Serial.println("");
Serial.print((rxPacket[1] & B11111110) >> 1);
Serial.println("");
Serial.print(F("FCtrl:\tADR: "));
Serial.print((rxPacket[5] & B10000000) >> 7);
Serial.print(F(" ADRAckReq: "));
Serial.print((rxPacket[5] & B01000000) >> 6);
Serial.print(F(" ACK: "));
Serial.print((rxPacket[5] & B00100000) >> 5);
Serial.print(F(" RFU: "));
Serial.print((rxPacket[5] & B00010000) >> 4);
Serial.print(F(" FOptsLen: "));
uint8_t foptslen = rxPacket[5] & B00001111;
Serial.println(foptslen);
Serial.print(F("FCnt: "));
Serial.print(rxPacket[6]);
Serial.print(rxPacket[7]);
if (foptslen > 0) {
Serial.println("");
Serial.print(F("FOpts: (MACCommand(s) byte 1: CID, bytes 2-4: Args) "));
for (i = 8; i < (8 + foptslen); i++) {
Serial.print(rxPacket[i]);
}
foptslen = i;
}
else {
foptslen = 8;
}
Serial.println("");
Serial.print(F("FPort: "));
Serial.print(rxPacket[foptslen]);
}
bool initSX() {
pinMode(SX_RESET, OUTPUT);
resetSX();
initSPI();
if (readSPI(RegVersion) == 0) {
return false;
}
setState(STATE_STANDBY);
return true;
}
void resetSX() {
digitalWrite(SX_RESET, LOW);
delayMicroseconds(SX_RESET_DELAY_L);
digitalWrite(SX_RESET, HIGH);
delay(SX_RESET_DELAY_H);
}
uint8_t readSPI(uint8_t addr) {
digitalWrite(SPI_SS, LOW);
SPI.transfer(addr);
delayMicroseconds(SPI_RW_DELAY);
uint8_t v = SPI.transfer(0x00);
digitalWrite(SPI_SS, HIGH);
return v;
}
void writeSPI(uint8_t addr, uint8_t v) {
digitalWrite(SPI_SS, LOW);
SPI.transfer(addr | 0x80);
delayMicroseconds(SPI_RW_DELAY);
SPI.transfer(v);
digitalWrite(SPI_SS, HIGH);
}
void initSPI()
{
digitalWrite(SPI_SS, HIGH);
pinMode(SPI_SS, OUTPUT);
SPI.begin();
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
}
Kommentit
Tämän blogin kommentit tarkistetaan ennen julkaisua.