LoRa/WiFi Gateway Code, MAX32620FTHR Side

Files at this revision

API Documentation at this revision

Comitter:
gov1
Date:
Tue Jul 31 16:36:17 2018 +0000
Commit message:
LoRa/WiFi Gateway Code, MAX32620FTHR Side

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
LoRa.cpp Show annotated file Show diff for this revision Revisions of this file
LoRa.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b24cccf38c35 .gitignore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Tue Jul 31 16:36:17 2018 +0000
@@ -0,0 +1,4 @@
+.build
+.mbed
+projectfiles
+*.py*
diff -r 000000000000 -r b24cccf38c35 LoRa.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LoRa.cpp	Tue Jul 31 16:36:17 2018 +0000
@@ -0,0 +1,487 @@
+#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_LNA                  0x0c
+#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_PKT_SNR_VALUE        0x1b
+#define REG_MODEM_CONFIG_1       0x1d
+#define REG_MODEM_CONFIG_2       0x1e
+#define REG_PREAMBLE_MSB         0x20
+#define REG_PREAMBLE_LSB         0x21
+#define REG_PAYLOAD_LENGTH       0x22
+#define REG_MODEM_CONFIG_3       0x26
+#define REG_RSSI_WIDEBAND        0x2c
+#define REG_DETECTION_OPTIMIZE   0x31
+#define REG_DETECTION_THRESHOLD  0x37
+#define REG_SYNC_WORD            0x39
+#define REG_DIO_MAPPING_1        0x40
+#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_CONTINUOUS       0x05
+#define MODE_RX_SINGLE           0x06
+
+// PA config
+#define PA_BOOST                 0x80
+
+// IRQ masks
+#define IRQ_TX_DONE_MASK           0x08
+#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
+#define IRQ_RX_DONE_MASK           0x40
+
+#define MAX_PKT_LENGTH           255
+
+SPI _spi(P5_1, P5_2, P5_0);
+
+LoRaClass::LoRaClass() :
+  spi(_spi),
+  _ss(LORA_DEFAULT_SS_PIN ), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
+  _frequency(0),
+  _packetIndex(0),
+  _implicitHeaderMode(0),
+  _onReceive(NULL)
+{
+  // overide Stream timeout value
+  //setTimeout(0);
+}
+
+int LoRaClass::begin(long frequency)
+{
+  // perform reset
+  _reset = 0;
+  wait(0.010);
+  _reset = 1;
+  wait(0.010);
+
+  // set SS high
+  _ss = 1;
+
+  // check version
+  uint8_t version = readRegister(REG_VERSION);
+  if (version != 0x12) {
+    return 0;
+  }
+
+  // put in sleep mode
+  sleep();
+
+  // set frequency
+  setFrequency(frequency);
+
+  // set base addresses
+  writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
+  writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
+
+  // set LNA boost
+  writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
+
+  // set auto AGC
+  writeRegister(REG_MODEM_CONFIG_3, 0x04);
+
+  // set output power to 17 dBm
+  setTxPower(17);
+
+  // put in standby mode
+  idle();
+
+  return 1;
+}
+
+void LoRaClass::end()
+{
+  // put in sleep mode
+  sleep();
+}
+
+int LoRaClass::beginPacket(int implicitHeader)
+{
+  // put in standby mode
+  idle();
+
+  if (implicitHeader) {
+    implicitHeaderMode();
+  } else {
+    explicitHeaderMode();
+  }
+
+  // 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, IRQ_TX_DONE_MASK);
+
+  return 1;
+}
+
+int LoRaClass::parsePacket(int size)
+{
+  int packetLength = 0;
+  int irqFlags = readRegister(REG_IRQ_FLAGS);
+
+  if (size > 0) {
+    implicitHeaderMode();
+
+    writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
+  } else {
+    explicitHeaderMode();
+  }
+
+  // clear IRQ's
+  writeRegister(REG_IRQ_FLAGS, irqFlags);
+
+  if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
+    // received a packet
+    _packetIndex = 0;
+
+    // read packet length
+    if (_implicitHeaderMode) {
+      packetLength = readRegister(REG_PAYLOAD_LENGTH);
+    } else {
+      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
+    idle();
+  } 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) - (_frequency < 868E6 ? 164 : 157));
+}
+
+float LoRaClass::packetSnr()
+{
+  return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25;
+}
+
+int LoRaClass::_putc(int value)
+{
+  char buf = (char) value;
+  size_t size = sizeof(buf);
+  int currentLength = readRegister(REG_PAYLOAD_LENGTH);
+
+  // check size
+  if ((currentLength + size) > MAX_PKT_LENGTH) {
+    size = MAX_PKT_LENGTH - currentLength;
+  }
+
+  writeRegister(REG_FIFO, buf);
+
+  // update length
+  writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
+  
+  return (int) buf;
+}
+
+int LoRaClass::available()
+{
+  return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
+}
+
+int LoRaClass::_getc()
+{
+  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::onReceive(void(*callback)(int))
+{
+  _onReceive = callback;
+
+  if (callback) {
+    writeRegister(REG_DIO_MAPPING_1, 0x00);
+
+    //attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING);
+    _dio0.rise(&LoRaClass::onDio0Rise);
+  } else {
+    //detachInterrupt(digitalPinToInterrupt(_dio0));
+    _dio0.rise(NULL);
+  }
+}
+
+void LoRaClass::receive(int size)
+{
+  if (size > 0) {
+    implicitHeaderMode();
+
+    writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
+  } else {
+    explicitHeaderMode();
+  }
+
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
+}
+
+void LoRaClass::idle()
+{
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
+}
+
+void LoRaClass::sleep()
+{
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
+}
+
+void LoRaClass::setTxPower(int level, int outputPin)
+{
+  if (PA_OUTPUT_RFO_PIN == outputPin) {
+    // RFO
+    if (level < 0) {
+      level = 0;
+    } else if (level > 14) {
+      level = 14;
+    }
+
+    writeRegister(REG_PA_CONFIG, 0x70 | level);
+  } else {
+    // PA BOOST
+    if (level < 2) {
+      level = 2;
+    } else if (level > 17) {
+      level = 17;
+    }
+
+    writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
+  }
+}
+
+void LoRaClass::setFrequency(long frequency)
+{
+  _frequency = 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));
+}
+
+void LoRaClass::setSpreadingFactor(int sf)
+{
+  if (sf < 6) {
+    sf = 6;
+  } else if (sf > 12) {
+    sf = 12;
+  }
+
+  if (sf == 6) {
+    writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
+    writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
+  } else {
+    writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
+    writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
+  }
+
+  writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
+}
+
+void LoRaClass::setSignalBandwidth(long sbw)
+{
+  int bw;
+
+  if (sbw <= 7.8E3) {
+    bw = 0;
+  } else if (sbw <= 10.4E3) {
+    bw = 1;
+  } else if (sbw <= 15.6E3) {
+    bw = 2;
+  } else if (sbw <= 20.8E3) {
+    bw = 3;
+  } else if (sbw <= 31.25E3) {
+    bw = 4;
+  } else if (sbw <= 41.7E3) {
+    bw = 5;
+  } else if (sbw <= 62.5E3) {
+    bw = 6;
+  } else if (sbw <= 125E3) {
+    bw = 7;
+  } else if (sbw <= 250E3) {
+    bw = 8;
+  } else /*if (sbw <= 250E3)*/ {
+    bw = 9;
+  }
+
+  writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4));
+}
+
+void LoRaClass::setCodingRate4(int denominator)
+{
+  if (denominator < 5) {
+    denominator = 5;
+  } else if (denominator > 8) {
+    denominator = 8;
+  }
+
+  int cr = denominator - 4;
+
+  writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1));
+}
+
+void LoRaClass::setPreambleLength(long length)
+{
+  writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8));
+  writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0));
+}
+
+void LoRaClass::setSyncWord(int sw)
+{
+  writeRegister(REG_SYNC_WORD, sw);
+}
+
+void LoRaClass::enableCrc()
+{
+  writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04);
+}
+
+void LoRaClass::disableCrc()
+{
+  writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb);
+}
+
+uint8_t LoRaClass::random()
+{
+  return readRegister(REG_RSSI_WIDEBAND);
+}
+
+void LoRaClass::dumpRegisters(Stream& out)
+{
+  for (int i = 0; i < 128; i++) {
+    out.printf("0x%x: 0x%x", i, readRegister(i));
+  }
+}
+
+void LoRaClass::explicitHeaderMode()
+{
+  _implicitHeaderMode = 0;
+
+  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
+}
+
+void LoRaClass::implicitHeaderMode()
+{
+  _implicitHeaderMode = 1;
+
+  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
+}
+
+void LoRaClass::handleDio0Rise()
+{
+  int irqFlags = readRegister(REG_IRQ_FLAGS);
+
+  // clear IRQ's
+  writeRegister(REG_IRQ_FLAGS, irqFlags);
+
+  if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
+    // received a packet
+    _packetIndex = 0;
+
+    // read packet length
+    int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES);
+
+    // set FIFO address to current RX address
+    writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
+
+    if (_onReceive) {
+      _onReceive(packetLength);
+    }
+
+    // reset FIFO address
+    writeRegister(REG_FIFO_ADDR_PTR, 0);
+  }
+}
+
+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;
+
+  _ss = 0;
+
+  spi.write(address);
+  response = spi.write(value);
+
+  _ss = 1;
+
+  return response;
+}
+
+void LoRaClass::onDio0Rise()
+{
+  LoRa.handleDio0Rise();
+}
+
+LoRaClass LoRa;
diff -r 000000000000 -r b24cccf38c35 LoRa.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LoRa.h	Tue Jul 31 16:36:17 2018 +0000
@@ -0,0 +1,89 @@
+#ifndef LORA_H
+#define LORA_H
+
+#include "mbed.h"
+
+#define LORA_DEFAULT_SS_PIN    P5_4
+#define LORA_DEFAULT_RESET_PIN P5_5
+#define LORA_DEFAULT_DIO0_PIN  P3_3
+
+#define PA_OUTPUT_RFO_PIN      0
+#define PA_OUTPUT_PA_BOOST_PIN 1
+
+class LoRaClass: public Stream
+{
+public:
+    LoRaClass();
+
+    int begin(long frequency);
+    void end();
+
+    int beginPacket(int implicitHeader = false);
+    int endPacket();
+
+    int parsePacket(int size = 0);
+    int packetRssi();
+    float packetSnr();
+
+    void onReceive(void(*callback)(int));
+
+    void receive(int size = 0);
+    void idle();
+    void sleep();
+
+    void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
+    void setFrequency(long frequency);
+    void setSpreadingFactor(int sf);
+    void setSignalBandwidth(long sbw);
+    void setCodingRate4(int denominator);
+    void setPreambleLength(long length);
+    void setSyncWord(int sw);
+    void enableCrc();
+    void disableCrc();
+
+    // deprecated
+    void crc() {
+        enableCrc();
+    }
+    void noCrc() {
+        disableCrc();
+    }
+
+    uint8_t random();
+
+    void dumpRegisters(Stream& out);
+
+//protected:
+    // from Print
+    virtual int _putc(int value);
+    virtual int _getc();
+
+    int available();
+    int peek();
+
+private:
+    void explicitHeaderMode();
+    void implicitHeaderMode();
+
+    void handleDio0Rise();
+
+    uint8_t readRegister(uint8_t address);
+    void writeRegister(uint8_t address, uint8_t value);
+    uint8_t singleTransfer(uint8_t address, uint8_t value);
+
+    static void onDio0Rise();
+
+private:
+    SPI &spi;
+    DigitalOut _ss;
+    DigitalOut _reset;
+    InterruptIn _dio0;
+    int _frequency;
+    int _packetIndex;
+    int _implicitHeaderMode;
+    void (*_onReceive)(int);
+};
+
+extern LoRaClass LoRa;
+
+#endif
diff -r 000000000000 -r b24cccf38c35 README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Tue Jul 31 16:36:17 2018 +0000
@@ -0,0 +1,57 @@
+# Getting started with Blinky on mbed OS
+
+This guide reviews the steps required to get Blinky working on an mbed OS platform.
+
+Please install [mbed CLI](https://github.com/ARMmbed/mbed-cli#installing-mbed-cli).
+
+## Import the example application
+
+From the command-line, import the example:
+
+```
+mbed import mbed-os-example-blinky
+cd mbed-os-example-blinky
+```
+
+### Now compile
+
+Invoke `mbed compile`, and specify the name of your platform and your favorite toolchain (`GCC_ARM`, `ARM`, `IAR`). For example, for the ARM Compiler 5:
+
+```
+mbed compile -m K64F -t ARM
+```
+
+Your PC may take a few minutes to compile your code. At the end, you see the following result:
+
+```
+[snip]
++----------------------------+-------+-------+------+
+| Module                     | .text | .data | .bss |
++----------------------------+-------+-------+------+
+| Misc                       | 13939 |    24 | 1372 |
+| core/hal                   | 16993 |    96 |  296 |
+| core/rtos                  |  7384 |    92 | 4204 |
+| features/FEATURE_IPV4      |    80 |     0 |  176 |
+| frameworks/greentea-client |  1830 |    60 |   44 |
+| frameworks/utest           |  2392 |   512 |  292 |
+| Subtotals                  | 42618 |   784 | 6384 |
++----------------------------+-------+-------+------+
+Allocated Heap: unknown
+Allocated Stack: unknown
+Total Static RAM memory (data + bss): 7168 bytes
+Total RAM memory (data + bss + heap + stack): 7168 bytes
+Total Flash memory (text + data + misc): 43402 bytes
+Image: .\.build\K64F\ARM\mbed-os-example-blinky.bin
+```
+
+### Program your board
+
+1. Connect your mbed device to the computer over USB.
+1. Copy the binary file to the mbed device.
+1. Press the reset button to start the program.
+
+The LED on your platform turns on and off.
+
+## Troubleshooting
+
+If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.
diff -r 000000000000 -r b24cccf38c35 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jul 31 16:36:17 2018 +0000
@@ -0,0 +1,70 @@
+#include "mbed.h"
+#include "LoRa.h"
+#include "UARTSerial.h"
+
+DigitalOut  idle(LED2);
+DigitalOut  receiving(LED1);
+
+Serial pc(USBTX, USBRX);
+Serial _serial(P3_1, P3_0,9600);
+
+
+int counter = 0;
+
+void onReceive(int packetSize);
+
+main()
+{
+    // setup
+    pc.printf("LoRa Callback Rx . . .\n");
+    if (!LoRa.begin(915E6))
+    {
+        pc.printf("LoRa Radio not Found!\n");
+    } else { 
+        pc.printf("LoRa Radio Started.\n");
+    }
+    idle = true;
+    LoRa.onReceive(onReceive);
+    LoRa.receive();
+    
+    //loop
+    while(1)
+    {
+        // do nothing
+    }
+}
+
+void onReceive(int packetSize)
+{
+    idle = false;
+    char msg[45];
+    pc.printf("PACKET RECEIVED, SIZE:%d \n", packetSize);
+    // pc.printf("MSG[0]: %c \n", msg[0]);
+    // pc.printf("MSG[1]: %c \n", msg[1]);
+    // pc.printf("MSG[2]: %c \n", msg[2]);
+    // pc.printf("MSG[3]: %c \n", msg[3]);
+    // pc.printf("MSG[4]: %c \n", msg[4]);
+    for (int i = 0; i<packetSize; i++)
+    {   
+        if ( i < 45) 
+        {
+            msg[i] = (char)LoRa._getc();
+        }
+        receiving = !receiving;
+    }
+    if (msg[0] == '1')
+    {
+        // indicates this message comes from the canary!
+        pc.printf("received from 0\n");
+        _serial.printf("%s\n", msg);
+    } 
+    else {
+        pc.printf("dont know who this was from\n");    
+    }
+    pc.printf("MSG: %s, ",msg);
+    pc.printf("RSSI:  %d\n", LoRa.packetRssi());
+    // _serial.printf("%s\n", msg);
+    receiving = false;
+    idle = true;
+}
+
diff -r 000000000000 -r b24cccf38c35 mbed-os.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Tue Jul 31 16:36:17 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#ae6c7c60f91c89cbf755a2f3c8ec9c66635849fd