summaryrefslogtreecommitdiff
path: root/src/app/lora32u4ii/main.cc
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2021-09-23 22:22:47 +0200
committerDaniel Friesel <derf@finalrewind.org>2021-09-23 22:22:47 +0200
commit8578e1ea7d078b60864b084094dbb02b6cac99c3 (patch)
tree19a02eef376f5b89c7044c48dcc0c0f43ea9d416 /src/app/lora32u4ii/main.cc
parent30a29dcd0d064ab8403a9afb32c59800bb346840 (diff)
Import partially adapted MCCI LoRaWAN LMIC library. Needs further work.
Diffstat (limited to 'src/app/lora32u4ii/main.cc')
-rw-r--r--src/app/lora32u4ii/main.cc234
1 files changed, 146 insertions, 88 deletions
diff --git a/src/app/lora32u4ii/main.cc b/src/app/lora32u4ii/main.cc
index b44652b..bb7cdae 100644
--- a/src/app/lora32u4ii/main.cc
+++ b/src/app/lora32u4ii/main.cc
@@ -8,16 +8,33 @@
#include "driver/stdout.h"
#include "driver/uptime.h"
#include "driver/adc.h"
-#include "driver/spi.h"
+
+/*
+ * Work in progress! Joining is sometimes successful, but that's about it.
+ * TX with user-defined payloads after joining doesn't appear to work yet.
+ */
#define CFG_eu868 1
#define CFG_sx1276_radio 1
+#define DISABLE_LMIC_FAILURE_TO
+
+#include <lmic.h>
+#include <hal/hal.h>
+
+static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
-#include "radio.h"
-#include "oslmic.h"
+static const u1_t PROGMEM DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
-unsigned char txbuf[4];
-unsigned char rxbuf[4];
+static const u1_t PROGMEM APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
+
+// Schedule TX every this many seconds (might become longer due to duty
+// cycle limitations).
+const unsigned TX_INTERVAL = 10;
+
+bool joined = false;
// DIYMall BSFrance LoRa32u4 II v1.3
// See also: arduino packages/adafruit/hardware/avr/1.4.13/variants/feather32u4/pins_arduino.h
@@ -25,95 +42,128 @@ unsigned char rxbuf[4];
// PB0 is also the !SS pin, so it must be configured as output in order to use SPI.
// PB5 "D9" <- Vbat/2 via voltage divider. Appears to also have a connection to the user LED
// PC7 "D13" -> User LED
-const GPIO::Pin rstpin = GPIO::pd4; // "D4" -> RST
-const GPIO::Pin cspin = GPIO::pb4; // "D8" -> NSS
-const GPIO::Pin dio0pin = GPIO::pe6; // "D7" <- DIO0 / IRQ
-const GPIO::Pin dio1pin = GPIO::pc6; // "D5" <- DIO1
-
-static void writeReg (u1_t addr, u1_t data) {
- txbuf[0] = addr | 0x80;
- txbuf[1] = data;
- gpio.write(cspin, 0);
- spi.xmit(2, txbuf, 0, rxbuf);
- gpio.write(cspin, 1);
-}
-
-static u1_t readReg (u1_t addr) {
- txbuf[0] = addr & 0x7f;
- gpio.write(cspin, 0);
- spi.xmit(1, txbuf, 2, rxbuf);
- gpio.write(cspin, 1);
- return rxbuf[1];
-}
-/*
-static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) {
- txbuf[0] = addr | 0x80;
- for (uint8_t i = 0; i < len; i++) {
- txbuf[i+1] = buf[i];
+const lmic_pinmap lmic_pins = {
+ .nss = GPIO::pb4,
+ .rxtx = LMIC_UNUSED_PIN,
+ .rst = GPIO::pd4,
+ .dio = {GPIO::pe6, GPIO::pc6, LMIC_UNUSED_PIN},
+};
+
+static osjob_t sendjob;
+
+void do_send(osjob_t* j){
+ uint16_t bat = adc.getVBat_mV(false);
+
+ // Check if there is not a current TX/RX job running
+ if (LMIC.opmode & OP_TXRXPEND) {
+ kout.pprint(PSTR("OP_TXRXPEND\n"));
+ } else {
+ // Prepare upstream data transmission at the next possible time.
+ LMIC_setTxData2(1, (uint8_t *)&bat, sizeof(bat), 0);
+ kout.pprint(PSTR("Packet queued\n"));
}
- spi.xmit(len+1, txbuf, 0, rxbuf);
+ // Next TX is scheduled after TX_COMPLETE event.
}
-static void readBuf (u1_t addr, xref2u1_t buf, u1_t len) {
- txbuf[0] = addr & 0x7f;
- spi.xmit(1, txbuf, len, buf);
-}
-*/
+void do_sleep(){
+ kout.pprint(PSTR("naptime\n"));
-static void writeOpmode(u1_t mode) {
- u1_t const maskedMode = mode & OPMODE_MASK;
- writeReg(RegOpMode, mode);
+ for(int i=0; i<75; i++){
+ arch.idle();
+ }
}
-static void opmode (u1_t mode) {
- writeOpmode((readReg(RegOpMode) & ~OPMODE_MASK) | mode);
-}
-
-
-
-bool radio_init()
-{
- // requestModuleActive(1); not required for sx yadayada
- gpio.output(cspin, 1);
-#ifdef CFG_sx1276_radio
- gpio.output(rstpin, 0);
-#else
- gpio.output(rstpin, 1);
-#endif
- arch.delay_ms(1);
- gpio.input(rstpin);
- gpio.write(rstpin, 0); // disable pull-up
- arch.delay_ms(5);
- opmode(OPMODE_SLEEP);
-
- u1_t v = readReg(RegVersion);
-#ifdef CFG_sx1276_radio
- if(v != 0x12 ) {
- kout << "Radio version mismatch: expected " << hex << 0x12 << ", got " << v << endl;
- return false;
- }
-#elif CFG_sx1272_radio
- if(v != 0x22) {
- kout << "Radio version mismatch: expected " << hex << 0x22 << ", got " << v << endl;
- return false;
- }
-#else
-#error Missing CFG_sx1272_radio/CFG_sx1276_radio
-#endif
- return true;
+void onEvent (ev_t ev) {
+ switch(ev) {
+ case EV_SCAN_TIMEOUT:
+ kout.pprint(PSTR("EV_SCAN_TIMEOUT\n"));
+ break;
+ case EV_JOINING:
+ kout.pprint(PSTR("EV_JOINING\n"));
+ break;
+ case EV_JOINED:
+ kout.pprint(PSTR("EV_JOINED\n"));
+ #if 1
+ {
+ u4_t netid = 0;
+ devaddr_t devaddr = 0;
+ u1_t nwkKey[16];
+ u1_t artKey[16];
+ LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
+ kout.pprint(PSTR("netid: "));
+ kout << dec << netid << endl;
+ kout.pprint(PSTR("devaddr: "));
+ kout << hex << devaddr << endl;
+ //Serial.print(PSTR("AppSKey: "));
+ for (size_t i=0; i<sizeof(artKey); ++i) {
+ if (i != 0) {
+ //Serial.print(PSTR("-"));
+ }
+ //printHex2(artKey[i]);
+ }
+ kout.pprint(PSTR(""));
+ //Serial.print(PSTR("NwkSKey: "));
+ for (size_t i=0; i<sizeof(nwkKey); ++i) {
+ if (i != 0) {
+ //Serial.print("-");
+ }
+ //printHex2(nwkKey[i]);
+ }
+ kout << endl;
+ }
+ #endif
+ joined = true;
+ break;
+ case EV_JOIN_FAILED:
+ kout.pprint(PSTR("EV_JOIN_FAILED\n"));
+ break;
+ case EV_TXCOMPLETE:
+ kout.pprint(PSTR("EV_TXCOMPLETE (includes waiting for RX windows)\n"));
+ // Schedule next transmission
+ if (joined) {
+ do_sleep();
+ do_send(&sendjob);
+ } else {
+ os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
+ }
+ break;
+ case EV_RESET:
+ kout.pprint(PSTR("EV_RESET\n"));
+ break;
+ case EV_RXCOMPLETE:
+ // data received in ping slot
+ kout.pprint(PSTR("EV_RXCOMPLETE\n"));
+ break;
+ case EV_LINK_DEAD:
+ kout.pprint(PSTR("EV_LINK_DEAD\n"));
+ break;
+ case EV_LINK_ALIVE:
+ kout.pprint(PSTR("EV_LINK_ALIVE\n"));
+ break;
+ case EV_TXSTART:
+ kout.pprint(PSTR("EV_TXSTART\n"));
+ break;
+ case EV_TXCANCELED:
+ kout.pprint(PSTR("EV_TXCANCELED\n"));
+ break;
+ case EV_RXSTART:
+ /* do not print anything -- it wrecks timing */
+ break;
+ case EV_JOIN_TXCOMPLETE:
+ kout.pprint(PSTR("EV_JOIN_TXCOMPLETE: no JoinAccept\n"));
+ break;
+
+ default:
+ kout.pprint(PSTR("Unknown event: "));
+ kout << (unsigned) ev;
+ break;
+ }
}
void loop(void)
{
- //gpio.led_toggle(1);
-#ifdef TIMER_S
- kout << dec << uptime.get_s() << endl;
-#else
- kout << "beep boop" << endl;
-#endif
- kout << "VCC = " << adc.getVCC_mV() << " mV" << endl;
- kout << "Vbat = " << adc.getVBat_mV(false) << " mV" << endl;
- gpio.led_toggle(0);
+ os_runloop_once();
+ gpio.led_toggle();
}
int main(void)
@@ -121,14 +171,22 @@ int main(void)
arch.setup();
gpio.setup();
kout.setup();
- spi.setup();
gpio.input(GPIO::pb5);
+ gpio.led_on();
- radio_init();
+ kout.pprint(PSTR("Hello, World!\n"));
+ kout.pprint(PSTR("Test, World!\n"));
- kout << "Hello, World!" << endl;
- kout << "Test, World!" << endl;
+ os_init();
+ LMIC_reset();
+ LMIC_setClockError(MAX_CLOCK_ERROR * 20 / 100);
+ LMIC_setAdrMode(0);
+ do_send(&sendjob);
+ while (1) {
+ os_runloop_once();
+ gpio.led_toggle();
+ }
arch.idle_loop();
return 0;