LMIC transmit example for NAmote-72 with GPS
Dependencies: lib_gps lib_mpl3115a2 lmic_MOTE_L152RC mbed
Deprecated and replaced with
Import programLoRaWAN-NAMote72-Application-Demo
Demonstration of Class-A LoRaWAN device using NAMote-72
LoRaWAN Network Configuration (in Config.h)
For Over the Air (OTA) activation of an End-Device, it must be configured with the following parameters:
DEVEUI
(8 Bytes) : Fist 3 Bytes is the Organizationally Unique Identifier (OUI) followed by 5 bytes of unique ID.APPEUI
(8 Bytes)APPKey
(or DEVKEY) (16 Bytes) The parameters can be entered as shown in the figure below
LoRaWAN Transmission Configuration (in Config.h)
- Inter-Frame Delay :
One can change the delay between each frame transmission using
MS_DELAY_NEXT_TX
It is advisable thatMS_DELAY_NEXT_TX
is greater than or equal to 3sec.
- Payload Length :
The lenght of the payload (in bytes) to be transmitted can be configured using
PAYLOAD_LENGTH
- Data Rate :
The data rate can be configured as per LoRaWAN specification using the paramter
FIXED_DR
- Channel Configuration :
In the case where the End-Device is transmitting over frequencies corresponding to a block of 8 channels, the block can be specified using
CHNL_HYBRID
. The value 0 corresponds to Block A, 1 corresponds to Block B and so on. When the End-Device transmits over more than 50 channels,CHNL_HYBRID
needs to be commented out
- Transmit Power :
The power of the data to be transmitted can be configured using the parameter
FIXED_TX_POWER
. The maximum transmit power allowed is as per FCC regulation, depending upon the mode of transmission.
Serial Terminal Display
By using a serial port connection using applications such as teraterm or putty, one can view the status of the End-Device. Once the End-Device Joins the network, transmission parameters such as payload data, transmit power, battery level etc. are displayed on the terminal.
Default Application Payload
This application defaults to sending uplink data to logical port 5. The application payload consists of:
Sample Application Payload Calculation for Longitude/Latitude
Payload => 00 19 F6 352BBA A94C20 FFFF
Temperature Calculation
19H => 2510
Temp = 25/2 = 12.5 oC
Battery Level
FFH => 100 %
F6H => 96.5 %
Longitude Calculation
longitude = A94C20H => 1109507210
longitudinal coordinate = -360 + (longitude10 x 180/(223))
longitudinal coordinate = -121.93
Latitude Calculation
latitude = 352BBAH = 348460210
latitude coordinate = (latitude10 x 90/(223-1))
latitude coordinate = 37.39
main.cpp@8:26682f47bff1, 2016-03-02 (annotated)
- Committer:
- ubhat
- Date:
- Wed Mar 02 08:11:33 2016 +0000
- Revision:
- 8:26682f47bff1
- Parent:
- 6:0b2b2d196ddd
Restructure Main.cpp & config.h
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ubhat | 8:26682f47bff1 | 1 | /******************************************************************************* |
ubhat | 8:26682f47bff1 | 2 | * Copyright (c) 2014-2015 IBM Corporation. |
ubhat | 8:26682f47bff1 | 3 | * All rights reserved. This program and the accompanying materials |
ubhat | 8:26682f47bff1 | 4 | * are made available under the terms of the Eclipse Public License v1.0 |
ubhat | 8:26682f47bff1 | 5 | * which accompanies this distribution, and is available at |
ubhat | 8:26682f47bff1 | 6 | * http://www.eclipse.org/legal/epl-v10.html |
ubhat | 8:26682f47bff1 | 7 | * |
ubhat | 8:26682f47bff1 | 8 | * Contributors: |
ubhat | 8:26682f47bff1 | 9 | * IBM Zurich Research Lab - initial API, implementation and documentation |
ubhat | 8:26682f47bff1 | 10 | *******************************************************************************/ |
dudmuck | 0:a5e3347bad61 | 11 | |
dudmuck | 0:a5e3347bad61 | 12 | #include "lmic.h" |
ubhat | 8:26682f47bff1 | 13 | #include "debug.h" |
ubhat | 8:26682f47bff1 | 14 | #include <mbed.h> |
dudmuck | 0:a5e3347bad61 | 15 | #include "gps.h" |
ubhat | 8:26682f47bff1 | 16 | #include "mpl3115a2.h" |
dudmuck | 0:a5e3347bad61 | 17 | |
ubhat | 8:26682f47bff1 | 18 | #define FHS_MAX_POW 30 /* Frequency Hopping Max Power */ |
ubhat | 8:26682f47bff1 | 19 | #define DMTS_MAX_POW 26 /* Digital Modulation Max Power */ |
ubhat | 8:26682f47bff1 | 20 | #define HS_MAX_POW 20 /* Hybrid System Max Power */ |
dudmuck | 0:a5e3347bad61 | 21 | |
ubhat | 8:26682f47bff1 | 22 | bool joined; |
dudmuck | 2:a8f00db60fdb | 23 | typedef enum { |
dudmuck | 2:a8f00db60fdb | 24 | MOTE_NONE = 0, |
dudmuck | 2:a8f00db60fdb | 25 | MOTE_V2, |
dudmuck | 2:a8f00db60fdb | 26 | MOTE_V3 |
dudmuck | 2:a8f00db60fdb | 27 | } mote_version_e; |
dudmuck | 2:a8f00db60fdb | 28 | mote_version_e mote_version = MOTE_NONE; |
dudmuck | 2:a8f00db60fdb | 29 | |
ubhat | 8:26682f47bff1 | 30 | DigitalOut gps_en(PB_11); // dis/enables voltage divider on PA_1 |
dudmuck | 2:a8f00db60fdb | 31 | DigitalOut pc_7(PC_7); |
dudmuck | 2:a8f00db60fdb | 32 | DigitalIn pc_1(PC_1); |
ubhat | 8:26682f47bff1 | 33 | AnalogIn *bat; |
ubhat | 8:26682f47bff1 | 34 | #define LOW_BAT_THRESHOLD 3.45 |
ubhat | 8:26682f47bff1 | 35 | #define AIN_VREF 3.3 // stm32 internal refernce |
ubhat | 8:26682f47bff1 | 36 | #define AIN_VBAT_DIV 2 // resistor divider |
ubhat | 8:26682f47bff1 | 37 | |
ubhat | 8:26682f47bff1 | 38 | #define LED_ON 0 |
ubhat | 8:26682f47bff1 | 39 | #define LED_OFF 1 |
ubhat | 8:26682f47bff1 | 40 | static DigitalOut led_red(PB_1); |
ubhat | 8:26682f47bff1 | 41 | static DigitalOut led_yellow(PB_10); |
ubhat | 8:26682f47bff1 | 42 | //static DigitalOut led_green(PC_3); |
ubhat | 8:26682f47bff1 | 43 | static DigitalOut led_usr(PA_5); |
dudmuck | 2:a8f00db60fdb | 44 | |
dudmuck | 2:a8f00db60fdb | 45 | |
dudmuck | 0:a5e3347bad61 | 46 | GPS gps(PB_6, PB_7, PB_11); |
dudmuck | 0:a5e3347bad61 | 47 | I2C i2c(I2C_SDA, I2C_SCL); |
dudmuck | 0:a5e3347bad61 | 48 | DigitalIn i2c_int_pin(PB_4); |
dudmuck | 0:a5e3347bad61 | 49 | MPL3115A2 mpl3115a2(i2c, i2c_int_pin); |
ubhat | 8:26682f47bff1 | 50 | volatile bool AppLedStateOn = false; |
ubhat | 8:26682f47bff1 | 51 | |
dudmuck | 0:a5e3347bad61 | 52 | |
dudmuck | 0:a5e3347bad61 | 53 | ////////////////////////////////////////////////// |
dudmuck | 0:a5e3347bad61 | 54 | // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW) |
dudmuck | 0:a5e3347bad61 | 55 | ////////////////////////////////////////////////// |
dudmuck | 0:a5e3347bad61 | 56 | |
ubhat | 8:26682f47bff1 | 57 | static const u1_t app_eui[ 8] = { APPEUI }; |
ubhat | 8:26682f47bff1 | 58 | //static u1_t dev_eui[ 8] = { OUI, 0x00, 0xff, 0xff, 0xff, 0xff }; |
ubhat | 8:26682f47bff1 | 59 | static u1_t dev_eui[ 8] = { DEVEUI }; |
ubhat | 8:26682f47bff1 | 60 | static const u1_t dev_key[16] = { DEVKEY }; |
dudmuck | 0:a5e3347bad61 | 61 | |
dudmuck | 0:a5e3347bad61 | 62 | |
dudmuck | 0:a5e3347bad61 | 63 | ////////////////////////////////////////////////// |
dudmuck | 0:a5e3347bad61 | 64 | // APPLICATION CALLBACKS |
dudmuck | 0:a5e3347bad61 | 65 | ////////////////////////////////////////////////// |
dudmuck | 0:a5e3347bad61 | 66 | |
dudmuck | 0:a5e3347bad61 | 67 | // provide application router ID (8 bytes, LSBF) |
dudmuck | 0:a5e3347bad61 | 68 | void os_getArtEui (u1_t* buf) { |
ubhat | 8:26682f47bff1 | 69 | LMIC_reverse_memcpy(buf, app_eui, sizeof(app_eui)); |
dudmuck | 0:a5e3347bad61 | 70 | } |
dudmuck | 0:a5e3347bad61 | 71 | |
dudmuck | 0:a5e3347bad61 | 72 | // provide device ID (8 bytes, LSBF) |
dudmuck | 0:a5e3347bad61 | 73 | void os_getDevEui (u1_t* buf) { |
ubhat | 8:26682f47bff1 | 74 | LMIC_reverse_memcpy(buf, dev_eui, sizeof(dev_eui)); |
dudmuck | 0:a5e3347bad61 | 75 | } |
dudmuck | 0:a5e3347bad61 | 76 | |
dudmuck | 0:a5e3347bad61 | 77 | // provide device key (16 bytes) |
dudmuck | 0:a5e3347bad61 | 78 | void os_getDevKey (u1_t* buf) { |
ubhat | 8:26682f47bff1 | 79 | memcpy(buf, dev_key, sizeof(dev_key)); |
dudmuck | 0:a5e3347bad61 | 80 | } |
dudmuck | 0:a5e3347bad61 | 81 | |
ubhat | 8:26682f47bff1 | 82 | |
dudmuck | 0:a5e3347bad61 | 83 | ////////////////////////////////////////////////// |
dudmuck | 0:a5e3347bad61 | 84 | // MAIN - INITIALIZATION AND STARTUP |
dudmuck | 0:a5e3347bad61 | 85 | ////////////////////////////////////////////////// |
dudmuck | 2:a8f00db60fdb | 86 | void get_mote_version() |
dudmuck | 2:a8f00db60fdb | 87 | { |
dudmuck | 2:a8f00db60fdb | 88 | char first; |
dudmuck | 2:a8f00db60fdb | 89 | |
dudmuck | 2:a8f00db60fdb | 90 | pc_7 = 1; |
dudmuck | 2:a8f00db60fdb | 91 | first = pc_1; |
dudmuck | 2:a8f00db60fdb | 92 | pc_7 = 0; |
dudmuck | 2:a8f00db60fdb | 93 | if (first && !pc_1) { |
ubhat | 8:26682f47bff1 | 94 | gps.en_invert = 1; |
dudmuck | 2:a8f00db60fdb | 95 | mote_version = MOTE_V2; |
ubhat | 8:26682f47bff1 | 96 | bat = new AnalogIn(PA_0); |
dudmuck | 2:a8f00db60fdb | 97 | } else { |
dudmuck | 2:a8f00db60fdb | 98 | mote_version = MOTE_V3; |
dudmuck | 3:d81e4a63fb2e | 99 | bat = new AnalogIn(PA_1); |
ubhat | 8:26682f47bff1 | 100 | //gps.en_invert = 0; |
ubhat | 8:26682f47bff1 | 101 | gps_en = 0; |
dudmuck | 2:a8f00db60fdb | 102 | } |
dudmuck | 2:a8f00db60fdb | 103 | } |
dudmuck | 0:a5e3347bad61 | 104 | |
ubhat | 8:26682f47bff1 | 105 | ////////////////////////////////////////////////// |
ubhat | 8:26682f47bff1 | 106 | // Display network parameters (DevEUI, AppEUI etc) |
ubhat | 8:26682f47bff1 | 107 | ////////////////////////////////////////////////// |
ubhat | 8:26682f47bff1 | 108 | void DisplayNetworkParam() |
ubhat | 8:26682f47bff1 | 109 | { |
ubhat | 8:26682f47bff1 | 110 | int i; |
ubhat | 8:26682f47bff1 | 111 | |
ubhat | 8:26682f47bff1 | 112 | if(mote_version == MOTE_V2) |
ubhat | 8:26682f47bff1 | 113 | printf("\r\nNA Mote Ver. 2\r\n"); |
ubhat | 8:26682f47bff1 | 114 | else |
ubhat | 8:26682f47bff1 | 115 | if(mote_version == MOTE_V3) |
ubhat | 8:26682f47bff1 | 116 | printf("\r\nNA Mote Ver. 3\r\n"); |
ubhat | 8:26682f47bff1 | 117 | else |
ubhat | 8:26682f47bff1 | 118 | printf("\r\nNA Mote Ver. NOT DEFINED\r\n"); |
ubhat | 8:26682f47bff1 | 119 | |
ubhat | 8:26682f47bff1 | 120 | printf("DEVEUI:"); |
ubhat | 8:26682f47bff1 | 121 | for (i = 0; i < sizeof(dev_eui); i++) { |
ubhat | 8:26682f47bff1 | 122 | printf("%02x", dev_eui[i]); |
ubhat | 8:26682f47bff1 | 123 | if (i < sizeof(dev_eui)-1) |
ubhat | 8:26682f47bff1 | 124 | printf("-"); |
ubhat | 8:26682f47bff1 | 125 | } |
ubhat | 8:26682f47bff1 | 126 | printf("\r\n"); |
ubhat | 8:26682f47bff1 | 127 | |
ubhat | 8:26682f47bff1 | 128 | printf("APPEUI:"); |
ubhat | 8:26682f47bff1 | 129 | for (i = 0; i < sizeof(app_eui); i++) { |
ubhat | 8:26682f47bff1 | 130 | printf("%02x", app_eui[i]); |
ubhat | 8:26682f47bff1 | 131 | if (i < sizeof(app_eui)-1) |
ubhat | 8:26682f47bff1 | 132 | printf("-"); |
ubhat | 8:26682f47bff1 | 133 | } |
ubhat | 8:26682f47bff1 | 134 | printf("\r\n"); |
ubhat | 8:26682f47bff1 | 135 | |
ubhat | 8:26682f47bff1 | 136 | printf("DEVKEY:"); |
ubhat | 8:26682f47bff1 | 137 | for (i = 0; i < sizeof(dev_key); i++) { |
ubhat | 8:26682f47bff1 | 138 | printf("%02x ", dev_key[i]); |
ubhat | 8:26682f47bff1 | 139 | } |
ubhat | 8:26682f47bff1 | 140 | printf("\r\n"); |
ubhat | 8:26682f47bff1 | 141 | } |
ubhat | 8:26682f47bff1 | 142 | |
ubhat | 8:26682f47bff1 | 143 | void DisplayData(uint8_t *pData, int len) |
ubhat | 8:26682f47bff1 | 144 | { |
ubhat | 8:26682f47bff1 | 145 | int i; |
ubhat | 8:26682f47bff1 | 146 | |
ubhat | 8:26682f47bff1 | 147 | for(i = 0; i < len; i++) |
ubhat | 8:26682f47bff1 | 148 | printf("%x ", pData[i]); |
ubhat | 8:26682f47bff1 | 149 | printf("\r\n"); |
ubhat | 8:26682f47bff1 | 150 | } |
ubhat | 8:26682f47bff1 | 151 | |
ubhat | 8:26682f47bff1 | 152 | osjob_t nJoinedJob; |
ubhat | 8:26682f47bff1 | 153 | |
ubhat | 8:26682f47bff1 | 154 | static void on_not_joined(osjob_t* j) |
ubhat | 8:26682f47bff1 | 155 | { |
ubhat | 8:26682f47bff1 | 156 | if (joined) |
ubhat | 8:26682f47bff1 | 157 | return; |
ubhat | 8:26682f47bff1 | 158 | |
ubhat | 8:26682f47bff1 | 159 | DisplayNetworkParam(); |
ubhat | 8:26682f47bff1 | 160 | |
ubhat | 8:26682f47bff1 | 161 | os_setTimedCallback( &nJoinedJob, os_getTime() + ms2osticks(7000), on_not_joined ); |
ubhat | 8:26682f47bff1 | 162 | } |
ubhat | 8:26682f47bff1 | 163 | |
ubhat | 8:26682f47bff1 | 164 | |
dudmuck | 0:a5e3347bad61 | 165 | // initial job |
ubhat | 8:26682f47bff1 | 166 | static void initfunc (osjob_t* j) |
ubhat | 8:26682f47bff1 | 167 | { |
ubhat | 8:26682f47bff1 | 168 | u4_t* id; |
ubhat | 8:26682f47bff1 | 169 | u4_t* u4_ptr; |
ubhat | 8:26682f47bff1 | 170 | |
ubhat | 8:26682f47bff1 | 171 | u4_ptr = (u4_t*)&dev_eui[4]; // [4] to [7] |
ubhat | 8:26682f47bff1 | 172 | |
ubhat | 8:26682f47bff1 | 173 | if(*u4_ptr == 0) |
ubhat | 8:26682f47bff1 | 174 | { |
ubhat | 8:26682f47bff1 | 175 | id = (u4_t*)0x1ff800d0; // STM32L1xx Cat3 |
ubhat | 8:26682f47bff1 | 176 | *u4_ptr = *id; |
ubhat | 8:26682f47bff1 | 177 | id = (u4_t*)0x1ff800d4; |
ubhat | 8:26682f47bff1 | 178 | *u4_ptr ^= *id; |
ubhat | 8:26682f47bff1 | 179 | id = (u4_t*)0x1ff800e4; |
ubhat | 8:26682f47bff1 | 180 | *u4_ptr ^= *id; |
ubhat | 8:26682f47bff1 | 181 | } |
ubhat | 8:26682f47bff1 | 182 | |
ubhat | 8:26682f47bff1 | 183 | get_mote_version(); |
ubhat | 8:26682f47bff1 | 184 | gps.init(); |
ubhat | 8:26682f47bff1 | 185 | |
ubhat | 8:26682f47bff1 | 186 | gps.enable(1); |
ubhat | 8:26682f47bff1 | 187 | mpl3115a2.init(); |
ubhat | 8:26682f47bff1 | 188 | |
dudmuck | 0:a5e3347bad61 | 189 | // reset MAC state |
dudmuck | 0:a5e3347bad61 | 190 | LMIC_reset(); |
ubhat | 8:26682f47bff1 | 191 | |
ubhat | 8:26682f47bff1 | 192 | os_setTimedCallback( &nJoinedJob, os_getTime() + ms2osticks(3000), on_not_joined ); |
ubhat | 8:26682f47bff1 | 193 | joined = false; |
dudmuck | 0:a5e3347bad61 | 194 | // start joining |
dudmuck | 0:a5e3347bad61 | 195 | LMIC_startJoining(); |
ubhat | 8:26682f47bff1 | 196 | |
ubhat | 8:26682f47bff1 | 197 | led_red = LED_ON; // indicate joining |
ubhat | 8:26682f47bff1 | 198 | led_yellow = LED_OFF; |
ubhat | 8:26682f47bff1 | 199 | //led_green = LED_OFF; |
dudmuck | 0:a5e3347bad61 | 200 | // init done - onEvent() callback will be invoked... |
dudmuck | 0:a5e3347bad61 | 201 | } |
dudmuck | 0:a5e3347bad61 | 202 | |
ubhat | 8:26682f47bff1 | 203 | |
ubhat | 8:26682f47bff1 | 204 | // application entry point |
ubhat | 8:26682f47bff1 | 205 | int main () { |
dudmuck | 0:a5e3347bad61 | 206 | osjob_t initjob; |
dudmuck | 0:a5e3347bad61 | 207 | |
dudmuck | 0:a5e3347bad61 | 208 | // initialize runtime env |
dudmuck | 0:a5e3347bad61 | 209 | os_init(); |
ubhat | 8:26682f47bff1 | 210 | // initialize debug library |
dudmuck | 0:a5e3347bad61 | 211 | debug_init(); |
dudmuck | 0:a5e3347bad61 | 212 | // setup initial job |
dudmuck | 0:a5e3347bad61 | 213 | os_setCallback(&initjob, initfunc); |
dudmuck | 0:a5e3347bad61 | 214 | // execute scheduled jobs and events |
dudmuck | 0:a5e3347bad61 | 215 | os_runloop(); |
dudmuck | 0:a5e3347bad61 | 216 | // (not reached) |
ubhat | 8:26682f47bff1 | 217 | return 0; |
dudmuck | 0:a5e3347bad61 | 218 | } |
dudmuck | 0:a5e3347bad61 | 219 | |
dudmuck | 3:d81e4a63fb2e | 220 | static void |
dudmuck | 3:d81e4a63fb2e | 221 | restore_hsi() |
dudmuck | 3:d81e4a63fb2e | 222 | { |
dudmuck | 3:d81e4a63fb2e | 223 | RCC_OscInitTypeDef osc_init; |
dudmuck | 3:d81e4a63fb2e | 224 | /* if HSI was shut off in deep sleep (needed for AnalogIn) */ |
dudmuck | 3:d81e4a63fb2e | 225 | HAL_RCC_GetOscConfig(&osc_init); |
dudmuck | 3:d81e4a63fb2e | 226 | if (osc_init.HSIState != RCC_HSI_ON) { |
dudmuck | 3:d81e4a63fb2e | 227 | // Enable the HSI (to clock the ADC) |
dudmuck | 3:d81e4a63fb2e | 228 | osc_init.OscillatorType = RCC_OSCILLATORTYPE_HSI; |
dudmuck | 3:d81e4a63fb2e | 229 | osc_init.HSIState = RCC_HSI_ON; |
dudmuck | 3:d81e4a63fb2e | 230 | osc_init.PLL.PLLState = RCC_PLL_NONE; |
dudmuck | 3:d81e4a63fb2e | 231 | HAL_RCC_OscConfig(&osc_init); |
dudmuck | 3:d81e4a63fb2e | 232 | } |
dudmuck | 3:d81e4a63fb2e | 233 | } |
dudmuck | 3:d81e4a63fb2e | 234 | |
ubhat | 8:26682f47bff1 | 235 | osjob_t sendFrameJob; |
ubhat | 8:26682f47bff1 | 236 | osjob_t indicateJob; |
dudmuck | 0:a5e3347bad61 | 237 | |
ubhat | 8:26682f47bff1 | 238 | static void tx_ind_cb(osjob_t* j) |
ubhat | 8:26682f47bff1 | 239 | { |
ubhat | 8:26682f47bff1 | 240 | led_red = LED_OFF; |
dudmuck | 0:a5e3347bad61 | 241 | } |
dudmuck | 0:a5e3347bad61 | 242 | |
dudmuck | 6:0b2b2d196ddd | 243 | static void onSendFrame (osjob_t* j) |
dudmuck | 6:0b2b2d196ddd | 244 | { |
ubhat | 8:26682f47bff1 | 245 | uint16_t altitudeGps; |
ubhat | 8:26682f47bff1 | 246 | |
ubhat | 8:26682f47bff1 | 247 | if (LMIC.opmode & OP_TXRXPEND) { |
dudmuck | 6:0b2b2d196ddd | 248 | return; |
ubhat | 8:26682f47bff1 | 249 | } |
ubhat | 8:26682f47bff1 | 250 | |
ubhat | 8:26682f47bff1 | 251 | #ifdef FIXED_DR |
ubhat | 8:26682f47bff1 | 252 | LMIC.datarate = FIXED_DR; |
ubhat | 8:26682f47bff1 | 253 | #endif |
ubhat | 8:26682f47bff1 | 254 | |
ubhat | 8:26682f47bff1 | 255 | #ifdef FIXED_TX_POWER |
ubhat | 8:26682f47bff1 | 256 | LMIC.txpow = FIXED_TX_POWER; |
ubhat | 8:26682f47bff1 | 257 | #endif |
ubhat | 8:26682f47bff1 | 258 | |
ubhat | 8:26682f47bff1 | 259 | restore_hsi(); |
ubhat | 8:26682f47bff1 | 260 | |
ubhat | 8:26682f47bff1 | 261 | if(LMIC.datarate == DR_SF8C) |
ubhat | 8:26682f47bff1 | 262 | LMIC.txpow_limit = DMTS_MAX_POW; |
ubhat | 8:26682f47bff1 | 263 | else |
ubhat | 8:26682f47bff1 | 264 | #ifdef CHNL_HYBRID |
ubhat | 8:26682f47bff1 | 265 | LMIC.txpow_limit = HS_MAX_POW; |
ubhat | 8:26682f47bff1 | 266 | #else |
ubhat | 8:26682f47bff1 | 267 | LMIC.txpow_limit = FHS_MAX_POW; |
ubhat | 8:26682f47bff1 | 268 | #endif |
ubhat | 8:26682f47bff1 | 269 | |
ubhat | 8:26682f47bff1 | 270 | if( LMIC.txpow > LMIC.txpow_limit) |
ubhat | 8:26682f47bff1 | 271 | LMIC.txpow = LMIC.txpow_limit; |
ubhat | 8:26682f47bff1 | 272 | |
ubhat | 8:26682f47bff1 | 273 | float volts = bat->read()*AIN_VREF*AIN_VBAT_DIV; |
ubhat | 8:26682f47bff1 | 274 | if (volts < LOW_BAT_THRESHOLD) { |
ubhat | 8:26682f47bff1 | 275 | if (LMIC.txpow_limit > 20) |
ubhat | 8:26682f47bff1 | 276 | LMIC.txpow_limit = 20; |
ubhat | 8:26682f47bff1 | 277 | if (LMIC.txpow > 20) |
ubhat | 8:26682f47bff1 | 278 | LMIC.txpow = 20; |
ubhat | 8:26682f47bff1 | 279 | } |
ubhat | 8:26682f47bff1 | 280 | |
ubhat | 8:26682f47bff1 | 281 | /////////////////////////////////////////////////////////////////// |
ubhat | 8:26682f47bff1 | 282 | gps.service(); |
ubhat | 8:26682f47bff1 | 283 | mpl3115a2.ReadTemperature(); |
ubhat | 8:26682f47bff1 | 284 | |
ubhat | 8:26682f47bff1 | 285 | uint8_t tmpData[PAYLOAD_LENGTH] = {0}; |
ubhat | 8:26682f47bff1 | 286 | |
ubhat | 8:26682f47bff1 | 287 | tmpData[0] = 15-(LMIC.txpow>>1); |
ubhat | 8:26682f47bff1 | 288 | tmpData[0] <<= 4; |
ubhat | 8:26682f47bff1 | 289 | #ifdef CHNL_HYBRID |
ubhat | 8:26682f47bff1 | 290 | tmpData[0] |= 0x04; // 8ch: set bit2 |
ubhat | 8:26682f47bff1 | 291 | #else |
ubhat | 8:26682f47bff1 | 292 | tmpData[0] |= 0x08; // 64ch: set bit3 |
ubhat | 8:26682f47bff1 | 293 | #endif |
ubhat | 8:26682f47bff1 | 294 | |
ubhat | 8:26682f47bff1 | 295 | tmpData[0] |= AppLedStateOn & 1; // (bit 0 == 1) => LED on |
ubhat | 8:26682f47bff1 | 296 | tmpData[1] = (int)mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So, +/-63 C |
ubhat | 8:26682f47bff1 | 297 | tmpData[2] = (bat->read_u16() >> 8) + (bat->read_u16() >> 9) ; // per LoRaMAC spec; 0=Charging; 1...254 = level, 255 = N/A |
ubhat | 8:26682f47bff1 | 298 | |
ubhat | 8:26682f47bff1 | 299 | tmpData[3] = ( gps.LatitudeBinary >> 16 ) & 0xFF; |
ubhat | 8:26682f47bff1 | 300 | tmpData[4] = ( gps.LatitudeBinary >> 8 ) & 0xFF; |
ubhat | 8:26682f47bff1 | 301 | tmpData[5] = gps.LatitudeBinary & 0xFF; |
ubhat | 8:26682f47bff1 | 302 | tmpData[6] = ( gps.LongitudeBinary >> 16 ) & 0xFF; |
ubhat | 8:26682f47bff1 | 303 | tmpData[7] = ( gps.LongitudeBinary >> 8 ) & 0xFF; |
ubhat | 8:26682f47bff1 | 304 | tmpData[8] = gps.LongitudeBinary & 0xFF; |
ubhat | 8:26682f47bff1 | 305 | |
ubhat | 8:26682f47bff1 | 306 | altitudeGps = atoi(gps.NmeaGpsData.NmeaAltitude); |
ubhat | 8:26682f47bff1 | 307 | tmpData[9] = ( altitudeGps >> 8 ) & 0xFF; |
ubhat | 8:26682f47bff1 | 308 | tmpData[10] = altitudeGps & 0xFF; |
ubhat | 8:26682f47bff1 | 309 | if (PAYLOAD_LENGTH > 11) { |
ubhat | 8:26682f47bff1 | 310 | for (int i = 11; i < PAYLOAD_LENGTH; i++) |
ubhat | 8:26682f47bff1 | 311 | tmpData[i] = i - 10; |
ubhat | 8:26682f47bff1 | 312 | } |
ubhat | 8:26682f47bff1 | 313 | |
ubhat | 8:26682f47bff1 | 314 | for(int i = 0; i < PAYLOAD_LENGTH; i++) |
ubhat | 8:26682f47bff1 | 315 | LMIC.frame[i] = tmpData[i]; |
dudmuck | 6:0b2b2d196ddd | 316 | |
ubhat | 8:26682f47bff1 | 317 | // port, buffer, buffer length, need_ack |
ubhat | 8:26682f47bff1 | 318 | LMIC_setTxData2(5, LMIC.frame, PAYLOAD_LENGTH, 0); |
ubhat | 8:26682f47bff1 | 319 | |
ubhat | 8:26682f47bff1 | 320 | led_red = LED_ON; |
ubhat | 8:26682f47bff1 | 321 | |
ubhat | 8:26682f47bff1 | 322 | // Display Info |
ubhat | 8:26682f47bff1 | 323 | |
ubhat | 8:26682f47bff1 | 324 | DisplayNetworkParam(); |
ubhat | 8:26682f47bff1 | 325 | |
ubhat | 8:26682f47bff1 | 326 | printf("Seq# %d\r\n",LMIC.seqnoUp-1); |
ubhat | 8:26682f47bff1 | 327 | |
ubhat | 8:26682f47bff1 | 328 | printf("TX Data: "); |
ubhat | 8:26682f47bff1 | 329 | DisplayData(tmpData, PAYLOAD_LENGTH); |
ubhat | 8:26682f47bff1 | 330 | |
ubhat | 8:26682f47bff1 | 331 | printf("TX Power: %d dBm\r\n",LMIC.txpow); |
ubhat | 8:26682f47bff1 | 332 | |
ubhat | 8:26682f47bff1 | 333 | printf("Battery: %f Volts\r\n",volts); |
ubhat | 8:26682f47bff1 | 334 | |
ubhat | 8:26682f47bff1 | 335 | os_setTimedCallback( &indicateJob, os_getTime() + ms2osticks(30), tx_ind_cb ); |
ubhat | 8:26682f47bff1 | 336 | |
dudmuck | 0:a5e3347bad61 | 337 | } |
dudmuck | 0:a5e3347bad61 | 338 | |
dudmuck | 0:a5e3347bad61 | 339 | |
ubhat | 8:26682f47bff1 | 340 | ////////////////////////////////////////////////// |
ubhat | 8:26682f47bff1 | 341 | // LMIC EVENT CALLBACK |
ubhat | 8:26682f47bff1 | 342 | ////////////////////////////////////////////////// |
dudmuck | 0:a5e3347bad61 | 343 | |
ubhat | 8:26682f47bff1 | 344 | void onEvent (ev_t ev) |
ubhat | 8:26682f47bff1 | 345 | { |
ubhat | 8:26682f47bff1 | 346 | debug_event(ev); |
ubhat | 8:26682f47bff1 | 347 | |
ubhat | 8:26682f47bff1 | 348 | switch(ev) { |
ubhat | 8:26682f47bff1 | 349 | case EV_JOINED: |
ubhat | 8:26682f47bff1 | 350 | // network joined, session established |
ubhat | 8:26682f47bff1 | 351 | debug_val("netid = ", LMIC.netid); |
ubhat | 8:26682f47bff1 | 352 | joined = true; |
ubhat | 8:26682f47bff1 | 353 | led_red = LED_OFF; // indicate joined |
ubhat | 8:26682f47bff1 | 354 | goto tx; |
ubhat | 8:26682f47bff1 | 355 | case EV_TXCOMPLETE: |
ubhat | 8:26682f47bff1 | 356 | // scheduled data sent (optionally data received) |
ubhat | 8:26682f47bff1 | 357 | if(LMIC.dataLen) { // data received in rx slot after tx |
ubhat | 8:26682f47bff1 | 358 | led_yellow = led_yellow ? 0 : 1; |
ubhat | 8:26682f47bff1 | 359 | if (LMIC.dataLen == 1) { // set LED state if exactly one byte is received |
ubhat | 8:26682f47bff1 | 360 | led_usr = LMIC.frame[LMIC.dataBeg] & 0x01; |
ubhat | 8:26682f47bff1 | 361 | } |
ubhat | 8:26682f47bff1 | 362 | debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen); |
dudmuck | 0:a5e3347bad61 | 363 | } |
dudmuck | 0:a5e3347bad61 | 364 | tx: |
ubhat | 8:26682f47bff1 | 365 | os_setTimedCallback( &sendFrameJob, os_getTime() + ms2osticks(MS_DELAY_NEXT_TX), onSendFrame ); |
ubhat | 8:26682f47bff1 | 366 | break; |
ubhat | 8:26682f47bff1 | 367 | default: |
ubhat | 8:26682f47bff1 | 368 | led_red = LED_ON; // indicate not joined |
ubhat | 8:26682f47bff1 | 369 | break; |
ubhat | 8:26682f47bff1 | 370 | } // ..switch(ev) |
ubhat | 8:26682f47bff1 | 371 | } |