diff options
author | Daniel Friesel <derf@finalrewind.org> | 2021-09-23 22:22:47 +0200 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2021-09-23 22:22:47 +0200 |
commit | 8578e1ea7d078b60864b084094dbb02b6cac99c3 (patch) | |
tree | 19a02eef376f5b89c7044c48dcc0c0f43ea9d416 /src/app/lora32u4ii/main.cc | |
parent | 30a29dcd0d064ab8403a9afb32c59800bb346840 (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.cc | 234 |
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; |