diff options
-rw-r--r-- | CommandTerminal/CmdDeleteSurveyDataFile.cpp | 13 | ||||
-rw-r--r-- | CommandTerminal/CmdGetSurveyDataFile.cpp | 38 | ||||
-rw-r--r-- | FileName.h | 6 | ||||
-rw-r--r-- | Layout/LayoutDemoSampling.cpp | 82 | ||||
-rw-r--r-- | Layout/LayoutDemoSampling.h | 39 | ||||
-rw-r--r-- | Layout/LayoutStartup.cpp | 11 | ||||
-rw-r--r-- | Layout/LayoutStartup.h | 2 | ||||
-rw-r--r-- | Layout/LayoutSurveyFailure.cpp | 64 | ||||
-rw-r--r-- | Layout/LayoutSurveyFailure.h | 18 | ||||
-rw-r--r-- | Layout/LayoutSurveySuccess.cpp | 33 | ||||
-rw-r--r-- | LoRaHandler/LoRaHandler.cpp | 50 | ||||
-rw-r--r-- | LoRaHandler/LoRaHandler.h | 13 | ||||
-rw-r--r-- | Mode/Mode.cpp | 56 | ||||
-rw-r--r-- | Mode/Mode.h | 9 | ||||
-rw-r--r-- | Mode/ModeConfig.cpp | 4 | ||||
-rw-r--r-- | Mode/ModeConfig.h | 2 | ||||
-rw-r--r-- | Mode/ModeDemo.cpp | 151 | ||||
-rw-r--r-- | Mode/ModeDemo.h | 39 | ||||
-rw-r--r-- | Mode/ModeJoin.cpp | 12 | ||||
-rw-r--r-- | Mode/ModeJoin.h | 2 | ||||
-rw-r--r-- | Mode/ModeSingle.cpp | 147 | ||||
-rw-r--r-- | Mode/ModeSingle.h | 4 | ||||
-rw-r--r-- | Mode/ModeSweep.cpp | 136 | ||||
-rw-r--r-- | Mode/ModeSweep.h | 2 | ||||
-rw-r--r-- | main.cpp | 80 |
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(); @@ -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; - } - } - } -} - |