Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:a761fba7f8a8, committed 2018-07-31
- Comitter:
- gov1
- Date:
- Tue Jul 31 16:30:32 2018 +0000
- Commit message:
- complete version with emer. batt low check
Changed in this revision
--- /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