gps still does not work
This commit is contained in:
parent
a1d0404a47
commit
1b11b44336
2
Makefile
2
Makefile
|
@ -142,7 +142,7 @@ flash: $(OUT)$(NAME)
|
||||||
avrdude -v -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:$(OUT)$(NAME).hex:i
|
avrdude -v -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:$(OUT)$(NAME).hex:i
|
||||||
|
|
||||||
run: flash
|
run: flash
|
||||||
screen /dev/ttyUSB0
|
screen /dev/ttyUSB0 4800
|
||||||
|
|
||||||
start: flash
|
start: flash
|
||||||
systemctl start lora-gateway-bridge loraserver
|
systemctl start lora-gateway-bridge loraserver
|
||||||
|
|
167
collar.cpp
167
collar.cpp
|
@ -33,7 +33,6 @@
|
||||||
#include "pb_encode.h"
|
#include "pb_encode.h"
|
||||||
#include "pb_decode.h"
|
#include "pb_decode.h"
|
||||||
|
|
||||||
#include "lmic_project_config.h"
|
|
||||||
#include "gateway/message.pb.h"
|
#include "gateway/message.pb.h"
|
||||||
|
|
||||||
// DHT digital pin and sensor type
|
// DHT digital pin and sensor type
|
||||||
|
@ -95,9 +94,6 @@ const lmic_pinmap lmic_pins = {
|
||||||
.rxtx = LMIC_UNUSED_PIN,
|
.rxtx = LMIC_UNUSED_PIN,
|
||||||
.rst = 9,
|
.rst = 9,
|
||||||
.dio = {2, 3, LMIC_UNUSED_PIN},
|
.dio = {2, 3, LMIC_UNUSED_PIN},
|
||||||
.rxtx_rx_active = 0,
|
|
||||||
.rssi_cal = 8, // LBT cal for the Adafruit Feather M0 LoRa, in dB
|
|
||||||
.spi_freq = 8000000,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// init. DHT
|
// init. DHT
|
||||||
|
@ -110,7 +106,7 @@ const lmic_pinmap lmic_pins = {
|
||||||
* - Software Serial
|
* - Software Serial
|
||||||
***************************************************/
|
***************************************************/
|
||||||
TinyGPSPlus gps;
|
TinyGPSPlus gps;
|
||||||
SoftwareSerial ss(6, 7);
|
// SoftwareSerial ss(6, 7);
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Track each pair of X and Y coordinates
|
* Track each pair of X and Y coordinates
|
||||||
|
@ -157,6 +153,8 @@ int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
|
||||||
}
|
}
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Test a coordinate against all vertices
|
* Test a coordinate against all vertices
|
||||||
|
* - takes current GPS coordinates
|
||||||
|
* - return 1 if in bounds
|
||||||
***************************************************/
|
***************************************************/
|
||||||
int check_bounds(float x, float y) {
|
int check_bounds(float x, float y) {
|
||||||
return pnpoly(n_poly, polyx, polyy, x, y);
|
return pnpoly(n_poly, polyx, polyy, x, y);
|
||||||
|
@ -167,9 +165,6 @@ int check_bounds(float x, float y) {
|
||||||
* - loading arrays in nanopb does not appear
|
* - loading arrays in nanopb does not appear
|
||||||
* to work.
|
* to work.
|
||||||
***************************************************/
|
***************************************************/
|
||||||
typedef struct {
|
|
||||||
float x,y;
|
|
||||||
} coord;
|
|
||||||
void import_protobuf(uint8_t *protobuffer, uint32_t size) {
|
void import_protobuf(uint8_t *protobuffer, uint32_t size) {
|
||||||
|
|
||||||
#define TYPE_STRING 0x0A
|
#define TYPE_STRING 0x0A
|
||||||
|
@ -235,26 +230,40 @@ void import_protobuf(uint8_t *protobuffer, uint32_t size) {
|
||||||
* this stuff does not work yet
|
* this stuff does not work yet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*coord coordinates[10];
|
uint32_t isr;
|
||||||
int32_t isr;
|
|
||||||
|
|
||||||
isr = 0;
|
isr = 0;
|
||||||
isr = protobuffer[1];
|
isr = protobuffer[1];
|
||||||
|
|
||||||
uint8_t *ptr = protobuffer+5;
|
Serial.print("Isr: ");
|
||||||
for(int i=0;i<isr;i++)
|
Serial.println(isr);
|
||||||
{
|
|
||||||
memcpy(&coordinates[i].x, ptr + i*12, 4);
|
if(isr>N_POLY_MAX) isr = N_POLY_MAX;
|
||||||
memcpy(&coordinates[i].y, ptr + i*12+5, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.println("Recieved valid protobuf data?");
|
Serial.println("Recieved valid protobuf data?");
|
||||||
|
|
||||||
clear_verts();
|
clear_verts();
|
||||||
for(int i=0;i<isr;i++) {
|
|
||||||
push_vert(coordinates[i].x, coordinates[i].y);
|
uint8_t *ptr = protobuffer+5;
|
||||||
}*/
|
for(uint32_t i=0;i<isr;i++) {
|
||||||
|
if(i%5==0)
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
float x,y;
|
||||||
|
memcpy(&x, ptr + i*12, 4);
|
||||||
|
memcpy(&y, ptr + i*12+5, 4);
|
||||||
|
|
||||||
|
Serial.print('(');
|
||||||
|
Serial.print(x);
|
||||||
|
Serial.print(',');
|
||||||
|
Serial.print(y);
|
||||||
|
Serial.print(')');
|
||||||
|
Serial.print(' ');
|
||||||
|
|
||||||
|
push_vert(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_send(osjob_t* j);
|
||||||
void onEvent (ev_t ev) {
|
void onEvent (ev_t ev) {
|
||||||
Serial.print(os_getTime());
|
Serial.print(os_getTime());
|
||||||
Serial.print(": ");
|
Serial.print(": ");
|
||||||
|
@ -294,18 +303,28 @@ void onEvent (ev_t ev) {
|
||||||
case EV_TXCOMPLETE:
|
case EV_TXCOMPLETE:
|
||||||
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
|
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
|
||||||
|
|
||||||
// if (LMIC.dataLen) {
|
|
||||||
// import_protobuf(LMIC.frame, LMIC.dataLen);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (LMIC.txrxFlags & TXRX_ACK)
|
if (LMIC.txrxFlags & TXRX_ACK)
|
||||||
Serial.println(F("Received ack"));
|
Serial.println(F("Received ack"));
|
||||||
if (LMIC.dataLen) {
|
if (LMIC.dataLen) {
|
||||||
Serial.println(F("Received "));
|
Serial.println(F("Received "));
|
||||||
Serial.println(LMIC.dataLen);
|
Serial.println(LMIC.dataLen);
|
||||||
Serial.println(F(" bytes of payload"));
|
|
||||||
|
// Serial.println(F(" bytes of payload"));
|
||||||
|
|
||||||
|
// for(int i=0;i<LMIC.dataLen;i++) {
|
||||||
|
// Serial.print(LMIC.frame[LMIC.dataBeg + i], HEX);
|
||||||
|
// Serial.print(' ');
|
||||||
|
// Serial.print('-');
|
||||||
|
// Serial.print(' ');
|
||||||
|
// if(i%10==0)
|
||||||
|
// Serial.println();
|
||||||
|
// }
|
||||||
|
// Serial.println();
|
||||||
|
|
||||||
|
import_protobuf(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
|
||||||
break;
|
break;
|
||||||
case EV_LOST_TSYNC:
|
case EV_LOST_TSYNC:
|
||||||
Serial.println(F("EV_LOST_TSYNC"));
|
Serial.println(F("EV_LOST_TSYNC"));
|
||||||
|
@ -358,14 +377,14 @@ void onEvent (ev_t ev) {
|
||||||
#define FIELD_TWO_VARIANT 0x10
|
#define FIELD_TWO_VARIANT 0x10
|
||||||
|
|
||||||
|
|
||||||
void do_send(osjob_t* j){
|
uint8_t buffer[] = {
|
||||||
uint8_t buffer[15] = {
|
|
||||||
TYPE_STRING,
|
TYPE_STRING,
|
||||||
PROTO_LEN,
|
PROTO_LEN,
|
||||||
FIELD_ONE_FLOAT, 0x00, 0x00, 0x48, 0x43,
|
FIELD_ONE_FLOAT, 0x00, 0x00, 0x48, 0x43,
|
||||||
FIELD_TWO_FLOAT, 0x00, 0x00, 0xc8, 0x42,
|
FIELD_TWO_FLOAT, 0x00, 0x00, 0xc8, 0x42,
|
||||||
FIELD_TWO_VARIANT, 0, 0};
|
FIELD_TWO_VARIANT, 0};
|
||||||
|
|
||||||
|
void do_send(osjob_t* j){
|
||||||
// Check if there is not a current TX/RX job running
|
// Check if there is not a current TX/RX job running
|
||||||
if (LMIC.opmode & OP_TXRXPEND) {
|
if (LMIC.opmode & OP_TXRXPEND) {
|
||||||
Serial.println(F("OP_TXRXPEND, not sending"));
|
Serial.println(F("OP_TXRXPEND, not sending"));
|
||||||
|
@ -374,25 +393,23 @@ void do_send(osjob_t* j){
|
||||||
// transmit on port 1 (the first parameter); you can use any value from 1 to 223 (others are reserved).
|
// transmit on port 1 (the first parameter); you can use any value from 1 to 223 (others are reserved).
|
||||||
// don't request an ack (the last parameter, if not zero, requests an ack from the network).
|
// don't request an ack (the last parameter, if not zero, requests an ack from the network).
|
||||||
// Remember, acks consume a lot of network resources; don't ask for an ack unless you really need it.
|
// Remember, acks consume a lot of network resources; don't ask for an ack unless you really need it.
|
||||||
|
float latitude = gps.location.lat();
|
||||||
float latitude = 123;
|
float longitude = gps.location.lng();
|
||||||
float longitude = 456;
|
int oob = check_bounds(latitude, longitude);
|
||||||
|
|
||||||
latitude = 44.558308;
|
|
||||||
longitude = -123.28341;
|
|
||||||
|
|
||||||
memcpy(buffer+3, (void*)&latitude, 4);
|
memcpy(buffer+3, (void*)&latitude, 4);
|
||||||
memcpy(buffer+8, (void*)&longitude, 4);
|
memcpy(buffer+8, (void*)&longitude, 4);
|
||||||
|
memcpy(buffer+13, (void*)&oob, 1);
|
||||||
|
|
||||||
LMIC_setTxData2(1, buffer, 14, 0);
|
LMIC_setTxData2(1, buffer, sizeof(buffer), 0);
|
||||||
}
|
}
|
||||||
// Next TX is scheduled after TX_COMPLETE event.
|
// Next TX is scheduled after TX_COMPLETE event.
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
delay(1000);
|
delay(1000);
|
||||||
Serial.begin(9600);
|
Serial.begin(4800);
|
||||||
ss.begin(4800);
|
// ss.begin(4800);
|
||||||
|
|
||||||
delay(100);
|
delay(100);
|
||||||
Serial.println(F("Starting"));
|
Serial.println(F("Starting"));
|
||||||
|
@ -436,7 +453,7 @@ void setup() {
|
||||||
// Set data rate and transmit power for uplink
|
// Set data rate and transmit power for uplink
|
||||||
LMIC_setDrTxpow(DR_SF7,14);
|
LMIC_setDrTxpow(DR_SF7,14);
|
||||||
|
|
||||||
delay(100);
|
delay(2000);
|
||||||
// Start job
|
// Start job
|
||||||
// do_send(&sendjob);
|
// do_send(&sendjob);
|
||||||
}
|
}
|
||||||
|
@ -446,10 +463,12 @@ void setup() {
|
||||||
***************************************************/
|
***************************************************/
|
||||||
int read_gps() {
|
int read_gps() {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
// while(ss.available()>0) {
|
// int timeout = 0;
|
||||||
// gps.encode(ss.read());
|
while(Serial.available()>0) {// || timeout < 20) {
|
||||||
// ret = 1;
|
gps.encode(Serial.read());
|
||||||
// }
|
ret = 1;
|
||||||
|
//timeout++;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
/****************************************************
|
/****************************************************
|
||||||
|
@ -458,12 +477,17 @@ int read_gps() {
|
||||||
const int16_t PROGRESS_BAR_COUNT = 50;
|
const int16_t PROGRESS_BAR_COUNT = 50;
|
||||||
const int16_t START_OF_LINE = 13;
|
const int16_t START_OF_LINE = 13;
|
||||||
|
|
||||||
|
int led_on = 0;
|
||||||
void clear_line() {
|
void clear_line() {
|
||||||
Serial.write(START_OF_LINE);
|
Serial.write(START_OF_LINE);
|
||||||
for(int i=0;i<PROGRESS_BAR_COUNT;i++)
|
for(int i=0;i<PROGRESS_BAR_COUNT;i++)
|
||||||
Serial.write(' ');
|
Serial.write(' ');
|
||||||
Serial.write(START_OF_LINE);
|
Serial.write(START_OF_LINE);
|
||||||
|
|
||||||
|
digitalWrite(LED_BUILTIN, led_on);
|
||||||
|
led_on = !led_on;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* State variables
|
* State variables
|
||||||
* - track events of main loop
|
* - track events of main loop
|
||||||
|
@ -476,36 +500,36 @@ enum STATE_ {
|
||||||
WAITING_LORA,
|
WAITING_LORA,
|
||||||
LORA_DONE
|
LORA_DONE
|
||||||
};
|
};
|
||||||
// int state = START_GPS;
|
int state = START_GPS;
|
||||||
int state = SENDING_LORA;
|
|
||||||
int loopCounter = 0;
|
int loopCounter = 0;
|
||||||
int startTime = 0;
|
int startTime = 0;
|
||||||
|
uint32_t got_data = 0;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
switch(state) {
|
||||||
if(state == START_GPS) {
|
case START_GPS:
|
||||||
Serial.println("Waiting for GPS");
|
Serial.println("Waiting for GPS");
|
||||||
state = WAITING_GPS;
|
state = WAITING_GPS;
|
||||||
}
|
break;
|
||||||
else if(state == WAITING_GPS) {
|
case WAITING_GPS:
|
||||||
int got_data =
|
got_data =
|
||||||
read_gps();
|
read_gps();
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* loading bar animation
|
* loading bar animation
|
||||||
***************************************************/
|
***************************************************/
|
||||||
if(got_data) {
|
if(got_data) {
|
||||||
//if(loopCounter%100==0)
|
if(loopCounter%100==0)
|
||||||
// Serial.write('.');
|
Serial.write('.');
|
||||||
if(loopCounter>PROGRESS_BAR_COUNT*100) {
|
if(loopCounter>PROGRESS_BAR_COUNT*100) {
|
||||||
// clear_line();
|
clear_line();
|
||||||
loopCounter=0;
|
loopCounter=0;
|
||||||
|
|
||||||
state = VERIFYING_GPS;
|
state = VERIFYING_GPS;
|
||||||
}
|
}
|
||||||
loopCounter++;
|
loopCounter++;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if(state == VERIFYING_GPS) {
|
case VERIFYING_GPS:
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* if no data has been received from the gps in 5 seconds
|
* if no data has been received from the gps in 5 seconds
|
||||||
* then the GPS is probably not connected properly
|
* then the GPS is probably not connected properly
|
||||||
|
@ -523,38 +547,15 @@ void loop() {
|
||||||
state = SENDING_LORA;
|
state = SENDING_LORA;
|
||||||
else
|
else
|
||||||
state = WAITING_GPS;
|
state = WAITING_GPS;
|
||||||
}
|
break;
|
||||||
else if(state == SENDING_LORA) {
|
case SENDING_LORA:
|
||||||
/****************************************************
|
|
||||||
* send encoded buffer over LoRaWAN
|
|
||||||
***************************************************/
|
|
||||||
Serial.println("Sending LoRa Data...");
|
|
||||||
do_send(&sendjob);
|
do_send(&sendjob);
|
||||||
|
|
||||||
/****************************************************
|
digitalWrite(LED_BUILTIN, 0);
|
||||||
* set reference time for LoRaWAN transmission delay
|
|
||||||
***************************************************/
|
|
||||||
startTime = millis() / 1000;
|
|
||||||
state = WAITING_LORA;
|
|
||||||
}
|
|
||||||
else if(state == WAITING_LORA) {
|
|
||||||
/****************************************************
|
|
||||||
* don't block the GPS from reading here
|
|
||||||
***************************************************/
|
|
||||||
// read_gps();
|
|
||||||
|
|
||||||
/****************************************************
|
|
||||||
* if enough seconds have been delayed then move to
|
|
||||||
* next state
|
|
||||||
***************************************************/
|
|
||||||
if((millis()/1000 - startTime) >= TX_INTERVAL) {
|
|
||||||
Serial.println("Lora has finished waiting");
|
|
||||||
state = LORA_DONE;
|
state = LORA_DONE;
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
else if(state == LORA_DONE) {
|
break;
|
||||||
state = VERIFYING_GPS;
|
|
||||||
state = SENDING_LORA;
|
|
||||||
}
|
}
|
||||||
os_runloop_once();
|
os_runloop_once();
|
||||||
}
|
}
|
||||||
|
|
737
lmic.h
737
lmic.h
|
@ -1,737 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2016 IBM Corporation.
|
|
||||||
* Copyright (c) 2016 Matthijs Kooijman.
|
|
||||||
* Copyright (c) 2016-2020 MCCI Corporation.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of the <organization> nor the
|
|
||||||
* names of its contributors may be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//! @file
|
|
||||||
//! @brief LMIC API
|
|
||||||
|
|
||||||
#ifndef _lmic_h_
|
|
||||||
#define _lmic_h_
|
|
||||||
|
|
||||||
#include "oslmic.h"
|
|
||||||
#include "lorabase.h"
|
|
||||||
|
|
||||||
#if LMIC_DEBUG_LEVEL > 0 || LMIC_X_DEBUG_LEVEL > 0
|
|
||||||
# if defined(LMIC_DEBUG_INCLUDE)
|
|
||||||
# define LMIC_STRINGIFY_(x) #x
|
|
||||||
# define LMIC_STRINGIFY(x) LMIC_STRINGIFY_(x)
|
|
||||||
# include LMIC_STRINGIFY(LMIC_DEBUG_INCLUDE)
|
|
||||||
# endif
|
|
||||||
# ifdef LMIC_DEBUG_PRINTF_FN
|
|
||||||
extern void LMIC_DEBUG_PRINTF_FN(const char *f, ...);
|
|
||||||
# endif // ndef LMIC_DEBUG_PRINTF_FN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// if LMIC_DEBUG_PRINTF is now defined, just use it. This lets you do anything
|
|
||||||
// you like with a sufficiently crazy header file.
|
|
||||||
#if LMIC_DEBUG_LEVEL > 0
|
|
||||||
# ifndef LMIC_DEBUG_PRINTF
|
|
||||||
// otherwise, check whether someone configured a print-function to be used,
|
|
||||||
// and use it if so.
|
|
||||||
# ifdef LMIC_DEBUG_PRINTF_FN
|
|
||||||
# define LMIC_DEBUG_PRINTF(f, ...) LMIC_DEBUG_PRINTF_FN(f, ## __VA_ARGS__)
|
|
||||||
# ifndef LMIC_DEBUG_INCLUDE // If you use LMIC_DEBUG_INCLUDE, put the declaration in there
|
|
||||||
void LMIC_DEBUG_PRINTF_FN(const char *f, ...);
|
|
||||||
# endif // ndef LMIC_DEBUG_INCLUDE
|
|
||||||
# else // ndef LMIC_DEBUG_PRINTF_FN
|
|
||||||
// if there's no other info, just use printf. In a pure Arduino environment,
|
|
||||||
// that's what will happen.
|
|
||||||
# include <stdio.h>
|
|
||||||
# define LMIC_DEBUG_PRINTF(f, ...) printf(f, ## __VA_ARGS__)
|
|
||||||
# endif // ndef LMIC_DEBUG_PRINTF_FN
|
|
||||||
# endif // ndef LMIC_DEBUG_PRINTF
|
|
||||||
# ifndef LMIC_DEBUG_FLUSH
|
|
||||||
# ifdef LMIC_DEBUG_FLUSH_FN
|
|
||||||
# define LMIC_DEBUG_FLUSH() LMIC_DEBUG_FLUSH_FN()
|
|
||||||
# else // ndef LMIC_DEBUG_FLUSH_FN
|
|
||||||
// if there's no other info, assume that flush is not needed.
|
|
||||||
# define LMIC_DEBUG_FLUSH() do { ; } while (0)
|
|
||||||
# endif // ndef LMIC_DEBUG_FLUSH_FN
|
|
||||||
# endif // ndef LMIC_DEBUG_FLUSH
|
|
||||||
#else // LMIC_DEBUG_LEVEL == 0
|
|
||||||
// If debug level is zero, printf and flush expand to nothing.
|
|
||||||
# define LMIC_DEBUG_PRINTF(f, ...) do { ; } while (0)
|
|
||||||
# define LMIC_DEBUG_FLUSH() do { ; } while (0)
|
|
||||||
#endif // LMIC_DEBUG_LEVEL == 0
|
|
||||||
|
|
||||||
//
|
|
||||||
// LMIC_X_DEBUG_LEVEL enables additional, special print functions for debugging
|
|
||||||
// RSSI features. This is used sparingly.
|
|
||||||
#if LMIC_X_DEBUG_LEVEL > 0
|
|
||||||
# ifdef LMIC_DEBUG_PRINTF_FN
|
|
||||||
# define LMIC_X_DEBUG_PRINTF(f, ...) LMIC_DEBUG_PRINTF_FN(f, ## __VA_ARGS__)
|
|
||||||
# else
|
|
||||||
# error "LMIC_DEBUG_PRINTF_FN must be defined for LMIC_X_DEBUG_LEVEL > 0."
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define LMIC_X_DEBUG_PRINTF(f, ...) do {;} while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
// LMIC version -- this is ths IBM LMIC version
|
|
||||||
#define LMIC_VERSION_MAJOR 1
|
|
||||||
#define LMIC_VERSION_MINOR 6
|
|
||||||
#define LMIC_VERSION_BUILD 1468577746
|
|
||||||
|
|
||||||
// Arduino LMIC version
|
|
||||||
#define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local) \
|
|
||||||
((((major)*UINT32_C(1)) << 24) | (((minor)*UINT32_C(1)) << 16) | (((patch)*UINT32_C(1)) << 8) | (((local)*UINT32_C(1)) << 0))
|
|
||||||
|
|
||||||
#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(3, 2, 0, 0) /* v3.2.0 */
|
|
||||||
|
|
||||||
#define ARDUINO_LMIC_VERSION_GET_MAJOR(v) \
|
|
||||||
((((v)*UINT32_C(1)) >> 24u) & 0xFFu)
|
|
||||||
|
|
||||||
#define ARDUINO_LMIC_VERSION_GET_MINOR(v) \
|
|
||||||
((((v)*UINT32_C(1)) >> 16u) & 0xFFu)
|
|
||||||
|
|
||||||
#define ARDUINO_LMIC_VERSION_GET_PATCH(v) \
|
|
||||||
((((v)*UINT32_C(1)) >> 8u) & 0xFFu)
|
|
||||||
|
|
||||||
#define ARDUINO_LMIC_VERSION_GET_LOCAL(v) \
|
|
||||||
((v) & 0xFFu)
|
|
||||||
|
|
||||||
//! Only For Antenna Tuning Tests !
|
|
||||||
//#define CFG_TxContinuousMode 1
|
|
||||||
|
|
||||||
// since this was annouunced as the API variable, we keep it. But it's not used,
|
|
||||||
// MAX_LEN_FRAME is what the code uses.
|
|
||||||
enum { MAX_FRAME_LEN = MAX_LEN_FRAME }; //!< Library cap on max frame length
|
|
||||||
|
|
||||||
enum { TXCONF_ATTEMPTS = 8 }; //!< Transmit attempts for confirmed frames
|
|
||||||
enum { MAX_MISSED_BCNS = (2 * 60 * 60 + 127) / 128 }; //!< threshold for dropping out of class B, triggering rejoin requests
|
|
||||||
// note that we need 100 ppm timing accuracy for
|
|
||||||
// this, to keep the timing error to +/- 700ms.
|
|
||||||
enum { MAX_RXSYMS = 350 }; // Stop tracking beacon if sync error grows beyond this. A 0.4% clock error
|
|
||||||
// at SF9.125k means 512 ms; one sybol is 4.096 ms,
|
|
||||||
// so this needs to be at least 125 for an STM32L0.
|
|
||||||
// And for 100ppm clocks and 2 hours of beacon misses,
|
|
||||||
// this needs to accomodate 1.4 seconds of error at
|
|
||||||
// 4.096 ms/sym or at least 342 symbols.
|
|
||||||
|
|
||||||
enum { LINK_CHECK_CONT = 0 , // continue with this after reported dead link
|
|
||||||
LINK_CHECK_DEAD = 32 , // after this UP frames and no response to ack from NWK assume link is dead (ADR_ACK_DELAY)
|
|
||||||
LINK_CHECK_UNJOIN_MIN = LINK_CHECK_DEAD + 4, // this is the minimum value of LINK_CHECK_UNJOIN if we parameterize
|
|
||||||
LINK_CHECK_UNJOIN = LINK_CHECK_DEAD + (3 * 240), // after this many UP frames and no response, switch to join (by default)
|
|
||||||
LINK_CHECK_INIT = -64 , // UP frame count until we ask for ack (ADR_ACK_LIMIT)
|
|
||||||
LINK_CHECK_OFF =-128 }; // link check disabled
|
|
||||||
|
|
||||||
enum { TIME_RESYNC = 6*128 }; // secs
|
|
||||||
enum { TXRX_GUARD_ms = 6000 }; // msecs - don't start TX-RX transaction before beacon
|
|
||||||
enum { JOIN_GUARD_ms = 9000 }; // msecs - don't start Join Req/Acc transaction before beacon
|
|
||||||
enum { TXRX_BCNEXT_secs = 2 }; // secs - earliest start after beacon time
|
|
||||||
enum { RETRY_PERIOD_secs = 3 }; // secs - random period for retrying a confirmed send
|
|
||||||
|
|
||||||
#if CFG_LMIC_EU_like // EU868 spectrum ====================================================
|
|
||||||
|
|
||||||
enum { MAX_CHANNELS = 16 }; //!< Max supported channels
|
|
||||||
enum { MAX_BANDS = 4 };
|
|
||||||
|
|
||||||
enum { LIMIT_CHANNELS = (1<<4) }; // EU868 will never have more channels
|
|
||||||
//! \internal
|
|
||||||
struct band_t {
|
|
||||||
u2_t txcap; // duty cycle limitation: 1/txcap
|
|
||||||
s1_t txpow; // maximum TX power
|
|
||||||
u1_t lastchnl; // last used channel
|
|
||||||
ostime_t avail; // channel is blocked until this time
|
|
||||||
};
|
|
||||||
TYPEDEF_xref2band_t; //!< \internal
|
|
||||||
|
|
||||||
struct lmic_saved_adr_state_s {
|
|
||||||
u4_t channelFreq[MAX_CHANNELS];
|
|
||||||
u2_t channelMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
#elif CFG_LMIC_US_like // US915 spectrum =================================================
|
|
||||||
|
|
||||||
enum { MAX_XCHANNELS = 2 }; // extra channels in RAM, channels 0-71 are immutable
|
|
||||||
|
|
||||||
struct lmic_saved_adr_state_s {
|
|
||||||
u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
|
|
||||||
u2_t activeChannels125khz;
|
|
||||||
u2_t activeChannels500khz;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ==========================================================================
|
|
||||||
|
|
||||||
typedef struct lmic_saved_adr_state_s lmic_saved_adr_state_t;
|
|
||||||
|
|
||||||
// Keep in sync with evdefs.hpp::drChange
|
|
||||||
enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD, DRCHG_FRAMESIZE };
|
|
||||||
enum { KEEP_TXPOW = -128 };
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(DISABLE_PING)
|
|
||||||
//! \internal
|
|
||||||
struct rxsched_t {
|
|
||||||
dr_t dr;
|
|
||||||
u1_t intvExp; // 0..7
|
|
||||||
u1_t slot; // runs from 0 to 128
|
|
||||||
rxsyms_t rxsyms;
|
|
||||||
ostime_t rxbase;
|
|
||||||
ostime_t rxtime; // start of next spot
|
|
||||||
u4_t freq;
|
|
||||||
};
|
|
||||||
TYPEDEF_xref2rxsched_t; //!< \internal
|
|
||||||
#endif // !DISABLE_PING
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
//! Parsing and tracking states of beacons.
|
|
||||||
enum { BCN_NONE = 0x00, //!< No beacon received
|
|
||||||
BCN_PARTIAL = 0x01, //!< Only first (common) part could be decoded (info,lat,lon invalid/previous)
|
|
||||||
BCN_FULL = 0x02, //!< Full beacon decoded
|
|
||||||
BCN_NODRIFT = 0x04, //!< No drift value measured yet
|
|
||||||
BCN_NODDIFF = 0x08 }; //!< No differential drift measured yet
|
|
||||||
//! Information about the last and previous beacons.
|
|
||||||
struct bcninfo_t {
|
|
||||||
ostime_t txtime; //!< Time when the beacon was sent
|
|
||||||
u4_t time; //!< GPS time in seconds of last beacon (received or surrogate)
|
|
||||||
s4_t lat; //!< Lat field of last beacon (valid only if BCN_FULL set)
|
|
||||||
s4_t lon; //!< Lon field of last beacon (valid only if BCN_FULL set)
|
|
||||||
s1_t rssi; //!< Adjusted RSSI value of last received beacon
|
|
||||||
s1_t snr; //!< Scaled SNR value of last received beacon
|
|
||||||
u1_t flags; //!< Last beacon reception and tracking states. See BCN_* values.
|
|
||||||
//
|
|
||||||
u1_t info; //!< Info field of last beacon (valid only if BCN_FULL set)
|
|
||||||
};
|
|
||||||
#endif // !DISABLE_BEACONS
|
|
||||||
|
|
||||||
// purpose of receive window - lmic_t.rxState
|
|
||||||
enum { RADIO_RST=0, RADIO_TX=1, RADIO_RX=2, RADIO_RXON=3, RADIO_TX_AT=4, };
|
|
||||||
// Netid values / lmic_t.netid
|
|
||||||
enum { NETID_NONE=(int)~0U, NETID_MASK=(int)0xFFFFFF };
|
|
||||||
// MAC operation modes (lmic_t.opmode).
|
|
||||||
enum { OP_NONE = 0x0000,
|
|
||||||
OP_SCAN = 0x0001, // radio scan to find a beacon
|
|
||||||
OP_TRACK = 0x0002, // track my networks beacon (netid)
|
|
||||||
OP_JOINING = 0x0004, // device joining in progress (blocks other activities)
|
|
||||||
OP_TXDATA = 0x0008, // TX user data (buffered in pendTxData)
|
|
||||||
OP_POLL = 0x0010, // send empty UP frame to ACK confirmed DN/fetch more DN data
|
|
||||||
OP_REJOIN = 0x0020, // occasionally send JOIN REQUEST
|
|
||||||
OP_SHUTDOWN = 0x0040, // prevent MAC from doing anything
|
|
||||||
OP_TXRXPEND = 0x0080, // TX/RX transaction pending
|
|
||||||
OP_RNDTX = 0x0100, // prevent TX lining up after a beacon
|
|
||||||
OP_PINGINI = 0x0200, // pingable is initialized and scheduling active
|
|
||||||
OP_PINGABLE = 0x0400, // we're pingable
|
|
||||||
OP_NEXTCHNL = 0x0800, // find a new channel
|
|
||||||
OP_LINKDEAD = 0x1000, // link was reported as dead
|
|
||||||
OP_TESTMODE = 0x2000, // developer test mode
|
|
||||||
OP_UNJOIN = 0x4000, // unjoin and rejoin on next engineUpdate().
|
|
||||||
};
|
|
||||||
// TX-RX transaction flags - report back to user
|
|
||||||
enum { TXRX_ACK = 0x80, // confirmed UP frame was acked
|
|
||||||
TXRX_NACK = 0x40, // confirmed UP frame was not acked
|
|
||||||
TXRX_NOPORT = 0x20, // set if a frame with a port was RXed, clr if no frame/no port
|
|
||||||
TXRX_PORT = 0x10, // set if a frame with a port was RXed, LMIC.frame[LMIC.dataBeg-1] => port
|
|
||||||
TXRX_LENERR = 0x08, // set if frame was discarded due to length error.
|
|
||||||
TXRX_PING = 0x04, // received in a scheduled RX slot
|
|
||||||
TXRX_DNW2 = 0x02, // received in 2dn DN slot
|
|
||||||
TXRX_DNW1 = 0x01, // received in 1st DN slot
|
|
||||||
};
|
|
||||||
|
|
||||||
// Event types for event callback
|
|
||||||
enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND,
|
|
||||||
EV_BEACON_MISSED, EV_BEACON_TRACKED, EV_JOINING,
|
|
||||||
EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED,
|
|
||||||
EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET,
|
|
||||||
EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE, EV_SCAN_FOUND,
|
|
||||||
EV_TXSTART, EV_TXCANCELED, EV_RXSTART, EV_JOIN_TXCOMPLETE };
|
|
||||||
typedef enum _ev_t ev_t;
|
|
||||||
|
|
||||||
// this macro can be used to initalize a normal table of event strings
|
|
||||||
#define LMIC_EVENT_NAME_TABLE__INIT \
|
|
||||||
"<<zero>>", \
|
|
||||||
"EV_SCAN_TIMEOUT", "EV_BEACON_FOUND", \
|
|
||||||
"EV_BEACON_MISSED", "EV_BEACON_TRACKED", "EV_JOINING", \
|
|
||||||
"EV_JOINED", "EV_RFU1", "EV_JOIN_FAILED", "EV_REJOIN_FAILED", \
|
|
||||||
"EV_TXCOMPLETE", "EV_LOST_TSYNC", "EV_RESET", \
|
|
||||||
"EV_RXCOMPLETE", "EV_LINK_DEAD", "EV_LINK_ALIVE", "EV_SCAN_FOUND", \
|
|
||||||
"EV_TXSTART", "EV_TXCANCELED", "EV_RXSTART", "EV_JOIN_TXCOMPLETE"
|
|
||||||
|
|
||||||
// if working on an AVR (or worried about it), you can use this multi-zero
|
|
||||||
// string and put this in a single const F() string. Index through this
|
|
||||||
// counting up from 0, until you get to the entry you want or to an
|
|
||||||
// entry that begins with a \0.
|
|
||||||
#define LMIC_EVENT_NAME_MULTISZ__INIT \
|
|
||||||
"<<zero>>\0" \
|
|
||||||
"EV_SCAN_TIMEOUT\0" "EV_BEACON_FOUND\0" \
|
|
||||||
"EV_BEACON_MISSED\0" "EV_BEACON_TRACKED\0" "EV_JOINING\0" \
|
|
||||||
"EV_JOINED\0" "EV_RFU1\0" "EV_JOIN_FAILED\0" "EV_REJOIN_FAILED\0" \
|
|
||||||
"EV_TXCOMPLETE\0" "EV_LOST_TSYNC\0" "EV_RESET\0" \
|
|
||||||
"EV_RXCOMPLETE\0" "EV_LINK_DEAD\0" "EV_LINK_ALIVE\0" "EV_SCAN_FOUND\0" \
|
|
||||||
"EV_TXSTART\0" "EV_TXCANCELED\0" "EV_RXSTART\0" "EV_JOIN_TXCOMPLETE\0"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
LMIC_ERROR_SUCCESS = 0,
|
|
||||||
LMIC_ERROR_TX_BUSY = -1,
|
|
||||||
LMIC_ERROR_TX_TOO_LARGE = -2,
|
|
||||||
LMIC_ERROR_TX_NOT_FEASIBLE = -3,
|
|
||||||
LMIC_ERROR_TX_FAILED = -4,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int lmic_tx_error_t;
|
|
||||||
|
|
||||||
#define LMIC_ERROR_NAME__INIT \
|
|
||||||
"LMIC_ERROR_SUCCESS", \
|
|
||||||
"LMIC_ERROR_TX_BUSY", \
|
|
||||||
"LMIC_ERROR_TX_TOO_LARGE", \
|
|
||||||
"LMIC_ERROR_TX_NOT_FEASIBLE", \
|
|
||||||
"LMIC_ERROR_TX_FAILED"
|
|
||||||
|
|
||||||
#define LMIC_ERROR_NAME_MULTISZ__INIT \
|
|
||||||
"LMIC_ERROR_SUCCESS\0" \
|
|
||||||
"LMIC_ERROR_TX_BUSY\0" \
|
|
||||||
"LMIC_ERROR_TX_TOO_LARGE\0" \
|
|
||||||
"LMIC_ERROR_TX_NOT_FEASIBLE\0" \
|
|
||||||
"LMIC_ERROR_TX_FAILED"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
LMIC_BEACON_ERROR_INVALID = -2,
|
|
||||||
LMIC_BEACON_ERROR_WRONG_NETWORK = -1,
|
|
||||||
LMIC_BEACON_ERROR_SUCCESS_PARTIAL = 0,
|
|
||||||
LMIC_BEACON_ERROR_SUCCESS_FULL = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef s1_t lmic_beacon_error_t;
|
|
||||||
|
|
||||||
static inline bit_t LMIC_BEACON_SUCCESSFUL(lmic_beacon_error_t e) {
|
|
||||||
return e < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// LMIC_CFG_max_clock_error_ppm
|
|
||||||
#if !defined(LMIC_CFG_max_clock_error_ppm)
|
|
||||||
# define LMIC_CFG_max_clock_error_ppm 2000 /* max clock error: 0.2% (2000 ppm) */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
// This value represents 100% error in LMIC.clockError
|
|
||||||
MAX_CLOCK_ERROR = 65536,
|
|
||||||
//! \brief maximum clock error that users can specify: 2000 ppm (0.2%).
|
|
||||||
//! \details This is the limit for clock error, unless LMIC_ENABLE_arbitrary_clock_error is set.
|
|
||||||
//! The default is 4,000 ppm, which is .004, or 0.4%; this is what you get on an
|
|
||||||
//! STM32L0 running with the HSI oscillator after cal. If your clock error is bigger,
|
|
||||||
//! usually you want to calibrate it so that millis() and micros() are reasonably
|
|
||||||
//! accurate. Important: do not use clock error to compensate for late serving
|
|
||||||
//! of the LMIC. If you see that LMIC.radio.rxlate_count is increasing, you need
|
|
||||||
//! to adjust your application logic so the LMIC gets serviced promptly when a
|
|
||||||
//! Class A downlink (or beacon) is pending.
|
|
||||||
LMIC_kMaxClockError_ppm = 4000,
|
|
||||||
};
|
|
||||||
|
|
||||||
// callbacks for client alerts.
|
|
||||||
// types and functions are always defined, to reduce #ifs in example code and libraries.
|
|
||||||
typedef void LMIC_ABI_STD lmic_rxmessage_cb_t(void *pUserData, uint8_t port, const uint8_t *pMessage, size_t nMessage);
|
|
||||||
typedef void LMIC_ABI_STD lmic_txmessage_cb_t(void *pUserData, int fSuccess);
|
|
||||||
typedef void LMIC_ABI_STD lmic_event_cb_t(void *pUserData, ev_t e);
|
|
||||||
|
|
||||||
// network time request callback function
|
|
||||||
// defined unconditionally, because APIs and types can't change based on config.
|
|
||||||
// This is called when a time-request succeeds or when we get a downlink
|
|
||||||
// without time request, "completing" the pending time request.
|
|
||||||
typedef void LMIC_ABI_STD lmic_request_network_time_cb_t(void *pUserData, int flagSuccess);
|
|
||||||
|
|
||||||
// how the network represents time.
|
|
||||||
typedef u4_t lmic_gpstime_t;
|
|
||||||
|
|
||||||
// rather than deal with 1/256 second tick, we adjust ostime back
|
|
||||||
// (as it's high res) to match tNetwork.
|
|
||||||
typedef struct lmic_time_reference_s lmic_time_reference_t;
|
|
||||||
|
|
||||||
struct lmic_time_reference_s {
|
|
||||||
// our best idea of when we sent the uplink (end of packet).
|
|
||||||
ostime_t tLocal;
|
|
||||||
// the network's best idea of when we sent the uplink.
|
|
||||||
lmic_gpstime_t tNetwork;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum lmic_request_time_state_e {
|
|
||||||
lmic_RequestTimeState_idle = 0, // we're not doing anything
|
|
||||||
lmic_RequestTimeState_tx, // we want to tx a time request on next uplink
|
|
||||||
lmic_RequestTimeState_rx, // we have tx'ed, next downlink completes.
|
|
||||||
lmic_RequestTimeState_success // we sucessfully got time.
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u1_t lmic_request_time_state_t;
|
|
||||||
|
|
||||||
enum lmic_engine_update_state_e {
|
|
||||||
lmic_EngineUpdateState_idle = 0, // engineUpdate is idle.
|
|
||||||
lmic_EngineUpdateState_busy = 1, // engineUpdate is busy, but has not been reentered.
|
|
||||||
lmic_EngineUpdateState_again = 2, // engineUpdate is busy, and has to be evaluated again.
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u1_t lmic_engine_update_state_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Structure: lmic_client_data_t
|
|
||||||
|
|
||||||
Function:
|
|
||||||
Holds LMIC client data that must live through LMIC_reset().
|
|
||||||
|
|
||||||
Description:
|
|
||||||
There are a variety of client registration linkage items that
|
|
||||||
must live through LMIC_reset(), because LMIC_reset() is called
|
|
||||||
at frame rollover time. We group them together into a structure
|
|
||||||
to make copies easy.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//! abstract type for collection of client data that survives LMIC_reset().
|
|
||||||
typedef struct lmic_client_data_s lmic_client_data_t;
|
|
||||||
|
|
||||||
//! contents of lmic_client_data_t
|
|
||||||
struct lmic_client_data_s {
|
|
||||||
|
|
||||||
/* pointer-width things come first */
|
|
||||||
#if LMIC_ENABLE_DeviceTimeReq
|
|
||||||
lmic_request_network_time_cb_t *pNetworkTimeCb; //! call-back routine for network time
|
|
||||||
void *pNetworkTimeUserData; //! call-back data for network time.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LMIC_ENABLE_user_events
|
|
||||||
lmic_event_cb_t *eventCb; //! user-supplied callback function for events.
|
|
||||||
void *eventUserData; //! data for eventCb
|
|
||||||
lmic_rxmessage_cb_t *rxMessageCb; //! user-supplied message-received callback
|
|
||||||
void *rxMessageUserData; //! data for rxMessageCb
|
|
||||||
lmic_txmessage_cb_t *txMessageCb; //! transmit-complete message handler; reset on each tx complete.
|
|
||||||
void *txMessageUserData; //! data for txMessageCb.
|
|
||||||
#endif // LMIC_ENABLE_user_events
|
|
||||||
|
|
||||||
/* next we have things that are (u)int32_t */
|
|
||||||
/* none at the moment */
|
|
||||||
|
|
||||||
/* next we have things that are (u)int16_t */
|
|
||||||
|
|
||||||
u2_t clockError; //! Inaccuracy in the clock. CLOCK_ERROR_MAX represents +/-100% error
|
|
||||||
|
|
||||||
/* finally, things that are (u)int8_t */
|
|
||||||
/* none at the moment */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Structure: lmic_radio_data_t
|
|
||||||
|
|
||||||
Function:
|
|
||||||
Holds LMIC radio driver.
|
|
||||||
|
|
||||||
Description:
|
|
||||||
Eventually this will be used for all portable things for the radio driver,
|
|
||||||
but for now it's where we can start to add things.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct lmic_radio_data_s lmic_radio_data_t;
|
|
||||||
|
|
||||||
struct lmic_radio_data_s {
|
|
||||||
// total os ticks of accumulated delay error. Can overflow!
|
|
||||||
ostime_t rxlate_ticks;
|
|
||||||
// number of rx late launches.
|
|
||||||
unsigned rxlate_count;
|
|
||||||
// total os ticks of accumulated tx delay error. Can overflow!
|
|
||||||
ostime_t txlate_ticks;
|
|
||||||
// number of tx late launches.
|
|
||||||
unsigned txlate_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Structure: lmic_t
|
|
||||||
|
|
||||||
Function:
|
|
||||||
Provides the instance data for the LMIC.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct lmic_t {
|
|
||||||
// client setup data, survives LMIC_reset().
|
|
||||||
lmic_client_data_t client;
|
|
||||||
|
|
||||||
// the OS job object. pointer alignment.
|
|
||||||
osjob_t osjob;
|
|
||||||
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
bcninfo_t bcninfo; // Last received beacon info
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(DISABLE_PING)
|
|
||||||
rxsched_t ping; // pingable setup
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// the radio driver portable context
|
|
||||||
lmic_radio_data_t radio;
|
|
||||||
|
|
||||||
/* (u)int32_t things */
|
|
||||||
|
|
||||||
// Radio settings TX/RX (also accessed by HAL)
|
|
||||||
ostime_t txend;
|
|
||||||
ostime_t rxtime;
|
|
||||||
|
|
||||||
// LBT info
|
|
||||||
ostime_t lbt_ticks; // ticks to listen
|
|
||||||
|
|
||||||
u4_t freq;
|
|
||||||
|
|
||||||
ostime_t globalDutyAvail; // time device can send again
|
|
||||||
|
|
||||||
u4_t netid; // current network id (~0 - none)
|
|
||||||
devaddr_t devaddr;
|
|
||||||
u4_t seqnoDn; // device level down stream seqno
|
|
||||||
u4_t seqnoUp;
|
|
||||||
u4_t dn2Freq;
|
|
||||||
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
ostime_t bcnRxtime;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LMIC_ENABLE_DeviceTimeReq
|
|
||||||
// put here for alignment, to reduce RAM use.
|
|
||||||
ostime_t localDeviceTime; // the LMIC.txend value for last DeviceTimeAns
|
|
||||||
lmic_gpstime_t netDeviceTime; // the netDeviceTime for lastDeviceTimeAns
|
|
||||||
// zero ==> not valid.
|
|
||||||
#endif // LMIC_ENABLE_DeviceTimeReq
|
|
||||||
|
|
||||||
// Channel scheduling -- very much private
|
|
||||||
#if CFG_LMIC_EU_like
|
|
||||||
band_t bands[MAX_BANDS];
|
|
||||||
u4_t channelFreq[MAX_CHANNELS];
|
|
||||||
#if !defined(DISABLE_MCMD_DlChannelReq)
|
|
||||||
u4_t channelDlFreq[MAX_CHANNELS];
|
|
||||||
#endif
|
|
||||||
// bit map of enabled datarates for each channel
|
|
||||||
u2_t channelDrMap[MAX_CHANNELS];
|
|
||||||
u2_t channelMap;
|
|
||||||
#elif CFG_LMIC_US_like
|
|
||||||
u4_t xchFreq[MAX_XCHANNELS]; // extra channel frequencies (if device is behind a repeater)
|
|
||||||
u2_t xchDrMap[MAX_XCHANNELS]; // extra channel datarate ranges ---XXX: ditto
|
|
||||||
u2_t channelMap[(72+MAX_XCHANNELS+15)/16]; // enabled bits
|
|
||||||
u2_t activeChannels125khz;
|
|
||||||
u2_t activeChannels500khz;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* (u)int16_t things */
|
|
||||||
rps_t rps; // radio parameter selections: SF, BW, CodingRate, NoCrc, implicit hdr
|
|
||||||
u2_t opmode; // engineUpdate() operating mode flags
|
|
||||||
u2_t devNonce; // last generated nonce
|
|
||||||
|
|
||||||
s2_t adrAckReq; // counter for link integrity tracking (LINK_CHECK_OFF=off)
|
|
||||||
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
s2_t drift; // last measured drift
|
|
||||||
s2_t lastDriftDiff;
|
|
||||||
s2_t maxDriftDiff;
|
|
||||||
rxsyms_t bcnRxsyms; //
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* (u)int8_t things */
|
|
||||||
lmic_engine_update_state_t engineUpdateState; // state of the engineUpdate() evaluator.
|
|
||||||
s1_t rssi;
|
|
||||||
s1_t snr; // LMIC.snr is SNR times 4
|
|
||||||
rxsyms_t rxsyms; // symbols for receive timeout.
|
|
||||||
u1_t dndr;
|
|
||||||
s1_t txpow; // transmit dBm (administrative)
|
|
||||||
s1_t radio_txpow; // the radio driver's copy of txpow, in dB limited by adrTxPow, and
|
|
||||||
// also adjusted for EIRP/antenna gain considerations.
|
|
||||||
// This is just the radio's idea of power. So if you are
|
|
||||||
// controlling EIRP, and you have 3 dB antenna gain, this
|
|
||||||
// needs to reduced by 3 dB.
|
|
||||||
s1_t lbt_dbmax; // max permissible dB on our channel (eg -80)
|
|
||||||
|
|
||||||
u1_t txChnl; // channel for next TX
|
|
||||||
u1_t globalDutyRate; // max rate: 1/2^k
|
|
||||||
|
|
||||||
u1_t upRepeat; // configured up repeat
|
|
||||||
s1_t adrTxPow; // ADR adjusted TX power
|
|
||||||
u1_t datarate; // current data rate
|
|
||||||
u1_t errcr; // error coding rate (used for TX only)
|
|
||||||
u1_t rejoinCnt; // adjustment for rejoin datarate
|
|
||||||
|
|
||||||
u1_t upRepeatCount; // current up-repeat
|
|
||||||
bit_t initBandplanAfterReset; // cleared by LMIC_reset(), set by first join. See issue #244
|
|
||||||
|
|
||||||
u1_t pendTxPort;
|
|
||||||
u1_t pendTxConf; // confirmed data
|
|
||||||
u1_t pendTxLen; // count of bytes in pendTxData.
|
|
||||||
u1_t pendTxData[MAX_LEN_PAYLOAD];
|
|
||||||
|
|
||||||
u1_t pendMacLen; // number of bytes of pending Mac response data
|
|
||||||
bit_t pendMacPiggyback; // received on port 0 or piggyback?
|
|
||||||
// response data if piggybacked
|
|
||||||
u1_t pendMacData[LWAN_FCtrl_FOptsLen_MAX];
|
|
||||||
|
|
||||||
u1_t nwkKey[16]; // network session key
|
|
||||||
u1_t artKey[16]; // application router session key
|
|
||||||
|
|
||||||
u1_t dnConf; // dn frame confirm pending: LORA::FCT_ACK or 0
|
|
||||||
u1_t lastDnConf; // downlink with seqnoDn-1 requested confirmation
|
|
||||||
u1_t adrChanged;
|
|
||||||
|
|
||||||
u1_t rxDelay; // Rx delay after TX
|
|
||||||
|
|
||||||
u1_t margin;
|
|
||||||
s1_t devAnsMargin; // SNR value between -32 and 31 (inclusive) for the last successfully received DevStatusReq command
|
|
||||||
u1_t adrEnabled;
|
|
||||||
u1_t moreData; // NWK has more data pending
|
|
||||||
#if LMIC_ENABLE_TxParamSetupReq
|
|
||||||
u1_t txParam; // the saved TX param byte.
|
|
||||||
#endif
|
|
||||||
#if LMIC_ENABLE_DeviceTimeReq
|
|
||||||
lmic_request_time_state_t txDeviceTimeReqState; // current state, initially idle.
|
|
||||||
u1_t netDeviceTimeFrac; // updated on any DeviceTimeAns.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// rx1DrOffset is the offset from uplink to downlink datarate
|
|
||||||
u1_t rx1DrOffset; // captured from join. zero by default.
|
|
||||||
|
|
||||||
// 2nd RX window (after up stream)
|
|
||||||
u1_t dn2Dr;
|
|
||||||
#if !defined(DISABLE_MCMD_RXParamSetupReq)
|
|
||||||
u1_t dn2Ans; // 0=no answer pend, 0x80+ACKs
|
|
||||||
#endif
|
|
||||||
#if !defined(DISABLE_MCMD_DlChannelReq)
|
|
||||||
u1_t macDlChannelAns; // 0 ==> no answer pending, 0x80+ACK bits
|
|
||||||
#endif
|
|
||||||
#if !defined(DISABLE_MCMD_RXTimingSetupReq)
|
|
||||||
bit_t macRxTimingSetupAns; // 0 ==> no answer pend, non-zero inserts response.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Class B state
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
u1_t missedBcns; // unable to track last N beacons
|
|
||||||
u1_t bcninfoTries; // how often to try (scan mode only)
|
|
||||||
#endif
|
|
||||||
// Public part of MAC state
|
|
||||||
u1_t txCnt;
|
|
||||||
u1_t txrxFlags; // transaction flags (TX-RX combo)
|
|
||||||
u1_t dataBeg; // 0 or start of data (dataBeg-1 is port)
|
|
||||||
u1_t dataLen; // 0 no data or zero length data, >0 byte count of data
|
|
||||||
u1_t frame[MAX_LEN_FRAME];
|
|
||||||
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
u1_t bcnChnl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u1_t noRXIQinversion;
|
|
||||||
u1_t saveIrqFlags; // last LoRa IRQ flags
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \var struct lmic_t LMIC
|
|
||||||
//! The state of LMIC MAC layer is encapsulated in this variable.
|
|
||||||
DECLARE_LMIC; //!< \internal
|
|
||||||
|
|
||||||
//! Construct a bit map of allowed datarates from drlo to drhi (both included).
|
|
||||||
#define DR_RANGE_MAP(drlo,drhi) (((u2_t)0xFFFF<<(drlo)) & ((u2_t)0xFFFF>>(15-(drhi))))
|
|
||||||
bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap);
|
|
||||||
bit_t LMIC_setupChannel (u1_t channel, u4_t freq, u2_t drmap, s1_t band);
|
|
||||||
bit_t LMIC_disableChannel (u1_t channel);
|
|
||||||
bit_t LMIC_enableSubBand(u1_t band);
|
|
||||||
bit_t LMIC_enableChannel(u1_t channel);
|
|
||||||
bit_t LMIC_disableSubBand(u1_t band);
|
|
||||||
bit_t LMIC_selectSubBand(u1_t band);
|
|
||||||
|
|
||||||
void LMIC_setDrTxpow (dr_t dr, s1_t txpow); // set default/start DR/txpow
|
|
||||||
void LMIC_setAdrMode (bit_t enabled); // set ADR mode (if mobile turn off)
|
|
||||||
|
|
||||||
#if !defined(DISABLE_JOIN)
|
|
||||||
bit_t LMIC_startJoining (void);
|
|
||||||
void LMIC_tryRejoin (void);
|
|
||||||
void LMIC_unjoin (void);
|
|
||||||
void LMIC_unjoinAndRejoin (void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void LMIC_shutdown (void);
|
|
||||||
void LMIC_init (void);
|
|
||||||
void LMIC_reset (void);
|
|
||||||
void LMIC_clrTxData (void);
|
|
||||||
void LMIC_setTxData (void);
|
|
||||||
void LMIC_setTxData_strict(void);
|
|
||||||
lmic_tx_error_t LMIC_setTxData2(u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed);
|
|
||||||
lmic_tx_error_t LMIC_setTxData2_strict(u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed);
|
|
||||||
lmic_tx_error_t LMIC_sendWithCallback(u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed, lmic_txmessage_cb_t *pCb, void *pUserData);
|
|
||||||
lmic_tx_error_t LMIC_sendWithCallback_strict(u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed, lmic_txmessage_cb_t *pCb, void *pUserData);
|
|
||||||
void LMIC_sendAlive (void);
|
|
||||||
|
|
||||||
#if !defined(DISABLE_BEACONS)
|
|
||||||
bit_t LMIC_enableTracking (u1_t tryBcnInfo);
|
|
||||||
void LMIC_disableTracking (void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(DISABLE_PING)
|
|
||||||
void LMIC_stopPingable (void);
|
|
||||||
void LMIC_setPingable (u1_t intvExp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey);
|
|
||||||
void LMIC_setLinkCheckMode (bit_t enabled);
|
|
||||||
void LMIC_setClockError(u2_t error);
|
|
||||||
|
|
||||||
u4_t LMIC_getSeqnoUp (void);
|
|
||||||
u4_t LMIC_setSeqnoUp (u4_t);
|
|
||||||
void LMIC_getSessionKeys (u4_t *netid, devaddr_t *devaddr, xref2u1_t nwkKey, xref2u1_t artKey);
|
|
||||||
|
|
||||||
void LMIC_requestNetworkTime(lmic_request_network_time_cb_t *pCallbackfn, void *pUserData);
|
|
||||||
int LMIC_getNetworkTimeReference(lmic_time_reference_t *pReference);
|
|
||||||
|
|
||||||
int LMIC_registerRxMessageCb(lmic_rxmessage_cb_t *pRxMessageCb, void *pUserData);
|
|
||||||
int LMIC_registerEventCb(lmic_event_cb_t *pEventCb, void *pUserData);
|
|
||||||
|
|
||||||
// APIs for client half of compliance.
|
|
||||||
typedef u1_t lmic_compliance_rx_action_t;
|
|
||||||
|
|
||||||
enum lmic_compliance_rx_action_e {
|
|
||||||
LMIC_COMPLIANCE_RX_ACTION_PROCESS = 0, // process this message normally
|
|
||||||
LMIC_COMPLIANCE_RX_ACTION_START, // enter compliance mode, discard this message
|
|
||||||
LMIC_COMPLIANCE_RX_ACTION_IGNORE, // continue in compliance mode, discard this message
|
|
||||||
LMIC_COMPLIANCE_RX_ACTION_END // exit compliance mode, discard this message
|
|
||||||
};
|
|
||||||
|
|
||||||
lmic_compliance_rx_action_t LMIC_complianceRxMessage(u1_t port, const u1_t *pMessage, size_t nMessage);
|
|
||||||
|
|
||||||
// Declare onEvent() function, to make sure any definition will have the
|
|
||||||
// C conventions, even when in a C++ file.
|
|
||||||
#if LMIC_ENABLE_onEvent
|
|
||||||
DECL_ON_LMIC_EVENT;
|
|
||||||
#endif /* LMIC_ENABLE_onEvent */
|
|
||||||
|
|
||||||
// Special APIs - for development or testing
|
|
||||||
// !!!See implementation for caveats!!!
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// names for backward compatibility
|
|
||||||
#include "lmic_compat.h"
|
|
||||||
|
|
||||||
#endif // _lmic_h_
|
|
|
@ -1,47 +0,0 @@
|
||||||
// project-specific definitions
|
|
||||||
//#define CFG_eu868 1
|
|
||||||
#define CFG_us915 1
|
|
||||||
//#define CFG_au915 1
|
|
||||||
//#define CFG_as923 1
|
|
||||||
// #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */
|
|
||||||
//#define CFG_kr920 1
|
|
||||||
//#define CFG_in866 1
|
|
||||||
#define CFG_sx1276_radio 1
|
|
||||||
//#define LMIC_USE_INTERRUPTS
|
|
||||||
// define this in lmic_project_config.h to disable all code related to joining
|
|
||||||
#define DISABLE_JOIN
|
|
||||||
// define this in lmic_project_config.h to disable all code related to ping
|
|
||||||
#define DISABLE_PING
|
|
||||||
// define this in lmic_project_config.h to disable all code related to beacon tracking.
|
|
||||||
// Requires ping to be disabled too
|
|
||||||
#define DISABLE_BEACONS
|
|
||||||
|
|
||||||
// define these in lmic_project_config.h to disable the corresponding MAC commands.
|
|
||||||
// Class A
|
|
||||||
//#define DISABLE_MCMD_DutyCycleReq // duty cycle cap
|
|
||||||
//#define DISABLE_MCMD_RXParamSetupReq // 2nd DN window param
|
|
||||||
//#define DISABLE_MCMD_NewChannelReq // set new channel
|
|
||||||
//#define DISABLE_MCMD_DlChannelReq // set downlink channel for RX1 for given uplink channel.
|
|
||||||
//#define DISABLE_MCMD_RXTimingSetupReq // delay between TX and RX
|
|
||||||
// Class B
|
|
||||||
//#define DISABLE_MCMD_PingSlotChannelReq // set ping freq, automatically disabled by DISABLE_PING
|
|
||||||
//#define ENABLE_MCMD_BeaconTimingAns // next beacon start, DEPRECATED, normally disabled by DISABLE_BEACON
|
|
||||||
|
|
||||||
// DEPRECATED(tmm@mcci.com); replaced by LMIC.noRXIQinversion (dynamic). Don't define this.
|
|
||||||
//#define DISABLE_INVERT_IQ_ON_RX
|
|
||||||
|
|
||||||
// This allows choosing between multiple included AES implementations.
|
|
||||||
// Make sure exactly one of these is uncommented.
|
|
||||||
//
|
|
||||||
// This selects the original AES implementation included LMIC. This
|
|
||||||
// implementation is optimized for speed on 32-bit processors using
|
|
||||||
// fairly big lookup tables, but it takes up big amounts of flash on the
|
|
||||||
// AVR architecture.
|
|
||||||
// #define USE_ORIGINAL_AES
|
|
||||||
//
|
|
||||||
// This selects the AES implementation written by Ideetroon for their
|
|
||||||
// own LoRaWAN library. It also uses lookup tables, but smaller
|
|
||||||
// byte-oriented ones, making it use a lot less flash space (but it is
|
|
||||||
// also about twice as slow as the original).
|
|
||||||
// #define USE_IDEETRON_AES
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user