From 41a5c0de1343c4a4163c7096ea33bbfd6c3e84cb Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Fri, 4 Dec 2015 09:53:21 -0600 Subject: implement demo mode logic - still need to add sensor data --- Layout/LayoutDemoSampling.cpp | 82 ++++++++++++++++++++ Layout/LayoutDemoSampling.h | 39 ++++++++++ Mode/ModeDemo.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++ Mode/ModeDemo.h | 39 ++++++++++ main.cpp | 38 +--------- 5 files changed, 336 insertions(+), 34 deletions(-) create mode 100644 Layout/LayoutDemoSampling.cpp create mode 100644 Layout/LayoutDemoSampling.h create mode 100644 Mode/ModeDemo.cpp create mode 100644 Mode/ModeDemo.h diff --git a/Layout/LayoutDemoSampling.cpp b/Layout/LayoutDemoSampling.cpp new file mode 100644 index 0000000..08d74ff --- /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/Mode/ModeDemo.cpp b/Mode/ModeDemo.cpp new file mode 100644 index 0000000..80d202c --- /dev/null +++ b/Mode/ModeDemo.cpp @@ -0,0 +1,172 @@ +#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; + case success: + break; + case failure: + 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; + case success: + break; + case failure: + 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 show_help: + break; + case sampling: + if (_mode == trigger) { + _sam.updateSw2("Send"); + } else { + _sam.updateSw1("Interval"); + _sam.updateInterval(_intervals[_interval]); + } + break; + case success: + break; + case failure: + break; + } + break; + + case LoRaHandler::send_failure: + switch (_state) { + case show_help: + break; + case sampling: + if (_mode == trigger) { + _sam.updateSw2("Send"); + } else { + _sam.updateSw1("Interval"); + _sam.updateInterval(_intervals[_interval]); + } + break; + case success: + break; + case failure: + 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 s_data = formatSensorData(_data); + logInfo("sending data %s %d", _dot->DataRateStr(_data_rate).c_str(), _power); + _sam.updateInfo("Sending..."); + _sam.updateSw1(" "); + _sam.updateSw2(" "); + send = false; + _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); + _sam.updateInfo(" "); + } + } +} + +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/main.cpp b/main.cpp index 9f42df3..5fbf58d 100644 --- a/main.cpp +++ b/main.cpp @@ -19,6 +19,7 @@ #include "ModeJoin.h" #include "ModeSingle.h" #include "ModeSweep.h" +#include "ModeDemo.h" #include "ModeConfig.h" // misc heders #include "FileName.h" @@ -50,6 +51,7 @@ MTSSerial gps_serial(XBEE_DOUT, XBEE_DIN, 256, 2048); ModeJoin* modeJoin; ModeSingle* modeSingle; ModeSweep* modeSweep; +ModeDemo* modeDemo; ModeConfig* modeConfig; // Serial debug port @@ -88,6 +90,7 @@ int main() { 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); logInfo("GPS %sdetected", gps->gpsDetected() ? "" : "not "); @@ -157,7 +160,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]) { @@ -172,36 +175,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; - } - } - } -} - -- cgit v1.2.3