summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CommandTerminal/CmdDeleteSurveyDataFile.cpp13
-rw-r--r--CommandTerminal/CmdGetSurveyDataFile.cpp38
-rw-r--r--FileName.h6
-rw-r--r--Layout/LayoutDemoSampling.cpp82
-rw-r--r--Layout/LayoutDemoSampling.h39
-rw-r--r--Layout/LayoutStartup.cpp11
-rw-r--r--Layout/LayoutStartup.h2
-rw-r--r--Layout/LayoutSurveyFailure.cpp64
-rw-r--r--Layout/LayoutSurveyFailure.h18
-rw-r--r--Layout/LayoutSurveySuccess.cpp33
-rw-r--r--LoRaHandler/LoRaHandler.cpp50
-rw-r--r--LoRaHandler/LoRaHandler.h13
-rw-r--r--Mode/Mode.cpp56
-rw-r--r--Mode/Mode.h9
-rw-r--r--Mode/ModeConfig.cpp4
-rw-r--r--Mode/ModeConfig.h2
-rw-r--r--Mode/ModeDemo.cpp151
-rw-r--r--Mode/ModeDemo.h39
-rw-r--r--Mode/ModeJoin.cpp12
-rw-r--r--Mode/ModeJoin.h2
-rw-r--r--Mode/ModeSingle.cpp147
-rw-r--r--Mode/ModeSingle.h4
-rw-r--r--Mode/ModeSweep.cpp136
-rw-r--r--Mode/ModeSweep.h2
-rw-r--r--main.cpp80
25 files changed, 677 insertions, 336 deletions
diff --git a/CommandTerminal/CmdDeleteSurveyDataFile.cpp b/CommandTerminal/CmdDeleteSurveyDataFile.cpp
index d6eca22..325ee7c 100644
--- a/CommandTerminal/CmdDeleteSurveyDataFile.cpp
+++ b/CommandTerminal/CmdDeleteSurveyDataFile.cpp
@@ -1,4 +1,5 @@
#include "CmdDeleteSurveyDataFile.h"
+#include "FileName.h"
CmdDeleteSurveyDataFile::CmdDeleteSurveyDataFile(mDot* dot, mts::MTSSerial& serial) :
Command(dot, "Delete Survey Data File", "AT+DSDF", "Delete the survey data file"), _serial(serial)
@@ -8,14 +9,12 @@ CmdDeleteSurveyDataFile::CmdDeleteSurveyDataFile(mDot* dot, mts::MTSSerial& seri
uint32_t CmdDeleteSurveyDataFile::action(std::vector<std::string> args)
{
-//ToDo: Delete the file.
- if (!_dot->saveConfig()) {
- setErrorMessage("Failed to save to flash");
- return 1;
- }
-
- return 0;
+ if (!_dot->deleteUserFile(file_name)) {
+ setErrorMessage("Failed to delete survey data file");
+ return 1;
+ }
+ return 0;
}
diff --git a/CommandTerminal/CmdGetSurveyDataFile.cpp b/CommandTerminal/CmdGetSurveyDataFile.cpp
index 11d9ae3..3fa4e46 100644
--- a/CommandTerminal/CmdGetSurveyDataFile.cpp
+++ b/CommandTerminal/CmdGetSurveyDataFile.cpp
@@ -1,4 +1,6 @@
#include "CmdGetSurveyDataFile.h"
+#include "FileName.h"
+#include "MTSLog.h"
CmdGetSurveyDataFile::CmdGetSurveyDataFile(mDot* dot, mts::MTSSerial& serial) :
Command(dot, "Get Survey Data File", "AT+GSDF", "Outputs the survey data file to the command port"), _serial(serial)
@@ -8,12 +10,38 @@ CmdGetSurveyDataFile::CmdGetSurveyDataFile(mDot* dot, mts::MTSSerial& serial) :
uint32_t CmdGetSurveyDataFile::action(std::vector<std::string> args)
{
-//ToDo: Output the file contents line by line.
- if (!_dot->saveConfig()) {
- setErrorMessage("Failed to save to flash");
- return 1;
+ mDot::mdot_file file;
+ int buf_size = 512;
+ char buf[buf_size];
+ int read;
+ int read_size;
+
+ file = _dot->openUserFile(file_name, mDot::FM_RDONLY);
+ if (file.fd < 0) {
+ setErrorMessage("Failed to open file");
+ return 1;
}
+
+ while (read < file.size) {
+ read_size = (file.size - read) > buf_size ? buf_size : file.size - read;
+ int size = _dot->readUserFile(file, (void*)buf, read_size);
+ if (size < 0) {
+ setErrorMessage("Failed to read file");
+ _dot->closeUserFile(file);
+ return 1;
+ }
+
+ for (int i = 0; i < size; i++) {
+ if (buf[i] == '\n')
+ _serial.writef("\r\n");
+ else
+ _serial.writef("%c", buf[i]);
+ }
+
+ read += size;
+ }
+
+ _dot->closeUserFile(file);
return 0;
-
}
diff --git a/FileName.h b/FileName.h
new file mode 100644
index 0000000..745981d
--- /dev/null
+++ b/FileName.h
@@ -0,0 +1,6 @@
+#ifndef __FILENAME_H__
+#define __FILENAME_H__
+
+extern char* file_name;
+
+#endif
diff --git a/Layout/LayoutDemoSampling.cpp b/Layout/LayoutDemoSampling.cpp
new file mode 100644
index 0000000..14a4cf7
--- /dev/null
+++ b/Layout/LayoutDemoSampling.cpp
@@ -0,0 +1,82 @@
+#include "LayoutDemoSampling.h"
+
+LayoutDemoSampling::LayoutDemoSampling(DOGS102* lcd)
+ : Layout(lcd),
+ _lAccx(0, 0, "AccX"),
+ _lAccy(6, 0, "AccY"),
+ _lAccz(12, 0, "AccZ"),
+ _lPres(0, 2, "Press="),
+ _lAlt(0, 3, "Alt="),
+ _lTemp(0, 4, "Temp="),
+ _lLight(0, 5, "Light="),
+ _fAccx(0, 1, 5),
+ _fAccy(6, 1, 5),
+ _fAccz(12, 1, 5),
+ _fPres(6, 2, 11),
+ _fAlt(4, 3, 13),
+ _fTemp(5, 4, 12),
+ _fLight(6, 5, 11),
+ _fInfo(0, 6, 17),
+ _fSw1(9, 7, 8),
+ _fSw2(0, 7, 8)
+{}
+
+LayoutDemoSampling::~LayoutDemoSampling() {}
+
+void LayoutDemoSampling::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lAccx);
+ writeLabel(_lAccy);
+ writeLabel(_lAccz);
+ writeLabel(_lPres);
+ writeLabel(_lAlt);
+ writeLabel(_lTemp);
+ writeLabel(_lLight);
+
+ endUpdate();
+}
+
+void LayoutDemoSampling::updateInfo(std::string info) {
+ writeField(_fInfo, info, true);
+}
+
+void LayoutDemoSampling::updateSw1(std::string sw1) {
+ writeField(_fSw1, sw1, true);
+}
+
+void LayoutDemoSampling::updateSw2(std::string sw2) {
+ writeField(_fSw2, sw2, true);
+}
+
+void LayoutDemoSampling::updateCountdown(uint32_t seconds) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ // for some reason, there's a % character that gets displayed in the last column
+ // add the extra spaces to wipe it out
+ writeField(_fInfo, "No Free Channel ", true);
+ size = snprintf(buf, sizeof(buf), "%lu s ", seconds);
+ writeField(_fSw2, buf, size, true);
+}
+
+void LayoutDemoSampling::updateInterval(uint32_t seconds) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, ' ', sizeof(buf));
+ writeField(_fInfo, buf, size, true);
+
+ memset(buf, 0, sizeof(buf));
+ if (seconds < 60)
+ size = snprintf(buf, sizeof(buf), "Interval %lu s", seconds);
+ else if (seconds < 60 * 60)
+ size = snprintf(buf, sizeof(buf), "Interval %lu min", seconds / 60);
+ else
+ size = snprintf(buf, sizeof(buf), "Interval %lu hr", seconds / (60 * 60));
+
+ writeField(_fInfo, buf, size, true);
+}
+
diff --git a/Layout/LayoutDemoSampling.h b/Layout/LayoutDemoSampling.h
new file mode 100644
index 0000000..9d075b2
--- /dev/null
+++ b/Layout/LayoutDemoSampling.h
@@ -0,0 +1,39 @@
+#ifndef __LAYOUTDEMOSAMPLING_H__
+#define __LAYOUTDEMOSAMPLING_H__
+
+#include "Layout.h"
+
+class LayoutDemoSampling : public Layout {
+ public:
+ LayoutDemoSampling(DOGS102* lcd);
+ ~LayoutDemoSampling();
+
+ void display();
+ void updateInfo(std::string info);
+ void updateSw1(std::string sw1);
+ void updateSw2(std::string sw2);
+ void updateCountdown(uint32_t seconds);
+ void updateInterval(uint32_t seconds);
+
+ private:
+ Label _lAccx;
+ Label _lAccy;
+ Label _lAccz;
+ Label _lPres;
+ Label _lAlt;
+ Label _lTemp;
+ Label _lLight;
+
+ Field _fAccx;
+ Field _fAccy;
+ Field _fAccz;
+ Field _fPres;
+ Field _fAlt;
+ Field _fTemp;
+ Field _fLight;
+ Field _fInfo;
+ Field _fSw1;
+ Field _fSw2;
+};
+
+#endif
diff --git a/Layout/LayoutStartup.cpp b/Layout/LayoutStartup.cpp
index c317a7f..1662155 100644
--- a/Layout/LayoutStartup.cpp
+++ b/Layout/LayoutStartup.cpp
@@ -11,6 +11,7 @@ LayoutStartup::LayoutStartup(DOGS102* lcd, mDot* dot)
_lVersion(0, 5, "Version"),
_fVersion(8, 5, 9),
_fId(0, 7, 17),
+ _fGps(0, 6, 17),
_iLogo(0, 0, MultiTech_Logo)
{}
@@ -32,3 +33,13 @@ void LayoutStartup::display() {
endUpdate();
}
+
+void LayoutStartup::updateGPS(bool gps) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "%sGPS Detected", gps ? "" : "No ");
+ writeField(_fGps, buf, size);
+}
+
diff --git a/Layout/LayoutStartup.h b/Layout/LayoutStartup.h
index c67ab1e..4490887 100644
--- a/Layout/LayoutStartup.h
+++ b/Layout/LayoutStartup.h
@@ -10,6 +10,7 @@ class LayoutStartup : public Layout {
~LayoutStartup();
void display();
+ void updateGPS(bool gps);
private:
mDot* _dot;
@@ -19,6 +20,7 @@ class LayoutStartup : public Layout {
Label _lVersion;
Field _fVersion;
+ Field _fGps;
Field _fId;
Image _iLogo;
diff --git a/Layout/LayoutSurveyFailure.cpp b/Layout/LayoutSurveyFailure.cpp
index aa2ce7c..4b313af 100644
--- a/Layout/LayoutSurveyFailure.cpp
+++ b/Layout/LayoutSurveyFailure.cpp
@@ -9,10 +9,10 @@ LayoutSurveyFailure::LayoutSurveyFailure(DOGS102* lcd)
_fId(2, 0, 5),
_fDr(10, 0, 2),
_fPwr(14, 0, 2),
- _fMsg1(0, 2, 17),
- _fMsg2(0, 3, 17),
- _fInfo1(0, 5, 17),
- _fInfo2(0, 6, 17),
+ _fGpsLat(0, 4, 17),
+ _fGpsLon(0, 3, 17),
+ _fGpsTime(0, 5, 17),
+ _fInfo(0, 6, 17),
_fSw1(9, 7, 8),
_fSw2(0, 7, 8)
{}
@@ -51,21 +51,54 @@ void LayoutSurveyFailure::updatePower(uint32_t power) {
writeField(_fPwr, buf, size, true);
}
-void LayoutSurveyFailure::updateInfo1(std::string info) {
- writeField(_fInfo1, info, true);
+void LayoutSurveyFailure::updateGpsLatitude(GPSPARSER::latitude lat) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "%d %d %d.%03d %c",
+ abs(lat.degrees),
+ lat.minutes,
+ (lat.seconds * 6) / 1000,
+ (lat.seconds * 6) % 1000,
+ (lat.degrees > 0) ? 'N' : 'S');
+ writeField(_fGpsLat, buf, size, true);
}
-void LayoutSurveyFailure::updateInfo2(std::string info) {
- writeField(_fInfo2, info, true);
+void LayoutSurveyFailure::updateGpsLatitude(std::string msg) {
+ writeField(_fGpsLat, msg, true);
}
-void LayoutSurveyFailure::updatePassFail(uint8_t pass, uint8_t fail) {
+void LayoutSurveyFailure::updateGpsLongitude(GPSPARSER::longitude lon) {
char buf[32];
size_t size;
memset(buf, 0, sizeof(buf));
- size = snprintf(buf, sizeof(buf), "Pass %u Fail %u", pass, fail);
- writeField(_fInfo1, buf, size, true);
+ size = snprintf(buf, sizeof(buf), "%d %d %d.%03d %c",
+ abs(lon.degrees),
+ lon.minutes,
+ (lon.seconds * 6) / 1000,
+ (lon.seconds * 6) % 1000,
+ (lon.degrees > 0) ? 'E' : 'W');
+ writeField(_fGpsLon, buf, size, true);
+}
+
+void LayoutSurveyFailure::updateGpsTime(struct tm time) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "%02d:%02d %02d/%02d/%04d",
+ time.tm_hour,
+ time.tm_min,
+ time.tm_mon + 1,
+ time.tm_mday,
+ time.tm_year + 1900);
+ writeField(_fGpsTime, buf, size, true);
+}
+
+void LayoutSurveyFailure::updateInfo(std::string info) {
+ writeField(_fInfo, info, true);
}
void LayoutSurveyFailure::updateSw1(std::string sw1) {
@@ -76,3 +109,12 @@ void LayoutSurveyFailure::updateSw2(std::string sw2) {
writeField(_fSw2, sw2, true);
}
+void LayoutSurveyFailure::updatePassFail(uint8_t pass, uint8_t fail) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "Pass %u Fail %u", pass, fail);
+ writeField(_fGpsTime, buf, size, true);
+}
+
diff --git a/Layout/LayoutSurveyFailure.h b/Layout/LayoutSurveyFailure.h
index ca6aebd..aac3142 100644
--- a/Layout/LayoutSurveyFailure.h
+++ b/Layout/LayoutSurveyFailure.h
@@ -2,6 +2,7 @@
#define __LAYOUTSURVEYFAILURE_H__
#include "Layout.h"
+#include "GPSPARSER.h"
class LayoutSurveyFailure : public Layout {
public:
@@ -12,11 +13,14 @@ class LayoutSurveyFailure : public Layout {
void updateId(uint32_t id);
void updateRate(std::string rate);
void updatePower(uint32_t power);
- void updateInfo1(std::string msg);
- void updateInfo2(std::string msg);
- void updatePassFail(uint8_t pass, uint8_t fail);
+ void updateGpsLatitude(GPSPARSER::latitude lat);
+ void updateGpsLatitude(std::string msg);
+ void updateGpsLongitude(GPSPARSER::longitude lon);
+ void updateGpsTime(struct tm time);
+ void updateInfo(std::string info);
void updateSw1(std::string sw1);
void updateSw2(std::string sw2);
+ void updatePassFail(uint8_t pass, uint8_t fail);
private:
Label _lTitle;
@@ -27,10 +31,10 @@ class LayoutSurveyFailure : public Layout {
Field _fId;
Field _fDr;
Field _fPwr;
- Field _fMsg1;
- Field _fMsg2;
- Field _fInfo1;
- Field _fInfo2;
+ Field _fGpsLat;
+ Field _fGpsLon;
+ Field _fGpsTime;
+ Field _fInfo;
Field _fSw1;
Field _fSw2;
};
diff --git a/Layout/LayoutSurveySuccess.cpp b/Layout/LayoutSurveySuccess.cpp
index 38edb5c..01a0c94 100644
--- a/Layout/LayoutSurveySuccess.cpp
+++ b/Layout/LayoutSurveySuccess.cpp
@@ -83,6 +83,17 @@ void LayoutSurveySuccess::updateStats(LoRaHandler::LoRaPing ping) {
}
void LayoutSurveySuccess::updateGpsLatitude(GPSPARSER::latitude lat) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "%d %d %d.%03d %c",
+ abs(lat.degrees),
+ lat.minutes,
+ (lat.seconds * 6) / 1000,
+ (lat.seconds * 6) % 1000,
+ (lat.degrees > 0) ? 'N' : 'S');
+ writeField(_fGpsLat, buf, size, true);
}
void LayoutSurveySuccess::updateGpsLatitude(std::string msg) {
@@ -90,9 +101,31 @@ void LayoutSurveySuccess::updateGpsLatitude(std::string msg) {
}
void LayoutSurveySuccess::updateGpsLongitude(GPSPARSER::longitude lon) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "%d %d %d.%03d %c",
+ abs(lon.degrees),
+ lon.minutes,
+ (lon.seconds * 6) / 1000,
+ (lon.seconds * 6) % 1000,
+ (lon.degrees > 0) ? 'E' : 'W');
+ writeField(_fGpsLon, buf, size, true);
}
void LayoutSurveySuccess::updateGpsTime(struct tm time) {
+ char buf[32];
+ size_t size;
+
+ memset(buf, 0, sizeof(buf));
+ size = snprintf(buf, sizeof(buf), "%02d:%02d %02d/%02d/%04d",
+ time.tm_hour,
+ time.tm_min,
+ time.tm_mon + 1,
+ time.tm_mday,
+ time.tm_year + 1900);
+ writeField(_fGpsTime, buf, size, true);
}
void LayoutSurveySuccess::updateInfo(std::string info) {
diff --git a/LoRaHandler/LoRaHandler.cpp b/LoRaHandler/LoRaHandler.cpp
index 7ba05f5..b4de8b3 100644
--- a/LoRaHandler/LoRaHandler.cpp
+++ b/LoRaHandler/LoRaHandler.cpp
@@ -26,6 +26,7 @@ void l_worker(void const* argument) {
e = Thread::signal_wait(signal);
if (e.status == osEventSignal) {
l->_status = LoRaHandler::busy;
+ l->_tick.attach(l, &LoRaHandler::blinker, 0.05);
switch (cmd) {
case l_ping:
l->_mutex.lock();
@@ -44,6 +45,8 @@ void l_worker(void const* argument) {
l->_status = LoRaHandler::ping_failure;
}
osSignalSet(l->_main, loraSignal);
+ l->_tick.detach();
+ l->_activity_led = LoRaHandler::green;
break;
case l_send:
@@ -55,6 +58,8 @@ void l_worker(void const* argument) {
else
l->_status = LoRaHandler::send_failure;
osSignalSet(l->_main, loraSignal);
+ l->_tick.detach();
+ l->_activity_led = LoRaHandler::green;
break;
case l_join:
@@ -68,6 +73,8 @@ void l_worker(void const* argument) {
l->_status = LoRaHandler::join_failure;
}
osSignalSet(l->_main, loraSignal);
+ l->_tick.detach();
+ l->_activity_led = LoRaHandler::green;
break;
default:
@@ -82,31 +89,11 @@ LoRaHandler::LoRaHandler(osThreadId main)
: _main(main),
_thread(l_worker, (void*)this),
_status(none),
- _join_attempts(1)
+ _join_attempts(1),
+ _activity_led(XBEE_DIO1, PIN_OUTPUT, PullNone, red)
{
_ping.status = false;
-}
-
-bool LoRaHandler::setDataRate(uint8_t rate) {
- int32_t res;
- _mutex.lock();
- res = _dot->setTxDataRate(rate);
- _mutex.unlock();
- if (res == mDot::MDOT_OK)
- return true;
-
- return false;
-}
-
-bool LoRaHandler::setPower(uint32_t power) {
- int32_t res;
- _mutex.lock();
- res = _dot->setTxPower(power);
- _mutex.unlock();
- if (res == mDot::MDOT_OK)
- return true;
-
- return false;
+ _activity_led = red;
}
bool LoRaHandler::ping() {
@@ -151,15 +138,6 @@ LoRaHandler::LoRaPing LoRaHandler::getPingResults() {
return ping;
}
-uint32_t LoRaHandler::getNextTx() {
- uint32_t ms;
- _mutex.lock();
- ms = _dot->getNextTxMs();
- _mutex.unlock();
-
- return ms;
-}
-
uint32_t LoRaHandler::getJoinAttempts() {
uint32_t val;
@@ -176,3 +154,11 @@ void LoRaHandler::resetJoinAttempts() {
_mutex.unlock();
}
+void LoRaHandler::blinker() {
+ _activity_led = !_activity_led;
+}
+
+void LoRaHandler::resetActivityLed() {
+ _activity_led = red;
+}
+
diff --git a/LoRaHandler/LoRaHandler.h b/LoRaHandler/LoRaHandler.h
index 1a68668..375c277 100644
--- a/LoRaHandler/LoRaHandler.h
+++ b/LoRaHandler/LoRaHandler.h
@@ -24,21 +24,24 @@ class LoRaHandler {
mDot::ping_response down;
} LoRaPing;
+ typedef enum {
+ green = 0,
+ red
+ } LedColor;
+
LoRaHandler(osThreadId main);
~LoRaHandler();
- bool setDataRate(uint8_t rate);
- bool setPower(uint32_t power);
bool ping();
bool send(std::vector<uint8_t> data);
bool join();
bool action(uint8_t cmd);
LoRaStatus getStatus();
LoRaPing getPingResults();
- uint32_t getNextTx();
uint32_t getJoinAttempts();
void resetJoinAttempts();
-
+ void blinker();
+ void resetActivityLed();
osThreadId _main;
Thread _thread;
@@ -47,6 +50,8 @@ class LoRaHandler {
mDot* _dot;
Mutex _mutex;
uint32_t _join_attempts;
+ DigitalInOut _activity_led;
+ Ticker _tick;
};
#endif
diff --git a/Mode/Mode.cpp b/Mode/Mode.cpp
index 8268a4a..a97b226 100644
--- a/Mode/Mode.cpp
+++ b/Mode/Mode.cpp
@@ -1,8 +1,6 @@
#include "Mode.h"
#include "MTSLog.h"
-const char* Mode::_file_name = "SurveyData.txt";
-
/*
* union for converting from 32-bit to 4 8-bit values
*/
@@ -22,11 +20,12 @@ union convert16 {
} convertS;
-Mode::Mode(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora)
+Mode::Mode(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps)
: _lcd(lcd),
_buttons(buttons),
_dot(dot),
_lora(lora),
+ _gps(gps),
_main_id(Thread::gettid()),
_index(0),
_band(_dot->getFrequencyBand()),
@@ -35,6 +34,7 @@ Mode::Mode(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora)
_power(2),
_next_tx(0),
_send_data(false),
+ _gps_available(_gps->gpsDetected()),
_gpsUART(PA_2, PA_3),
_mdot_gps(&_gpsUART),
_mdot_sensors()
@@ -48,8 +48,8 @@ bool Mode::deleteDataFile() {
// if survey data file exists, attempt to delete it
std::vector<mDot::mdot_file> files = _dot->listUserFiles();
for (std::vector<mDot::mdot_file>::iterator it = files.begin(); it != files.end(); it++)
- if (it->name == _file_name) {
- if (! _dot->deleteUserFile(_file_name))
+ if (it->name == file_name) {
+ if (! _dot->deleteUserFile(file_name))
ret = false;
break;
}
@@ -79,18 +79,18 @@ bool Mode::appendDataFile(const DataItem& data) {
snprintf(id_buf, sizeof(id_buf), "%c%ld", (data.type == single) ? 'P' : 'S', data.index);
// if we had GPS lock, format GPS data
- if (data.lock > 0) {
- snprintf(lat_buf, sizeof(lat_buf), "%3d %2d %2d.%03d %c",
+ if (data.gps_lock) {
+ snprintf(lat_buf, sizeof(lat_buf), "%d %d %d.%03d %c",
abs(data.gps_latitude.degrees),
data.gps_latitude.minutes,
(data.gps_latitude.seconds * 6) / 1000,
- (data.gps_latitude.seconds % 6) / 1000,
+ (data.gps_latitude.seconds * 6) % 1000,
(data.gps_latitude.degrees > 0) ? 'N' : 'S');
- snprintf(lon_buf, sizeof(lon_buf), "%3d %2d %2d.%03d %c",
+ snprintf(lon_buf, sizeof(lon_buf), "%d %d %d.%03d %c",
abs(data.gps_longitude.degrees),
data.gps_longitude.minutes,
(data.gps_longitude.seconds * 6) / 1000,
- (data.gps_longitude.seconds % 6) / 1000,
+ (data.gps_longitude.seconds * 6) % 1000,
(data.gps_longitude.degrees > 0) ? 'E' : 'W');
snprintf(alt_buf, sizeof(alt_buf), "%d",
data.gps_altitude);
@@ -106,7 +106,7 @@ bool Mode::appendDataFile(const DataItem& data) {
if (data.status) {
float up_snr = (float)data.ping.up.snr / 10.0;
float down_snr = (float)data.ping.down.snr / 4.0;
- snprintf(stats_buf, sizeof(stats_buf), "%3d,%2.1f,%3d,%2.1f",
+ snprintf(stats_buf, sizeof(stats_buf), "%d,%2.1f,%d,%2.1f",
abs(data.ping.up.rssi),
up_snr,
abs(data.ping.down.rssi),
@@ -116,11 +116,11 @@ bool Mode::appendDataFile(const DataItem& data) {
size = snprintf(main_buf, sizeof(main_buf), "%s,%c,%ld,%s,%s,%s,%s,%s,%s,%lu\n",
id_buf,
data.status ? 'S' : 'F',
- data.lock,
- (data.lock > 0) ? lat_buf : "",
- (data.lock > 0) ? lon_buf : "",
- (data.lock > 0) ? alt_buf : "",
- (data.lock > 0) ? time_buf : "",
+ data.gps_lock ? data.gps_sats : 0,
+ (data.gps_lock) ? lat_buf : "",
+ (data.gps_lock) ? lon_buf : "",
+ (data.gps_lock) ? alt_buf : "",
+ (data.gps_lock) ? time_buf : "",
data.status ? stats_buf : ",,,",
_dot->DataRateStr(data.data_rate).substr(3).c_str(),
data.power);
@@ -130,7 +130,7 @@ bool Mode::appendDataFile(const DataItem& data) {
return false;
}
- if (! _dot->appendUserFile(_file_name, (void*)main_buf, size)) {
+ if (! _dot->appendUserFile(file_name, (void*)main_buf, size)) {
logError("failed to write survey data to file");
return false;
} else {
@@ -144,10 +144,12 @@ void Mode::updateData(DataItem& data, DataType type, bool status) {
data.type = type;
data.index = _index;
data.status = status;
- data.lock = 0;
- data.gps_longitude = _mdot_gps.getLongitude();
- data.gps_latitude = _mdot_gps.getLatitude();
- data.gps_altitude = _mdot_gps.getAltitude();
+ data.gps_lock = _gps->getLockStatus();
+ data.gps_sats = _gps->getNumSatellites();
+ data.gps_longitude = _gps->getLongitude();
+ data.gps_latitude = _gps->getLatitude();
+ data.gps_altitude = _gps->getAltitude();
+ data.gps_time = _gps->getTimestamp();
data.ping = _ping_result;
data.data_rate = _data_rate;
data.power = _power;
@@ -183,7 +185,7 @@ uint32_t Mode::getIndex(DataType type) {
else
search = 'S';
- file = _dot->openUserFile(_file_name, mDot::FM_RDONLY);
+ file = _dot->openUserFile(file_name, mDot::FM_RDONLY);
if (file.fd < 0) {
logError("failed to open survey data file");
} else {
@@ -213,10 +215,12 @@ uint32_t Mode::getIndex(DataType type) {
return 0;
}
logInfo("read %d bytes [%s]", ret, buf);
+ bytes_read = file.size - read_offset - 1;
+ logInfo("read %d total bytes", bytes_read);
// read_size - 1 is the last byte in the buffer
for (current = read_size - 1; current >= 0; current--) {
- if ((buf[current] == '\n' && current != read_size - 1) || current == 0) {
+ if ((buf[current] == '\n' && current != read_size - 1) || (current == 0 && bytes_read >= file.size)) {
int test = current;
logInfo("found potential %d, %c", read_offset + current, buf[test + 1]);
if (buf[test + 1] == search) {
@@ -258,12 +262,12 @@ std::vector<uint8_t> Mode::formatSurveyData(DataItem& data) {
send_data.push_back(data.ping.down.snr);
// collect GPS data if GPS device detected
- if (_mdot_gps.gpsDetected() && ((_data_rate != mDot::SF_10) || (_band == mDot::FB_868))){
+ if (_gps->gpsDetected() && ((_data_rate != mDot::SF_10) || (_band == mDot::FB_868))){
send_data.push_back(0x19); // key for GPS Lock Status
- satfix = (_mdot_gps.getNumSatellites() << 4 ) | (_mdot_gps.getFixStatus() & 0x0F );
+ satfix = (_gps->getNumSatellites() << 4 ) | (_gps->getFixStatus() & 0x0F );
send_data.push_back(satfix);
- if (_mdot_gps.getLockStatus()){ // if gps has a lock
+ if (_gps->getLockStatus()){ // if gps has a lock
// Send GPS data if GPS device locked
send_data.push_back(0x15); // key for GPS Latitude
send_data.push_back(data.gps_latitude.degrees);
diff --git a/Mode/Mode.h b/Mode/Mode.h
index ff9ba6c..ca8433a 100644
--- a/Mode/Mode.h
+++ b/Mode/Mode.h
@@ -9,6 +9,7 @@
#include "ISL29011.h"
#include "MMA845x.h"
#include "MPL3115A2.h"
+#include "FileName.h"
#include "SensorHandler.h"
class Mode {
@@ -22,7 +23,8 @@ class Mode {
DataType type;
int32_t index;
bool status;
- int32_t lock;
+ bool gps_lock;
+ int32_t gps_sats;
GPSPARSER::longitude gps_longitude;
GPSPARSER::latitude gps_latitude;
int16_t gps_altitude;
@@ -42,7 +44,7 @@ class Mode {
float altitude;
} SensorItem;
- Mode(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora);
+ Mode(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps);
~Mode();
virtual bool start() = 0;
@@ -61,8 +63,8 @@ class Mode {
ButtonHandler* _buttons;
mDot* _dot;
LoRaHandler* _lora;
+ GPSPARSER* _gps;
osThreadId _main_id;
- static const char* _file_name;
uint32_t _index;
uint8_t _band;
uint8_t _sub_band;
@@ -74,6 +76,7 @@ class Mode {
LoRaHandler::LoRaPing _ping_result;
uint8_t _state;
bool _send_data;
+ bool _gps_available;
mts::MTSSerial _gpsUART;
GPSPARSER _mdot_gps;
SensorHandler _mdot_sensors;
diff --git a/Mode/ModeConfig.cpp b/Mode/ModeConfig.cpp
index 35a81bd..babd898 100644
--- a/Mode/ModeConfig.cpp
+++ b/Mode/ModeConfig.cpp
@@ -19,8 +19,8 @@ void ModeConfig::addCommand(Command* cmd) {
_commands.push_back(cmd);
}
-ModeConfig::ModeConfig(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora)
-: Mode(lcd, buttons, dot, lora),
+ModeConfig::ModeConfig(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps)
+: Mode(lcd, buttons, dot, lora, gps),
_lc(lcd),
_serial(USBTX, USBRX, 512, 512)
{
diff --git a/Mode/ModeConfig.h b/Mode/ModeConfig.h
index 1192a8c..6c0ac73 100644
--- a/Mode/ModeConfig.h
+++ b/Mode/ModeConfig.h
@@ -13,7 +13,7 @@ class ModeConfig : public Mode {
public:
- ModeConfig(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora);
+ ModeConfig(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps);
// Command error text...
static const char command_error[];
diff --git a/Mode/ModeDemo.cpp b/Mode/ModeDemo.cpp
new file mode 100644
index 0000000..e70ccbd
--- /dev/null
+++ b/Mode/ModeDemo.cpp
@@ -0,0 +1,151 @@
+#include "ModeDemo.h"
+#include "MTSLog.h"
+
+// 10 s, 30 s, 1 min, 5 min, 10 min, 15 min, 30 min 1 hour
+const uint32_t ModeDemo::_intervals[] = { 10, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60, 60 * 60 };
+
+ModeDemo::ModeDemo(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps)
+ : Mode(lcd, buttons, dot, lora, gps),
+ _help(lcd),
+ _sam(lcd),
+ _interval(0)
+{}
+
+ModeDemo::~ModeDemo() {}
+
+bool ModeDemo::start() {
+ bool send = false;
+ bool no_channel = false;
+
+ // clear any stale signals
+ osSignalClear(_main_id, buttonSignal | loraSignal);
+
+ _state = show_help;
+ displayHelp();
+
+ while (true) {
+ osEvent e = Thread::signal_wait(0, 250);
+ if (e.status == osEventSignal) {
+ if (e.value.signals & buttonSignal) {
+ _be = _buttons->getButtonEvent();
+
+ switch (_be) {
+ case ButtonHandler::sw1_press:
+ switch (_state) {
+ case show_help:
+ _state = sampling;
+ _mode = trigger;
+ _sam.display();
+ _sam.updateSw2("Send");
+ break;
+ case sampling:
+ if (_mode == interval) {
+ _interval = (_interval + 1) % (sizeof(_intervals) / sizeof(uint32_t));
+ _sam.updateInterval(_intervals[_interval]);
+ }
+ break;
+ }
+ break;
+
+ case ButtonHandler::sw2_press:
+ switch (_state) {
+ case show_help:
+ _state = sampling;
+ _mode = interval;
+ _send_timer.start();
+ _sam.display();
+ _sam.updateSw1("Interval");
+ _sam.updateInterval(_intervals[_interval]);
+ break;
+ case sampling:
+ if (_mode == trigger) {
+ if (_dot->getNextTxMs() > 0)
+ no_channel = true;
+ else
+ send = true;
+ }
+ break;
+ }
+ break;
+ case ButtonHandler::sw1_hold:
+ _send_timer.stop();
+ _send_timer.reset();
+ return true;
+ }
+ }
+ if (e.value.signals & loraSignal) {
+ _ls = _lora->getStatus();
+ switch (_ls) {
+ case LoRaHandler::send_success:
+ switch (_state) {
+ case sampling:
+ if (_mode == trigger) {
+ _sam.updateSw2("Send");
+ _sam.updateInfo(" ");
+ } else {
+ _sam.updateSw1("Interval");
+ _sam.updateInterval(_intervals[_interval]);
+ }
+ break;
+ }
+ break;
+
+ case LoRaHandler::send_failure:
+ switch (_state) {
+ case sampling:
+ if (_mode == trigger) {
+ _sam.updateSw2("Send");
+ _sam.updateInfo(" ");
+ } else {
+ _sam.updateSw1("Interval");
+ _sam.updateInterval(_intervals[_interval]);
+ }
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ if (_send_timer.read_ms() > _intervals[_interval] * 1000) {
+ _send_timer.reset();
+ if (_dot->getNextTxMs() > 0)
+ no_channel = true;
+ else
+ send = true;
+ }
+ if (no_channel) {
+ uint32_t t = _dot->getNextTxMs();
+ if (t > 0) {
+ logInfo("next tx %lu ms", t);
+ _sam.updateCountdown(t / 1000);
+ } else {
+ no_channel = false;
+ send = true;
+ }
+ }
+ if (send) {
+ std::vector<uint8_t> s_data = formatSensorData(_data);
+ logInfo("sending data %s %d", _dot->DataRateStr(_dot->getTxDataRate()).c_str(), _dot->getTxPower());
+ _sam.updateInfo("Sending...");
+ _sam.updateSw1(" ");
+ _sam.updateSw2(" ");
+ send = false;
+ // we don't care if the server actually gets this packet or not
+ // we won't retry anyway
+ _dot->setAck(0);
+ _dot->setTxWait(false);
+ _lora->send(s_data);
+ osDelay(500);
+ }
+ }
+}
+
+void ModeDemo::displayHelp() {
+ _help.display();
+ _help.updateMode("LoRa Demo");
+ _help.updateDescription("Select TX Method");
+ _help.updateSw1(" Trigger");
+ _help.updateSw2("Interval");
+}
+
diff --git a/Mode/ModeDemo.h b/Mode/ModeDemo.h
new file mode 100644
index 0000000..b2aaf21
--- /dev/null
+++ b/Mode/ModeDemo.h
@@ -0,0 +1,39 @@
+#ifndef __MODEDEMO_H__
+#define __MODEDEMO_H__
+
+#include "Mode.h"
+#include "LayoutHelp.h"
+#include "LayoutDemoSampling.h"
+
+class ModeDemo : public Mode {
+ public:
+ ModeDemo(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps);
+ ~ModeDemo();
+
+ bool start();
+
+ private:
+ void displayHelp();
+
+ typedef enum {
+ show_help = 0,
+ sampling,
+ success,
+ failure
+ } state;
+
+ typedef enum {
+ trigger = 0,
+ interval
+ } mode;
+
+ LayoutHelp _help;
+ LayoutDemoSampling _sam;
+ SensorItem _data;
+ mode _mode;
+ Timer _send_timer;
+ uint8_t _interval;
+ static const uint32_t _intervals[];
+};
+
+#endif
diff --git a/Mode/ModeJoin.cpp b/Mode/ModeJoin.cpp
index d1e69ea..5b0a7ed 100644
--- a/Mode/ModeJoin.cpp
+++ b/Mode/ModeJoin.cpp
@@ -2,8 +2,8 @@
#include "MTSLog.h"
#include "MTSText.h"
-ModeJoin::ModeJoin(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora)
- : Mode(lcd, buttons, dot, lora),
+ModeJoin::ModeJoin(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps)
+ : Mode(lcd, buttons, dot, lora, gps),
_join(lcd, _band),
_joined(false)
{}
@@ -22,13 +22,13 @@ bool ModeJoin::start() {
display();
- _lora->setDataRate(_data_rate);
- _lora->setPower(_power);
+ _dot->setTxDataRate(_data_rate);
+ _dot->setTxPower(_power);
_lora->resetJoinAttempts();
while (! _joined) {
- _next_tx = _lora->getNextTx();
- if (_next_tx) {
+ _next_tx = _dot->getNextTxMs();
+ if (! joining && _next_tx > 0) {
logInfo("next tx %lu ms", _next_tx);
_join.updateStatus("Waiting...");
_join.updateCountdown(_next_tx / 1000);
diff --git a/Mode/ModeJoin.h b/Mode/ModeJoin.h
index af48d94..cad3f61 100644
--- a/Mode/ModeJoin.h
+++ b/Mode/ModeJoin.h
@@ -6,7 +6,7 @@
class ModeJoin : public Mode {
public:
- ModeJoin(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora);
+ ModeJoin(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps);
~ModeJoin();
bool start();
diff --git a/Mode/ModeSingle.cpp b/Mode/ModeSingle.cpp
index 083b72d..737301f 100644
--- a/Mode/ModeSingle.cpp
+++ b/Mode/ModeSingle.cpp
@@ -1,8 +1,8 @@
#include "ModeSingle.h"
#include "MTSLog.h"
-ModeSingle::ModeSingle(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora)
- : Mode(lcd, buttons, dot, lora),
+ModeSingle::ModeSingle(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps)
+ : Mode(lcd, buttons, dot, lora, gps),
_help(lcd),
_file(lcd),
_confirm(lcd),
@@ -30,7 +30,7 @@ bool ModeSingle::start() {
// see if survey data file exists
std::vector<mDot::mdot_file> files = _dot->listUserFiles();
for (std::vector<mDot::mdot_file>::iterator it = files.begin(); it != files.end(); it++) {
- if (strcmp(it->name, _file_name) == 0) {
+ if (strcmp(it->name, file_name) == 0) {
logInfo("found survey data file");
data_file = true;
break;
@@ -65,23 +65,15 @@ bool ModeSingle::start() {
break;
case show_help:
incrementRatePower();
- _help.updateMsg(formatNewRatePower());
- logInfo("new data rate %u, power %lu", _data_rate, _power);
- break;
- case in_progress:
- // do nothing
+ _help.updateMsg(formatRatePower());
break;
case success:
incrementRatePower();
- _success.updateInfo(formatNewRatePower());
- logInfo("new data rate %u, power %lu", _data_rate, _power);
- break;
- case data:
+ _success.updateInfo(formatRatePower());
break;
case failure:
incrementRatePower();
- _failure.updateInfo2(formatNewRatePower());
- logInfo("new data rate %u, power %lu", _data_rate, _power);
+ _failure.updateInfo(formatRatePower());
break;
}
break;
@@ -95,35 +87,30 @@ bool ModeSingle::start() {
case confirm:
_state = show_help;
logInfo("deleting survey data file");
- _dot->deleteUserFile(_file_name);
+ _dot->deleteUserFile(file_name);
_index = 0;
displayHelp();
break;
case show_help:
_state = in_progress;
_progress.display();
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_ping = true;
else
send_ping = true;
break;
- case in_progress:
- // do nothing
- break;
case success:
_state = in_progress;
_progress.display();
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_ping = true;
else
send_ping = true;
break;
- case data:
- break;
case failure:
_state = in_progress;
_progress.display();
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_ping = true;
else
send_ping = true;
@@ -139,12 +126,6 @@ bool ModeSingle::start() {
switch (_ls) {
case LoRaHandler::ping_success:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
case in_progress:
_ping_result = _lora->getPingResults();
displaySuccess();
@@ -153,7 +134,7 @@ bool ModeSingle::start() {
appendDataFile(_data);
if (_send_data) {
_state = data;
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_data = true;
else
send_data = true;
@@ -163,23 +144,11 @@ bool ModeSingle::start() {
_success.updateSw2("Survey");
}
break;
- case success:
- break;
- case data:
- break;
- case failure:
- break;
}
break;
case LoRaHandler::ping_failure:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
case in_progress:
_state = failure;
_failure.display();
@@ -189,64 +158,50 @@ bool ModeSingle::start() {
updateData(_data, single, false);
appendDataFile(_data);
_failure.updatePower(_power);
+ if (_gps_available && _gps->getLockStatus()) {
+ GPSPARSER::latitude lat = _gps->getLatitude();
+ GPSPARSER::longitude lon = _gps->getLongitude();
+ struct tm time = _gps->getTimestamp();
+ _failure.updateGpsLatitude(lat);
+ _failure.updateGpsLongitude(lon);
+ _failure.updateGpsTime(time);
+ } else {
+ _failure.updateGpsLatitude("No GPS Lock");
+ }
_failure.updateSw1(" Power");
_failure.updateSw2("Survey");
logInfo("ping failed");
break;
- case success:
- break;
- case data:
- break;
- case failure:
- break;
}
break;
case LoRaHandler::send_success:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
- case in_progress:
- break;
- case success:
- break;
case data:
_state = success;
- _success.updateInfo("Data Send Success");
+ _success.updateInfo(" ");
_success.updateSw1(" Power");
_success.updateSw2("Survey");
+ // turn acks and receive windows back on
+ _dot->setAck(1);
+ _dot->setTxWait(true);
logInfo("data send success");
break;
- case failure:
- break;
}
break;
case LoRaHandler::send_failure:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
- case in_progress:
- break;
- case success:
- break;
case data:
_state = success;
- _success.updateInfo("Data Send Failure");
+ _success.updateInfo(" ");
_success.updateSw1(" Power");
_success.updateSw2("Survey");
+ // turn acks and receive windows back on
+ _dot->setAck(1);
+ _dot->setTxWait(true);
logInfo("data send failed");
break;
- case failure:
- break;
}
break;
}
@@ -254,7 +209,7 @@ bool ModeSingle::start() {
}
if (no_channel_ping) {
- uint32_t t = _lora->getNextTx();
+ uint32_t t = _dot->getNextTxMs();
if (t > 0) {
logInfo("next tx %lu ms", t);
_progress.updateCountdown(t / 1000);
@@ -265,7 +220,7 @@ bool ModeSingle::start() {
}
}
if (no_channel_data) {
- uint32_t t = _lora->getNextTx();
+ uint32_t t = _dot->getNextTxMs();
if (t > 0) {
logInfo("next tx %lu ms", t);
_success.updateCountdown(t / 1000);
@@ -278,19 +233,24 @@ bool ModeSingle::start() {
if (send_ping) {
logInfo("sending ping %s %d", _dot->DataRateStr(_data_rate).c_str(), _power);
send_ping = false;
- _lora->setDataRate(_data_rate);
- _lora->setPower(_power);
+ _dot->setTxDataRate(_data_rate);
+ _dot->setTxPower(_power);
_lora->ping();
_index++;
}
if (send_data) {
- std::vector<uint8_t> s_data;
+ std::vector<uint8_t> s_data = formatSurveyData(_data);
logInfo("sending data %s %d", _dot->DataRateStr(_data_rate).c_str(), _power);
send_data = false;
_success.updateInfo("Data Sending...");
- _lora->setDataRate(_data_rate);
- _lora->setPower(_power);
+ _dot->setTxDataRate(_data_rate);
+ _dot->setTxPower(_power);
+ // we don't care if the server actually gets this packet or not
+ // we won't retry anyway
+ _dot->setAck(0);
+ _dot->setTxWait(false);
_lora->send(s_data);
+ osDelay(500);
}
}
}
@@ -300,29 +260,38 @@ void ModeSingle::displayHelp() {
_help.updateMode("Survey Single");
_help.updateSw1(" DR/PWR");
_help.updateSw2("Survey");
+ _help.updateMsg(formatRatePower());
}
void ModeSingle::displaySuccess() {
+ logInfo("gps lock: %s", _gps->getLockStatus() ? "true" : "false");
+ uint8_t fix = _gps->getFixStatus();
+ logInfo("gps fix: %s", fix == 3 ? "3D" : fix == 2 ? "2D" : "none");
_success.display();
_success.updateId(_index);
// mDot::DataRateStr returns format SF_XX - we only want to display the XX part
_success.updateRate(_dot->DataRateStr(_data_rate).substr(3));
_success.updatePower(_power);
_success.updateStats(_ping_result);
- // if GPS lock
- // display GPS latitude, longitude, and time
- // else
- // display "no lock"
- _success.updateGpsLatitude("No GPS Lock");
+ if (_gps_available && _gps->getLockStatus()) {
+ GPSPARSER::latitude lat = _gps->getLatitude();
+ GPSPARSER::longitude lon = _gps->getLongitude();
+ struct tm time = _gps->getTimestamp();
+ _success.updateGpsLatitude(lat);
+ _success.updateGpsLongitude(lon);
+ _success.updateGpsTime(time);
+ } else {
+ _success.updateGpsLatitude("No GPS Lock");
+ }
}
-std::string ModeSingle::formatNewRatePower() {
+std::string ModeSingle::formatRatePower() {
std::string msg;
char buf[8];
size_t size;
memset(buf, 0, sizeof(buf));
- msg += "New DR=";
+ msg += "DR=";
msg += _dot->DataRateStr(_data_rate).substr(3);
msg += " P=";
size = snprintf(buf, sizeof(buf), "%u", _power);
@@ -360,5 +329,7 @@ void ModeSingle::incrementRatePower() {
} else {
_power += 3;
}
+
+ logInfo("new data rate %u, power %lu", _data_rate, _power);
}
diff --git a/Mode/ModeSingle.h b/Mode/ModeSingle.h
index df656ba..1ddfc33 100644
--- a/Mode/ModeSingle.h
+++ b/Mode/ModeSingle.h
@@ -11,7 +11,7 @@
class ModeSingle : public Mode {
public:
- ModeSingle(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora);
+ ModeSingle(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps);
~ModeSingle();
bool start();
@@ -19,7 +19,7 @@ class ModeSingle : public Mode {
private:
void displayHelp();
void displaySuccess();
- std::string formatNewRatePower();
+ std::string formatRatePower();
void incrementRatePower();
typedef enum {
diff --git a/Mode/ModeSweep.cpp b/Mode/ModeSweep.cpp
index 938ec83..17047b3 100644
--- a/Mode/ModeSweep.cpp
+++ b/Mode/ModeSweep.cpp
@@ -1,8 +1,8 @@
#include "ModeSweep.h"
#include "MTSLog.h"
-ModeSweep::ModeSweep(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora)
- : Mode(lcd, buttons, dot, lora),
+ModeSweep::ModeSweep(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps)
+ : Mode(lcd, buttons, dot, lora, gps),
_help(lcd),
_file(lcd),
_confirm(lcd),
@@ -54,7 +54,7 @@ bool ModeSweep::start() {
// see if survey data file exists
std::vector<mDot::mdot_file> files = _dot->listUserFiles();
for (std::vector<mDot::mdot_file>::iterator it = files.begin(); it != files.end(); it++) {
- if (strcmp(it->name, _file_name) == 0) {
+ if (strcmp(it->name, file_name) == 0) {
logInfo("found survey data file");
data_file = true;
break;
@@ -89,10 +89,6 @@ bool ModeSweep::start() {
_state = check_file;
_file.display();
break;
- case show_help:
- break;
- case in_progress:
- break;
case success:
_state = complete;
_display_timer.stop();
@@ -105,8 +101,6 @@ bool ModeSweep::start() {
_survey_success = 0;
_survey_failure = 0;
break;
- case data:
- break;
case failure:
_state = complete;
_display_timer.stop();
@@ -119,8 +113,6 @@ bool ModeSweep::start() {
_survey_success = 0;
_survey_failure = 0;
break;
- case complete:
- break;
}
break;
@@ -133,7 +125,7 @@ bool ModeSweep::start() {
case confirm:
_state = show_help;
logInfo("deleting survey data file");
- _dot->deleteUserFile(_file_name);
+ _dot->deleteUserFile(file_name);
_index = 1;
displayHelp();
break;
@@ -141,25 +133,17 @@ bool ModeSweep::start() {
_state = in_progress;
_progress.display();
_progress.updateProgress(_survey_current, _survey_total);
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_ping = true;
else
send_ping = true;
break;
- case in_progress:
- break;
- case success:
- break;
- case data:
- break;
- case failure:
- break;
case complete:
_state = in_progress;
_survey_current = 1;
_progress.display();
_progress.updateProgress(_survey_current, _survey_total);
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_ping = true;
else
send_ping = true;
@@ -175,12 +159,6 @@ bool ModeSweep::start() {
switch (_ls) {
case LoRaHandler::ping_success:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
case in_progress:
_survey_success++;
_ping_result = _lora->getPingResults();
@@ -190,7 +168,7 @@ bool ModeSweep::start() {
appendDataFile(_data);
if (_send_data) {
_state = data;
- if (_lora->getNextTx() > 0)
+ if (_dot->getNextTxMs() > 0)
no_channel_data = true;
else
send_data = true;
@@ -200,25 +178,11 @@ bool ModeSweep::start() {
_display_timer.start();
}
break;
- case success:
- break;
- case data:
- break;
- case failure:
- break;
- case complete:
- break;
}
break;
case LoRaHandler::ping_failure:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
case in_progress:
_survey_failure++;
_state = failure;
@@ -227,6 +191,14 @@ bool ModeSweep::start() {
// mDot::DataRateStr returns format SF_XX - we only want to display the XX part
_failure.updateRate(_dot->DataRateStr(_data_rate).substr(3));
_failure.updatePower(_power);
+ if (_gps_available && _gps->getLockStatus()) {
+ GPSPARSER::latitude lat = _gps->getLatitude();
+ GPSPARSER::longitude lon = _gps->getLongitude();
+ _failure.updateGpsLatitude(lat);
+ _failure.updateGpsLongitude(lon);
+ } else {
+ _failure.updateGpsLatitude("No GPS Lock");
+ }
_failure.updatePassFail(_survey_success, _survey_failure);
_failure.updateSw1(" Cancel");
updateData(_data, sweep, false);
@@ -234,66 +206,36 @@ bool ModeSweep::start() {
logInfo("ping failed");
_display_timer.start();
break;
- case success:
- break;
- case data:
- break;
- case failure:
- break;
- case complete:
- break;
}
break;
case LoRaHandler::send_success:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
- case in_progress:
- break;
- case success:
- break;
case data:
_state = success;
- _success.updateInfo("Data Send Success");
+ _success.updateInfo(" ");
_success.updateSw1(" Cancel");
logInfo("data send success");
+ // turn acks and receive windows back on
+ _dot->setAck(1);
+ _dot->setTxWait(true);
_display_timer.start();
break;
- case failure:
- break;
- case complete:
- break;
}
break;
case LoRaHandler::send_failure:
switch (_state) {
- case check_file:
- break;
- case confirm:
- break;
- case show_help:
- break;
- case in_progress:
- break;
- case success:
- break;
case data:
_state = success;
- _success.updateInfo("Data Send Failure");
+ _success.updateInfo(" ");
_success.updateSw1(" Cancel");
logInfo("data send failed");
+ // turn acks and receive windows back on
+ _dot->setAck(1);
+ _dot->setTxWait(true);
_display_timer.start();
break;
- case failure:
- break;
- case complete:
- break;
}
break;
}
@@ -323,7 +265,7 @@ bool ModeSweep::start() {
}
if (no_channel_ping) {
- uint32_t t = _lora->getNextTx();
+ uint32_t t = _dot->getNextTxMs();
if (t > 0) {
logInfo("next tx %lu ms", t);
_progress.updateCountdown(t / 1000);
@@ -335,7 +277,7 @@ bool ModeSweep::start() {
}
}
if (no_channel_data) {
- uint32_t t = _lora->getNextTx();
+ uint32_t t = _dot->getNextTxMs();
if (t > 0) {
logInfo("next tx %lu ms", t);
_success.updateCountdown(t / 1000);
@@ -351,18 +293,23 @@ bool ModeSweep::start() {
_power = p.second;
logInfo("sending ping %s %d", _dot->DataRateStr(_data_rate).c_str(), _power);
send_ping = false;
- _lora->setDataRate(_data_rate);
- _lora->setPower(_power);
+ _dot->setTxDataRate(_data_rate);
+ _dot->setTxPower(_power);
_lora->ping();
}
if (send_data) {
- std::vector<uint8_t> s_data;
+ std::vector<uint8_t> s_data = formatSurveyData(_data);
logInfo("sending data %s %d", _dot->DataRateStr(_data_rate).c_str(), _power);
send_data = false;
_success.updateInfo("Data Sending...");
- _lora->setDataRate(_data_rate);
- _lora->setPower(_power);
+ _dot->setTxDataRate(_data_rate);
+ _dot->setTxPower(_power);
+ // we don't care if the server actually gets this packet or not
+ // we won't retry anyway
+ _dot->setAck(0);
+ _dot->setTxWait(false);
_lora->send(s_data);
+ osDelay(500);
}
}
}
@@ -381,11 +328,14 @@ void ModeSweep::displaySuccess() {
_success.updateRate(_dot->DataRateStr(_data_rate).substr(3));
_success.updatePower(_power);
_success.updateStats(_ping_result);
- // if GPS lock
- // display GPS latitude, longitude, and time
- // else
- // display "no lock"
- _success.updateGpsLatitude("No GPS Lock");
+ if (_gps_available && _gps->getLockStatus()) {
+ GPSPARSER::latitude lat = _gps->getLatitude();
+ GPSPARSER::longitude lon = _gps->getLongitude();
+ _success.updateGpsLatitude(lat);
+ _success.updateGpsLongitude(lon);
+ } else {
+ _success.updateGpsLatitude("No GPS Lock");
+ }
_success.updatePassFail(_survey_success, _survey_failure);
}
diff --git a/Mode/ModeSweep.h b/Mode/ModeSweep.h
index 5eebda1..f7522aa 100644
--- a/Mode/ModeSweep.h
+++ b/Mode/ModeSweep.h
@@ -14,7 +14,7 @@ typedef std::pair<uint8_t, uint32_t> point;
class ModeSweep : public Mode {
public:
- ModeSweep(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora);
+ ModeSweep(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps);
~ModeSweep();
bool start();
diff --git a/main.cpp b/main.cpp
index 6dc9447..d75f821 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,17 +19,19 @@
#include "ModeJoin.h"
#include "ModeSingle.h"
#include "ModeSweep.h"
+#include "ModeDemo.h"
#include "ModeConfig.h"
// misc heders
+#include "FileName.h"
#include <string>
-// LCD and backlight controllers
+// LCD and LED controllers
SPI lcd_spi(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
-I2C backlight_i2c(I2C_SDA, I2C_SCL);
+I2C led_i2c(I2C_SDA, I2C_SCL);
DigitalOut lcd_spi_cs(SPI1_CS, 1);
DigitalOut lcd_cd(XBEE_ON_SLEEP, 1);
DOGS102* lcd;
-NCP5623B* lcd_backlight;
+NCP5623B* led_cont;
// Thread informaiton
osThreadId main_id;
@@ -41,44 +43,60 @@ ButtonHandler* buttons;
LoRaHandler* lora;
mDot* dot;
+// GPS
+GPSPARSER* gps;
+MTSSerial gps_serial(XBEE_DOUT, XBEE_DIN, 256, 2048);
+
// Modes
ModeJoin* modeJoin;
ModeSingle* modeSingle;
ModeSweep* modeSweep;
+ModeDemo* modeDemo;
ModeConfig* modeConfig;
// Serial debug port
Serial debug(USBTX, USBRX);
+// Survey Data File
+char* file_name;
+
// Prototypes
void mainMenu();
-void join();
-void loraDemo();
-void surveySingle();
-void surveySweep();
int main() {
debug.baud(115200);
+ file_name = "SurveyData.txt";
lcd = new DOGS102(lcd_spi, lcd_spi_cs, lcd_cd);
- lcd_backlight = new NCP5623B(backlight_i2c);
+ // NCP5623B::LEDs 1 & 2 are the screen backlight - not used on default build
+ // NCP5623B::LED3 is EVB LED2
+ led_cont = new NCP5623B(led_i2c);
main_id = Thread::gettid();
buttons = new ButtonHandler(main_id);
dot = mDot::getInstance();
lora = new LoRaHandler(main_id);
+ gps = new GPSPARSER(&gps_serial, led_cont);
+
+ led_cont->setLEDCurrent(16);
+
+ MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
+
+ modeJoin = new ModeJoin(lcd, buttons, dot, lora, gps);
+ modeSingle = new ModeSingle(lcd, buttons, dot, lora, gps);
+ modeSweep = new ModeSweep(lcd, buttons, dot, lora, gps);
+ modeDemo = new ModeDemo(lcd, buttons, dot, lora, gps);
+ modeConfig = new ModeConfig(lcd, buttons, dot, lora, gps);
- modeJoin = new ModeJoin(lcd, buttons, dot, lora);
- modeSingle = new ModeSingle(lcd, buttons, dot, lora);
- modeSweep = new ModeSweep(lcd, buttons, dot, lora);
- modeConfig = new ModeConfig(lcd, buttons, dot, lora);
+ osDelay(1000);
+ logInfo("%sGPS detected", gps->gpsDetected() ? "" : "no ");
// display startup screen for 3 seconds
LayoutStartup ls(lcd, dot);
ls.display();
+ ls.updateGPS(gps->gpsDetected());
osDelay(3000);
- MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
logInfo("displaying main menu");
mainMenu();
@@ -114,6 +132,7 @@ void mainMenu() {
while (true) {
// reset session between modes
dot->resetNetworkSession();
+ lora->resetActivityLed();
LayoutScrollSelect menu(lcd, items, menu_strings[0], menu_strings[1]);
menu.display();
@@ -139,7 +158,7 @@ void mainMenu() {
if (selected == menu_strings[demo]) {
if (modeJoin->start())
- loraDemo();
+ modeDemo->start();
} else if (selected == menu_strings[config]) {
modeConfig->start();
} else if (selected == menu_strings[single]) {
@@ -154,36 +173,3 @@ void mainMenu() {
}
}
-void loraDemo() {
- LayoutHelp lh(lcd);
- lh.display();
- lh.updateMode("LoRa Demo");
- lh.updateDescription("Select TX Method");
- lh.updateSw1(" Trigger");
- lh.updateSw2("Interval");
-
- // clear any stale signals
- osSignalClear(main_id, buttonSignal | loraSignal);
-
- logInfo("demo mode");
-
- while (true) {
- osEvent e = Thread::signal_wait(buttonSignal);
- if (e.status == osEventSignal) {
- ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
- switch (ev) {
- case ButtonHandler::sw1_press:
- logInfo("trigger TX mode");
- break;
- case ButtonHandler::sw2_press:
- logInfo("interval TX mode");
- break;
- case ButtonHandler::sw1_hold:
- return;
- default:
- break;
- }
- }
- }
-}
-