alan broad / Mbed OS carbon_v5_arm_studio

Dependencies:   libxDot-mbed5

Files at this revision

API Documentation at this revision

Comitter:
alan1974
Date:
Mon Jun 18 17:31:35 2018 +0000
Child:
1:0d25d9ddbe9f
Commit message:
first checkin

Changed in this revision

.hgignore Show annotated file Show diff for this revision Revisions of this file
README Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
inc/RadioEvent.h Show annotated file Show diff for this revision Revisions of this file
inc/commI2C.h Show annotated file Show diff for this revision Revisions of this file
inc/dot_util.h Show annotated file Show diff for this revision Revisions of this file
inc/externals.h Show annotated file Show diff for this revision Revisions of this file
inc/history.h Show annotated file Show diff for this revision Revisions of this file
inc/wbit_util.h Show annotated file Show diff for this revision Revisions of this file
libxDot-mbed5.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
setup.sh Show annotated file Show diff for this revision Revisions of this file
src/commI2C.cpp Show annotated file Show diff for this revision Revisions of this file
src/dot_util.cpp Show annotated file Show diff for this revision Revisions of this file
src/main.cpp Show annotated file Show diff for this revision Revisions of this file
src/wbit_util.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,6 @@
+mbed-os
+.build
+/mdot/
+/mdot-library/
+/BUILD/
+/.git/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,22 @@
+Instructions for building Dot-Examples
+
+1. Import dot-examples
+$ mbed import http://os.mbed.com/teams/MultiTech/code/Dot-Examples/
+
+2. cd to the Dot-Examples/examples and import the dot library stack
+Choose either the stable or dev library for your dot device
+e.g. to get the latest development library for the xDot
+$ mbed add http://os.mbed.com/teams/MultiTech/code/libxDot-dev-mbed5/
+
+3. Update mbed-os revision to match that of the dot library you just imported.
+This information can be found in the library's commit history.
+e.g.
+$ cd Dot-Examples/mbed-os
+$ mbed update mbed-os-5.7.6
+
+4. Modify the Dot-Examples/examples/example_config.h to select the channel plan and which example to build
+By default, the OTA example is selected to build with the US channel plan
+
+5. Once the example is selected, modify the example source file to match the configuration of your gateway.
+Make sure the network_name, network_passphrase, frequency_sub_band (US), public_network, and join_delay settings match that of your gateway
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,89 @@
+# Getting started with Blinky on mbed OS
+
+This is a very simple guide, reviewing the steps required to get Blinky working on an mbed OS platform.
+
+Please install [mbed CLI](https://github.com/ARMmbed/mbed-cli#installing-mbed-cli).
+
+## Get the example application!
+
+From the command line, import the example:
+
+```
+mbed import mbed-os-example-blinky
+cd mbed-os-example-blinky
+```
+
+### Now compile
+
+Invoke `mbed compile` specifying the name of your platform and your favorite toolchain (`GCC_ARM`, `ARM`, `IAR`). For example, for the ARM Compiler 5:
+
+```
+mbed compile -m K64F -t ARM
+```
+
+Your PC may take a few minutes to compile your code. At the end you should get the following result:
+
+```
+[snip]
++----------------------------+-------+-------+------+
+| Module                     | .text | .data | .bss |
++----------------------------+-------+-------+------+
+| Misc                       | 13939 |    24 | 1372 |
+| core/hal                   | 16993 |    96 |  296 |
+| core/rtos                  |  7384 |    92 | 4204 |
+| features/FEATURE_IPV4      |    80 |     0 |  176 |
+| frameworks/greentea-client |  1830 |    60 |   44 |
+| frameworks/utest           |  2392 |   512 |  292 |
+| Subtotals                  | 42618 |   784 | 6384 |
++----------------------------+-------+-------+------+
+Allocated Heap: unknown
+Allocated Stack: unknown
+Total Static RAM memory (data + bss): 7168 bytes
+Total RAM memory (data + bss + heap + stack): 7168 bytes
+Total Flash memory (text + data + misc): 43402 bytes
+Image: .\.build\K64F\ARM\mbed-os-example-blinky.bin
+```
+
+### Program your board
+
+1. Connect your mbed device to the computer over USB.
+1. Copy the binary file to the mbed device .
+1. Press the reset button to start the program.
+
+You should see the LED of your platform turning on and off.
+
+Congratulations if you managed to complete this test!
+
+## Export the project to Keil MDK and debug your application
+
+From the command line, run the following command:
+
+```
+mbed export -m K64F -i uvision
+```
+
+To debug the application:
+
+1. Start uVision.
+1. Import the uVision project generated earlier.
+1. Compile your application and generate an `.axf` file.
+1. Make sure uVision is configured to debug over CMSIS-DAP (From the Project menu > Options for Target '...' > Debug tab > Use CMSIS-DAP Debugger).
+1. Set breakpoints and start a debug session.
+
+![Image of uVision](img/uvision.png)
+
+## Troubleshooting
+
+1. Make sure `mbed-cli` is working correctly and its version is greater than `0.8.9`
+
+ ```
+ mbed --version
+ ```
+
+ If not, you can update it easily:
+
+ ```
+ pip install mbed-cli --upgrade
+ ```
+
+2. If using Keil MDK, make sure you have a license installed. [MDK-Lite](http://www.keil.com/arm/mdk.asp) has a 32KB restriction on code size.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/RadioEvent.h	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,106 @@
+#ifndef __RADIO_EVENT_H__
+#define __RADIO_EVENT_H__
+
+#include "dot_util.h"
+#include "mDotEvent.h"
+
+//extern bool downstream_packet_received;
+
+class RadioEvent : public mDotEvent
+{
+ 
+private:
+    bool downstream_packet_received; 
+    std::vector<uint8_t> received_packet;
+ 
+public:
+    RadioEvent() {
+        downstream_packet_received = false;    
+    }
+ 
+    virtual ~RadioEvent() {}
+ 
+    std::vector<uint8_t> get_downstream_packet() {
+        
+        downstream_packet_received = false;
+        return received_packet; //0x4567;
+    }
+ 
+    bool is_packet_received() {
+        return downstream_packet_received;    
+    }
+    
+    /*!
+     * MAC layer event callback prototype.
+     *
+     * \param [IN] flags Bit field indicating the MAC events occurred
+     * \param [IN] info  Details about MAC events occurred
+     */
+    virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
+ 
+        //printf("--------------------- DRT. this is a test. Bits.Rx = %d\r\n", flags->Bits.Rx);
+ 
+        if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+            std::string msg = "OK";
+            switch (info->Status) {
+                case LORAMAC_EVENT_INFO_STATUS_ERROR:
+                    msg = "ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
+                    msg = "TX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
+                    msg = "RX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
+                    msg = "RX_ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
+                    msg = "JOIN_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
+                    msg = "DOWNLINK_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
+                    msg = "ADDRESS_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
+                    msg = "MIC_FAIL";
+                    break;
+                default:
+                    break;
+            }
+            logTrace("Event: %s", msg.c_str());
+ 
+            logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
+                     flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
+            logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
+                     info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
+                     info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
+        }
+ 
+        if (flags->Bits.Rx) {
+            
+            logDebug("Rx %d bytes", info->RxBufferSize);
+            if (info->RxBufferSize > 0) {
+                // print RX data as hexadecimal
+                //printf("******* DRT ****** Rx data: %s\r\n", mts::Text::bin2hexString(info->RxBuffer, info->RxBufferSize).c_str());
+                //downstream_packet_received = true;
+                int i;
+                received_packet.clear();
+                for (i=0; i<(info->RxBufferSize); i++)
+                {
+                    printf("Rx Data %d = %x\r\n", i, info->RxBuffer[i]);                    
+                    received_packet.push_back(info->RxBuffer[i]);
+                }
+                downstream_packet_received = true;
+                // print RX data as string
+                //std::string rx((const char*)info->RxBuffer, info->RxBufferSize);
+                //printf("Rx data: %s\r\n", rx.c_str());
+            }
+        }
+    }
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/commI2C.h	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,159 @@
+/*
+ * WaterBit, Inc. ("COMPANY") CONFIDENTIAL
+ * Unpublished Copyright (c) 2015-2016 WaterBit, Inc, All Rights Reserved.
+ * NOTICE: All information contained herein is, and remains the property of COMPANY. The intellectual and technical concepts contained herein are proprietary to COMPANY and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret or copyright law.
+ * 
+ * Dissemination of this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from COMPANY.
+ *
+ * Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees, managers or contractors who have executed Confidentiality and Non-disclosure agreements explicitly covering such access.
+ *
+ * The copyright notice above does not evidence any actual or intended publication or disclosure of this source code, which includes information that is confidential and/or proprietary, and is a trade secret, of COMPANY.
+ *
+ * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLICPE RFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
+ */
+
+#ifndef _COMMI2C_H_
+#define _COMMi2C_H_
+
+#include "mbed.h"
+
+
+
+
+#define BUFFER_SIZE_I2C     64
+#define I2C_MIN_WAIT_DELAY  200    //minimum time between rcv/xmit i2c data and pulsing wake
+#define I2C_ACK_PROC       0xff     //first byte of i2c ack msg back to proc
+#define I2C_MAX_ACK_DATA   0x32     //max data bytes accepted from Rx downstream pkt
+//cmds to xdot    
+enum{
+   XDOT_CMD_XMIT_PKT = 1,   //transmit data
+   XDOT_CMD_GET_EUI,        //get xdot EUI 
+   XDOT_CMD_SET_RADIO,      //set's radio parameters
+   XDOT_CMD_SET_KEY_X,      //set one of the security keys
+   XDOT_CMD_GOTO_SLEEP,     //go to sleep 
+   XDOT_CMD_GATEWAY_PING,   //ping gateway for RSSI
+   XDOT_CMD_UNDEFINED,      //last cmd, not used 
+};
+
+
+enum I2C_XFR_TYPE{
+ I2C_READ =0,
+ I2C_WRITE};   
+ 
+ //structure: upstream pkt for xdot to transmit
+ //txData bfr: is located in the struc immediately after dataLen parameter
+ //          : this allows extending pkt_upstrm struc as new control parameters are needed
+#define PKT_UPSTRM_RSVD  (BUFFER_SIZE_I2C- (I2C_MAX_ACK_DATA + 7))
+typedef struct {   
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt
+  uint8_t   txData[I2C_MAX_ACK_DATA];   //array for tx Data     
+  uint8_t   joinAttemps;                //max attempts to join network before quitting 
+  uint8_t   subBand;                    //frequency sub-band (ex: 1 for public, 4 for private)  
+  uint8_t   bPublicNetwork;             //true if public network, false if private network  ---- not used
+  uint8_t   bSetAdr;                    //true to enabled ADR (adaptive data rate)          ---- not used
+  uint8_t   rxvd[PKT_UPSTRM_RSVD];      //rserved filler bytes
+  uint8_t   chksum;                     //chksum of all previous, last byte in pkt
+ }pkt_upstrm;
+//structure: results returned to proc  of upstream data transmit
+typedef struct {
+  uint8_t   ack;                        //ack header response
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt
+  uint8_t   bXmitAttempted;             //true if xmit attempted, (fail of pkt len too big)
+  uint8_t   joinAttempts;               //# of join attempts before join occured, if bJoined=0 this = max attempts
+  uint8_t   bJoined;                    //true if successfully joined  
+  uint8_t   bAck;                       //true if ack return from xmit
+  uint8_t   bRx1;                       //true if rx1 return
+  uint8_t   bAckdata;                   //true if rx data
+  int8_t    rssi;                       //last rssi, 0 if no rx1/2 ack
+  uint8_t   rxLen;                      //length of returned rxdata
+  uint8_t   rxData[I2C_MAX_ACK_DATA];   //array for rx Data    
+  int16_t   mdot_ret;                   //mdot return code after calling send function
+  uint8_t   chksum_err;                 //1 if chksum err on proc upstream pkt
+}pkt_ack;
+//structure: results returned to proc for eui and api_level
+//v0307: eui pkt now used to read/set radio params also
+typedef struct {
+  uint8_t   ack;                        //ack header response
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt
+  uint8_t   euiData[16];                //eui 
+  uint8_t   apiLvlData[4];              //api level 
+  uint8_t   verLvlData[4];              //ver level   
+}pkt_eui;
+
+//cmds to set radio params   
+enum{
+   XDOT_CMD_RADIO_SUB_BAND = 1,   //set/read radio subband
+   XDOT_CMD_RADIO_ADR,            //set enable/disable ADR or read
+   XDOT_CMD_RADIO_ANT_GAIN,       //set/read antenna gain
+   XDOT_CMD_RADIO_XMIT_PWR,       //set/read transit power
+   XDOT_CMD_RADIO_SF,             //set/read spreading factor
+   XDOT_CMD_RADIO_SAVE_CFG,       //save cfg to non-volative memory => restore in next reboot
+};
+
+//structure: cmd structure to proc for setting radio parameters
+//upstream pkt struc
+typedef struct {  
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt  
+  bool      bSetParams;                 //if true then set and save variable params to nvm; false=> read params
+  uint8_t   maxDataLen;                 //max data length in pkt (read only)
+  uint8_t   maxTxPowerdBm;              //max power              (read only) 
+  uint8_t   minTxPowerdBm;              //min power              (read only)
+  uint8_t   public_network;             //public = true, private = false;
+  uint8_t   sub_band;                   //network subband #
+  bool      aDR;                        //true if ADR enabled
+  int8_t    antennaGaindBi;             //antenna gain
+  uint8_t   txPowerdBm;                 //transmit power
+  uint8_t   dataRate;                   //data rate 
+  uint8_t   appPort;                     //app port  
+}pkt_setradioup;
+
+//downstream pkt struc
+//structure: cmd structure to proc for setting radio parameters
+typedef struct {
+  uint8_t   ack;                        //ack header response
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt  
+  uint8_t   maxDataLen;                 //max data length in pkt
+  uint8_t   maxTxPowerdBm;              //max power
+  uint8_t   minTxPowerdBm;              //min power
+  uint8_t   public_network;             //public = true, private = false;
+  uint8_t   sub_band;                   //network subband #
+  bool      aDR;                        //true if ADR enabled
+  int8_t    antennaGaindBi;             //antenna gain
+  uint8_t   txPowerdBm;                 //transmit power
+  uint8_t   dataRate;                   //data rate 
+  uint8_t   appPort;                     //app port  
+}pkt_setradiodwn;
+
+
+//structure: results returned to proc of gateway ping
+typedef struct {
+  uint8_t   ack;                        //ack header response
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt
+  int8_t   status;                      //ping status return, 0 = success
+  int8_t   rssi;                        //rssi that gateway heard from node
+  int8_t   snr;                         //snr  that ....
+}pkt_ping;
+
+
+
+
+typedef struct {
+  uint8_t   ack;                        //ack header response
+  uint8_t   cmd;                        //cmd received from proc
+  uint8_t   dataLen;                    //datalen found in pkt
+  uint8_t   rxData[I2C_MAX_ACK_DATA];   //Data    
+}data_ack;
+
+
+void i2c_proc_init();
+void i2c_wait4wake_lo(void);
+void i2c_pulse_wake(void);
+I2C_XFR_TYPE i2c_proc_comm();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/dot_util.h	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,43 @@
+#ifndef __DOT_UTIL_H__
+#define __DOT_UTIL_H__
+
+#include "mbed.h"
+#include "mDot.h"
+#include "ChannelPlans.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+//#include "ISL29011.h"
+//#include "example_config.h"
+
+extern mDot* dot;
+
+void display_config();
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack);
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power);
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold);
+
+void join_network();
+
+
+void sleep_wake_rtc_only(bool deepsleep);
+
+void sleep_wake_interrupt_only(bool deepsleep);
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep);
+
+void sleep_save_io();
+
+void sleep_configure_io();
+
+void sleep_restore_io();
+
+void send_data(std::vector<uint8_t> data);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/externals.h	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,6 @@
+#ifndef WB_EXTERNALS
+#define WB_EXTERNALS
+
+extern Serial pc;
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/history.h	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,22 @@
+#ifdef COMMENTS_ONLY
+Data:       Rev:    API:    Comments:
+14June2018 0007    003      -added new command: XDOT_CMD_SET_RADIO to read/set radio parameters
+
+?          0006    002      -changed security keys?
+18Dec2017  0005    002      -added chksum on xdot send pkt from proc and return ack
+                            -added maxDataLen (max data length in pkt) returned in eui ack
+14Dec2017  0004    002      -added mdot_ret to pkt_ack (commI2C.h). This API rev is backward compatible                             
+5Nov2017   0003    001      -modified pkt xmit cmd to allow changing sub_band and network type (public or private) 
+                            -tried to change to private/public network on the fly, but not working,
+                            -added network info (public/private) and subband info into eui pkt
+                            
+                    
+18Oct2017   0002    000     -commI2c.h->pkt_ack->bPrevJoined to pkt_ack->JoinAttempts to report nmb of join attempts
+                            -pkt_ack->bPrevJoined was of no value regarding previous join state
+13Oct2017   0001            -Moved waterbt specific code to wbit_util.cpp
+                            -Reset api level to 0-0-0-0
+                            -Added version level ver_level and added into eui message to proc
+12Oct2017   0305            -Fixed logic error in calling joined = join_network_waterbit(pUp->joinAttemps);
+19Sept2017: 0305            -Added join_network_waterbit to fix eternal join looping if node not registered or gateway down
+                            -Added proc sending the number of join attempts in each upstream pkt
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/wbit_util.h	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,8 @@
+#ifndef __WBIT_UTIL_H__
+#define __WBIT_UTIL_H__
+#include "mbed.h"
+
+uint8_t join_network_attempts_wbit();
+bool join_network_wbit(uint8_t nmbAttempts);  //waterbit specific because Multitech doesn't seem to know what a forever loop will do to power consumption
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libxDot-mbed5.lib	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/MultiTech/code/libxDot-mbed5/#fc3817b65dca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#fc1836545dcc2fc86f03b01292b62bf2089f67c3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.sh	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,3 @@
+if [ ! -d ISL29011 ]; then
+    hg clone https://developer.mbed.org/teams/Multi-Hackers/code/ISL29011/
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/commI2C.cpp	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,125 @@
+#include "mbed.h"
+#include "commI2C.h"
+
+extern uint8_t buf_xmt[BUFFER_SIZE_I2C];  //outgoing data
+extern uint8_t buf_rcv[BUFFER_SIZE_I2C];  //incoming data
+I2CSlave slave(PB_9, PB_8);
+DigitalInOut wake(PA_0); 
+
+extern Serial pc;
+//#define TEST
+   
+
+//==============================================================================
+// i2c_proc_init
+// - init i2c comm to proc
+//==============================================================================     
+void i2c_proc_init()
+{   
+    slave.frequency(100000);                   // added DRT NOT NEEDED BY SLAVE????,asb, need this ????
+    uint8_t slave_address = 0xA0;                //PROC code uses 7bit address shifted by one so 0xA0 (xdot) => 0x50 (PROC)
+    slave.address(slave_address);  
+    //set wake hi 
+    
+    return;
+}
+//==============================================================================
+// i2c_wait4wake_lo
+// - wait for the wake signal from proc to go low
+// NEEDS TO BE CORRECTED, THIS WAITS FOR A HI THEN A LOW !!!!
+//==============================================================================   
+#ifdef NOT_USED  
+void i2c_wait4wake_lo(void){
+   wake.input();
+//   pc.printf("\n\r waiting for wake to go hi %d",wake);  
+   bool wakeHi=  false;
+   while(!wakeHi){               
+        wait_ms(10);  //need this wait else loop below will block previous printout
+        wakeHi =  wake;   // state of wake signal
+   }
+  // pc.printf("\n\r detected wake hi");  
+   wait_ms(100);  //need this wait else loop below will block previous printout
+ //wake signal hi,wait until it goes back lo => psoc is going to wait for ....           
+   // pc.printf("\n\r waiting for wake to go lo %d",wake);    
+    bool wakeLo = true;
+    while(wakeLo){ 
+        wait_ms(10);  //need this wait else loop below will block previous printout
+        wakeLo =  wake;   // state of wake signal
+   }
+    //pc.printf("\n\r detected wake lo "); 
+    wait_ms(100);  //wait for proc to get ready for i2c comm, proc leave wake in low state   
+    
+    
+    return;    
+}
+#endif
+//==============================================================================
+// i2c_pulse_wake
+// - pulse the wake signal to tell proc that xdot ready for i2c xfr
+//==============================================================================     
+void i2c_pulse_wake(void){
+    wake.mode(OpenDrain);
+    wake.output();
+    wake = 1;                            
+    wait_ms(10);  //proc uses interrupts on lora_wake, so don't need to wait,just pulse it
+    wake = 0;       // set wake lo  
+    wait_ms(1);  
+    wake.input();   //go back to input mode   !!! wake pull hi if go back to input mode ??? 
+    return;
+}
+//==============================================================================
+// i2c_proc_comm
+//- set WAKE low to notify proc that's OK to read/write i2c data
+//- waits FOREVER  or timeout for proc to write or read i2 data
+// - returns point to read or write i2c bfr
+//- returns true  if xdot rcvd data into buf_rcv from proc
+//          false if xdot wrote  data from buf_xmt to proc
+//- before returning sets WAKE hi
+//------------------------------------------------------------------------------
+// xdot i2c slave operation:
+// - xdot does not work correctly as a i2c slave
+// - if xdot does not respond to first incoming bytes from master (responseTime)
+//    within a defined period the xdot will hang the i2c bus until it is reset
+// - the strategy here is sit in a very tight while loop polling continually for
+//   incoming i2c bytee within the respnseTime
+// - the time around the while loop below must be < responseTime
+// - reponseTime for the while loop below is measured at 1.25 usec
+// - responseTimes upto 80 usec have been measured to be OK
+//------------------------------------------------------------------------------
+// timeout:
+// - safety mechanism to get xdot back to sleep mode if proc goes unresponsive
+// - cpu clock dependant..what mhz is cpu? presently this will give 1.1sec timout before 
+// -  0x000fffff gives a 1.1 second timeout
+// - after proc wakes xdot from sleep then proc must send an i2c omd within timout
+// - once xdot pulses wake to notify proc that i2c ack msg is ready, proc must do i2c read within timeout
+//==============================================================================
+I2C_XFR_TYPE i2c_proc_comm(void)
+{
+     bool verbose = false;    
+    uint32_t timeout = 0x000fffff;  //1.1second timeout
+  
+    while(1){
+        int i = slave.receive();  
+        switch (i) {
+            case I2CSlave::ReadAddressed:       //xdot  -> proc                     
+                slave.write((char *)buf_xmt, BUFFER_SIZE_I2C);                 
+                return I2C_WRITE;            
+            case I2CSlave::WriteAddressed:   //xdot <- proc                                                  
+                slave.read((char *)buf_rcv, BUFFER_SIZE_I2C);                 
+                if (verbose){
+                    pc.printf("\n\r Incoming buffer(hex): \n\r");                               
+                    int j;
+                    for (j = 0; j < BUFFER_SIZE_I2C; j++){
+                    pc.printf("%x", buf_rcv[j]);
+                    pc.printf(" ");
+                 }       
+                    
+                }    
+                return I2C_READ;                                          
+            default:
+        }; //switch  
+        
+        timeout--;
+        if(timeout == 0)return I2C_WRITE;  //just go to sleep 
+      }; //while  
+}             
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dot_util.cpp	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,746 @@
+#include "dot_util.h"
+#if defined(TARGET_XDOT_L151CC)
+#include "xdot_low_power.h"
+#endif
+
+#if defined(TARGET_MTS_MDOT_F411RE)
+uint32_t portA[6];
+uint32_t portB[6];
+uint32_t portC[6];
+uint32_t portD[6];
+uint32_t portH[6];
+#endif
+
+
+void display_config() {
+    // display configuration and library version information
+    logInfo("=====================");
+    logInfo("general configuration");
+    logInfo("=====================");
+    logInfo("version ------------------ %s", dot->getId().c_str());
+    logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
+    logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
+    logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
+    }
+    logInfo("public network ----------- %s", dot->getPublicNetwork() ? "on" : "off");
+    logInfo("=========================");
+    logInfo("credentials configuration");
+    logInfo("=========================");
+    logInfo("device class ------------- %s", dot->getClass().c_str());
+    logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
+    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
+	logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
+	logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
+    } else {
+	logInfo("network name ------------- %s", dot->getNetworkName().c_str());
+	logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
+	logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
+	logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
+    }
+    logInfo("========================");
+    logInfo("communication parameters");
+    logInfo("========================");
+    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
+	logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
+    } else {
+	logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
+    }
+    logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
+    logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
+    logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
+    logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
+    if (dot->getLbtTimeUs()) {
+	logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
+	logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
+    }
+}
+
+void update_ota_config_name_phrase(std::string network_name, std::string network_passphrase, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::string current_network_name = dot->getNetworkName();
+    std::string current_network_passphrase = dot->getNetworkPassphrase();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+    
+    if (current_network_name != network_name) {
+        logInfo("changing network name from \"%s\" to \"%s\"", current_network_name.c_str(), network_name.c_str());
+        if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
+            logError("failed to set network name to \"%s\"", network_name.c_str());
+        }
+    }
+    
+    if (current_network_passphrase != network_passphrase) {
+        logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
+        if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
+            logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
+        }
+    }
+    
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	if (current_frequency_sub_band != frequency_sub_band) {
+	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+		logError("failed to set frequency sub band to %u", frequency_sub_band);
+	    }
+	}
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_ota_config_id_key(uint8_t *network_id, uint8_t *network_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_id = dot->getNetworkId();
+    std::vector<uint8_t> current_network_key = dot->getNetworkKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_id_vector(network_id, network_id + 8);
+    std::vector<uint8_t> network_key_vector(network_key, network_key + 16);
+    
+    if (current_network_id != network_id_vector) {
+        logInfo("changing network ID from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_id).c_str(), mts::Text::bin2hexString(network_id_vector).c_str());
+        if (dot->setNetworkId(network_id_vector) != mDot::MDOT_OK) {
+            logError("failed to set network ID to \"%s\"", mts::Text::bin2hexString(network_id_vector).c_str());
+        }
+    }
+    
+    if (current_network_key != network_key_vector) {
+        logInfo("changing network KEY from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_key).c_str(), mts::Text::bin2hexString(network_key_vector).c_str());
+        if (dot->setNetworkKey(network_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network KEY to \"%s\"", mts::Text::bin2hexString(network_key_vector).c_str());
+        }
+    }
+    
+    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
+	if (current_frequency_sub_band != frequency_sub_band) {
+	    logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+	    if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+		logError("failed to set frequency sub band to %u", frequency_sub_band);
+	    }
+	}
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_manual_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint8_t frequency_sub_band, bool public_network, uint8_t ack) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
+    bool current_public_network = dot->getPublicNetwork();
+    uint8_t current_ack = dot->getAck();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_frequency_sub_band != frequency_sub_band) {
+        logInfo("changing frequency sub band from %u to %u", current_frequency_sub_band, frequency_sub_band);
+        if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
+            logError("failed to set frequency sub band to %u", frequency_sub_band);
+        }
+    }
+    
+    if (current_public_network != public_network) {
+        logInfo("changing public network from %s to %s", current_public_network ? "on" : "off", public_network ? "on" : "off");
+        if (dot->setPublicNetwork(public_network) != mDot::MDOT_OK) {
+            logError("failed to set public network to %s", public_network ? "on" : "off");
+        }
+    }
+    
+    if (current_ack != ack) {
+        logInfo("changing acks from %u to %u", current_ack, ack);
+        if (dot->setAck(ack) != mDot::MDOT_OK) {
+            logError("failed to set acks to %u", ack);
+        }
+    }
+}
+
+void update_peer_to_peer_config(uint8_t *network_address, uint8_t *network_session_key, uint8_t *data_session_key, uint32_t tx_frequency, uint8_t tx_datarate, uint8_t tx_power) {
+    std::vector<uint8_t> current_network_address = dot->getNetworkAddress();
+    std::vector<uint8_t> current_network_session_key = dot->getNetworkSessionKey();
+    std::vector<uint8_t> current_data_session_key = dot->getDataSessionKey();
+    uint32_t current_tx_frequency = dot->getTxFrequency();
+    uint8_t current_tx_datarate = dot->getTxDataRate();
+    uint8_t current_tx_power = dot->getTxPower();
+
+    std::vector<uint8_t> network_address_vector(network_address, network_address + 4);
+    std::vector<uint8_t> network_session_key_vector(network_session_key, network_session_key + 16);
+    std::vector<uint8_t> data_session_key_vector(data_session_key, data_session_key + 16);
+
+    if (current_network_address != network_address_vector) {
+        logInfo("changing network address from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_address).c_str(), mts::Text::bin2hexString(network_address_vector).c_str());
+        if (dot->setNetworkAddress(network_address_vector) != mDot::MDOT_OK) {
+            logError("failed to set network address to \"%s\"", mts::Text::bin2hexString(network_address_vector).c_str());
+        }
+    }
+    
+    if (current_network_session_key != network_session_key_vector) {
+        logInfo("changing network session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_network_session_key).c_str(), mts::Text::bin2hexString(network_session_key_vector).c_str());
+        if (dot->setNetworkSessionKey(network_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set network session key to \"%s\"", mts::Text::bin2hexString(network_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_data_session_key != data_session_key_vector) {
+        logInfo("changing data session key from \"%s\" to \"%s\"", mts::Text::bin2hexString(current_data_session_key).c_str(), mts::Text::bin2hexString(data_session_key_vector).c_str());
+        if (dot->setDataSessionKey(data_session_key_vector) != mDot::MDOT_OK) {
+            logError("failed to set data session key to \"%s\"", mts::Text::bin2hexString(data_session_key_vector).c_str());
+        }
+    }
+    
+    if (current_tx_frequency != tx_frequency) {
+	logInfo("changing TX frequency from %lu to %lu", current_tx_frequency, tx_frequency);
+	if (dot->setTxFrequency(tx_frequency) != mDot::MDOT_OK) {
+	    logError("failed to set TX frequency to %lu", tx_frequency);
+	}
+    }
+
+    if (current_tx_datarate != tx_datarate) {
+	logInfo("changing TX datarate from %u to %u", current_tx_datarate, tx_datarate);
+	if (dot->setTxDataRate(tx_datarate) != mDot::MDOT_OK) {
+	    logError("failed to set TX datarate to %u", tx_datarate);
+	}
+    }
+
+    if (current_tx_power != tx_power) {
+	logInfo("changing TX power from %u to %u", current_tx_power, tx_power);
+	if (dot->setTxPower(tx_power) != mDot::MDOT_OK) {
+	    logError("failed to set TX power to %u", tx_power);
+	}
+    }
+}
+
+void update_network_link_check_config(uint8_t link_check_count, uint8_t link_check_threshold) {
+    uint8_t current_link_check_count = dot->getLinkCheckCount();
+    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
+
+    if (current_link_check_count != link_check_count) {
+	logInfo("changing link check count from %u to %u", current_link_check_count, link_check_count);
+	if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
+	    logError("failed to set link check count to %u", link_check_count);
+	}
+    }
+
+    if (current_link_check_threshold != link_check_threshold) {
+	logInfo("changing link check threshold from %u to %u", current_link_check_threshold, link_check_threshold);
+	if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
+	    logError("failed to set link check threshold to %u", link_check_threshold);
+	}
+    }
+}
+
+#ifdef OLD_CODE
+bool join_network_waterbit(uint8_t nmbAttempts) {
+    int32_t j_attempts = 0;
+    int32_t ret = mDot::MDOT_ERROR;
+    
+    // attempt to join the network
+    while (ret != mDot::MDOT_OK) {
+        logInfo("attempt %d to join network", ++j_attempts);
+        ret = dot->joinNetwork();
+        if (ret == mDot::MDOT_OK) return true;
+        
+        logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        if (j_attempts >= nmbAttempts)
+        {
+    		logInfo("attempts %d to join network exceeds specified attempts $d ",j_attempts,nmbAttempts);	
+        	return false;
+        }	        	
+        // in some frequency bands we need to wait until another channel is available before transmitting again
+        uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
+        if (delay_s < 2) {
+        	logInfo("waiting %lu s until next free channel", delay_s);
+            wait(delay_s);
+        } else {
+        	logInfo("sleeping %lu s until next free channel", delay_s);
+            dot->sleep(delay_s, mDot::RTC_ALARM, false);
+        }        
+    }//while
+    return false;
+}
+#endif
+
+
+void join_network() {
+    int32_t j_attempts = 0;
+    int32_t ret = mDot::MDOT_ERROR;
+    
+    // attempt to join the network
+    while (ret != mDot::MDOT_OK) {
+        logInfo("attempt %d to join network", ++j_attempts);
+        ret = dot->joinNetwork();
+        if (ret != mDot::MDOT_OK) {
+            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+            // in some frequency bands we need to wait until another channel is available before transmitting again
+            uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
+            if (delay_s < 2) {
+                logInfo("waiting %lu s until next free channel", delay_s);
+                wait(delay_s);
+            } else {
+                logInfo("sleeping %lu s until next free channel", delay_s);
+                dot->sleep(delay_s, mDot::RTC_ALARM, false);
+            }
+        }//if ret
+    }//while
+}
+
+void sleep_wake_rtc_only(bool deepsleep) {
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+    
+    logInfo("%ssleeping %lus", deepsleep ? "deep" : "", delay_s);
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep for delay_s seconds and wake using the RTC alarm
+    dot->sleep(delay_s, mDot::RTC_ALARM, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_interrupt_only(bool deepsleep) {
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping until interrupt on %s pin", deepsleep ? "deep" : "", deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake on rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // since we're not waking on the RTC alarm, the interval is ignored
+    dot->sleep(0, mDot::INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_wake_rtc_or_interrupt(bool deepsleep) {
+    // in some frequency bands we need to wait until another channel is available before transmitting again
+    // wait at least 10s between transmissions
+    uint32_t delay_s = dot->getNextTxMs() / 1000;
+    if (delay_s < 10) {
+        delay_s = 10;
+    }
+
+#if defined (TARGET_XDOT_L151CC)
+    if (deepsleep) {
+        // for xDot, WAKE pin (connected to S2 on xDot-DK) is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure WAKE pin (connected to S2 on xDot-DK) as the pin that will wake the xDot from low power modes
+        //      other pins can be confgured instead: GPIO0-3 or UART_RX
+        dot->setWakePin(WAKE);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "WAKE" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#else
+    if (deepsleep) {
+        // for mDot, XBEE_DIO7 pin is the only pin that can wake the processor from deepsleep
+        // it is automatically configured when INTERRUPT or RTC_ALARM_OR_INTERRUPT is the wakeup source and deepsleep is true in the mDot::sleep call
+    } else {
+        // configure XBEE_DIO7 pin as the pin that will wake the mDot from low power modes
+        //      other pins can be confgured instead: XBEE_DIO2-6, XBEE_DI8, XBEE_DIN
+        dot->setWakePin(XBEE_DIO7);    
+    }
+
+    logInfo("%ssleeping %lus or until interrupt on %s pin", deepsleep ? "deep" : "", delay_s, deepsleep ? "DIO7" : mDot::pinName2Str(dot->getWakePin()).c_str());
+#endif
+
+    logInfo("application will %s after waking up", deepsleep ? "execute from beginning" : "resume");
+
+    // lowest current consumption in sleep mode can only be achieved by configuring IOs as analog inputs with no pull resistors
+    // the library handles all internal IOs automatically, but the external IOs are the application's responsibility
+    // certain IOs may require internal pullup or pulldown resistors because leaving them floating would cause extra current consumption
+    // for xDot: UART_*, I2C_*, SPI_*, GPIO*, WAKE
+    // for mDot: XBEE_*, USBTX, USBRX, PB_0, PB_1
+    // steps are:
+    //   * save IO configuration
+    //   * configure IOs to reduce current consumption
+    //   * sleep
+    //   * restore IO configuration
+    if (! deepsleep) {
+	// save the GPIO state.
+	sleep_save_io();
+
+	// configure GPIOs for lowest current
+	sleep_configure_io();
+    }
+    
+    // go to sleep/deepsleep and wake using the RTC alarm after delay_s seconds or rising edge of configured wake pin (only the WAKE pin in deepsleep)
+    // whichever comes first will wake the xDot
+    dot->sleep(delay_s, mDot::RTC_ALARM_OR_INTERRUPT, deepsleep);
+
+    if (! deepsleep) {
+	// restore the GPIO state.
+	sleep_restore_io();
+    }
+}
+
+void sleep_save_io() {
+#if defined(TARGET_XDOT_L151CC)
+	xdot_save_gpio_state();
+#else
+	portA[0] = GPIOA->MODER;
+	portA[1] = GPIOA->OTYPER;
+	portA[2] = GPIOA->OSPEEDR;
+	portA[3] = GPIOA->PUPDR;
+	portA[4] = GPIOA->AFR[0];
+	portA[5] = GPIOA->AFR[1];
+
+	portB[0] = GPIOB->MODER;
+	portB[1] = GPIOB->OTYPER;
+	portB[2] = GPIOB->OSPEEDR;
+	portB[3] = GPIOB->PUPDR;
+	portB[4] = GPIOB->AFR[0];
+	portB[5] = GPIOB->AFR[1];
+
+	portC[0] = GPIOC->MODER;
+	portC[1] = GPIOC->OTYPER;
+	portC[2] = GPIOC->OSPEEDR;
+	portC[3] = GPIOC->PUPDR;
+	portC[4] = GPIOC->AFR[0];
+	portC[5] = GPIOC->AFR[1];
+
+	portD[0] = GPIOD->MODER;
+	portD[1] = GPIOD->OTYPER;
+	portD[2] = GPIOD->OSPEEDR;
+	portD[3] = GPIOD->PUPDR;
+	portD[4] = GPIOD->AFR[0];
+	portD[5] = GPIOD->AFR[1];
+
+	portH[0] = GPIOH->MODER;
+	portH[1] = GPIOH->OTYPER;
+	portH[2] = GPIOH->OSPEEDR;
+	portH[3] = GPIOH->PUPDR;
+	portH[4] = GPIOH->AFR[0];
+	portH[5] = GPIOH->AFR[1];
+#endif
+}
+
+void sleep_configure_io() {
+#if defined(TARGET_XDOT_L151CC)
+    // GPIO Ports Clock Enable
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+    __GPIOH_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    // I2C_SDA & I2C_SCL to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    if (dot->getWakePin() != WAKE || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO0 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO1 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != GPIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_2;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+    }
+    if (dot->getWakePin() != UART1_RX || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_10;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#else
+    /* GPIO Ports Clock Enable */
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    __GPIOC_CLK_ENABLE();
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    // XBEE_DOUT, XBEE_DIN, XBEE_DO8, XBEE_RSSI, USBTX, USBRX, PA_12, PA_13, PA_14 & PA_15 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 
+                | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);    
+
+    // PB_0, PB_1, PB_3 & PB_4 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
+
+    // PC_9 & PC_13 to analog nopull
+    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_13;
+    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
+
+    // iterate through potential wake pins - leave the configured wake pin alone if one is needed
+    // XBEE_DIN - PA3
+    // XBEE_DIO2 - PA5
+    // XBEE_DIO3 - PA4
+    // XBEE_DIO4 - PA7
+    // XBEE_DIO5 - PC1
+    // XBEE_DIO6 - PA1
+    // XBEE_DIO7 - PA0
+    // XBEE_SLEEPRQ - PA11
+                
+    if (dot->getWakePin() != XBEE_DIN || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_3;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO2 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_5;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+    if (dot->getWakePin() != XBEE_DIO3 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_4;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+         if (dot->getWakePin() != XBEE_DIO4 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_7;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO5 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO6 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_1;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_DIO7 || dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_0;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+
+     if (dot->getWakePin() != XBEE_SLEEPRQ|| dot->getWakeMode() == mDot::RTC_ALARM) {
+        GPIO_InitStruct.Pin = GPIO_PIN_11;
+        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+    }
+#endif
+}
+
+void sleep_restore_io() {
+#if defined(TARGET_XDOT_L151CC)
+    xdot_restore_gpio_state();
+#else
+    GPIOA->MODER = portA[0];
+    GPIOA->OTYPER = portA[1];
+    GPIOA->OSPEEDR = portA[2];
+    GPIOA->PUPDR = portA[3];
+    GPIOA->AFR[0] = portA[4];
+    GPIOA->AFR[1] = portA[5];
+
+    GPIOB->MODER = portB[0];
+    GPIOB->OTYPER = portB[1];
+    GPIOB->OSPEEDR = portB[2];
+    GPIOB->PUPDR = portB[3];
+    GPIOB->AFR[0] = portB[4];
+    GPIOB->AFR[1] = portB[5];
+
+    GPIOC->MODER = portC[0];
+    GPIOC->OTYPER = portC[1];
+    GPIOC->OSPEEDR = portC[2];
+    GPIOC->PUPDR = portC[3];
+    GPIOC->AFR[0] = portC[4];
+    GPIOC->AFR[1] = portC[5];
+
+    GPIOD->MODER = portD[0];
+    GPIOD->OTYPER = portD[1];
+    GPIOD->OSPEEDR = portD[2];
+    GPIOD->PUPDR = portD[3];
+    GPIOD->AFR[0] = portD[4];
+    GPIOD->AFR[1] = portD[5];
+
+    GPIOH->MODER = portH[0];
+    GPIOH->OTYPER = portH[1];
+    GPIOH->OSPEEDR = portH[2];
+    GPIOH->PUPDR = portH[3];
+    GPIOH->AFR[0] = portH[4];
+    GPIOH->AFR[1] = portH[5];
+#endif
+}
+
+void send_data(std::vector<uint8_t> data) {
+    int32_t ret;
+
+    ret = dot->send(data);
+    if (ret != mDot::MDOT_OK) {
+        logError("failed to send data to %s [%d][%s]", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway", ret, mDot::getReturnCodeString(ret).c_str());
+    } else {
+        logInfo("successfully sent data to %s", dot->getJoinMode() == mDot::PEER_TO_PEER ? "peer" : "gateway");
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.cpp	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,477 @@
+#include "mbed.h"
+#include "commI2C.h"
+#include "dot_util.h"
+#include "wbit_util.h"
+#include "mDot.h"
+#include "RadioEvent.h"
+#include "Lora.h"
+
+//=======================================================================================================
+// enable some GPIO for scope trigger or led 
+//=======================================================================================================
+//#define GPIO_ENABLE
+//=======================================================================================================
+// configure for either private (test only) or public network (standard)
+//=======================================================================================================
+//#define MT_PRIVATE_NETWORK          //ENABLE THIS FOR PRIVATE NETWORK
+
+//=======================================================================================================
+//code api level and version
+//api_level: proc code will not run if api level (last two bytess) greater than what it expects
+//=======================================================================================================
+uint8_t api_level[4] = { 0x00, 0x00, 0x00, 0x03 };  //api-level, determines if xdot code works with proc code
+uint8_t ver_level[4] = { 0x00, 0x00, 0x00, 0x07 };  //updated for every code check-in
+
+//=======================================================================================================
+//configuring mbed pinsa; https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/io/DigitalInOut/
+// * these options must match the settings on your gateway //
+// * edit their values to match your configuration         //
+// * frequency sub band is only relevant for the 915 bands //
+// * either the network name and passphrase can be used or //
+//     the network ID (8 bytes) and KEY (16 bytes)         //
+//=======================================================================================================
+static std::string network_name = "asdfqwer";
+static std::string network_passphrase = "zxcvasdf";
+
+static uint8_t network_id[] = { 0x90, 0xF1, 0x47, 0x90, 0x6C, 0x48, 0x1D, 0x29 };   //static id not used anymore but don't comment out                                
+static uint8_t network_key[] = { 0x0F, 0xF9, 0xA2, 0x90, 0x2E, 0xAA, 0x6B, 0x8C, 0x6A, 0x4E, 0xFD, 0x67, 0xF9, 0xA6, 0xF3, 0xD3 };                                 
+
+
+#ifdef MT_PRIVATE_NETWORK
+static uint8_t frequency_sub_band = 4; 
+static bool public_network = false;
+static uint8_t ack = 1; //0;
+#else
+static uint8_t frequency_sub_band = 1; 
+static bool public_network = true; //false
+static uint8_t ack = 1; //0;
+#endif
+
+static bool adr = false;    //set adaptive data rate
+
+//=======================================================================================================
+// deepsleep consumes slightly less current than sleep
+// in sleep mode, IO state is maintained, RAM is retained, and application will resume after waking up
+// in deepsleep mode, IOs float, RAM is lost, and application will start from beginning after waking up
+// if deep_sleep == true, device will enter deepsleep mode
+//=======================================================================================================
+static bool deep_sleep = false; //false;
+
+uint32_t packets_sent = 0;
+uint32_t acks_rcvd = 0;
+int8_t   rssi =0;           //rssi of last rcvd rx1/rx2
+std::string eui = " ";
+static bool led_enabled = false; //true; //false;
+mDot* dot = NULL;
+lora::ChannelPlan* plan = NULL;
+uint8_t buf_xmt[BUFFER_SIZE_I2C];  //outgoing data
+uint8_t buf_rcv[BUFFER_SIZE_I2C];  //incoming data
+std::vector<uint8_t> upstream_packet; 
+
+#ifdef GPIO_ENABLE
+DigitalOut led1(PB_0); //LED1);
+DigitalInOut gpio1(PA_5);  //scope debug PA-5 is connected to SW1 pads on Loren v04 and can be used for scope debug
+#endif
+
+Serial pc(USBTX, USBRX);   //serial port output
+
+//=================================================================================================
+//LED_test
+//=================================================================================================
+void LED_test(int num)
+{
+    #ifdef GPIO_ENABLE
+    if (led_enabled)
+    {
+        pc.printf("LED_test()\r\n");
+        int test;
+        for (test=0; test<num; test++)
+        {
+            led1 = 0; 
+            wait_ms(500);
+            led1 = 1;
+            wait_ms(500);           
+        }
+    }
+    #endif        
+}
+//==================================================================================
+//chksum
+//compute checksum over i2c buffer except for last byte (chksum byte)
+//==================================================================================
+uint8_t chksum_proc(uint8_t *bfr_xdot){
+    uint8_t i;
+    uint8_t chksum = 0;
+    for (i=0; i < BUFFER_SIZE_I2C-1;i++)chksum += bfr_xdot[i];//good code   
+    return chksum;
+} 
+//=================================================================================================
+//cfg_network:
+// configure the network public/private and sub-band
+// bForceCfg : true => force a network cfg
+//           false => only change if bPublic or sub_band have changed
+// bPublic : true if network is public, else private
+// sub_band: sub band number (1..8)
+
+// NOTE: THIS ONLY WORKS WHEN THE XDOT BOOTS UP. IT DOES NOT WORK WHEN TRYING TO CHANGE AFTER.
+// NOT SURE WHY...WHEN THE XDOT REJOINS IT SHOULD USE NEW SESSION SETTINGS... asb
+//
+//asb:dec 2017: try this later and see if it works:mdot.h: 
+//   int32_t setPublicNetwork(const bool& on);
+//    bool getPublicNetwork();
+//    int32_t setFrequencySubBand(const uint8_t& band);
+//=================================================================================================
+bool cfg_network(bool bForceCfg,bool bPublic,uint8_t sub_band){
+// if bForceCfg false and network parameters haven't changed then just exit
+    if (!bForceCfg){
+        pc.printf("no configuration change needed subband the same");
+        if ((public_network ==bPublic) && (frequency_sub_band ==sub_band))return true;           
+    }         
+    pc.printf("changing to subband: %d\r\n",sub_band);
+// update network settings   
+    public_network = bPublic;
+    frequency_sub_band =sub_band;
+// start from a well-known state
+    logInfo("defaulting Dot configuration");
+    //dot->resetConfig();             //reset config to factory default not used for v0307
+    dot->resetNetworkSession();     //Reset current network session, essentially disconnecting from the network
+        
+    if (dot->getJoinMode() != mDot::OTA) {  // update configuration if necessary
+        logInfo("changing network join mode to OTA");
+        if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) {
+            logError("failed to set network join mode to OTA");
+            return false;
+        }
+    }    
+// in OTA and AUTO_OTA join modes, the credentials can be passed to the library as a name and passphrase or an ID and KEY
+// only one method or the other should be used!
+    if (public_network){
+        update_ota_config_id_key(network_id, network_key, frequency_sub_band, public_network, ack);
+        logInfo("--------------  network configured for public access -----------------------------");
+    }    
+    else{
+        update_ota_config_name_phrase(network_name, network_passphrase, frequency_sub_band, public_network, ack);
+        logInfo("--------------  network configured for private access -------------------------------");
+    }        
+        
+// configure network link checks
+// network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
+// check the link every count packets
+// declare the Dot disconnected after threshold failed link checks
+// for count = 3 and threshold = 5, the Dot will ask for a link check response every 5 packets and will consider the connection lost if it fails to receive 3 responses in a row
+        update_network_link_check_config(3, 5);   
+        
+/*  done thru radio cmds        
+// save changes to configuration
+        logInfo("saving configuration");
+        if (!dot->saveConfig()) {
+            logError("failed to save configuration");
+            return false;
+        }        
+        display_config();
+*/        
+        return true;
+}    
+
+//=================================================================================================
+//main()
+// main() runs in its own thread in the OS
+// (note the calls to wait below for delays)
+//=================================================================================================
+int main() {
+    RadioEvent events;
+    
+    mDotEvent  mdotevent;   //used to get ping info????
+    plan = new lora::ChannelPlan_US915();
+#ifdef GPIO_ENABLE   
+    gpio1.output();    
+    gpio1 =0;         
+    led1 = 1;
+#endif    
+    pc.baud(115200); 
+    pc.printf("\r\n**********************************************************\r\n");
+    pc.printf("\r\n XDOT BOOT\r\n");
+    pc.printf("COMM api_level = <HEX> %x.%x.%x.%x\r\n",api_level[0],api_level[1],api_level[2],api_level[3]);
+    pc.printf("COMM version   =       %x.%x.%x.%x\r\n",ver_level[0],ver_level[1],ver_level[2],ver_level[3]);
+    pc.printf("**********************************************************\r\n"); 
+//    LED_test(2);             
+    assert(plan);
+    dot = mDot::getInstance(plan);
+    assert(dot);
+    
+    //static bool deploy_mode = true;        
+    //dot->setLogLevel((deploy_mode) ? mts::MTSLog::INFO_LEVEL : mts::MTSLog::TRACE_LEVEL);  // TRACE_LEVEL        , INFO_LEVEL    
+    dot->setLogLevel((true) ? mts::MTSLog::TRACE_LEVEL : mts::MTSLog::TRACE_LEVEL);  // TRACE_LEVEL        , INFO_LEVEL       
+    dot->setEvents(&events); 
+ 
+//new !!    
+        // make sure library logging is turned on
+        //dot->setLogLevel(mts::MTSLog::TRACE_LEVEL);  
+
+
+// getStandbyFlag() should return the state of the standby flag directly from the processor
+// Standby flag: This bit is set by hardware and cleared only by a POR/PDR (power on reset/power down reset) or by setting the CSBF bit in the PWR power control register (PWR_CR)
+//  0: Device has not been in Standby mode
+//  1: Device has been in Standby mode
+//  The xDot should enter standby mode when deep sleep in invoked. So you should see the standby flag set if it came out of deep sleep.
+    if (!dot->getStandbyFlag()) {  //if 0 the power-up/reset which should always be the case at this point
+        logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
+
+        pc.printf("\r\n saved configuration: ");
+        frequency_sub_band = dot->getFrequencySubBand();        
+        pc.printf("\r\n subband: %d ",frequency_sub_band);                 
+        pc.printf("\r\n ADR: %d ",dot->getAdr());                 
+        pc.printf("\r\n antenna gain: %d ",dot->getAntennaGain());                 
+        pc.printf("\r\n transmit max pwr: %d ",dot->getMaxTxPower());                         
+        pc.printf("\r\n transmit min pwr: %d ",dot->getMinTxPower());                         
+        pc.printf("\r\n transmit pwr: %d ",dot->getTxPower());                         
+        pc.printf("\r\n TxDataRate: %d ",dot->getTxDataRate());                        
+        pc.printf("\r\n maxPktLen: %d ",dot->getMaxPacketLength());                                
+        pc.printf("\r\n port nmb: %d ",dot->getAppPort());                         
+        
+        cfg_network(true,public_network,frequency_sub_band);  //force network cfg,              
+        
+    } else {
+        // restore the saved session (join OTAA info) if the dot woke from deepsleep mode
+        // useful to use with deepsleep because session info is otherwise lost when the dot enters deepsleep
+        logInfo("restoring network session from NVM");
+        dot->restoreNetworkSession();
+    }
+//--------------------------------------------------------------------------------------------------------------------------------------------
+// configure network link checks
+// network link checks are a good alternative to requiring the gateway to ACK every packet and should allow a single gateway to handle more Dots
+//asb: not sure this is correct
+// check the link every count packets
+// declare the Dot disconnected after threshold failed link checks
+// for count = 3 and threshold = 5, the Dot will be considered disconnected after 15 missed packets in a row
+// asb: i think this is correct:
+//       : see mdot.h -> setLinkCheckCount(const uint8_t& count); 
+//       : LinkCounts only used if ACKs disabled
+//       only LinkCountThreshold is used => rejoin after LinkCountThreshold acks have been missed
+    update_network_link_check_config(3, 5);
+//----------------------------------------------------------------------------------------------------------------------------------------------
+
+// save changes to configuration
+//    logInfo("saving configuration");
+  
+  eui = mts::Text::bin2hexString(dot->getDeviceId()).c_str();
+  pc.printf("\r\nEUI: %s",eui);
+       
+    bool joined = false;        
+ //   std::vector<uint8_t> upstream_packet; 
+    uint8_t i;  
+        
+    i2c_proc_init();  //init i2c comm  
+    pc.printf("\r\nGoing to sleep\r\n");    //3.00 fails on startup to respond,move code further down
+    sleep_wake_interrupt_only(deep_sleep);
+    
+//scope test    
+//    gpio1 =1;
+
+
+//==============================================================================
+//  -loop here forever
+//       -sleep until LORA_WAKE goes hi => proc ready to send i2c cmd
+//       -start polling incoming i2c bus for proc cmd
+//       -execute cmd
+//       -take control of LORA_WAKE and toggle it hi to signal proc that xdot
+//        ready to send i2c ack message
+//       -go back to sleep
+//==============================================================================
+    bool bPulseLoraWake = false;
+    while(1)
+    {    
+        pc.printf("\n\r ***************************** ");       
+          
+        switch (i2c_proc_comm()){
+            case I2C_WRITE:                 //xdot ack ->proc                   
+                pc.printf("\n\r xdot ack -> proc done,going to sleep\n\r ");  
+                bPulseLoraWake = false;                
+//                gpio1 =0;
+                sleep_wake_interrupt_only(deep_sleep);   //wait for wake      
+//                gpio1 =1;
+                pc.printf("\n\r lora wake detected -> monitoring i2c bus\n\r ");                            
+                break;                            
+            case I2C_READ:      //xdot <- proc  
+                bPulseLoraWake = true;                    
+                switch (buf_rcv[0])
+                {
+                    case XDOT_CMD_XMIT_PKT:           
+                        pkt_upstrm  *pUp= (pkt_upstrm*)&buf_rcv[0];                       
+                        pkt_ack *pAck = (pkt_ack*)&buf_xmt[0];                       
+                        pAck->ack = I2C_ACK_PROC;
+                        pAck->cmd = XDOT_CMD_XMIT_PKT;                                             
+                        //pAck->dataLen = buf_rcv[1];
+                        pAck->dataLen = pUp->dataLen; //data len of xmitted pkt          
+                        pc.printf("\r\npkt to xmit data len: %d\r\n",pAck->dataLen);                        
+                        uint8_t chksum = chksum_proc(buf_rcv);
+                        //pc.printf("\r\chksum rcvd: %d, chksum computed: %d\r\n",chksum,pkt_upstrm->chksum);                        
+                        pc.printf("\r\nI2C chksum rcvd: %d",chksum);                        
+                        pc.printf(" chksum computed: %d",pUp->chksum);                        
+                        pAck->bXmitAttempted = 1;                            
+                        pAck->chksum_err = 0;
+                        if(pUp->chksum != chksum){
+                            pc.printf(" chksum err, aborting xmit");  
+                            pAck->bXmitAttempted = 0;                                                  
+                            pAck->mdot_ret = -2048;  //wbit rtn code?
+                            pAck->chksum_err = 1;
+                            break;
+                        }
+                        if (pUp->dataLen ==  0){ //datalen  non zero?                               
+                            pAck->bXmitAttempted = 0;                            
+                            break;
+                        }    
+                        upstream_packet.clear();    //xfr data from incoming bfr to xmit bfr
+                        for (i=0; i< pUp->dataLen;i++) upstream_packet.push_back(pUp->txData[i]);                                  
+                        pc.printf("\r\n[TEST],Upstream Packet Received"); // no \r\n because it comes below
+                        for(std::vector<uint8_t>::iterator it = upstream_packet.begin(); it != upstream_packet.end(); ++it) pc.printf(",0x%x", *it);                                 
+                        pc.printf("\r\n"); // see i told you.       
+               
+//not done here, done thru radio commands
+                       // cfg_network(false,pUp->bPublicNetwork,pUp->subBand);  //chk for change in network cfg                                                                                       
+                       // dot->setAdr(pUp->bSetAdr);  // enable or disable Adaptive Data Rate
+                        
+                        joined = dot->getNetworkJoinStatus();   //are we joined to Lorawan?
+                        pAck->joinAttempts = 0;                 //no attempts made yet to join                
+                        if(!joined) {                //if not previously joined, then need to join now
+                            pAck->bJoined = 0;                 
+                            pc.printf("\r\n----------- NETWORK NOT JOINED YET, WILL TRY TO JOIN %d TIMES\r\n",pUp->joinAttemps);                                                            
+                            joined = join_network_wbit(pUp->joinAttemps);
+                            pAck->joinAttempts = join_network_attempts_wbit();
+                            if (!joined)pc.printf("\r\n----------- FAILED TO JOIN...GIVING UP\r\n");  // join network if not joined
+                        }         
+                        if (joined){          
+                            pAck->bJoined = 1;      //we are joined to the network
+                            pAck->bAck = 0;         //won't know if we receive a lorawan ack until after xmit
+                            pAck->bAckdata = 0;     //won't know if we receive a lorawan ack downstream data until after xmit
+                            pAck->rssi = 0;         //if not rx1/rx2 then no RSSI value                             
+                            packets_sent++;  
+ //send packet
+ //return code indicates results, send return code back to proc Dec14,2017
+                            pAck->mdot_ret = dot->send(upstream_packet);
+                            printf("\n\rdata->send() return code: %d\r\n",pAck->mdot_ret);                                     
+                            if (pAck->mdot_ret == mDot::MDOT_OK){  //xmit the pkt in blocking mode, return false if no ack                                                                                              
+                            //if (dot->send(upstream_packet) == mDot::MDOT_OK){  //xmit the pkt in blocking mode, return false if no ack                                                                                              
+                                acks_rcvd++;
+                                pAck->bAck = 1;                //we got a Rx1 or Rx2 ack                           
+                                mDot::rssi_stats rssiStats = dot->getRssiStats();        //rssi stat         
+                                pAck->rssi = (int8_t)rssiStats.last;  
+                                printf("\n\rdata->send()=  true => ack rcvd :ack=: %d, rssi=: %d\r\n",pAck->bAck,pAck->rssi);                                     
+                                
+//test for subband change   
+//                                pc.printf("\r\n----------- CHANGING SUBBANDS-------------------------------------\r\n");                                                                                         
+//                                cfg_network(false,pUp->bPublicNetwork,2);  //chk for change in network cfg                        
+                                
+                                if (events.is_packet_received()){    //any downstream data from the Rx1/Rx2 pkt?                                     
+                                    printf("\n\revents.is_packet_received = true\r\n");                                       
+                                    pAck->bAckdata = 1;                                          
+                                    upstream_packet.clear();    
+                                    upstream_packet = events.get_downstream_packet();
+                                    pAck->rxLen = upstream_packet.size();     
+                                    if (pAck->rxLen > I2C_MAX_ACK_DATA){
+                                        pc.printf("\r\n got ack with pkt data too large.. rejected\r\n");
+                                        break;  
+                                    }                                        
+                                    pc.printf("\r\n pkt data: ");                                  
+                                    for (i=0; i< pAck->rxLen;i++) {
+                                        pAck->rxData[i]= upstream_packet[i]; 
+                                        pc.printf(" %x",pAck->rxData[i]);                                                                                                              
+                                    }
+                                } //if  downstream data rcvd                                     
+                                else{
+                                    printf("\n\revents.is_packet_received ()=  false => ack rcvd but no data\r\n");                                                                             
+                                }                                        
+                             } //send() returns K
+                             else{
+                                printf("\n\rdata->send()=  false => no ack\r\n");     //could be some other error                                    
+                             }                                                                 
+                          }//if joined
+                        break;
+                    case XDOT_CMD_SET_RADIO:
+                        pc.printf("\n\r proc cmd: CMD_SET_RADIO");  
+                        pkt_setradiodwn *pDwnRadio= (pkt_setradiodwn*)&buf_xmt[0];                                 
+                        pkt_setradioup  *pUpRadio = (pkt_setradioup*)&buf_rcv[0];                                
+                        pDwnRadio->ack = I2C_ACK_PROC;
+                        pDwnRadio->cmd = XDOT_CMD_SET_RADIO;
+
+                        if (pUpRadio->bSetParams){
+                            pc.printf("\n\r setting subband to %d ",pUpRadio->sub_band);                                   
+                            cfg_network(false,true,(uint8_t)pUpRadio->sub_band);                                                
+                            pc.printf("\n\r setting adr to %d ",pUpRadio->aDR);                                   
+                            dot->setAdr((uint8_t)pUpRadio->aDR);  // enable or disable Adaptive Data Rate
+                            pc.printf("\n\r setting antenna gain to %d ",pUpRadio->antennaGaindBi);                                   
+                            dot->setAntennaGain(pUpRadio->antennaGaindBi);
+                            pc.printf("\n\r setting radio tx power to %d ",pUpRadio->txPowerdBm);                                   
+                            dot->setTxPower(pUpRadio->txPowerdBm);
+                            pc.printf("\n\r setting tx datarate to %d ",pUpRadio->dataRate);                                   
+                            dot->setTxDataRate(pUpRadio->dataRate);                         
+                            pc.printf("\n\r setting application port %d ",pUpRadio->appPort);                                   
+                            dot->setAppPort(pUpRadio->appPort);
+                            pc.printf("\n\r saving configuration");
+                            if (!dot->saveConfig())logError("failed to save configuration");                                                        
+                            display_config();                              
+                        }
+                        
+                        pDwnRadio->public_network = public_network;
+                        pDwnRadio->sub_band = dot->getFrequencySubBand();
+                        pDwnRadio->maxDataLen = dot->getMaxPacketLength();                   
+                        pDwnRadio->maxTxPowerdBm = dot->getMaxTxPower();
+                        pDwnRadio->minTxPowerdBm = dot->getMinTxPower();
+                        pDwnRadio->aDR = dot->getAdr();
+                        pDwnRadio->antennaGaindBi = dot->getAntennaGain();
+                        pDwnRadio->txPowerdBm = dot->getTxPower();                      
+                        pDwnRadio->dataRate = dot->getTxDataRate();
+                        pDwnRadio->appPort = dot->getAppPort();                         
+                        break;    
+
+                    case XDOT_CMD_GET_EUI:   //0307: modified to include radio parameter settings   
+                        pc.printf("\n\r proc cmd: get EUI");                        
+                        pkt_eui *peui = (pkt_eui*)&buf_xmt[0];                                
+                        peui->ack = I2C_ACK_PROC;
+                        peui->cmd = XDOT_CMD_GET_EUI;
+                        upstream_packet.clear(); 
+                        upstream_packet = dot->getDeviceId();                                                
+                        peui->dataLen = upstream_packet.size();                           
+                        for (i=0; i< peui->dataLen;i++) peui->euiData[i] = upstream_packet[i];  
+                        for (i=0; i< 4;i++) peui->apiLvlData[i] =  api_level[i];
+                        for (i=0; i< 4;i++) peui->verLvlData[i] =  ver_level[i];
+                        peui->dataLen = sizeof(pkt_eui)-3;  //size of struc minus first 3 bytes                                      
+                        pc.printf("\n\r eui data length: %d",peui->dataLen);                                                                                              
+                        break;    
+                    case XDOT_CMD_SET_KEY_X:
+                        pc.printf("\n\r proc cmd: set a key, simulating minm delay before wake pulse\r\n");                                  
+                        wait_ms(I2C_MIN_WAIT_DELAY);
+                        buf_xmt[0] = I2C_ACK_PROC;
+                        buf_xmt[1] = XDOT_CMD_SET_KEY_X;
+                        break;                       
+                    case XDOT_CMD_GATEWAY_PING:
+                        pc.printf("\n\r proc cmd: xmit gateway ping\r\n");   
+                        pkt_ping *pPing = (pkt_ping*)&buf_xmt[0];                                
+                        pPing->ack = I2C_ACK_PROC;
+                        pPing->cmd = XDOT_CMD_GATEWAY_PING;
+                        pPing->dataLen = 3;  //only 3 bytes returned
+                        pc.printf("\r\n----------- SENDING GATEWAY PING \r\n");  
+                        mDot::ping_response ping_res;
+                        ping_res = dot->ping();
+                        pPing->status = (int8_t)ping_res.status;
+                        pPing->rssi = (int8_t)ping_res.rssi;
+                        pPing->snr = (int8_t)ping_res.snr;          
+                        if (ping_res.status == 0)            
+                            pc.printf("\r\n----------- GATEWAY PING SUCCEEDED \r\n");  
+                        else
+                            pc.printf("\r\n----------- GATEWAY PING FAIL \r\n");  
+                        break;                         
+                    default:
+                        pc.printf("\n\r proc cmd not recognized:%x",buf_rcv[0]);  
+                        wait_ms(I2C_MIN_WAIT_DELAY);
+                        buf_xmt[0] = I2C_ACK_PROC;
+                        buf_xmt[1] = XDOT_CMD_UNDEFINED;
+                } //switch buf_rcv[0]
+                //gpio1 =1;       //test
+                if (bPulseLoraWake) i2c_pulse_wake(); //pulse wake-up lo->hi->lo to signal proc that xdot ready to send ack
+                
+        } //switch i2c_proc_comm
+    } //while 
+
+} //main
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wbit_util.cpp	Mon Jun 18 17:31:35 2018 +0000
@@ -0,0 +1,41 @@
+#include "wbit_util.h"
+#include "dot_util.h"
+#include "mbed.h"
+#include "mDot.h"
+
+uint8_t j_attempts = 0;
+//return number of attempts it took to join the network
+uint8_t join_network_attempts_wbit() {
+    return j_attempts;
+}    
+
+bool join_network_wbit(uint8_t nmbAttempts) {
+    //int32_t j_attempts = 0;
+    j_attempts = 0;
+    int32_t ret = mDot::MDOT_ERROR;
+    
+// attempt to join the network
+    while (ret != mDot::MDOT_OK) {
+        j_attempts++;
+        logInfo("attempt %d to join network",j_attempts);
+        ret = dot->joinNetwork();
+        if (ret == mDot::MDOT_OK) return true;
+        
+        logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        if (j_attempts >= nmbAttempts)
+        {
+            logInfo("attempts %d to join network exceeds specified attempts $d ",j_attempts,nmbAttempts);   
+            return false;
+        }               
+        // in some frequency bands we need to wait until another channel is available before transmitting again
+        uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
+        if (delay_s < 2) {
+            logInfo("waiting %lu s until next free channel", delay_s);
+            wait(delay_s);
+        } else {
+            logInfo("sleeping %lu s until next free channel", delay_s);
+            dot->sleep(delay_s, mDot::RTC_ALARM, false);
+        }        
+    }//while
+    return false;
+}
\ No newline at end of file