Greg Voronin / Mbed OS gammaCanary02

Files at this revision

API Documentation at this revision

Comitter:
gov1
Date:
Tue Jul 31 16:30:32 2018 +0000
Commit message:
complete version with emer. batt low check

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
LoRa.cpp Show annotated file Show diff for this revision Revisions of this file
LoRa.h Show annotated file Show diff for this revision Revisions of this file
MAX17055.cpp Show annotated file Show diff for this revision Revisions of this file
MAX17055.h Show annotated file Show diff for this revision Revisions of this file
MBed_Adafruit_GPS.cpp Show annotated file Show diff for this revision Revisions of this file
MBed_Adafruit_GPS.h 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
main.cpp 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,4 @@
+.build
+.mbed
+projectfiles
+*.py*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LoRa.cpp	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,487 @@
+#include <LoRa.h>
+
+// registers
+#define REG_FIFO                 0x00
+#define REG_OP_MODE              0x01
+#define REG_FRF_MSB              0x06
+#define REG_FRF_MID              0x07
+#define REG_FRF_LSB              0x08
+#define REG_PA_CONFIG            0x09
+#define REG_LNA                  0x0c
+#define REG_FIFO_ADDR_PTR        0x0d
+#define REG_FIFO_TX_BASE_ADDR    0x0e
+#define REG_FIFO_RX_BASE_ADDR    0x0f
+#define REG_FIFO_RX_CURRENT_ADDR 0x10
+#define REG_IRQ_FLAGS            0x12
+#define REG_RX_NB_BYTES          0x13
+#define REG_PKT_RSSI_VALUE       0x1a
+#define REG_PKT_SNR_VALUE        0x1b
+#define REG_MODEM_CONFIG_1       0x1d
+#define REG_MODEM_CONFIG_2       0x1e
+#define REG_PREAMBLE_MSB         0x20
+#define REG_PREAMBLE_LSB         0x21
+#define REG_PAYLOAD_LENGTH       0x22
+#define REG_MODEM_CONFIG_3       0x26
+#define REG_RSSI_WIDEBAND        0x2c
+#define REG_DETECTION_OPTIMIZE   0x31
+#define REG_DETECTION_THRESHOLD  0x37
+#define REG_SYNC_WORD            0x39
+#define REG_DIO_MAPPING_1        0x40
+#define REG_VERSION              0x42
+
+// modes
+#define MODE_LONG_RANGE_MODE     0x80
+#define MODE_SLEEP               0x00
+#define MODE_STDBY               0x01
+#define MODE_TX                  0x03
+#define MODE_RX_CONTINUOUS       0x05
+#define MODE_RX_SINGLE           0x06
+
+// PA config
+#define PA_BOOST                 0x80
+
+// IRQ masks
+#define IRQ_TX_DONE_MASK           0x08
+#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
+#define IRQ_RX_DONE_MASK           0x40
+
+#define MAX_PKT_LENGTH           255
+
+SPI _spi(P5_1, P5_2, P5_0);
+
+LoRaClass::LoRaClass() :
+  spi(_spi),
+  _ss(LORA_DEFAULT_SS_PIN ), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
+  _frequency(0),
+  _packetIndex(0),
+  _implicitHeaderMode(0),
+  _onReceive(NULL)
+{
+  // overide Stream timeout value
+  //setTimeout(0);
+}
+
+int LoRaClass::begin(long frequency)
+{
+  // perform reset
+  _reset = 0;
+  wait(0.010);
+  _reset = 1;
+  wait(0.010);
+
+  // set SS high
+  _ss = 1;
+
+  // check version
+  uint8_t version = readRegister(REG_VERSION);
+  if (version != 0x12) {
+    return 0;
+  }
+
+  // put in sleep mode
+  sleep();
+
+  // set frequency
+  setFrequency(frequency);
+
+  // set base addresses
+  writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
+  writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
+
+  // set LNA boost
+  writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
+
+  // set auto AGC
+  writeRegister(REG_MODEM_CONFIG_3, 0x04);
+
+  // set output power to 17 dBm
+  setTxPower(17);
+
+  // put in standby mode
+  idle();
+
+  return 1;
+}
+
+void LoRaClass::end()
+{
+  // put in sleep mode
+  sleep();
+}
+
+int LoRaClass::beginPacket(int implicitHeader)
+{
+  // put in standby mode
+  idle();
+
+  if (implicitHeader) {
+    implicitHeaderMode();
+  } else {
+    explicitHeaderMode();
+  }
+
+  // reset FIFO address and paload length
+  writeRegister(REG_FIFO_ADDR_PTR, 0);
+  writeRegister(REG_PAYLOAD_LENGTH, 0);
+
+  return 1;
+}
+
+int LoRaClass::endPacket()
+{
+  // put in TX mode
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
+
+  // wait for TX done
+  while((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0);
+
+  // clear IRQ's
+  writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
+
+  return 1;
+}
+
+int LoRaClass::parsePacket(int size)
+{
+  int packetLength = 0;
+  int irqFlags = readRegister(REG_IRQ_FLAGS);
+
+  if (size > 0) {
+    implicitHeaderMode();
+
+    writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
+  } else {
+    explicitHeaderMode();
+  }
+
+  // clear IRQ's
+  writeRegister(REG_IRQ_FLAGS, irqFlags);
+
+  if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
+    // received a packet
+    _packetIndex = 0;
+
+    // read packet length
+    if (_implicitHeaderMode) {
+      packetLength = readRegister(REG_PAYLOAD_LENGTH);
+    } else {
+      packetLength = readRegister(REG_RX_NB_BYTES);
+    }
+
+    // set FIFO address to current RX address
+    writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
+
+    // put in standby mode
+    idle();
+  } else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
+    // not currently in RX mode
+
+    // reset FIFO address
+    writeRegister(REG_FIFO_ADDR_PTR, 0);
+
+    // put in single RX mode
+    writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
+  }
+
+  return packetLength;
+}
+
+int LoRaClass::packetRssi()
+{
+  return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868E6 ? 164 : 157));
+}
+
+float LoRaClass::packetSnr()
+{
+  return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25;
+}
+
+int LoRaClass::_putc(int value)
+{
+  char buf = (char) value;
+  size_t size = sizeof(buf);
+  int currentLength = readRegister(REG_PAYLOAD_LENGTH);
+
+  // check size
+  if ((currentLength + size) > MAX_PKT_LENGTH) {
+    size = MAX_PKT_LENGTH - currentLength;
+  }
+
+  writeRegister(REG_FIFO, buf);
+
+  // update length
+  writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
+  
+  return (int) buf;
+}
+
+int LoRaClass::available()
+{
+  return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
+}
+
+int LoRaClass::_getc()
+{
+  if (!available()) {
+    return -1;
+  }
+
+  _packetIndex++;
+
+  return readRegister(REG_FIFO);
+}
+
+int LoRaClass::peek()
+{
+  if (!available()) {
+    return -1;
+  }
+
+  // store current FIFO address
+  int currentAddress = readRegister(REG_FIFO_ADDR_PTR);
+
+  // read
+  uint8_t b = readRegister(REG_FIFO);
+
+  // restore FIFO address
+  writeRegister(REG_FIFO_ADDR_PTR, currentAddress);
+
+  return b;
+}
+
+void LoRaClass::onReceive(void(*callback)(int))
+{
+  _onReceive = callback;
+
+  if (callback) {
+    writeRegister(REG_DIO_MAPPING_1, 0x00);
+
+    //attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING);
+    _dio0.rise(&LoRaClass::onDio0Rise);
+  } else {
+    //detachInterrupt(digitalPinToInterrupt(_dio0));
+    _dio0.rise(NULL);
+  }
+}
+
+void LoRaClass::receive(int size)
+{
+  if (size > 0) {
+    implicitHeaderMode();
+
+    writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
+  } else {
+    explicitHeaderMode();
+  }
+
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
+}
+
+void LoRaClass::idle()
+{
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
+}
+
+void LoRaClass::sleep()
+{
+  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
+}
+
+void LoRaClass::setTxPower(int level, int outputPin)
+{
+  if (PA_OUTPUT_RFO_PIN == outputPin) {
+    // RFO
+    if (level < 0) {
+      level = 0;
+    } else if (level > 14) {
+      level = 14;
+    }
+
+    writeRegister(REG_PA_CONFIG, 0x70 | level);
+  } else {
+    // PA BOOST
+    if (level < 2) {
+      level = 2;
+    } else if (level > 17) {
+      level = 17;
+    }
+
+    writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
+  }
+}
+
+void LoRaClass::setFrequency(long frequency)
+{
+  _frequency = frequency;
+
+  uint64_t frf = ((uint64_t)frequency << 19) / 32000000;
+
+  writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
+  writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
+  writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
+}
+
+void LoRaClass::setSpreadingFactor(int sf)
+{
+  if (sf < 6) {
+    sf = 6;
+  } else if (sf > 12) {
+    sf = 12;
+  }
+
+  if (sf == 6) {
+    writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
+    writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
+  } else {
+    writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
+    writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
+  }
+
+  writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
+}
+
+void LoRaClass::setSignalBandwidth(long sbw)
+{
+  int bw;
+
+  if (sbw <= 7.8E3) {
+    bw = 0;
+  } else if (sbw <= 10.4E3) {
+    bw = 1;
+  } else if (sbw <= 15.6E3) {
+    bw = 2;
+  } else if (sbw <= 20.8E3) {
+    bw = 3;
+  } else if (sbw <= 31.25E3) {
+    bw = 4;
+  } else if (sbw <= 41.7E3) {
+    bw = 5;
+  } else if (sbw <= 62.5E3) {
+    bw = 6;
+  } else if (sbw <= 125E3) {
+    bw = 7;
+  } else if (sbw <= 250E3) {
+    bw = 8;
+  } else /*if (sbw <= 250E3)*/ {
+    bw = 9;
+  }
+
+  writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4));
+}
+
+void LoRaClass::setCodingRate4(int denominator)
+{
+  if (denominator < 5) {
+    denominator = 5;
+  } else if (denominator > 8) {
+    denominator = 8;
+  }
+
+  int cr = denominator - 4;
+
+  writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1));
+}
+
+void LoRaClass::setPreambleLength(long length)
+{
+  writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8));
+  writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0));
+}
+
+void LoRaClass::setSyncWord(int sw)
+{
+  writeRegister(REG_SYNC_WORD, sw);
+}
+
+void LoRaClass::enableCrc()
+{
+  writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04);
+}
+
+void LoRaClass::disableCrc()
+{
+  writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb);
+}
+
+uint8_t LoRaClass::random()
+{
+  return readRegister(REG_RSSI_WIDEBAND);
+}
+
+void LoRaClass::dumpRegisters(Stream& out)
+{
+  for (int i = 0; i < 128; i++) {
+    out.printf("0x%x: 0x%x", i, readRegister(i));
+  }
+}
+
+void LoRaClass::explicitHeaderMode()
+{
+  _implicitHeaderMode = 0;
+
+  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
+}
+
+void LoRaClass::implicitHeaderMode()
+{
+  _implicitHeaderMode = 1;
+
+  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
+}
+
+void LoRaClass::handleDio0Rise()
+{
+  int irqFlags = readRegister(REG_IRQ_FLAGS);
+
+  // clear IRQ's
+  writeRegister(REG_IRQ_FLAGS, irqFlags);
+
+  if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
+    // received a packet
+    _packetIndex = 0;
+
+    // read packet length
+    int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES);
+
+    // set FIFO address to current RX address
+    writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
+
+    if (_onReceive) {
+      _onReceive(packetLength);
+    }
+
+    // reset FIFO address
+    writeRegister(REG_FIFO_ADDR_PTR, 0);
+  }
+}
+
+uint8_t LoRaClass::readRegister(uint8_t address)
+{
+  return singleTransfer(address & 0x7f, 0x00);
+}
+
+void LoRaClass::writeRegister(uint8_t address, uint8_t value)
+{
+  singleTransfer(address | 0x80, value);
+}
+
+uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
+{
+  uint8_t response;
+
+  _ss = 0;
+
+  spi.write(address);
+  response = spi.write(value);
+
+  _ss = 1;
+
+  return response;
+}
+
+void LoRaClass::onDio0Rise()
+{
+  LoRa.handleDio0Rise();
+}
+
+LoRaClass LoRa;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LoRa.h	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,89 @@
+#ifndef LORA_H
+#define LORA_H
+
+#include "mbed.h"
+
+#define LORA_DEFAULT_SS_PIN    P5_4
+#define LORA_DEFAULT_RESET_PIN P5_5
+#define LORA_DEFAULT_DIO0_PIN  P3_3
+
+#define PA_OUTPUT_RFO_PIN      0
+#define PA_OUTPUT_PA_BOOST_PIN 1
+
+class LoRaClass: public Stream
+{
+public:
+    LoRaClass();
+
+    int begin(long frequency);
+    void end();
+
+    int beginPacket(int implicitHeader = false);
+    int endPacket();
+
+    int parsePacket(int size = 0);
+    int packetRssi();
+    float packetSnr();
+
+    void onReceive(void(*callback)(int));
+
+    void receive(int size = 0);
+    void idle();
+    void sleep();
+
+    void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
+    void setFrequency(long frequency);
+    void setSpreadingFactor(int sf);
+    void setSignalBandwidth(long sbw);
+    void setCodingRate4(int denominator);
+    void setPreambleLength(long length);
+    void setSyncWord(int sw);
+    void enableCrc();
+    void disableCrc();
+
+    // deprecated
+    void crc() {
+        enableCrc();
+    }
+    void noCrc() {
+        disableCrc();
+    }
+
+    uint8_t random();
+
+    void dumpRegisters(Stream& out);
+
+//protected:
+    // from Print
+    virtual int _putc(int value);
+    virtual int _getc();
+
+    int available();
+    int peek();
+
+private:
+    void explicitHeaderMode();
+    void implicitHeaderMode();
+
+    void handleDio0Rise();
+
+    uint8_t readRegister(uint8_t address);
+    void writeRegister(uint8_t address, uint8_t value);
+    uint8_t singleTransfer(uint8_t address, uint8_t value);
+
+    static void onDio0Rise();
+
+private:
+    SPI &spi;
+    DigitalOut _ss;
+    DigitalOut _reset;
+    InterruptIn _dio0;
+    int _frequency;
+    int _packetIndex;
+    int _implicitHeaderMode;
+    void (*_onReceive)(int);
+};
+
+extern LoRaClass LoRa;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX17055.cpp	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,501 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "MAX17055.h"
+
+//******************************************************************************
+MAX17055::MAX17055(I2C &i2c, int address) :
+    i2c(i2c),
+    addr(address)
+{
+}
+
+//******************************************************************************
+MAX17055::~MAX17055()
+{
+}
+
+//******************************************************************************
+void MAX17055::init(float r_sense)
+{
+    this->r_sense = r_sense;
+    i_lsb = MAX17055_I_LSB_UV / r_sense;
+    i_min_max_lsb = MAX17055_I_MAX_MIN_LSB_MV / r_sense;
+}
+
+//******************************************************************************
+int MAX17055::status(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::STATUS, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (unsigned int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::v_cell(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::V_CELL, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (unsigned int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::v_cell(float *value)
+{
+    int v;
+
+    if (v_cell(&v)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = v * MAX17055_V_LSB_MV;
+
+    return MAX17055_NO_ERROR;
+}
+
+/** ************************************************************************ **/
+/** ************************ added by gv 7/8/2018 ************************** **/
+/** ************************************************************************ **/
+int MAX17055::soc1(int *value)
+{
+    char buf[2];
+    
+    if (readReg(MAX17055::REP_SOC,buf,2))
+    {
+        return MAX17055_ERROR;    
+    }   
+      
+    *value = (unsigned int)((buf[1]<<8) | buf[0]);
+    
+    return MAX17055_NO_ERROR;
+} 
+
+int MAX17055::soc2(int *valueLow, int *valueHigh)
+{
+
+    char buf[2];
+
+    if (readReg(MAX17055::REP_SOC, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *valueHigh = (unsigned char)buf[1];
+    *valueLow = (unsigned char)buf[0];
+    return MAX17055_NO_ERROR;
+    
+}
+
+int MAX17055::reportSOC(int *valueHigh)
+{
+
+    char buf[2];
+
+    if (readReg(MAX17055::REP_SOC, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *valueHigh = (unsigned char)buf[1];
+    
+    return MAX17055_NO_ERROR;
+    
+}
+
+int MAX17055::tte1(int *value)
+{
+    char buf[2];
+    
+    if (readReg(MAX17055::TTE,buf,2))
+    {
+        return MAX17055_ERROR;    
+    }   
+      
+    *value = (unsigned int)((buf[1]<<8) | buf[0]);
+    
+    return MAX17055_NO_ERROR;
+} 
+
+int MAX17055::tte2(int *valueLow, int *valueHigh)
+{
+
+    char buf[2];
+
+    if (readReg(MAX17055::TTE, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *valueHigh = (unsigned char)buf[1];
+    *valueLow = (unsigned char)buf[0];
+    
+    return MAX17055_NO_ERROR;
+}
+
+
+/** ************************************************************************ **/
+/** ************************************************************************ **/
+
+//******************************************************************************
+int MAX17055::avg_v_cell(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::AVG_V_CELL, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (unsigned int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::avg_v_cell(float *value)
+{
+    int avc;
+
+    if (avg_v_cell(&avc)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = avc * MAX17055_V_LSB_MV;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::max_min_volt(int *max, int *min)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::MAX_MIN_VOLT, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *max = (unsigned char)buf[1];
+    *min = (unsigned char)buf[0];
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::max_min_volt(float *max, float *min)
+{
+    int v_max, v_min;
+
+    if (max_min_volt(&v_max, &v_min)) {
+        return MAX17055_ERROR;
+    }
+
+    *max = v_max * MAX17055_V_MAX_MIN_LSB_MV;
+    *min = v_min * MAX17055_V_MAX_MIN_LSB_MV;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::current(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::CURRENT, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (short int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::current(float *value)
+{
+    int i;
+
+    if (current(&i)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = i * i_lsb;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::avg_current(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::AVG_CURRENT, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (short int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::avg_current(float *value)
+{
+    int i_a;
+
+    if (avg_current(&i_a)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = i_a * i_lsb;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::max_min_curr(int *max, int *min)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::MAX_MIN_CURR, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *max = (signed char)buf[1];
+    *min = (signed char)buf[0];
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::max_min_curr(float *max, float *min)
+{
+    int i_max, i_min;
+
+    if (max_min_curr(&i_max, &i_min)) {
+        return MAX17055_ERROR;
+    }
+
+    *max = i_max * i_min_max_lsb;
+    *min = i_min * i_min_max_lsb;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::temp(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::TEMP, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (short int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::temp(float *value)
+{
+    int t;
+
+    if (temp(&t)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = t * (1.0f / 256);
+
+    return MAX17055_NO_ERROR;
+}
+
+
+//******************************************************************************
+int MAX17055::avg_ta(int *value)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::AVG_TA, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = (short int)((buf[1] << 8) | buf[0]);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::avg_ta(float *value)
+{
+    int ta;
+
+    if (avg_ta(&ta)) {
+        return MAX17055_ERROR;
+    }
+
+    *value = ta * (1.0f / 256);
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::max_min_temp(int *max, int *min)
+{
+    char buf[2];
+
+    if (readReg(MAX17055::MAX_MIN_TEMP, buf, 2)) {
+        return MAX17055_ERROR;
+    }
+
+    *max = (signed char)buf[1];
+    *min = (signed char)buf[0];
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::max_min_temp(float *max, float *min)
+{
+    int t_max, t_min;
+
+    if (max_min_temp(&t_max, &t_min)) {
+        return MAX17055_ERROR;
+    }
+
+    *max = t_max;
+    *min = t_min;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::writeReg(reg_t reg, char value, bool verify)
+{
+    char buf[] = { (char)reg, value };
+
+    if (i2c.write(addr, buf, sizeof(buf))) {
+        return MAX17055_ERROR;
+    }
+
+    return MAX17055_NO_ERROR;
+}
+
+/** ************************************************************************ **/
+/** ************ Special to write config to use Thermistor ***************** **/
+/** ************************************************************************ **/
+int MAX17055::writeConfig()
+{
+    char cmd[3];
+    cmd[0] = MAX17055::CONFIG;
+    cmd[1] = 0xA2;
+    cmd[2] = 0x10;    
+    
+    
+   if (i2c.write(0x6C, cmd, 3))
+   {
+        return MAX17055_ERROR;    
+   }
+   Thread::wait(1);
+   return MAX17055_NO_ERROR; 
+}
+
+
+
+//******************************************************************************
+int MAX17055::writeReg(reg_t reg, uint16_t value, bool verify)
+{
+    char wbuf[3];
+    char rbuf[2];
+    int attempt;
+
+    wbuf[0] = reg;
+    wbuf[1] = value;
+    wbuf[2] = value >> 8;
+
+    attempt = 0;
+
+    do {
+        if (i2c.write(addr, wbuf, 3)) return MAX17055_ERROR;
+
+        if (!verify) break;
+
+        Thread::wait(1);
+
+        if (i2c.read(addr, rbuf, 2)) return MAX17055_ERROR;
+
+    } while ((((rbuf[1] << 8) | rbuf[0]) != value) && (attempt++ < 3));
+
+    if (attempt == 3) return MAX17055_ERROR;
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::readReg(reg_t reg, char *value)
+{
+    char buf[] = { (char)reg };
+
+    if (i2c.write(addr, buf, sizeof(buf))) {
+        return MAX17055_ERROR;
+    }
+
+    if (i2c.read(addr, value, 1)) {
+        return MAX17055_ERROR;
+    }
+
+    return MAX17055_NO_ERROR;
+}
+
+//******************************************************************************
+int MAX17055::readReg(reg_t reg, char *buf, int len)
+{
+    *buf = (char)reg;
+
+    if (i2c.write(addr, buf, 1)) {
+        return MAX17055_ERROR;
+    }
+
+    if (i2c.read(addr, buf, len)) {
+        return MAX17055_ERROR;
+    }
+
+    return MAX17055_NO_ERROR;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX17055.h	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,463 @@
+/*******************************************************************************
+ * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#ifndef _MAX17055_H_
+#define _MAX17055_H_
+
+#include "mbed.h"
+
+#define MAX17055_I2C_ADDRESS   0x6C
+
+#define MAX17055_NO_ERROR 0
+#define MAX17055_ERROR    -1
+
+#define MAX17055_V_LSB_MV         7.8125E-5f
+#define MAX17055_V_MAX_MIN_LSB_MV 2.0E-2f
+#define MAX17055_I_LSB_UV         1.5625E-3f
+#define MAX17055_I_MAX_MIN_LSB_MV 0.0004f
+
+/**
+ * @brief MAX17055 7µA 1-Cell Fuel Gauge with ModelGauge m5 EZ
+ *
+ * @details The MAX17055 is a low 7μA operating current fuel gauge which
+ * implements Maxim ModelGauge™ m5 EZ algorithm.  ModelGauge m5 EZ makes
+ * fuel gauge implementation easy by eliminating battery characterization
+ * requirements and simplifying host software interaction.
+ * The ModelGauge m5 EZ robust algorithm provides tolerance against battery
+ * diversity for most lithium batteries and applications.
+ * <br>https://www.maximintegrated.com/en/products/power/battery-management/MAX17055.html
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "MAX17055.h"
+ *
+ * // I2C Master 2
+ * I2C i2c(I2C2_SDA, I2C2_SCL);
+ *
+ * MAX17055 max17055(i2c);
+ *
+ * int main()
+ * {
+ *     int status;
+ *     float f_value;
+ *
+ *     // Set sense resistor value
+ *     max17055.init(0.05f);
+ *
+ *     // Print status
+ *     max17055.status(&status);
+ *     printf("MAX17055 status: %04X\r\n", (uint16_t)status);
+ *
+ *     for (;;) {
+ *         // Print formatted voltage, current and temperature values
+ *         max17055.v_cell(&f_value);
+ *         printf("%6.3fV ", f_value);
+ *         max17055.current(&f_value);
+ *         printf("%6.3fI ", f_value);
+ *         max17055.temp(&f_value);
+ *         printf("%6.3fC ", f_value);
+ *         printf("\r\n");
+ *
+ *         Thread::wait(3000);
+ *     }
+ * }
+ * @endcode
+ */
+
+class MAX17055
+{
+public:
+
+    /**
+     * @brief   Register Address
+     * @details MAX17055 register addresses
+     */
+    typedef enum {
+        STATUS = 0x00,
+        V_ALRT_TH,
+        T_ALRT_TH,
+        S_ALRT_TH,
+        AT_RATE,
+        REP_CAP,
+        REP_SOC,
+        AGE,
+        TEMP,
+        V_CELL,
+        CURRENT,
+        AVG_CURRENT,
+        Q_RESIDUAL,
+        MIX_SOC,
+        AV_SOC,
+        MIX_CAP,
+        FULL_CAP_REP,
+        TTE,
+        QR_TABLE_00,
+        FULL_SOC_THR,
+        R_CELL,
+        AVG_TA = 0x16,
+        CYCLES,
+        DESIGN_CAP,
+        AVG_V_CELL,
+        MAX_MIN_TEMP,
+        MAX_MIN_VOLT,
+        MAX_MIN_CURR,
+        CONFIG,
+        I_CHG_TERM,
+        AV_CAP,
+        TTF,
+        DEV_NAME,
+        QR_TABLE_10,
+        FULL_CAP_NOM,
+        AIN = 0x27,
+        LEARN_CFG,
+        FILTER_CFG,
+        RELAX_CFG,
+        MISC_CFG,
+        T_GAIN,
+        T_OFF,
+        C_GAIN,
+        C_OFF,
+        QR_TABLE_20 = 0x32,
+        DIE_TEMP = 0x34,
+        FULL_CAP,
+        R_COMP0 = 0x38,
+        TEMP_CO,
+        V_EMPTY,
+        F_STAT = 0x3D,
+        TIMER,
+        SHDN_TIMER,
+        USER_MEM1,
+        QR_TABLE_30 = 0x42,
+        R_GAIN,
+        DQ_ACC = 0x45,
+        DP_ACC,
+        CONVG_CFG = 0x49,
+        VF_REM_CAP,
+        QH = 0x4D,
+        STATUS_2 = 0xB0,
+        POWER,
+        ID_USER_MEM2,
+        AVG_POWER,
+        I_ALRT_TH,
+        TTF_CFG,
+        CV_MIX_CAP,
+        CV_HALF_TIME,
+        CG_TEMP_CO,
+        CURVE,
+        HIB_CFG,
+        CONFIG2,
+        V_RIPPLE,
+        RIPPLE_CFG,
+        TIMER_H,
+        R_SENSE_USER_MEM3 = 0xD0,
+        SC_OCV_LIM,
+        SOC_HOLD,
+        MAX_PEAK_POWER,
+        SUS_PEAK_POWER,
+        PACK_RESISTANCE,
+        SYS_RESISTANCE,
+        MIN_SYS_VOLTAGE,
+        MPP_CURRENT,
+        SPP_CURRENT,
+        MODEL_CFG,
+        AT_Q_RESIDUAL,
+        AT_TTE,
+        AT_AV_SOC,
+        AT_AV_CA
+    } reg_t;
+
+    /**
+     * MAX17055 constructor
+     *
+     * @param i2c I2C object to use.
+     * @param address Slave Address of the device.
+     */
+    MAX17055(I2C &i2c, int address = MAX17055_I2C_ADDRESS);
+
+    /**
+     * MAX17055 destructor
+     */
+    ~MAX17055();
+
+    /**
+     * @brief   Initialize driver state
+     * @details Initialize driver with supplied sense resistor value.
+     * @param   value The sense resistor value in ohms
+     * @returns 0 if no errors, -1 if error
+     */
+    void init(float r_sense);
+
+    /**
+     * @brief   Read status register
+     * @details Read status register.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int status(int *value);
+
+    /**
+     * @brief   Read VCell register
+     * @details Read VCell register reports the voltage measured between
+     * BATT and CSP.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int v_cell(int *value);
+
+    /**
+     * @brief   Read VCell register
+     * @details The VCell register reports the voltage measured between
+     * BATT and CSP.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int v_cell(float *value);
+
+    /**
+     * @brief   Read AvgVCell register
+     * @details The AvgVCell register reports an average of the VCell
+     * register readings.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int avg_v_cell(int *value);
+
+    /**
+     * @brief   Read AvgVCell register
+     * @details The AvgVCell register reports an average of the VCell
+     * register readings.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int avg_v_cell(float *value);
+
+    /**
+     * @brief   Read MaxMinVolt register
+     * @details The MaxMinVolt register maintains the maximum and minimum
+     * of VCell register values since device reset.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int max_min_volt(int *max, int *min);
+
+    /**
+     * @brief   Read MaxMinVolt register
+     * @details The MaxMinVolt register maintains the maximum and minimum
+     * of VCell register values since device reset.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int max_min_volt(float *max, float *min);
+
+    /**
+     * @brief   Read Current register
+     * @details The Current register reports the voltage between the
+     * CSP and CSN pins.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int current(int *value);
+
+    /**
+     * @brief   Read Current register
+     * @details The Current register reports the voltage between the
+     * CSP and CSN pins.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int current(float *value);
+
+    /**
+     * @brief   Read AvgCurrent register
+     * @details The AvgCurrent register reports an average of Current
+     * register readings.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int avg_current(int *value);
+
+    /**
+     * @brief   Read AvgCurrent register
+     * @details The AvgCurrent register reports an average of Current
+     * register readings.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int avg_current(float *value);
+
+    /**
+     * @brief   Read MinMaxCurr register
+     * @details The MaxMinCurr register maintains the maximum and
+     * minimum Current register values since the last IC reset
+     * or until cleared by host software.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int max_min_curr(int *max, int *min);
+
+    /**
+     * @brief   Read MinMaxCurrent register
+     * @details The MaxMinCurr register maintains the maximum and
+     * minimum Current register values since the last IC reset
+     * or until cleared by host software.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int max_min_curr(float *max, float *min);
+
+    /**
+     * @brief   Read Temp register
+     * @details The Temp register provides the temperature measured
+     * by the thermistor or die temperature.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int temp(int *value);
+
+    /**
+     * @brief   Read Temp register
+     * @details The Temp register provides the temperature measured
+     * by the thermistor or die temperature.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int temp(float *value);
+
+    /**
+     * @brief   Read AvgTA register
+     * @details The AvgTA register reports an average of the readings
+     * from the Temp register.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int avg_ta(int *value);
+
+    /**
+     * @brief   Read AvgTA register
+     * @details The AvgTA register reports an average of the readings
+     * from the Temp register.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int avg_ta(float *value);
+
+    /**
+     * @brief   Read MaxMinTemp register
+     * @details The MaxMinTemp register maintains the maximum and
+     * minimum Temp register values since the last fuel-gauge reset
+     * or until cleared by host software.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int max_min_temp(int *max, int *min);
+
+    /**
+     * @brief   Read MaxMinTemp register
+     * @details The MaxMinTemp register maintains the maximum and
+     * minimum Temp register values since the last fuel-gauge reset
+     * or until cleared by host software.
+     * @param   value The location to store value read
+     * @returns 0 if no errors, -1 if error
+     */
+    int max_min_temp(float *max, float *min);
+
+    /**
+     * @brief   Write 8-Bit Register
+     * @details Writes the given value to the specified register.
+     * @param   reg The register to be written
+     * @param   value The data to be written
+     * @param   verify Verify data after write
+     * @returns 0 if no errors, -1 if error.
+     */
+    int writeReg(reg_t reg, char value, bool verify = false);
+
+    /**
+     * @brief   Write 16-Bit Register
+     * @details Writes the given value to the specified register.
+     * @param   reg The register to be written
+     * @param   value The data to be written
+     * @param   verify Verify data after write
+     * @returns 0 if no errors, -1 if error.
+     */
+    int writeReg(reg_t reg, uint16_t value, bool verify = false);
+
+    /**
+     * @brief   Read 8-Bit Register
+     * @details Reads from the specified register
+     * @param   reg The register to be read
+     * @param   value Pointer for where to store the data
+     * @returns 0 if no errors, -1 if error.
+     */
+    int readReg(reg_t reg, char *value);
+
+    /**
+     * @brief   Read 8-Bit Register(s)
+     * @details Reads len bytes starting from the specified register
+     * @param   reg The register to be read
+     * @param   value Pointer for where to store the data
+     * @param   len Number of bytes to read
+     * @returns 0 if no errors, -1 if error.
+     */
+    int readReg(reg_t reg, char *buf, int len);
+
+    /**
+     * @brief   Read 16-Bit Register
+     * @details Reads from the specified register
+     * @param   reg The register to be read
+     * @param   value Pointer for where to store the data
+     * @returns 0 if no errors, -1 if error.
+     */
+    int readReg16(reg_t reg, int *value);
+    
+//** ***************************************************************** **/
+//** *********************** added by gv 7/8/2018 ******************** **/
+//** ***************************************************************** **/
+    int MAX17055::soc1(int *value);
+    int MAX17055::soc2(int *valueLow, int *valueHigh);
+    
+    int MAX17055::reportSOC(int *valueHigh);
+    
+    int MAX17055::tte1(int *value);
+    int MAX17055::tte2(int *valueLow, int *valueHigh);
+    int MAX17055::writeConfig(void);
+    
+private:
+    I2C &i2c;
+    int addr;
+
+    float r_sense;
+    float i_lsb;
+    float i_min_max_lsb;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MBed_Adafruit_GPS.cpp	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,350 @@
+/***********************************
+This is our GPS library
+
+Adafruit invests time and resources providing this open source code,
+please support Adafruit and open-source hardware by purchasing
+products from Adafruit!
+
+Written by Limor Fried/Ladyada for Adafruit Industries.
+BSD license, check license.txt for more information
+All text above must be included in any redistribution
+****************************************/
+
+#include "MBed_Adafruit_GPS.h"
+
+// how long are max NMEA lines to parse?
+#define MAXLINELENGTH 120
+
+// we double buffer: read one line in and leave one for the main program
+volatile char line1[MAXLINELENGTH];
+volatile char line2[MAXLINELENGTH];
+// our index into filling the current line
+volatile uint16_t lineidx=0;
+// pointers to the double buffers
+volatile char *currentline;
+volatile char *lastline;
+volatile bool recvdflag;
+volatile bool inStandbyMode;
+
+
+bool Adafruit_GPS::parse(char *nmea) {
+  // do checksum check
+
+  // first look if we even have one
+  if (nmea[strlen(nmea)-4] == '*') {
+    uint16_t sum = parseHex(nmea[strlen(nmea)-3]) * 16;
+    sum += parseHex(nmea[strlen(nmea)-2]);
+    
+    // check checksum 
+    for (uint8_t i=1; i < (strlen(nmea)-4); i++) {
+      sum ^= nmea[i];
+    }
+    if (sum != 0) {
+      // bad checksum :(
+      //return false;
+    }
+  }
+
+  // look for a few common sentences
+  if (strstr(nmea, "$GPGGA")) {
+    // found GGA
+    char *p = nmea;
+    // get time
+    p = strchr(p, ',')+1;
+    float timef = atof(p);
+    uint32_t time = timef;
+    hour = time / 10000;
+    minute = (time % 10000) / 100;
+    seconds = (time % 100);
+
+    milliseconds = fmod((double) timef, 1.0) * 1000;
+
+    // parse out latitude
+    p = strchr(p, ',')+1;
+    latitude = atof(p);
+
+    p = strchr(p, ',')+1;
+    if (p[0] == 'N') lat = 'N';
+    else if (p[0] == 'S') lat = 'S';
+    else if (p[0] == ',') lat = 0;
+    else return false;
+
+    // parse out longitude
+    p = strchr(p, ',')+1;
+    longitude = atof(p);
+
+    p = strchr(p, ',')+1;
+    if (p[0] == 'W') lon = 'W';
+    else if (p[0] == 'E') lon = 'E';
+    else if (p[0] == ',') lon = 0;
+    else return false;
+
+    p = strchr(p, ',')+1;
+    fixquality = atoi(p);
+
+    p = strchr(p, ',')+1;
+    satellites = atoi(p);
+
+    p = strchr(p, ',')+1;
+    HDOP = atof(p);
+
+    p = strchr(p, ',')+1;
+    altitude = atof(p);
+    p = strchr(p, ',')+1;
+    p = strchr(p, ',')+1;
+    geoidheight = atof(p);
+    return true;
+  }
+  if (strstr(nmea, "$GPRMC")) {
+   // found RMC
+    char *p = nmea;
+
+    // get time
+    p = strchr(p, ',')+1;
+    float timef = atof(p);
+    uint32_t time = timef;
+    hour = time / 10000;
+    minute = (time % 10000) / 100;
+    seconds = (time % 100);
+
+    milliseconds = fmod((double) timef, 1.0) * 1000;
+
+    p = strchr(p, ',')+1;
+    // Serial.println(p);
+    if (p[0] == 'A') 
+      fix = true;
+    else if (p[0] == 'V')
+      fix = false;
+    else
+      return false;
+
+    // parse out latitude
+    p = strchr(p, ',')+1;
+    latitude = atof(p);
+
+    p = strchr(p, ',')+1;
+    if (p[0] == 'N') lat = 'N';
+    else if (p[0] == 'S') lat = 'S';
+    else if (p[0] == ',') lat = 0;
+    else return false;
+
+    // parse out longitude
+    p = strchr(p, ',')+1;
+    longitude = atof(p);
+
+    p = strchr(p, ',')+1;
+    if (p[0] == 'W') lon = 'W';
+    else if (p[0] == 'E') lon = 'E';
+    else if (p[0] == ',') lon = 0;
+    else return false;
+
+    // speed
+    p = strchr(p, ',')+1;
+    speed = atof(p);
+
+    // angle
+    p = strchr(p, ',')+1;
+    angle = atof(p);
+
+    p = strchr(p, ',')+1;
+    uint32_t fulldate = atof(p);
+    day = fulldate / 10000;
+    month = (fulldate % 10000) / 100;
+    year = (fulldate % 100);
+
+    // we dont parse the remaining, yet!
+    return true;
+  }
+
+  return false;
+}
+
+char Adafruit_GPS::read(void) {
+  char c = 0;
+  
+  if (paused) return c;
+
+    if(!gpsSerial->readable()) return c;
+    c = gpsSerial->getc();
+
+  //Serial.print(c);
+
+  if (c == '$') {
+    currentline[lineidx] = 0;
+    lineidx = 0;
+  }
+  if (c == '\n') {
+    currentline[lineidx] = 0;
+
+    if (currentline == line1) {
+      currentline = line2;
+      lastline = line1;
+    } else {
+      currentline = line1;
+      lastline = line2;
+    }
+
+    lineidx = 0;
+    recvdflag = true;
+  }
+
+  currentline[lineidx++] = c;
+  if (lineidx >= MAXLINELENGTH)
+    lineidx = MAXLINELENGTH-1;
+
+  return c;
+}
+
+Adafruit_GPS::Adafruit_GPS (Serial *ser)
+{
+  common_init();     // Set everything to common state, then...
+  gpsSerial = ser; // ...override gpsSwSerial with value passed.
+}
+
+// Initialization code used by all constructor types
+void Adafruit_GPS::common_init(void) {
+  gpsSerial = NULL;
+  recvdflag   = false;
+  paused      = false;
+  lineidx     = 0;
+  currentline = line1;
+  lastline    = line2;
+
+  hour = minute = seconds = year = month = day =
+    fixquality = satellites = 0; // uint8_t
+  lat = lon = mag = 0; // char
+  fix = false; // bool
+  milliseconds = 0; // uint16_t
+  latitude = longitude = geoidheight = altitude =
+    speed = angle = magvariation = HDOP = 0.0; // float
+}
+
+void Adafruit_GPS::begin(int baud)
+{
+  gpsSerial->baud(baud);
+  wait_ms(10);
+}
+
+void Adafruit_GPS::sendCommand(char *str) {
+  gpsSerial->printf("%s",str);
+}
+
+bool Adafruit_GPS::newNMEAreceived(void) {
+  return recvdflag;
+}
+
+void Adafruit_GPS::pause(bool p) {
+  paused = p;
+}
+
+char *Adafruit_GPS::lastNMEA(void) {
+  recvdflag = false;
+  return (char *)lastline;
+}
+
+// read a Hex value and return the decimal equivalent
+uint8_t Adafruit_GPS::parseHex(char c) {
+    if (c < '0')
+      return 0;
+    if (c <= '9')
+      return c - '0';
+    if (c < 'A')
+       return 0;
+    if (c <= 'F')
+       return (c - 'A')+10;
+}
+
+bool Adafruit_GPS::waitForSentence(char *wait4me, uint8_t max) {
+  char str[20];
+
+  uint8_t i=0;
+  while (i < max) {
+    if (newNMEAreceived()) { 
+      char *nmea = lastNMEA();
+      strncpy(str, nmea, 20);
+      str[19] = 0;
+      i++;
+
+      if (strstr(str, wait4me))
+    return true;
+    }
+  }
+
+  return false;
+}
+
+bool Adafruit_GPS::LOCUS_StartLogger(void) {
+  sendCommand(PMTK_LOCUS_STARTLOG);
+  recvdflag = false;
+  return waitForSentence(PMTK_LOCUS_LOGSTARTED);
+}
+
+bool Adafruit_GPS::LOCUS_ReadStatus(void) {
+  sendCommand(PMTK_LOCUS_QUERY_STATUS);
+  
+  if (! waitForSentence("$PMTKLOG"))
+    return false;
+
+  char *response = lastNMEA();
+  uint16_t parsed[10];
+  uint8_t i;
+  
+  for (i=0; i<10; i++) parsed[i] = -1;
+  
+  response = strchr(response, ',');
+  for (i=0; i<10; i++) {
+    if (!response || (response[0] == 0) || (response[0] == '*')) 
+      break;
+    response++;
+    parsed[i]=0;
+    while ((response[0] != ',') && 
+       (response[0] != '*') && (response[0] != 0)) {
+      parsed[i] *= 10;
+      char c = response[0];
+      if (isdigit(c))
+        parsed[i] += c - '0';
+      else
+        parsed[i] = c;
+      response++;
+    }
+  }
+  LOCUS_serial = parsed[0];
+  LOCUS_type = parsed[1];
+  if (isalpha(parsed[2])) {
+    parsed[2] = parsed[2] - 'a' + 10; 
+  }
+  LOCUS_mode = parsed[2];
+  LOCUS_config = parsed[3];
+  LOCUS_interval = parsed[4];
+  LOCUS_distance = parsed[5];
+  LOCUS_speed = parsed[6];
+  LOCUS_status = !parsed[7];
+  LOCUS_records = parsed[8];
+  LOCUS_percent = parsed[9];
+
+  return true;
+}
+
+// Standby Mode Switches
+bool Adafruit_GPS::standby(void) {
+  if (inStandbyMode) {
+    return false;  // Returns false if already in standby mode, so that you do not wake it up by sending commands to GPS
+  }
+  else {
+    inStandbyMode = true;
+    sendCommand(PMTK_STANDBY);
+    //return waitForSentence(PMTK_STANDBY_SUCCESS);  // don't seem to be fast enough to catch the message, or something else just is not working
+    return true;
+  }
+}
+
+bool Adafruit_GPS::wakeup(void) {
+  if (inStandbyMode) {
+   inStandbyMode = false;
+    sendCommand("");  // send byte to wake it up
+    return waitForSentence(PMTK_AWAKE);
+  }
+  else {
+      return false;  // Returns false if not in standby mode, nothing to wakeup
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MBed_Adafruit_GPS.h	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,115 @@
+/***********************************
+This is the Adafruit GPS library - the ultimate GPS library
+for the ultimate GPS module!
+
+Tested and works great with the Adafruit Ultimate GPS module
+using MTK33x9 chipset
+    ------> http://www.adafruit.com/products/746
+Pick one up today at the Adafruit electronics shop 
+and help support open source hardware & software! -ada
+
+Adafruit invests time and resources providing this open source code, 
+please support Adafruit and open-source hardware by purchasing 
+products from Adafruit!
+
+Written by Limor Fried/Ladyada  for Adafruit Industries.  
+BSD license, check license.txt for more information
+All text above must be included in any redistribution
+****************************************/
+#include "mbed.h"
+#include <stdint.h>
+#include <math.h>
+#include <ctype.h>
+
+#ifndef _MBED_ADAFRUIT_GPS_H
+#define _MBED_ADAFRUIT_GPS_H
+
+
+// different commands to set the update rate from once a second (1 Hz) to 10 times a second (10Hz)
+#define PMTK_SET_NMEA_UPDATE_1HZ  "$PMTK220,1000*1F"
+#define PMTK_SET_NMEA_UPDATE_5HZ  "$PMTK220,200*2C"
+#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"
+
+
+#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C"
+#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"
+
+// turn on only the second sentence (GPRMC)
+#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
+// turn on GPRMC and GGA
+#define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
+// turn on ALL THE DATA
+#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
+// turn off output
+#define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
+
+// to generate your own sentences, check out the MTK command datasheet and use a checksum calculator
+// such as the awesome http://www.hhhh.org/wiml/proj/nmeaxor.html
+
+#define PMTK_LOCUS_STARTLOG  "$PMTK185,0*22"
+#define PMTK_LOCUS_LOGSTARTED "$PMTK001,185,3*3C"
+#define PMTK_LOCUS_QUERY_STATUS "$PMTK183*38"
+#define PMTK_LOCUS_ERASE_FLASH "$PMTK184,1*22"
+#define LOCUS_OVERLAP 0
+#define LOCUS_FULLSTOP 1
+
+// standby command & boot successful message
+#define PMTK_STANDBY "$PMTK161,0*28"
+#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*36"  // Not needed currently
+#define PMTK_AWAKE "$PMTK010,002*2D"
+
+// ask for the release and version
+#define PMTK_Q_RELEASE "$PMTK605*31"
+
+// request for updates on antenna status 
+#define PGCMD_ANTENNA "$PGCMD,33,1*6C" 
+#define PGCMD_NOANTENNA "$PGCMD,33,0*6D" 
+
+// how long to wait when we're looking for a response
+#define MAXWAITSENTENCE 5
+
+
+
+class Adafruit_GPS {
+ public:
+  void begin(int baud); 
+
+  Adafruit_GPS(Serial * ser);
+
+  char *lastNMEA(void);
+  bool newNMEAreceived();
+  void common_init(void);
+  void sendCommand(char *);
+  void pause(bool b);
+
+  bool parseNMEA(char *response);
+  uint8_t parseHex(char c);
+
+  char read(void);
+  bool parse(char * nmea);
+  void interruptReads(bool r);
+
+  bool wakeup(void);
+  bool standby(void);
+
+  uint8_t hour, minute, seconds, year, month, day;
+  uint16_t milliseconds;
+  float latitude, longitude, geoidheight, altitude;
+  float speed, angle, magvariation, HDOP;
+  char lat, lon, mag;
+  bool fix;
+  uint8_t fixquality, satellites;
+
+  bool waitForSentence(char *wait, uint8_t max = MAXWAITSENTENCE);
+  bool LOCUS_StartLogger(void);
+  bool LOCUS_ReadStatus(void);
+
+  uint16_t LOCUS_serial, LOCUS_records;
+  uint8_t LOCUS_type, LOCUS_mode, LOCUS_config, LOCUS_interval, LOCUS_distance, LOCUS_speed, LOCUS_status, LOCUS_percent;
+ private:
+  bool paused;
+  
+  Serial * gpsSerial;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,57 @@
+# Getting started with Blinky on mbed OS
+
+This guide reviews 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).
+
+## Import 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`, and specify 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 see 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.
+
+The LED on your platform turns on and off.
+
+## Troubleshooting
+
+If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,392 @@
+#include "mbed.h"
+#include "LoRa.h"
+#include "MBed_Adafruit_GPS.h"
+#include "MAX17055.h"
+
+Serial pc (USBTX, USBRX);       // debug serial port
+DigitalOut led1(LED1);          // debug blinker
+
+/******************************************************************************/
+/*************************** Power & Fuel Gauge *******************************/                                 
+/******************************************************************************/
+DigitalOut powerHLD(P2_2, 1); //keep power on when connected to battery
+I2C i2c(I2C2_SDA, I2C2_SCL);
+MAX17055 max17055(i2c);
+int gaugeStatus;
+int stateOfCharge, timeToEmpty;
+float batteryVoltage, batteryCurrent, boardTemperature, tteReport;
+#define FUEL_REFRESH 30 // 120 secs, 2 minutes for now, testing . . .
+
+Timer fuelTimer;
+Timer batteryEmergencyPause; // avoid sending alert right after starting unit up!
+bool startBatteryEmergency;
+bool inBatteryEmergencyState;
+#define EMERBEGIN 180000 // 3 minutes  in millissecond after setup runs
+void readFuelGauge(void);
+/************************* End Power & Fuel Guage *****************************/
+
+/******************************************************************************/
+/***************************** LoRa TxRx **************************************/
+/******************************************************************************/
+#define GATEWAYID           0x30 // LoRa Gateway ID
+#define LOCALADDRESSID      0x31 // this gamma canary ID
+#define GPSDATA             0x40
+#define CPMDATA             0x41
+#define FUELDATA            0x42
+#define LOWBATTERY          0x43
+// #define CPMALERT            0x44
+
+// data transmission/report intervals
+// #define LOCATION_INTERVAL 15.0      // GPS location every 120 secs
+// #define CPM_INTERVAL  60.0          // CPM every 60 secs
+// #define FUEL_INTERVAL 90.0          // Fuel Gauge every 90 secs
+
+// data transmission/report intervals
+float LOCATION_INTERVAL = 15.0;         // GPS location every 120 secs
+float CPM_INTERVAL      = 60.0;         // CPM every 60 secs
+float FUEL_INTERVAL     = 90.0;         // Fuel Gauge every 90 secs
+
+volatile int locationCountDown, cpmCountDown, fuelCountDown; 
+
+Ticker transmissionTicker;
+void transmitLoRaTicker(void)
+{
+    if (locationCountDown > 0) locationCountDown--;
+    if (cpmCountDown > 0) cpmCountDown--;
+    if (fuelCountDown >0) fuelCountDown--;
+} 
+
+void transmitLocation(void);
+void transmitCPM(void);
+void transmitFuel(void);
+void batteryLowTransmit();
+void onReceive(int packetSize);
+/*************************** End LoRa *****************************************/
+
+/******************************************************************************/
+/******************************** GPS *****************************************/
+/******************************************************************************/
+double currentLatitude, currentLongitude, previousLatitude, previousLongitude;
+Serial * _gpsSerial;
+
+#define GPS_REFRESH 5000 // 2000 millisecs???
+Timer gpsTimer; // GPS data collection/refresh timer
+
+void transformGPSData(double lat, char p, double lon, char m);
+// GPS command list at http://www.adafruit.com/datasheets/PMTK_A08.pdf
+/**************************** End GPS *****************************************/
+
+/******************************************************************************/
+/*********************** Begin Radiation Monitoring ***************************/
+/******************************************************************************/
+// PMOD Port 1 pins for radiation sensor
+volatile int signalCounter, noiseCounter;
+InterruptIn signalPin(P1_0);
+InterruptIn noisePin(P1_1);
+// interrupt service routines(ISR) which count are called whenever signal or noise pins are triggered
+void signalISR(){ signalCounter++; led1 = !led1;}
+void noiseISR(){ noiseCounter++; } 
+
+// #define CPMALERTLEVEL   50 // set very low or testing purposes.
+// #DEFINE CPMMAXALERTS     3 // only three at a time to not bomb SMS network!
+#define CPM_REFRESH     60 // 60 seconds in a minute
+Timer cpmTimer; // CPM data collection, determine total current counts per minute
+
+int currentSignalCount, currentNoiseCount, previousCPM, currentCPM;
+int previousTotalSignalCount, previousTotalNoiseCount;
+
+void calculateCPM();
+/*********************** End Radiation Monitoring *****************************/
+
+
+int main()
+{
+    /****************************** Setup *************************************/
+    pc.printf(" ********* gamma canary v001 ********* \n");
+    
+    /** 0. Confirm running on battery power **/
+    if (powerHLD.is_connected()) {pc.printf("Battery power connected...\n");}
+    
+    /** 1. LoRa TxRx initialization **/
+    if (!LoRa.begin(915E6)) {pc.printf("LoRa not found!");} 
+    else {  pc.printf("LoRa started...\n");}
+    // LoRa.onReceive(onReceive);
+    // LoRa.receive();
+    transmissionTicker.attach(&transmitLoRaTicker,1.0);
+    
+    /** 2. GPS/NMEA Initialization **/
+    currentLongitude = 0.00;
+    previousLongitude = currentLongitude;
+    currentLatitude = 0.00;
+    previousLatitude = currentLatitude;
+    
+    _gpsSerial = new Serial(P3_1,P3_0); //serial object for use w/ GPS
+    Adafruit_GPS myGPS(_gpsSerial); 
+    myGPS.begin(9600);  
+    char c;
+    myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation
+    myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
+    myGPS.sendCommand(PGCMD_ANTENNA);
+    gpsTimer.start();
+    pc.printf("GPS setup done...\n");
+    
+    //** 3. Radiation Detecton - CPM(Counts Per Minute)
+    currentSignalCount = 0;
+    previousTotalSignalCount = 0;
+    currentNoiseCount = 0;
+    previousTotalNoiseCount = 0;
+    currentCPM = 0;
+    previousCPM = 0;
+    signalPin.rise(&signalISR);     // attach ISR function to the rising edge
+    noisePin.rise(&noiseISR);       // attach ISR function to the rising edge
+    cpmTimer.start();
+    pc.printf("Starting radiation monitoring...\n");
+
+    /** 4. Fuel Gauge/Battery Monitoring **/
+    max17055.init(0.05f);
+    max17055.status(&gaugeStatus);
+    fuelTimer.start();
+    startBatteryEmergency = false;
+    inBatteryEmergencyState = false;
+    batteryEmergencyPause.start();
+    pc.printf("MAX17055 status: %04X\r\n", (uint16_t)gaugeStatus);
+    wait(3.0);
+    pc.printf("Setup complete...\n");
+    
+    /***************************** End Setup **********************************/
+    // loop()
+    while(1)
+    {
+        
+        /** GPS/Location Data Collection"loop" here **/
+        c = myGPS.read();   //queries the GPS
+        if ( myGPS.newNMEAreceived() ) 
+        {
+            if ( !myGPS.parse(myGPS.lastNMEA()) ) {
+                continue;   
+            }    
+        }
+        
+        //check if enough time has passed to warrant printing GPS info to screen
+        //note if refresh_Time is too low or pc.baud is too low, GPS data may be lost during printing
+        if (gpsTimer.read_ms() >= GPS_REFRESH) 
+        {
+            gpsTimer.reset();
+            if (myGPS.fix) {
+                // pc.printf("Location: %5.2f%c, %5.2f%c\n", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon);
+                // previousLatitude = currentLatitude;
+                // previousLongitude = currentLongitude;            
+                // currentLatitude = myGPS.latitude;
+                // currentLongitude = myGPS.longitude;
+                transformGPSData(myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon);
+            }
+        }        
+        
+        if (cpmTimer.read() >= CPM_REFRESH)
+        {
+            cpmTimer.reset();
+            calculateCPM();    
+        }
+        
+        if (fuelTimer.read() >= FUEL_REFRESH)
+        {
+            fuelTimer.reset();
+            readFuelGauge();    
+        }
+        
+        // special 1 time timer to begin battery monitoring for emergency lo battery warning
+        
+        if( batteryEmergencyPause.read_ms() >= EMERBEGIN )
+        {
+            batteryEmergencyPause.stop();
+            startBatteryEmergency = true;  
+        }
+        
+        /** LoRa Data Transmision **/
+        if (locationCountDown == 0) 
+        { 
+            locationCountDown = LOCATION_INTERVAL;
+            transmitLocation();      
+        }
+        if (cpmCountDown == 0) 
+        {
+            cpmCountDown = CPM_INTERVAL;
+            transmitCPM();    
+        }
+        if (fuelCountDown == 0) 
+        {
+            fuelCountDown = FUEL_INTERVAL;
+            transmitFuel();    
+        }
+        
+    } // end loop
+    
+} 
+
+/** GPS Functions **/
+void transformGPSData(double lat, char parallel, double lon, char meridian)
+{
+    float degrees = floor(lat/100.00);
+    double minutes = lat - (100.00*degrees);
+    minutes /= 60.00;
+    degrees += minutes;
+    if (parallel=='S') { degrees *= -1.00; }
+    
+    double dLatitude = degrees;
+    
+    degrees = floor(lon/100.00);
+    minutes = lon - (100.00*degrees);
+    minutes /= 60.00;
+    degrees += minutes;
+    if (meridian == 'W') { degrees *= -1.00; }
+    
+    double dLongitude = degrees;
+    currentLatitude = dLatitude;
+    currentLongitude = dLongitude;
+    pc.printf("LAT: %f ", dLatitude);
+    pc.printf("LON: %f\n", dLongitude);
+}
+
+/** CPM functions **/
+void calculateCPM()
+{   
+    
+    currentSignalCount = signalCounter - previousTotalSignalCount;
+    previousTotalSignalCount = signalCounter;
+    
+    currentNoiseCount = noiseCounter - previousTotalNoiseCount;
+    previousTotalNoiseCount = noiseCounter;
+    
+    previousCPM = currentCPM;
+    currentCPM = currentSignalCount - currentNoiseCount;
+    
+    pc.printf("signal: %d, noise: %d, ", currentSignalCount, currentNoiseCount);
+    pc.printf("Current CPM: %d\n", currentCPM);
+   
+}
+
+/** Fuel Guage Functions **/
+void readFuelGauge()
+{
+    max17055.v_cell(&batteryVoltage);
+    printf("%6.3fV ", batteryVoltage);
+    
+    max17055.current(&batteryCurrent);
+    printf("%6.3fI ", batteryCurrent);
+    
+    max17055.temp(&boardTemperature);
+    printf("%6.3fC ", boardTemperature);
+    
+    max17055.reportSOC(&stateOfCharge);
+    if (startBatteryEmergency and !inBatteryEmergencyState)
+    {
+        pc.printf("emergency battery monitoring set\n");
+        if (stateOfCharge < 51.0)
+        {  
+           inBatteryEmergencyState = true; // prevents sending messages over and over again, future versions to reset this when bat > 50 again;   
+           batteryLowTransmit();
+        }
+    }
+    printf(" SOC:%d\\% ",stateOfCharge);
+    
+    // max17055.tte1(&timeToEmpty);
+    // tteReport = ((5.625)*timeToEmpty)/120.0;
+    // printf(" TTE:%6.2fhours \n", tteReport);
+    
+}
+
+/** LoRa TxRx Functions **/
+void transmitLocation()
+{
+    // transmite GPS/Location data, lat/lon
+    LoRa.beginPacket();
+    
+    // Packet Header 
+    LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**");    
+    LoRa.printf("%c",GPSDATA); LoRa.printf("**");    
+    
+    // Packet Contents
+    LoRa.printf("%f",currentLatitude);LoRa.printf("**");
+    LoRa.printf("%f",currentLongitude);LoRa.printf("**");
+    
+    LoRa.endPacket();
+    pc.printf("LoRa GPS Packet Sent\n");    
+}
+
+void transmitCPM()
+{
+    // Transmit Radiation data: CPM = Counts Per Minute, current reading
+    LoRa.beginPacket();
+    
+    // Packet Header 
+    LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**");    
+    LoRa.printf("%c",CPMDATA); LoRa.printf("**");    
+    
+    // Packet Contents
+    LoRa.printf("%d",currentCPM);LoRa.printf("**");
+    LoRa.printf("%d", "-1");LoRa.printf("**");
+    
+    LoRa.endPacket();
+    pc.printf("LoRa CPM Packet Sent\n");  
+}
+void transmitFuel()
+{
+    // Transimet Battery/Fuel Gauge data: voltage, current, temp 
+    LoRa.beginPacket();
+    
+    // Packet Header 
+    LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**");    
+    LoRa.printf("%c",FUELDATA); LoRa.printf("**");    
+    
+    LoRa.printf("%d",stateOfCharge);LoRa.printf("**"); 
+    LoRa.printf("%f",tteReport);LoRa.printf("**"); // time to empty in hours
+    LoRa.printf("%f",boardTemperature);LoRa.printf("**");
+       
+    // Packet Contents
+    
+    LoRa.endPacket();
+    pc.printf("LoRa Fuel Gauge Packet Sent\n");
+}
+
+void batteryLowTransmit() 
+{
+    /** broadcast warning low battery/increased transmisson intervals **/
+    
+    // extend transmission intervals to conserve power
+    LOCATION_INTERVAL  = 150.0;     
+    CPM_INTERVAL       = 600.0;          
+    FUEL_INTERVAL      = 900.0;          
+    
+    // Transimet Battery/Fuel Gauge data: voltage, current, temp 
+    LoRa.beginPacket();
+    
+    // Packet Header 
+    LoRa.printf("%c",LOCALADDRESSID); LoRa.printf("**");    
+    LoRa.printf("%c",LOWBATTERY); LoRa.printf("**");    
+    
+    LoRa.printf("%d",stateOfCharge);LoRa.printf("**"); 
+    
+    LoRa.endPacket();
+    pc.printf("LoRa Low Battery Packet Sent\n");
+    
+}
+
+void onReceive(int packetSize)
+{
+    char msg[45];
+    pc.printf("PACKET RECEIVED, SIZE:%d \n", packetSize);
+    for (int i = 0; i<packetSize; i++)
+    {   if ( i < 45) 
+        {
+            msg[i] = (char)LoRa._getc();
+        }
+    }
+    pc.printf("RSSI:  %d, ", LoRa.packetRssi()); pc.printf("MSG:%s \n",msg); 
+    if (msg[0] == LOCALADDRESSID)
+    {
+        pc.printf("received from %x\n", msg[0]);
+    } 
+    else {
+        pc.printf("dont know who, %x is, ignore msg\n", msg[0]);    
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Tue Jul 31 16:30:32 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#50bd61a4a72332baa6b1bac6caccb44dc5423309