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:

  1. DEVEUI (8 Bytes) : Fist 3 Bytes is the Organizationally Unique Identifier (OUI) followed by 5 bytes of unique ID.
  2. APPEUI (8 Bytes)
  3. APPKey (or DEVKEY) (16 Bytes) The parameters can be entered as shown in the figure below /media/uploads/ubhat/nwkconfig.png

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 that MS_DELAY_NEXT_TX is greater than or equal to 3sec. /media/uploads/ubhat/txtiming.png
  • Payload Length : The lenght of the payload (in bytes) to be transmitted can be configured using PAYLOAD_LENGTH /media/uploads/ubhat/payload.png
  • Data Rate : The data rate can be configured as per LoRaWAN specification using the paramter FIXED_DR /media/uploads/ubhat/datarate.png
  • 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. /media/uploads/ubhat/hybrid.png When the End-Device transmits over more than 50 channels, CHNL_HYBRID needs to be commented out /media/uploads/ubhat/frequencyhopping.png
  • 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. /media/uploads/ubhat/txpower.png

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.

/media/uploads/ubhat/teraterm.png

Default Application Payload

This application defaults to sending uplink data to logical port 5. The application payload consists of: /media/uploads/jknapp_smtc/payload.png

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

Files at this revision

API Documentation at this revision

Comitter:
ubhat
Date:
Wed Mar 02 08:11:33 2016 +0000
Parent:
7:7de55330772d
Commit message:
Restructure Main.cpp & config.h

Changed in this revision

config.h Show annotated file Show diff for this revision Revisions of this file
lib_mpl3115a2.lib Show annotated file Show diff for this revision Revisions of this file
lmic_MOTE_L152RC.lib 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
diff -r 7de55330772d -r 26682f47bff1 config.h
--- a/config.h	Fri Jan 15 18:24:10 2016 +0000
+++ b/config.h	Wed Mar 02 08:11:33 2016 +0000
@@ -1,5 +1,31 @@
+// Organizationally Unique Identifier
+#define OUI         0x00, 0x00, 0x00
+
+/* DEVEUI = {[OUI] [5 bytes of Unique ID]}
+if last 4 bytes of DEVEUI equals 0, then the firmware will assign a unique ID
+*/
+#define DEVEUI      OUI, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define APPEUI      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+#define DEVKEY      0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+
+// Time between transmissions in msec
+#define MS_DELAY_NEXT_TX        3000
+
+// Length of payload (Must be within the Maximum Length as defined in 7.2.6 of LoRaWAN 1.0 Specification
+#define PAYLOAD_LENGTH          11  
+
+/* DR_SF10 = 0, DR_SF9 = 1, DR_SF8 = 2, DR_SF7 = 3, DR_SF8C = 4  [as defined in Table 18 of Section 7 of LoRaWAN 1.0 Specification */
+#define FIXED_DR                DR_SF10 
+
+/* US 915MHz ISM Band */
 #define CFG_us915
 
+/* SX1272 chip */
 #define CFG_sx1272_radio
 
-//#define CHNL_HYBRID     0       /* 0-7 to select block of 8 channels used */
\ No newline at end of file
+// 0-7 to select block of 8 channels (Block A = 0, Block B = 1 ... Block H = 7). Comment this line to enable all 64 channels
+#define CHNL_HYBRID     0       
+
+// Set Tx Power in dBm (Max = 30dBm for frequency hopping over 50channels; 26dBm with Digital Modulation; 21dBm in Hybrid mode)
+#define FIXED_TX_POWER  20      
diff -r 7de55330772d -r 26682f47bff1 lib_mpl3115a2.lib
--- a/lib_mpl3115a2.lib	Fri Jan 15 18:24:10 2016 +0000
+++ b/lib_mpl3115a2.lib	Wed Mar 02 08:11:33 2016 +0000
@@ -1,1 +1,1 @@
-https://developer.mbed.org/users/dudmuck/code/lib_mpl3115a2/#3cd1f21925e8
+https://developer.mbed.org/users/dudmuck/code/lib_mpl3115a2/#0eb8b0ad292b
diff -r 7de55330772d -r 26682f47bff1 lmic_MOTE_L152RC.lib
--- a/lmic_MOTE_L152RC.lib	Fri Jan 15 18:24:10 2016 +0000
+++ b/lmic_MOTE_L152RC.lib	Wed Mar 02 08:11:33 2016 +0000
@@ -1,1 +1,1 @@
-https://developer.mbed.org/teams/Semtech/code/lmic_MOTE_L152RC/#0faa1bb768b5
+https://developer.mbed.org/teams/Semtech/code/lmic_MOTE_L152RC/#6c0830baf10f
diff -r 7de55330772d -r 26682f47bff1 main.cpp
--- a/main.cpp	Fri Jan 15 18:24:10 2016 +0000
+++ b/main.cpp	Wed Mar 02 08:11:33 2016 +0000
@@ -1,26 +1,25 @@
-/*
- / _____)             _              | |
-( (____  _____ ____ _| |_ _____  ____| |__
- \____ \| ___ |    (_   _) ___ |/ ___)  _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
-    (C)2013 Semtech
-
-Description: MBED example application
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
+/*******************************************************************************
+ * Copyright (c) 2014-2015 IBM Corporation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Zurich Research Lab - initial API, implementation and documentation
+ *******************************************************************************/
 
-Maintainer: Miguel Luis and Gregory Cristian
-*/
-#include "mbed.h"
 #include "lmic.h"
-#include "mpl3115a2.h"
+#include "debug.h"
+#include <mbed.h>
 #include "gps.h"
-#include "debug.h"
+#include "mpl3115a2.h"
 
-#define SENET_F
-//#define SMTC
+#define FHS_MAX_POW     30      /* Frequency Hopping Max Power */
+#define DMTS_MAX_POW    26      /* Digital Modulation Max Power */
+#define HS_MAX_POW      20      /* Hybrid System Max Power */
 
+bool joined;
 typedef enum {
     MOTE_NONE = 0,
     MOTE_V2,
@@ -28,89 +27,38 @@
 } mote_version_e;
 mote_version_e mote_version = MOTE_NONE;
 
+DigitalOut gps_en(PB_11);   // dis/enables voltage divider on PA_1
 DigitalOut pc_7(PC_7);
 DigitalIn pc_1(PC_1);
+AnalogIn *bat;
+#define LOW_BAT_THRESHOLD   3.45
+#define AIN_VREF        3.3     // stm32 internal refernce
+#define AIN_VBAT_DIV    2       // resistor divider
+
+#define LED_ON          0
+#define LED_OFF         1
+static DigitalOut led_red(PB_1);
+static DigitalOut led_yellow(PB_10);
+//static DigitalOut led_green(PC_3);
+static DigitalOut led_usr(PA_5);
 
 
-/* ****************************************** */
-/* ***** Basic App and Network Parameters *** */
-/* ****************************************** */
-// Hybrid Mode must be defined in lmic.h      //
-// DevEUI and Keys defined by Activation type //
-#define APP_DATA_SIZE               11
-#define APP_ACK                     0
-#define MS_DELAY_NEXT_TX               400
-#ifdef SMTC
-#define OVER_THE_AIR_ACTIVATION     1 //0
-#else
-#define OVER_THE_AIR_ACTIVATION     1
-#endif /* SMTC */
-
-/* ***************************************** */
-
-#define LED_RED         PB_1
-#define LED_YEL         PB_10
-
-static DigitalOut led1(LED_RED);
-static DigitalOut led2(LED_YEL);
-
-/*  gps(tx, rx, en); */
 GPS gps(PB_6, PB_7, PB_11);
-
 I2C i2c(I2C_SDA, I2C_SCL);
 DigitalIn i2c_int_pin(PB_4);
 MPL3115A2 mpl3115a2(i2c, i2c_int_pin);
-AnalogIn *bat;
-#define LOW_BAT_THRESHOLD   3.45
+volatile bool AppLedStateOn = false;
+
 
 //////////////////////////////////////////////////
 // CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
 //////////////////////////////////////////////////
-#ifdef SENET_F
-// application router ID (LSBF)
-//static const u1_t APPEUI[8]  = { 0x01, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x25, 0x00  };
-static const u1_t reverse_APPEUI[8]  = { 0x00, 0x25, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x01 };
-
-// unique device ID (LSBF)
-//static const u1_t DEVEUI[8]  = { 0x0f, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x25, 0x00 };
-static const u1_t reverse_DEVEUI[8]  = { 0x00, 0x25, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x0F };
-
-// device-specific AES key (derived from device EUI)
-static const u1_t DEVKEY[16] = { 0xe4, 0x72, 0x71, 0xc5, 0xf5, 0x30, 0xa9, 0x9f, 0xcf, 0xc4, 0x0e, 0xab, 0xea, 0xd7, 0x19, 0x42, };
-                             //    E4   -72   -71   -C5   -F5   -30   -A9   -9F   -CF   -C4   -0E   -AB   -EA   -D7   -19   -42
-#endif /* SENET_F */
-
-#ifdef SMTC
-// Semtech Activation (v1.x server)
-// application router ID (LSBF)
-static const u1_t reverse_APPEUI[8]  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    //AA-AA-AA-AA-FF-FF-FF-FF
-//static const u1_t APPEUI[8]  = { 0xff, 0xff, 0xff, 0xff, 0xaa, 0xaa, 0xaa, 0xaa };   
-//static const u1_t reverse_APPEUI[8]  = { 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff, 0xff };  
 
-// unique device ID (LSBF)
-//static const u1_t DEVEUI[8]  = { 0x21, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x25, 0x00 };
-static const u1_t reverse_DEVEUI[8]  = { 0x00, 0x25, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x20 };
-//static const u1_t DEVEUI[8]  = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
-//static const u1_t reverse_DEVEUI[8]  = { 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01 };
-
-// device-specific AES key (derived from device EUI)
-static const u1_t DEVKEY[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff  };
-//static const u1_t DEVKEY[16] = { 0xab, 0x89, 0xef, 0xcd, 0x23, 0x01, 0x67, 0x45, 0x54, 0x76, 0x10, 0x32, 0xdc, 0xfe, 0x98, 0xba };
+static const u1_t app_eui[ 8] = { APPEUI };
+//static       u1_t dev_eui[ 8] = { OUI, 0x00, 0xff, 0xff, 0xff, 0xff };
+static       u1_t dev_eui[ 8] = { DEVEUI };
+static const u1_t dev_key[16] = { DEVKEY };
 
-/*static uint8_t NwkSKey[] = 
-{ 
-    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
-    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
-};
-
-static uint8_t ArtSKey[] = 
-{ 
-    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
-    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
-};*/
-
-#endif /* SMTC */
 
 //////////////////////////////////////////////////
 // APPLICATION CALLBACKS
@@ -118,21 +66,20 @@
 
 // provide application router ID (8 bytes, LSBF)
 void os_getArtEui (u1_t* buf) {
-    //memcpy(buf, APPEUI, 8);
-    LMIC_reverse_memcpy(buf, reverse_APPEUI, 8);
+    LMIC_reverse_memcpy(buf, app_eui, sizeof(app_eui));
 }
 
 // provide device ID (8 bytes, LSBF)
 void os_getDevEui (u1_t* buf) {
-    //memcpy(buf, DEVEUI, 8);
-    LMIC_reverse_memcpy(buf, reverse_DEVEUI, 8);
+    LMIC_reverse_memcpy(buf, dev_eui, sizeof(dev_eui));
 }
 
 // provide device key (16 bytes)
 void os_getDevKey (u1_t* buf) {
-    memcpy(buf, DEVKEY, 16);
+    memcpy(buf, dev_key, sizeof(dev_key));
 }
 
+
 //////////////////////////////////////////////////
 // MAIN - INITIALIZATION AND STARTUP
 //////////////////////////////////////////////////
@@ -144,74 +91,130 @@
     first = pc_1;
     pc_7 = 0;
     if (first && !pc_1) {
+        gps.en_invert = 1;
         mote_version = MOTE_V2;
-        printf("v2\r\n");
-        bat = new AnalogIn(PA_0);
+        bat = new AnalogIn(PA_0);       
     } else {
         mote_version = MOTE_V3;
-        printf("v3\r\n");
         bat = new AnalogIn(PA_1);
+        //gps.en_invert = 0;        
+        gps_en = 0;
     }
 }
 
+//////////////////////////////////////////////////
+// Display network parameters (DevEUI, AppEUI etc)
+//////////////////////////////////////////////////
+void DisplayNetworkParam()
+{
+    int i;
+
+    if(mote_version == MOTE_V2)
+        printf("\r\nNA Mote Ver. 2\r\n");
+    else
+        if(mote_version == MOTE_V3)
+            printf("\r\nNA Mote Ver. 3\r\n");
+        else
+            printf("\r\nNA Mote Ver. NOT DEFINED\r\n");
+        
+    printf("DEVEUI:");
+    for (i = 0; i < sizeof(dev_eui); i++) {
+        printf("%02x", dev_eui[i]);
+        if (i < sizeof(dev_eui)-1)
+            printf("-");
+    }
+    printf("\r\n");
+    
+    printf("APPEUI:");
+    for (i = 0; i < sizeof(app_eui); i++) {
+        printf("%02x", app_eui[i]);
+        if (i < sizeof(app_eui)-1)
+            printf("-");        
+    }
+    printf("\r\n");
+        
+    printf("DEVKEY:");
+    for (i = 0; i < sizeof(dev_key); i++) {
+        printf("%02x ", dev_key[i]);
+    }
+    printf("\r\n"); 
+}
+
+void DisplayData(uint8_t *pData, int len)
+{
+    int i;
+
+    for(i = 0; i < len; i++)
+        printf("%x ", pData[i]);
+    printf("\r\n");
+}
+
+osjob_t nJoinedJob;
+
+static void on_not_joined(osjob_t* j)
+{   
+    if (joined)
+        return;
+
+    DisplayNetworkParam();
+    
+    os_setTimedCallback( &nJoinedJob, os_getTime() + ms2osticks(7000), on_not_joined );
+}
+
+
 // initial job
-static void initfunc (osjob_t* j) {
-    debug_str("B: INITFUNC\n");
+static void initfunc (osjob_t* j)
+{
+    u4_t* id;
+    u4_t* u4_ptr;
+    
+    u4_ptr = (u4_t*)&dev_eui[4];   // [4] to [7]
+
+    if(*u4_ptr == 0)
+    {
+        id = (u4_t*)0x1ff800d0; // STM32L1xx Cat3
+        *u4_ptr = *id;
+        id = (u4_t*)0x1ff800d4;
+        *u4_ptr ^= *id;
+        id = (u4_t*)0x1ff800e4;
+        *u4_ptr ^= *id;    
+    }
+    
+    get_mote_version(); 
+    gps.init();
+        
+    gps.enable(1);
+    mpl3115a2.init();       
+    
     // reset MAC state
     LMIC_reset();
+    
+    os_setTimedCallback( &nJoinedJob, os_getTime() + ms2osticks(3000), on_not_joined );
+    joined = false;
     // start joining
-#if( OVER_THE_AIR_ACTIVATION != 0 )
     LMIC_startJoining();
-#else
-    devaddr_t *serial_id = (devaddr_t *) 0x1FF800d0;        // cat3 device stm32l152rc
-    LMIC_setSession( 0, *serial_id, NwkSKey, ArtSKey );
-    debug_val("SN = ", *serial_id);
-#endif
+    
+    led_red = LED_ON;   // indicate joining
+    led_yellow = LED_OFF;
+    //led_green = LED_OFF;
     // init done - onEvent() callback will be invoked...
-
-    //DEBUG_STR("E: INITFUNC");
-    get_mote_version();
-    if (mote_version == MOTE_V3)
-        gps.en_invert = false;
-    else
-        gps.en_invert = true;
-        
-    gps.init();
-    gps.enable(1);
-    //gps.verbose = 1;
-
-    mpl3115a2.init();
 }
 
-int main(void)
-{
+
+// application entry point
+int main () {
     osjob_t initjob;
 
     // initialize runtime env
     os_init();
+    // initialize debug library
     debug_init();
     // setup initial job
     os_setCallback(&initjob, initfunc);
     // execute scheduled jobs and events
     os_runloop();
     // (not reached)
-}
-
-//////////////////////////////////////////////////
-// LMIC EVENT CALLBACK
-//////////////////////////////////////////////////
-osjob_t rxLedJob;
-osjob_t txLedJob;
-osjob_t sendFrameJob;
-
-static void onRxLed (osjob_t* j) {
-    debug_val("LED2 = ", 1 );
-    led2 = 1;
-}
-
-static void onTxLed (osjob_t* j) {
-    debug_val("LED1 = ", 1 );
-    led1 = 1;
+    return 0;
 }
 
 static void
@@ -229,100 +232,140 @@
     }    
 }
 
-static bool AppLedStateOn = false;
-
-#define AIN_VREF        3.3     // stm32 internal refernce
-#define AIN_VBAT_DIV    2       // resistor divider
-static void PrepareDataFrame( void )
-{
-    uint16_t altitudeGps;
-    
-    restore_hsi();
-
-    gps.service();
-    //printf("lat:%f  long:%f\r\n", gps.Latitude, gps.Longitude);
-    mpl3115a2.ReadTemperature();
+osjob_t sendFrameJob;
+osjob_t indicateJob;
 
-    // immediately prepare next transmission
-    //LMIC.frame[0] = LMIC.rxq.snr;
-    LMIC.frame[0] = AppLedStateOn; // (bit 0 == 1) => LED on
-    LMIC.frame[1] = (int)mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So,  +/-63 C
-    LMIC.frame[2] = (bat->read_u16() >> 8) + (bat->read_u16() >> 9) ; // per LoRaMAC spec; 0=Charging; 1...254 = level, 255 = N/A
-    
-    LMIC.frame[3] = ( gps.LatitudeBinary >> 16 ) & 0xFF;
-    LMIC.frame[4] = ( gps.LatitudeBinary >> 8 ) & 0xFF;
-    LMIC.frame[5] = gps.LatitudeBinary & 0xFF;
-    LMIC.frame[6] = ( gps.LongitudeBinary >> 16 ) & 0xFF;
-    LMIC.frame[7] = ( gps.LongitudeBinary >> 8 ) & 0xFF;
-    LMIC.frame[8] = gps.LongitudeBinary & 0xFF;
-
-    altitudeGps = atoi(gps.NmeaGpsData.NmeaAltitude);
-    //printf("alt:%d\r\n", altitudeGps);
-    LMIC.frame[9] = ( altitudeGps >> 8 ) & 0xFF;
-    LMIC.frame[10] = altitudeGps & 0xFF;
-    
-
-    //printf("bat:%.2f\r\n", volts);
-#ifndef CHNL_HYBRID
-    float volts = bat->read()*AIN_VREF*AIN_VBAT_DIV;
-    if (volts < LOW_BAT_THRESHOLD)
-        LMIC.txpow_limit = 20;
-    else
-        LMIC.txpow_limit = 30;
-#endif /* !CHNL_HYBRID */  
+static void tx_ind_cb(osjob_t* j)
+{
+    led_red = LED_OFF;    
 }
 
 static void onSendFrame (osjob_t* j)
 {
-    if (LMIC.opmode & OP_TXRXPEND)
+    uint16_t altitudeGps;
+    
+    if (LMIC.opmode & OP_TXRXPEND) {
         return;
+    }
+    
+#ifdef FIXED_DR
+    LMIC.datarate = FIXED_DR;
+#endif
+    
+#ifdef FIXED_TX_POWER
+    LMIC.txpow = FIXED_TX_POWER;
+#endif
+    
+    restore_hsi();
+    
+    if(LMIC.datarate == DR_SF8C)
+        LMIC.txpow_limit = DMTS_MAX_POW;
+    else
+#ifdef CHNL_HYBRID
+        LMIC.txpow_limit = HS_MAX_POW;
+#else
+        LMIC.txpow_limit = FHS_MAX_POW;
+#endif
+
+    if( LMIC.txpow > LMIC.txpow_limit)
+        LMIC.txpow = LMIC.txpow_limit;
+    
+    float volts = bat->read()*AIN_VREF*AIN_VBAT_DIV;
+    if (volts < LOW_BAT_THRESHOLD) {
+        if (LMIC.txpow_limit > 20)
+            LMIC.txpow_limit = 20;
+        if (LMIC.txpow > 20)
+            LMIC.txpow = 20;
+    }
+    
+    ///////////////////////////////////////////////////////////////////    
+    gps.service();
+    mpl3115a2.ReadTemperature();    
+
+    uint8_t tmpData[PAYLOAD_LENGTH] = {0};
+
+    tmpData[0] = 15-(LMIC.txpow>>1);
+    tmpData[0] <<= 4;
+#ifdef CHNL_HYBRID
+    tmpData[0] |= 0x04;  // 8ch: set bit2
+#else
+    tmpData[0] |= 0x08;  // 64ch: set bit3
+#endif
+
+    tmpData[0] |= AppLedStateOn & 1; // (bit 0 == 1) => LED on
+    tmpData[1] = (int)mpl3115a2.Temperature; // Signed degrees Celcius in half degree units. So,  +/-63 C
+    tmpData[2] = (bat->read_u16() >> 8) + (bat->read_u16() >> 9) ; // per LoRaMAC spec; 0=Charging; 1...254 = level, 255 = N/A
+    
+    tmpData[3] = ( gps.LatitudeBinary >> 16 ) & 0xFF;
+    tmpData[4] = ( gps.LatitudeBinary >> 8 ) & 0xFF;
+    tmpData[5] = gps.LatitudeBinary & 0xFF;
+    tmpData[6] = ( gps.LongitudeBinary >> 16 ) & 0xFF;
+    tmpData[7] = ( gps.LongitudeBinary >> 8 ) & 0xFF;
+    tmpData[8] = gps.LongitudeBinary & 0xFF;
+
+    altitudeGps = atoi(gps.NmeaGpsData.NmeaAltitude);
+    tmpData[9] = ( altitudeGps >> 8 ) & 0xFF;
+    tmpData[10] = altitudeGps & 0xFF;
+    if (PAYLOAD_LENGTH > 11) {
+        for (int i = 11; i < PAYLOAD_LENGTH; i++)
+            tmpData[i] = i - 10;
+    }
+
+    for(int i = 0; i < PAYLOAD_LENGTH; i++)
+        LMIC.frame[i] = tmpData[i];
         
-    PrepareDataFrame( );
-    // schedule transmission (port 1, data[], datalen 1, ACK requested)
-    // (will be sent as soon as duty cycle permits)
-             
-    LMIC_setTxData2(5, LMIC.frame, APP_DATA_SIZE, APP_ACK);
+    // port, buffer, buffer length, need_ack
+    LMIC_setTxData2(5, LMIC.frame, PAYLOAD_LENGTH, 0);
+
+    led_red = LED_ON;
+
+    // Display Info
+
+    DisplayNetworkParam();
+
+    printf("Seq# %d\r\n",LMIC.seqnoUp-1);
+
+    printf("TX Data: ");
+    DisplayData(tmpData, PAYLOAD_LENGTH);
+
+    printf("TX Power: %d dBm\r\n",LMIC.txpow);
+
+    printf("Battery: %f Volts\r\n",volts);
+
+    os_setTimedCallback( &indicateJob, os_getTime() + ms2osticks(30), tx_ind_cb );  
+    
 }
 
-void onEvent (ev_t ev) {
 
-    debug_event(ev);
-
-    gps.service();
+//////////////////////////////////////////////////
+// LMIC EVENT CALLBACK
+//////////////////////////////////////////////////
 
-    switch(ev) 
-    {
-    // network joined, session established
-    case EV_JOINED:
-        debug_val("Net ID = ", LMIC.netid);
-        goto tx;
-    // scheduled data sent (optionally data received)
-    case EV_TXCOMPLETE:
-        if(LMIC.dataLen) 
-        { // data received in rx slot after tx
-            debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
-            if(LMIC.dataLen == 1) { // set LED state if exactly one byte is received
-                AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
-                debug_val("LED3 = ", AppLedStateOn ? 0 : 1 );
+void onEvent (ev_t ev)
+{
+    debug_event(ev);
+    
+    switch(ev) {
+        case EV_JOINED:
+            // network joined, session established
+            debug_val("netid = ", LMIC.netid);
+            joined = true;
+            led_red = LED_OFF;   // indicate joined
+            goto tx;
+        case EV_TXCOMPLETE:
+            // scheduled data sent (optionally data received)
+            if(LMIC.dataLen) { // data received in rx slot after tx
+                led_yellow = led_yellow ? 0 : 1;
+                if (LMIC.dataLen == 1) { // set LED state if exactly one byte is received
+                    led_usr = LMIC.frame[LMIC.dataBeg] & 0x01; 
+                }
+                debug_buf(LMIC.frame+LMIC.dataBeg, LMIC.dataLen);
             }
-        }
-        if((LMIC.txrxFlags & (TXRX_DNW1|TXRX_DNW2) )!= 0 )
-        {
-            debug_val("LED2 = ", 0 );
-            led2 = 0;
-            os_setTimedCallback( &rxLedJob, os_getTime() + ms2osticks(15), onRxLed );
-        }
 tx:
-        os_setTimedCallback( &sendFrameJob, os_getTime() + ms2osticks(MS_DELAY_NEXT_TX), onSendFrame ); // Change the Tx periodicity
-        //onSendFrame(NULL);
-        
-        // Blink Tx LED
-        debug_val("LED1 = ", 0 );
-        led1 = 0;
-        
-        os_setTimedCallback( &txLedJob, os_getTime() + ms2osticks(25), onTxLed );
-        break;
-    default:
-        break;
-    }
-}
+            os_setTimedCallback( &sendFrameJob, os_getTime() + ms2osticks(MS_DELAY_NEXT_TX), onSendFrame );           
+            break;
+        default:
+            led_red = LED_ON;   // indicate not joined
+            break;
+    } // ..switch(ev)
+}
\ No newline at end of file