summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ButtonHandler/ButtonHandler.cpp125
-rw-r--r--ButtonHandler/ButtonHandler.h25
-rw-r--r--Layout/Layout.cpp61
-rw-r--r--Layout/Layout.h11
-rw-r--r--Layout/LayoutConfig.cpp23
-rw-r--r--Layout/LayoutConfig.h20
-rw-r--r--Layout/LayoutDemoHelp.cpp28
-rw-r--r--Layout/LayoutDemoHelp.h22
-rw-r--r--Layout/LayoutJoin.cpp104
-rw-r--r--Layout/LayoutJoin.h46
-rw-r--r--Layout/LayoutScrollSelect.cpp244
-rw-r--r--Layout/LayoutScrollSelect.h40
-rw-r--r--Layout/LayoutSingleHelp.cpp26
-rw-r--r--Layout/LayoutSingleHelp.h21
-rw-r--r--Layout/LayoutStartup.cpp14
-rw-r--r--Layout/LayoutSweepHelp.cpp26
-rw-r--r--Layout/LayoutSweepHelp.h21
-rw-r--r--LoRaHandler/LoRaHandler.cpp160
-rw-r--r--LoRaHandler/LoRaHandler.h50
-rw-r--r--Mode/Mode.cpp19
-rw-r--r--Mode/Mode.h47
-rw-r--r--Mode/ModeJoin.cpp86
-rw-r--r--Mode/ModeJoin.h30
-rw-r--r--main.cpp242
24 files changed, 1427 insertions, 64 deletions
diff --git a/ButtonHandler/ButtonHandler.cpp b/ButtonHandler/ButtonHandler.cpp
index 23bcb02..edc9ea1 100644
--- a/ButtonHandler/ButtonHandler.cpp
+++ b/ButtonHandler/ButtonHandler.cpp
@@ -1,45 +1,136 @@
#include "ButtonHandler.h"
+#define signal (int32_t)0xA0
+
+typedef enum {
+ b_none = 0,
+ b_sw1_fall,
+ b_sw1_rise,
+ b_sw2_fall,
+ b_sw2_rise
+} InternalButtonEvent;
+
+InternalButtonEvent event = b_none;
+bool check_sw1 = false;
+
+void b_worker(void const* argument) {
+ ButtonHandler* b = (ButtonHandler*)argument;
+ osEvent e;
+
+ while (true) {
+ e = Thread::signal_wait(signal, 250);
+ if (e.status == osEventSignal) {
+ switch (event) {
+ case b_sw1_fall:
+ if (! b->_sw1_running) {
+ check_sw1 = true;
+ b->_sw1_running = true;
+ b->_sw1_timer.reset();
+ b->_sw1_timer.start();
+ }
+ break;
+
+ case b_sw1_rise:
+ if (b->_sw1_running) {
+ check_sw1 = false;
+ b->_sw1_running = false;
+ b->_sw1_timer.stop();
+ b->_sw1_time = b->_sw1_timer.read_ms();
+
+ if (b->_sw1_time > b->_debounce_time) {
+ b->_event = ButtonHandler::sw1_press;
+ osSignalSet(b->_main, buttonSignal);
+ }
+ }
+ break;
+
+ case b_sw2_fall:
+ if (! b->_sw2_running) {
+ b->_sw2_running = true;
+ b->_sw2_timer.reset();
+ b->_sw2_timer.start();
+ }
+ break;
+
+ case b_sw2_rise:
+ if (b->_sw2_running) {
+ b->_sw2_running = false;
+ b->_sw2_timer.stop();
+ b->_sw2_time = b->_sw2_timer.read_ms();
+
+ if (b->_sw2_time > b->_debounce_time) {
+ b->_event = ButtonHandler::sw2_press;
+ osSignalSet(b->_main, buttonSignal);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (check_sw1) {
+ if (b->_sw1_timer.read_ms() > b->_hold_threshold) {
+ check_sw1 = false;
+ b->_sw1_running = false;
+ b->_sw1_timer.stop();
+ b->_event = ButtonHandler::sw1_hold;
+ osSignalSet(b->_main, buttonSignal);
+ }
+ }
+ }
+}
+
ButtonHandler::ButtonHandler(osThreadId main)
: _main(main),
+ _thread(b_worker, (void*)this),
_sw1(PA_12),
_sw2(PA_11),
_sw1_time(0),
- _event(none)
+ _sw2_time(0),
+ _event(none),
+ _debounce_time(20),
+ _hold_threshold(500)
{
- // gpio goes low when push button is pressed
- // fall handler will be the press, rise handler will be the release
+ // fall handler called on press, rise handler called on release
_sw1.fall(this, &ButtonHandler::sw1_fall);
_sw1.rise(this, &ButtonHandler::sw1_rise);
// need to set mode to PullUp after attaching handlers - won't work otherwise
_sw1.mode(PullUp);
_sw2.fall(this, &ButtonHandler::sw2_fall);
+ _sw2.rise(this, &ButtonHandler::sw2_rise);
_sw2.mode(PullUp);
}
-ButtonEvent ButtonHandler::getButtonEvent() {
+ButtonHandler::ButtonEvent ButtonHandler::getButtonEvent() {
ButtonEvent event = _event;
_event = none;
return event;
}
-void ButtonHandler::sw1_rise() {
- _sw1_timer.stop();
- _sw1_time = _sw1_timer.read_ms();
-
- if (_sw1_time > 10) {
- _event = (_sw1_time > 500) ? sw1_hold : sw1_press;
- osSignalSet(_main, buttonSignal);
- }
+void ButtonHandler::sw1_fall() {
+ event = b_sw1_fall;
+ _thread.signal_set(signal);
+ _thread.signal_clr(signal);
}
-void ButtonHandler::sw1_fall() {
- _sw1_timer.reset();
- _sw1_timer.start();
+void ButtonHandler::sw1_rise() {
+ event = b_sw1_rise;
+ _thread.signal_set(signal);
+ _thread.signal_clr(signal);
}
void ButtonHandler::sw2_fall() {
- _event = sw2_press;
- osSignalSet(_main, buttonSignal);
+ event = b_sw2_fall;
+ _thread.signal_set(signal);
+ _thread.signal_clr(signal);
}
+
+void ButtonHandler::sw2_rise() {
+ event = b_sw2_rise;
+ _thread.signal_set(signal);
+ _thread.signal_clr(signal);
+}
+
diff --git a/ButtonHandler/ButtonHandler.h b/ButtonHandler/ButtonHandler.h
index 3eb8298..e99c767 100644
--- a/ButtonHandler/ButtonHandler.h
+++ b/ButtonHandler/ButtonHandler.h
@@ -4,33 +4,40 @@
#include "mbed.h"
#include "rtos.h"
-#define buttonSignal (uint32_t)0x01
-
-typedef enum {
- none = 0,
- sw1_press,
- sw1_hold,
- sw2_press
-} ButtonEvent;
+#define buttonSignal (int32_t)0x01
class ButtonHandler {
public:
+ typedef enum {
+ none = 0,
+ sw1_press,
+ sw1_hold,
+ sw2_press
+ } ButtonEvent;
+
ButtonHandler(osThreadId main);
~ButtonHandler();
ButtonEvent getButtonEvent();
- private:
void sw1_fall();
void sw1_rise();
void sw2_fall();
+ void sw2_rise();
osThreadId _main;
+ Thread _thread;
InterruptIn _sw1;
InterruptIn _sw2;
Timer _sw1_timer;
+ Timer _sw2_timer;
time_t _sw1_time;
+ time_t _sw2_time;
+ bool _sw1_running;
+ bool _sw2_running;
ButtonEvent _event;
+ time_t _debounce_time;
+ time_t _hold_threshold;
};
#endif
diff --git a/Layout/Layout.cpp b/Layout/Layout.cpp
index b2ca942..7b0c375 100644
--- a/Layout/Layout.cpp
+++ b/Layout/Layout.cpp
@@ -35,15 +35,22 @@ void Layout::endUpdate() {
_lcd->endUpdate();
}
-bool Layout::writeField(uint8_t col, uint8_t row, std::string field, bool apply) {
- return writeField(col, row, field.c_str(), field.size(), apply);
+bool Layout::writeLabel(const Label& label) {
+ return writeText(label._col, label._row, label._value.c_str(), label._value.size());
}
-bool Layout::writeField(uint8_t col, uint8_t row, const char* field, size_t size, bool apply) {
+bool Layout::writeField(const Field& field, const std::string& value, bool apply) {
+ bool ret;
+ std::string v = value;
+
if (apply)
startUpdate();
- _lcd->writeText(col*6, row, font_6x8, field, size);
+ // fill the whole length with blank space in case the previous value was longer than this one
+ while (v.size() < field._maxSize)
+ v += " ";
+
+ ret = writeText(field._col, field._row, v.c_str(), field._maxSize);
if (apply)
endUpdate();
@@ -51,11 +58,20 @@ bool Layout::writeField(uint8_t col, uint8_t row, const char* field, size_t size
return true;
}
-bool Layout::writeImage(uint8_t col, uint8_t row, const uint8_t* bmp, bool apply) {
+bool Layout::writeField(const Field& field, const char* value, size_t size, bool apply) {
+ bool ret;
+ char buf[32];
+ size_t s = (field._maxSize > size) ? size : field._maxSize;
+
+ // fill the whole length with blank space in case the previous value was longer than this one
+ memset(buf, 0x20, sizeof(buf));
+
if (apply)
startUpdate();
- _lcd->writeBitmap(col, row, bmp);
+ snprintf(buf, s, "%s", value);
+
+ ret = writeText(field._col, field._row, value, field._maxSize);
if (apply)
endUpdate();
@@ -63,3 +79,36 @@ bool Layout::writeImage(uint8_t col, uint8_t row, const uint8_t* bmp, bool apply
return true;
}
+bool Layout::writeImage(const Image& image, bool apply) {
+ bool ret;
+
+ if (apply)
+ startUpdate();
+
+ ret = writeBmp(image._row, image._col, image._bmp);
+
+ if (apply)
+ endUpdate();
+
+ return ret;
+}
+
+void Layout::removeField(const Field& field) {
+ startUpdate();
+ std::string s(' ', field._maxSize);
+ writeText(field._row, field._col, s.c_str(), s.size());
+ endUpdate();
+}
+
+bool Layout::writeText(uint8_t col, uint8_t row, const char* value, size_t size) {
+ _lcd->writeText(col*6, row, font_6x8, value, size);
+
+ return true;
+}
+
+bool Layout::writeBmp(uint8_t col, uint8_t row, const uint8_t* bmp) {
+ _lcd->writeBitmap(col*6, row, bmp);
+
+ return true;
+}
+
diff --git a/Layout/Layout.h b/Layout/Layout.h
index 5b25458..29d59ff 100644
--- a/Layout/Layout.h
+++ b/Layout/Layout.h
@@ -42,11 +42,16 @@ class Layout {
void clear();
void startUpdate();
void endUpdate();
- bool writeField(uint8_t col, uint8_t row, std::string field, bool apply = false);
- bool writeField(uint8_t col, uint8_t row, const char* field, size_t size, bool apply = false);
- bool writeImage(uint8_t col, uint8_t row, const uint8_t* bmp, bool apply = false);
+ bool writeLabel(const Label& label);
+ bool writeField(const Field& field, const std::string& value, bool apply = false);
+ bool writeField(const Field& field, const char* value, size_t size, bool apply = false);
+ bool writeImage(const Image& image, bool apply = false);
+ void removeField(const Field& field);
private:
+ bool writeText(uint8_t col, uint8_t row, const char* value, size_t size);
+ bool writeBmp(uint8_t col, uint8_t row, const uint8_t* bmp);
+
DOGS102* _lcd;
};
diff --git a/Layout/LayoutConfig.cpp b/Layout/LayoutConfig.cpp
new file mode 100644
index 0000000..dc28738
--- /dev/null
+++ b/Layout/LayoutConfig.cpp
@@ -0,0 +1,23 @@
+#include "LayoutConfig.h"
+
+LayoutConfig::LayoutConfig(DOGS102* lcd)
+ : Layout(lcd),
+ _lMode(0, 0, "Configuration"),
+ _lHelp1(0, 2, "Connect USB debug"),
+ _lHelp2(0, 3, "to PC at 115200"),
+ _lHelp3(0, 4, "baud to configure")
+{}
+
+LayoutConfig::~LayoutConfig() {}
+
+void LayoutConfig::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lMode);
+ writeLabel(_lHelp1);
+ writeLabel(_lHelp2);
+ writeLabel(_lHelp3);
+
+ endUpdate();
+}
diff --git a/Layout/LayoutConfig.h b/Layout/LayoutConfig.h
new file mode 100644
index 0000000..0fdba1c
--- /dev/null
+++ b/Layout/LayoutConfig.h
@@ -0,0 +1,20 @@
+#ifndef __LAYOUTCONFIG_H__
+#define __LAYOUTCONFIG_H__
+
+#include "Layout.h"
+
+class LayoutConfig : public Layout {
+ public:
+ LayoutConfig(DOGS102* lcd);
+ ~LayoutConfig();
+
+ void display();
+
+ private:
+ Label _lMode;
+ Label _lHelp1;
+ Label _lHelp2;
+ Label _lHelp3;
+};
+
+#endif
diff --git a/Layout/LayoutDemoHelp.cpp b/Layout/LayoutDemoHelp.cpp
new file mode 100644
index 0000000..dab907e
--- /dev/null
+++ b/Layout/LayoutDemoHelp.cpp
@@ -0,0 +1,28 @@
+#include "LayoutDemoHelp.h"
+
+LayoutDemoHelp::LayoutDemoHelp(DOGS102* lcd)
+ : Layout(lcd),
+ _lMode(0, 0, "LoRa Demo"),
+ _lDesc(0, 1, "Select TX Method"),
+ _lIns1(0, 4, "Hold SW1 any time"),
+ _lIns2(0, 5, "for Main Menu"),
+ _lSw1(10, 7, "Trigger"),
+ _lSw2(0, 7, "Interval")
+{}
+
+LayoutDemoHelp::~LayoutDemoHelp() {}
+
+void LayoutDemoHelp::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lMode);
+ writeLabel(_lDesc);
+ writeLabel(_lIns1);
+ writeLabel(_lIns2);
+ writeLabel(_lSw1);
+ writeLabel(_lSw2);
+
+ endUpdate();
+}
+
diff --git a/Layout/LayoutDemoHelp.h b/Layout/LayoutDemoHelp.h
new file mode 100644
index 0000000..3e20df9
--- /dev/null
+++ b/Layout/LayoutDemoHelp.h
@@ -0,0 +1,22 @@
+#ifndef __LAYOUTDEMOHELP_H__
+#define __LAYOUTDEMOHELP_H__
+
+#include "Layout.h"
+
+class LayoutDemoHelp : public Layout {
+ public:
+ LayoutDemoHelp(DOGS102* lcd);
+ ~LayoutDemoHelp();
+
+ void display();
+
+ private:
+ Label _lMode;
+ Label _lDesc;
+ Label _lIns1;
+ Label _lIns2;
+ Label _lSw1;
+ Label _lSw2;
+};
+
+#endif
diff --git a/Layout/LayoutJoin.cpp b/Layout/LayoutJoin.cpp
new file mode 100644
index 0000000..3b67c28
--- /dev/null
+++ b/Layout/LayoutJoin.cpp
@@ -0,0 +1,104 @@
+#include "LayoutJoin.h"
+
+LayoutJoin::LayoutJoin(DOGS102* lcd, uint8_t band)
+ : Layout(lcd),
+ _lId(0, 1, "NI="),
+ _lKey(0, 2, "NK="),
+ _lFsb(0, 3, "FSB="),
+ _lRate(0, 5, "DR="),
+ _lPower(6, 5, "P="),
+ _lAttempt(11, 5, "A="),
+ _fStatus(0, 0, 17),
+ _fId(3, 1, 14),
+ _fKey(3, 2, 14),
+ _fFsb(4, 3, 2),
+ _fRate(3, 5, 2),
+ _fPower(8, 5, 2),
+ _fAttempt(13, 5, 4),
+ _fCountdown(0, 7, 9),
+ _fCountdownLabel(0, 6, 17),
+ _fCancel(11, 7, 6),
+ _band(band)
+{}
+
+LayoutJoin::~LayoutJoin() {}
+
+void LayoutJoin::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lId);
+ writeLabel(_lKey);
+ if (_band == mDot::FB_915) {
+ writeLabel(_lFsb);
+ }
+ writeLabel(_lRate);
+ writeLabel(_lPower);
+ writeLabel(_lAttempt);
+
+ displayCancel();
+
+ endUpdate();
+}
+
+void LayoutJoin::updateId(std::string id) {
+ writeField(_fId, id, true);
+}
+
+void LayoutJoin::updateKey(std::string key) {
+ writeField(_fKey, key, true);
+}
+
+void LayoutJoin::updateFsb(uint8_t band) {
+ char buf[8];
+ size_t size;
+
+ size = snprintf(buf, sizeof(buf), "%u", band);
+ writeField(_fFsb, buf, size, true);
+}
+
+void LayoutJoin::updateRate(std::string rate) {
+ writeField(_fRate, rate);
+}
+
+void LayoutJoin::updatePower(uint32_t power) {
+ char buf[16];
+ size_t size;
+
+ size = snprintf(buf, sizeof(buf), "%lu", power);
+ writeField(_fPower, buf, size, true);
+}
+
+void LayoutJoin::updateAttempt(uint32_t attempt) {
+ char buf[16];
+ size_t size;
+
+ size = snprintf(buf, sizeof(buf), "%lu", attempt);
+ writeField(_fAttempt, buf, size, true);
+}
+
+void LayoutJoin::updateStatus(std::string status) {
+ writeField(_fStatus, status, true);
+}
+
+void LayoutJoin::updateCountdown(uint32_t seconds) {
+ char buf[16];
+ size_t size;
+
+ writeField(_fCountdownLabel, "No Free Channel");
+ size = snprintf(buf, sizeof(buf), "%lu", seconds);
+ writeField(_fPower, buf, size, true);
+}
+
+void LayoutJoin::removeCountdown() {
+ removeField(_fCountdownLabel);
+ removeField(_fCountdown);
+}
+
+void LayoutJoin::displayCancel(bool display) {
+ if (display)
+ writeField(_fCancel, "Cancel", true);
+ else
+ removeField(_fCancel);
+}
+
diff --git a/Layout/LayoutJoin.h b/Layout/LayoutJoin.h
new file mode 100644
index 0000000..2f71aec
--- /dev/null
+++ b/Layout/LayoutJoin.h
@@ -0,0 +1,46 @@
+#ifndef __LAYOUTJOIN_H__
+#define __LAYOUTJOIN_H__
+
+#include "Layout.h"
+#include "mDot.h"
+
+class LayoutJoin : public Layout {
+ public:
+ LayoutJoin(DOGS102* lcd, uint8_t band);
+ ~LayoutJoin();
+
+ void display();
+
+ void updateId(std::string id);
+ void updateKey(std::string key);
+ void updateFsb(uint8_t band);
+ void updateRate(std::string rate);
+ void updatePower(uint32_t power);
+ void updateAttempt(uint32_t attempt);
+ void updateStatus(std::string status);
+ void updateCountdown(uint32_t seconds);
+ void removeCountdown();
+ void displayCancel(bool display = true);
+
+ private:
+ Label _lId;
+ Label _lKey;
+ Label _lFsb;
+ Label _lRate;
+ Label _lPower;
+ Label _lAttempt;
+
+ Field _fStatus;
+ Field _fId;
+ Field _fKey;
+ Field _fFsb;
+ Field _fRate;
+ Field _fPower;
+ Field _fAttempt;
+ Field _fCountdown;
+ Field _fCountdownLabel;
+ Field _fCancel;
+ uint8_t _band;
+};
+
+#endif
diff --git a/Layout/LayoutScrollSelect.cpp b/Layout/LayoutScrollSelect.cpp
new file mode 100644
index 0000000..5c7072e
--- /dev/null
+++ b/Layout/LayoutScrollSelect.cpp
@@ -0,0 +1,244 @@
+#include "LayoutScrollSelect.h"
+#include "MTSLog.h"
+
+LayoutScrollSelect::LayoutScrollSelect(DOGS102* lcd, Items items, std::string info1, std::string info2)
+ : Layout(lcd),
+ _lSw1(0, 7, "Scroll"),
+ _lSw2(11, 7, "Select"),
+ _lInfo1(0, 0, info1),
+ _lInfo2(0, 1, info2),
+ _lCursor(0, 4, "=>"),
+ _fItem1(3, 2, 14),
+ _fItem2(3, 3, 14),
+ _fItem3(3, 4, 14),
+ _fItem4(3, 5, 14),
+ _fItem5(3, 6, 14),
+ _items(items)
+{
+ _size = _items.size();
+ _selected = 0;
+}
+
+LayoutScrollSelect::~LayoutScrollSelect() {}
+
+void LayoutScrollSelect::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lSw1);
+ writeLabel(_lSw2);
+ writeLabel(_lInfo1);
+ writeLabel(_lInfo2);
+ writeLabel(_lCursor);
+
+ switch (_size) {
+ case 0:
+ // special case - no items
+ // (empty)
+ // (empty)
+ // => (empty)
+ // (empty)
+ // (empty)
+ break;
+
+ case 1:
+ // special case - 1 item
+ // (empty)
+ // (empty)
+ // => item1
+ // (empty)
+ // (empty)
+ writeField(_fItem3, _items[0]);
+ break;
+
+ case 2:
+ // special case - 2 items
+ // (empty)
+ // (empty)
+ // => item1
+ // item2
+ // (empty)
+ writeField(_fItem3, _items[0]);
+ writeField(_fItem4, _items[1]);
+ break;
+
+ case 3:
+ // special case - 3 items
+ // (empty)
+ // item3
+ // => item1
+ // item2
+ // (empty)
+ writeField(_fItem2, _items[2]);
+ writeField(_fItem3, _items[0]);
+ writeField(_fItem4, _items[1]);
+ break;
+
+ case 4:
+ // special case - 4 items
+ // item3
+ // item4
+ // => item1
+ // item2
+ // (empty)
+ writeField(_fItem1, _items[2]);
+ writeField(_fItem2, _items[3]);
+ writeField(_fItem3, _items[0]);
+ writeField(_fItem4, _items[1]);
+ break;
+
+ default:
+ // this is the generic case - should handle lists of 5+ items correctly
+ // item4 item6 item9
+ // item5 item7 item10
+ // => item1 => item1 => item1
+ // item2 item2 item2
+ // item3 item3 item3
+ writeField(_fItem1, _items[_size - 2]);
+ writeField(_fItem2, _items[_size - 1]);
+ writeField(_fItem3, _items[0]);
+ writeField(_fItem4, _items[1]);
+ writeField(_fItem5, _items[2]);
+ break;
+ }
+
+ endUpdate();
+}
+
+void LayoutScrollSelect::scroll() {
+ size_t index;
+
+ switch (_size) {
+ case 0:
+ case 1:
+ // nothing to scroll
+ break;
+
+ case 2:
+ // special case - 2 items
+ // (empty) -> (empty)
+ // (empty) -> (empty)
+ // => item1 -> => item2
+ // item2 -> item1
+ // (empty) -> (empty)
+
+ index = _selected;
+ // keep selected item up to date
+ increment(_selected);
+
+ startUpdate();
+ // previously selected item moves down to field4
+ writeField(_fItem4, _items[index]);
+ increment(index);
+ // other item moves up to field3
+ writeField(_fItem3, _items[index]);
+ endUpdate();
+ break;
+
+ case 3:
+ // special case - 3 items
+ // (empty) -> (empty)
+ // item3 -> item1
+ // => item1 -> => item2
+ // item2 -> item3
+ // (empty) -> (empty)
+
+ index = _selected;
+ // keep selected item up to date
+ increment(_selected);
+
+ startUpdate();
+ // previously selected item moves up to field2
+ writeField(_fItem2, _items[index]);
+ increment(index);
+ // new selected item moves up to field3
+ writeField(_fItem3, _items[index]);
+ increment(index);
+ // item from field2 moves down to field4
+ writeField(_fItem4, _items[index]);
+ endUpdate();
+ break;
+
+ case 4:
+ // special case - 4 items
+ // item3 -> item4
+ // item4 -> item1
+ // => item1 -> => item2
+ // item2 -> item3
+ // (empty) -> (empty)
+
+ index = _selected;
+ // keep selected item up to date
+ increment(_selected);
+
+ startUpdate();
+ // previously selected item moves up to field2
+ writeField(_fItem2, _items[index]);
+ increment(index);
+ // new selected item moves up to field3
+ writeField(_fItem3, _items[index]);
+ increment(index);
+ // item from field1 moves down to field4
+ writeField(_fItem4, _items[index]);
+ increment(index);
+ // item from field2 moves up to field1
+ writeField(_fItem1, _items[index]);
+ endUpdate();
+ break;
+
+ default:
+ // this is the generic case - should handle lists of 5+ items correctly
+ // item4 -> item5 item6 -> item7
+ // item5 -> item1 item7 -> item1
+ // => item1 -> => item2 => item1 -> => item2
+ // item2 -> item3 item2 -> item3
+ // item3 -> item4 item3 -> item4
+
+ index = _selected;
+ // keep selected item up to date
+ increment(_selected);
+
+ startUpdate();
+ decrement(index);
+ // item from field2 moves up to field1
+ writeField(_fItem1, _items[index]);
+ increment(index);
+ // previously selected item moves up to field2
+ writeField(_fItem2, _items[index]);
+ increment(index);
+ // new selected item moves up to field3
+ writeField(_fItem3, _items[index]);
+ increment(index);
+ // item from field5 moves up to field4
+ writeField(_fItem4, _items[index]);
+ increment(index);
+ // next item (from field1 or off screen) moves up to field5
+ writeField(_fItem5, _items[index]);
+ endUpdate();
+ break;
+ }
+}
+
+std::string LayoutScrollSelect::select() {
+ std::string selected = "";
+ if (_size > 0)
+ selected = _items[_selected];
+
+ return selected;
+}
+
+void LayoutScrollSelect::increment(size_t& index) {
+ if (_size > 1) {
+ index++;
+ index %= _size;
+ }
+}
+
+void LayoutScrollSelect::decrement(size_t& index) {
+ if (_size > 1) {
+ if (index == 0)
+ index = _size - 1;
+ else
+ index--;
+ }
+}
diff --git a/Layout/LayoutScrollSelect.h b/Layout/LayoutScrollSelect.h
new file mode 100644
index 0000000..4811ae5
--- /dev/null
+++ b/Layout/LayoutScrollSelect.h
@@ -0,0 +1,40 @@
+#ifndef __LAYOUTSCROLLSELECT_H__
+#define __LAYOUTSCROLLSELECT_H__
+
+#include "Layout.h"
+#include <vector>
+
+typedef std::vector<std::string> Items;
+
+class LayoutScrollSelect : public Layout {
+ public:
+ LayoutScrollSelect(DOGS102* lcd, Items items, std::string info1 = "", std::string info2 = "");
+ ~LayoutScrollSelect();
+
+ void display();
+
+ void scroll();
+ std::string select();
+
+ private:
+ void increment(size_t& index);
+ void decrement(size_t& index);
+
+ Label _lSw1;
+ Label _lSw2;
+ Label _lInfo1;
+ Label _lInfo2;
+ Label _lCursor;
+
+ Field _fItem1;
+ Field _fItem2;
+ Field _fItem3;
+ Field _fItem4;
+ Field _fItem5;
+
+ Items _items;
+ size_t _selected;
+ size_t _size;
+};
+
+#endif
diff --git a/Layout/LayoutSingleHelp.cpp b/Layout/LayoutSingleHelp.cpp
new file mode 100644
index 0000000..82c4270
--- /dev/null
+++ b/Layout/LayoutSingleHelp.cpp
@@ -0,0 +1,26 @@
+#include "LayoutSingleHelp.h"
+
+LayoutSingleHelp::LayoutSingleHelp(DOGS102* lcd)
+ : Layout(lcd),
+ _lMode(0, 0, "Survey Single"),
+ _lIns1(0, 4, "Hold SW1 any time"),
+ _lIns2(0, 5, "for Main Menu"),
+ _lSw1(11, 7, "DR/PWR"),
+ _lSw2(0, 7, "Survey")
+{}
+
+LayoutSingleHelp::~LayoutSingleHelp() {}
+
+void LayoutSingleHelp::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lMode);
+ writeLabel(_lIns1);
+ writeLabel(_lIns2);
+ writeLabel(_lSw1);
+ writeLabel(_lSw2);
+
+ endUpdate();
+}
+
diff --git a/Layout/LayoutSingleHelp.h b/Layout/LayoutSingleHelp.h
new file mode 100644
index 0000000..421bc1c
--- /dev/null
+++ b/Layout/LayoutSingleHelp.h
@@ -0,0 +1,21 @@
+#ifndef __LAYOUTSINGLEHELP_H__
+#define __LAYOUTSINGLEHELP_H__
+
+#include "Layout.h"
+
+class LayoutSingleHelp : public Layout {
+ public:
+ LayoutSingleHelp(DOGS102* lcd);
+ ~LayoutSingleHelp();
+
+ void display();
+
+ private:
+ Label _lMode;
+ Label _lIns1;
+ Label _lIns2;
+ Label _lSw1;
+ Label _lSw2;
+};
+
+#endif
diff --git a/Layout/LayoutStartup.cpp b/Layout/LayoutStartup.cpp
index c005b2f..850ea50 100644
--- a/Layout/LayoutStartup.cpp
+++ b/Layout/LayoutStartup.cpp
@@ -11,15 +11,19 @@ LayoutStartup::LayoutStartup(DOGS102* lcd)
_iLogo(0, 0, MultiTech_Logo)
{}
+LayoutStartup::~LayoutStartup() {}
+
void LayoutStartup::display() {
+ std::string version = MTDOT_BOX_VERSION;
+
clear();
startUpdate();
- writeImage(_iLogo._col, _iLogo._row, _iLogo._bmp);
- writeField(_lName._col, _lName._row, _lName._value);
- writeField(_lInfo._col, _lInfo._row, _lInfo._value);
- writeField(_lVersion._col, _lVersion._row, _lVersion._value);
- writeField(_fVersion._col, _fVersion._row, MTDOT_BOX_VERSION, sizeof(MTDOT_BOX_VERSION));
+ writeImage(_iLogo);
+ writeLabel(_lName);
+ writeLabel(_lInfo);
+ writeLabel(_lVersion);
+ writeField(_fVersion, version);
endUpdate();
}
diff --git a/Layout/LayoutSweepHelp.cpp b/Layout/LayoutSweepHelp.cpp
new file mode 100644
index 0000000..eb40013
--- /dev/null
+++ b/Layout/LayoutSweepHelp.cpp
@@ -0,0 +1,26 @@
+#include "LayoutSweepHelp.h"
+
+LayoutSweepHelp::LayoutSweepHelp(DOGS102* lcd)
+ : Layout(lcd),
+ _lMode(0, 0, "Survey Sweep"),
+ _lIns1(0, 4, "Hold SW1 any time"),
+ _lIns2(0, 5, "for Main Menu"),
+ _lSw1(11, 7, "Cancel"),
+ _lSw2(0, 7, "Sweep")
+{}
+
+LayoutSweepHelp::~LayoutSweepHelp() {}
+
+void LayoutSweepHelp::display() {
+ clear();
+ startUpdate();
+
+ writeLabel(_lMode);
+ writeLabel(_lIns1);
+ writeLabel(_lIns2);
+ writeLabel(_lSw1);
+ writeLabel(_lSw2);
+
+ endUpdate();
+}
+
diff --git a/Layout/LayoutSweepHelp.h b/Layout/LayoutSweepHelp.h
new file mode 100644
index 0000000..0ec0e45
--- /dev/null
+++ b/Layout/LayoutSweepHelp.h
@@ -0,0 +1,21 @@
+#ifndef __LAYOUTSWEEPHELP_H__
+#define __LAYOUTSWEEPHELP_H__
+
+#include "Layout.h"
+
+class LayoutSweepHelp : public Layout {
+ public:
+ LayoutSweepHelp(DOGS102* lcd);
+ ~LayoutSweepHelp();
+
+ void display();
+
+ private:
+ Label _lMode;
+ Label _lIns1;
+ Label _lIns2;
+ Label _lSw1;
+ Label _lSw2;
+};
+
+#endif
diff --git a/LoRaHandler/LoRaHandler.cpp b/LoRaHandler/LoRaHandler.cpp
new file mode 100644
index 0000000..27eb266
--- /dev/null
+++ b/LoRaHandler/LoRaHandler.cpp
@@ -0,0 +1,160 @@
+#include "LoRaHandler.h"
+
+#define signal (int32_t)0xA0
+
+typedef enum {
+ l_none = 0,
+ l_ping,
+ l_send,
+ l_join
+} InternalLoRa;
+
+uint8_t cmd = l_none;
+std::vector<uint8_t> send_data;
+
+void l_worker(void const* argument) {
+ LoRaHandler* l = (LoRaHandler*)argument;
+ osEvent e;
+
+ l->_dot = mDot::getInstance();
+ int32_t ret;
+ mDot::ping_response pr;
+ mDot::rssi_stats rs;
+ mDot::snr_stats ss;
+
+ while (true) {
+ e = Thread::signal_wait(signal);
+ if (e.status == osEventSignal) {
+ l->_status = LoRaHandler::busy;
+ switch (cmd) {
+ case l_ping:
+ l->_mutex.lock();
+ pr = l->_dot->ping();
+ l->_mutex.unlock();
+ if (pr.status == mDot::MDOT_OK) {
+ l->_ping.up = pr;
+ l->_mutex.lock();
+ rs = l->_dot->getRssiStats();
+ ss = l->_dot->getSnrStats();
+ l->_mutex.unlock();
+ l->_ping.down.rssi = rs.last;
+ l->_ping.down.snr = ss.last;
+ l->_status = LoRaHandler::ping_success;
+ } else {
+ l->_status = LoRaHandler::ping_failure;
+ }
+ osSignalSet(l->_main, loraSignal);
+ break;
+
+ case l_send:
+ l->_mutex.lock();
+ ret = l->_dot->send(send_data);
+ l->_mutex.unlock();
+ if (ret == mDot::MDOT_OK)
+ l->_status = LoRaHandler::send_success;
+ else
+ l->_status = LoRaHandler::send_failure;
+ osSignalSet(l->_main, loraSignal);
+ break;
+
+ case l_join:
+ l->_mutex.lock();
+ ret = l->_dot->joinNetworkOnce();
+ l->_mutex.unlock();
+ if (ret == mDot::MDOT_OK) {
+ l->_status = LoRaHandler::join_success;
+ } else {
+ l->_status = LoRaHandler::join_failure;
+ }
+ osSignalSet(l->_main, loraSignal);
+ break;
+
+ default:
+ l->_status = LoRaHandler::none;
+ break;
+ }
+ }
+ }
+}
+
+LoRaHandler::LoRaHandler(osThreadId main)
+ : _main(main),
+ _thread(l_worker, (void*)this),
+ _status(none)
+{
+ _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;
+}
+
+bool LoRaHandler::ping() {
+ return action(l_ping);
+}
+
+bool LoRaHandler::send(std::vector<uint8_t> data) {
+ send_data = data;
+ return action(l_send);
+}
+
+bool LoRaHandler::join() {
+ return action(l_join);
+}
+
+bool LoRaHandler::action(uint8_t c) {
+ if (_status != busy) {
+ cmd = c;
+ _thread.signal_set(signal);
+ _thread.signal_clr(signal);
+ return true;
+ }
+
+ return false;
+}
+
+LoRaHandler::LoRaStatus LoRaHandler::getStatus() {
+ LoRaStatus status;
+ _mutex.lock();
+ status = _status;
+ _mutex.unlock();
+
+ return status;
+}
+
+LoRaHandler::LoRaPing LoRaHandler::getPingResults() {
+ LoRaPing ping;
+ _mutex.lock();
+ ping = _ping;
+ _mutex.unlock();
+
+ return ping;
+}
+
+uint32_t LoRaHandler::getNextTx() {
+ uint32_t ms;
+ _mutex.lock();
+ ms = _dot->getNextTxMs();
+ _mutex.unlock();
+
+ return ms;
+}
+
diff --git a/LoRaHandler/LoRaHandler.h b/LoRaHandler/LoRaHandler.h
new file mode 100644
index 0000000..20f9d6f
--- /dev/null
+++ b/LoRaHandler/LoRaHandler.h
@@ -0,0 +1,50 @@
+#ifndef __LORAHANDLER_H__
+#define __LORAHANDLER_H__
+
+#include "mDot.h"
+
+#define loraSignal (int32_t)0x02
+
+class LoRaHandler {
+ public:
+ typedef enum {
+ none = 0,
+ busy,
+ ping_success,
+ send_success,
+ join_success,
+ ping_failure,
+ send_failure,
+ join_failure
+ } LoRaStatus;
+
+ typedef struct {
+ bool status;
+ mDot::ping_response up;
+ mDot::ping_response down;
+ } LoRaPing;
+
+ 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();
+
+
+ osThreadId _main;
+ Thread _thread;
+ LoRaStatus _status;
+ LoRaPing _ping;
+ mDot* _dot;
+ Mutex _mutex;
+};
+
+#endif
+
diff --git a/Mode/Mode.cpp b/Mode/Mode.cpp
new file mode 100644
index 0000000..eea6d3c
--- /dev/null
+++ b/Mode/Mode.cpp
@@ -0,0 +1,19 @@
+#include "Mode.h"
+
+Mode::Mode(DOGS102* lcd, ButtonHandler* buttons)
+ : _lcd(lcd),
+ _buttons(buttons),
+ _index(0),
+ _main_id(Thread::gettid())
+{}
+
+Mode::~Mode() {}
+
+bool Mode::deleteDataFile() {
+ return true;
+}
+
+bool Mode::appendDataFile(const DataItem& data) {
+ return true;
+}
+
diff --git a/Mode/Mode.h b/Mode/Mode.h
new file mode 100644
index 0000000..1254a9e
--- /dev/null
+++ b/Mode/Mode.h
@@ -0,0 +1,47 @@
+#ifndef __MODE_H__
+#define __MODE_H__
+
+#include "DOGS102.h"
+#include "ButtonHandler.h"
+#include "GPSPARSER.h"
+
+class Mode {
+ public:
+ typedef enum {
+ single = 0,
+ sweep
+ } DataType;
+
+ typedef struct {
+ DataType type;
+ int32_t index;
+ bool status;
+ int32_t lock;
+ GPSPARSER::longitude gps_longitude;
+ GPSPARSER::latitude gps_latitude;
+ int16_t gps_altitude;
+ struct tm gps_time;
+ int16_t rssi_up;
+ int16_t snr_up;
+ int16_t rssi_down;
+ int16_t snr_down;
+ uint8_t data_rate;
+ uint8_t power;
+ } DataItem;
+
+ Mode(DOGS102* lcd, ButtonHandler* buttons);
+ ~Mode();
+
+ virtual bool start() = 0;
+
+ protected:
+ bool deleteDataFile();
+ bool appendDataFile(const DataItem& data);
+
+ DOGS102* _lcd;
+ ButtonHandler* _buttons;
+ uint32_t _index;
+ osThreadId _main_id;
+};
+
+#endif
diff --git a/Mode/ModeJoin.cpp b/Mode/ModeJoin.cpp
new file mode 100644
index 0000000..f1f0e9a
--- /dev/null
+++ b/Mode/ModeJoin.cpp
@@ -0,0 +1,86 @@
+#include "ModeJoin.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+
+ModeJoin::ModeJoin(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, uint8_t band)
+ : Mode(lcd, buttons),
+ _lj(lcd, band),
+ _dot(dot),
+ _lora(lora),
+ _band(band),
+ _data_rate(band == mDot::FB_915 ? mDot::SF_10 : mDot::SF_12),
+ _power(20),
+ _next_tx(0),
+ _joined(false)
+{}
+
+ModeJoin::~ModeJoin() {}
+
+bool ModeJoin::start() {
+ // clear any stale signals
+ osSignalClear(_main_id, buttonSignal | loraSignal);
+
+ _lj.display();
+ _lj.updateStatus("Joining...");
+ if (_dot->getJoinMode() == mDot::MANUAL) {
+ _lj.updateId(mts::Text::bin2hexString(_dot->getNetworkId()));
+ _lj.updateKey(mts::Text::bin2hexString(_dot->getNetworkKey()));
+ } else {
+ _lj.updateId(_dot->getNetworkName());
+ _lj.updateKey(_dot->getNetworkPassphrase());
+ }
+ if (_band == mDot::FB_915) {
+ _sub_band = _dot->getFrequencySubBand();
+ _lj.updateFsb(_sub_band);
+ }
+ // mDot::DataRateStr returns format SF_XX - we only want to display the XX part
+ _lj.updateRate(_dot->DataRateStr(_data_rate).substr(3));
+ _lj.updatePower(_power);
+
+ _lora->setDataRate(_data_rate);
+ _lora->setPower(_power);
+
+ while (! _joined) {
+ _next_tx = _lora->getNextTx();
+ if (_next_tx) {
+ _lj.updateCountdown(_next_tx * 1000);
+ } else {
+ _lj.updateAttempt(++_index);
+ _lj.updateStatus("Joining...");
+ _lora->join();
+ }
+
+ osEvent e = Thread::signal_wait(0);
+ if (e.status == osEventSignal) {
+ if (e.value.signals & buttonSignal) {
+ _be = _buttons->getButtonEvent();
+ switch (_be) {
+ case ButtonHandler::sw1_press:
+ return false;
+ case ButtonHandler::sw2_press:
+ break;
+ case ButtonHandler::sw1_hold:
+ return false;
+ }
+ }
+ if (e.value.signals & loraSignal) {
+ _ls = _lora->getStatus();
+ switch (_ls) {
+ case LoRaHandler::join_success:
+ _lj.updateStatus("Join Success!");
+ _lj.displayCancel(false);
+ logInfo("joined");
+ _joined = true;
+ osDelay(2000);
+ return true;
+
+ case LoRaHandler::join_failure:
+ logInfo("failed to join");
+ break;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/Mode/ModeJoin.h b/Mode/ModeJoin.h
new file mode 100644
index 0000000..5b88e25
--- /dev/null
+++ b/Mode/ModeJoin.h
@@ -0,0 +1,30 @@
+#ifndef __MODEJOIN_H__
+#define __MODEJOIN_H__
+
+#include "Mode.h"
+#include "LayoutJoin.h"
+#include "mDot.h"
+#include "LoRaHandler.h"
+
+class ModeJoin : public Mode {
+ public:
+ ModeJoin(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, uint8_t band);
+ ~ModeJoin();
+
+ bool start();
+
+ private:
+ LayoutJoin _lj;
+ mDot* _dot;
+ LoRaHandler* _lora;
+ uint8_t _band;
+ uint8_t _sub_band;
+ uint8_t _data_rate;
+ uint8_t _power;
+ uint32_t _next_tx;
+ bool _joined;
+ ButtonHandler::ButtonEvent _be;
+ LoRaHandler::LoRaStatus _ls;
+};
+
+#endif
diff --git a/main.cpp b/main.cpp
index f5f00c5..5b9cbde 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,7 +4,7 @@
// MTS headers
#include "mDot.h"
#include "MTSLog.h"
-#include "CommandTerminal.h"
+#include "MTSText.h"
// sensor headers
#include "ISL29011.h"
#include "MMA845x.h"
@@ -14,14 +14,20 @@
#include "DOGS102.h"
#include "NCP5623B.h"
#include "LayoutStartup.h"
+#include "LayoutScrollSelect.h"
+#include "LayoutConfig.h"
+#include "LayoutDemoHelp.h"
+#include "LayoutSingleHelp.h"
+#include "LayoutSweepHelp.h"
// button header
#include "ButtonHandler.h"
+// LoRa header
+#include "LoRaHandler.h"
+// mode objects
+#include "ModeJoin.h"
// misc heders
#include <string>
-// only here for button handling example code in main
-#include "font_6x8.h"
-
// LCD and backlight controllers
SPI lcd_spi(SPI1_MOSI, SPI1_MISO, SPI1_SCK);
I2C backlight_i2c(I2C_SDA, I2C_SCL);
@@ -30,29 +36,93 @@ DigitalOut lcd_cd(XBEE_ON_SLEEP, 1);
DOGS102* lcd;
NCP5623B* lcd_backlight;
+// Thread informaiton
+osThreadId main_id;
+
// Button controller
ButtonHandler* buttons;
+// LoRa controller
+LoRaHandler* lora;
+mDot* dot;
+
+// Modes
+ModeJoin* modeJoin;
+
// Serial debug port
Serial debug(USBTX, USBRX);
mts::MTSSerial serial(USBTX, USBRX, 512, 512);
+// Prototypes
+void mainMenu();
+void join();
+void configuration();
+void loraDemo();
+void surveySingle();
+void surveySweep();
+
int main() {
debug.baud(115200);
- MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
lcd = new DOGS102(lcd_spi, lcd_spi_cs, lcd_cd);
lcd_backlight = new NCP5623B(backlight_i2c);
+ main_id = Thread::gettid();
+ buttons = new ButtonHandler(main_id);
+ dot = mDot::getInstance();
+ lora = new LoRaHandler(main_id);
+
+ modeJoin = new ModeJoin(lcd, buttons, dot, lora, dot->getFrequencyBand());
+
// display startup screen for 3 seconds
LayoutStartup ls(lcd);
ls.display();
osDelay(3000);
- osThreadId main_id = Thread::gettid();
- buttons = new ButtonHandler(main_id);
+ // start of temporary stuff!
+ if (dot->getFrequencyBand() == mDot::FB_915)
+ dot->setFrequencySubBand(mDot::FSB_7);
+ dot->setJoinMode(mDot::OTA);
+ dot->setNetworkName("mikes_lora_network");
+ dot->setNetworkPassphrase("password_123");
+ dot->setAck(1);
+ // end of temporary stuff!
+
+ //MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
+ MTSLog::setLogLevel(MTSLog::INFO_LEVEL);
+ logInfo("displaying main menu");
+ mainMenu();
+
+ return 0;
+}
+
+void mainMenu() {
+ bool mode_selected = false;
+ std::string selected;
+
+ typedef enum {
+ demo = 2,
+ config,
+ single,
+ sweep
+ } menu_items;
+
+ std::string menu_strings[] = {
+ "MultiTech EVB",
+ "Select Mode",
+ "LoRa Demo",
+ "Configuration",
+ "Survey Single",
+ "Survey Sweep"
+ };
+
+ std::vector<std::string> items;
+ items.push_back(menu_strings[demo]);
+ items.push_back(menu_strings[config]);
+ items.push_back(menu_strings[single]);
+ items.push_back(menu_strings[sweep]);
@@ -69,33 +139,157 @@ int main() {
while (true) {
- char buf[16];
- size_t size;
+ LayoutScrollSelect menu(lcd, items, menu_strings[0], menu_strings[1]);
+ menu.display();
+
+ while (! mode_selected) {
+ osEvent e = Thread::signal_wait(buttonSignal);
+ if (e.status == osEventSignal) {
+ ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
+ switch (ev) {
+ case ButtonHandler::sw1_press:
+ selected = menu.select();
+ mode_selected = true;
+ break;
+ case ButtonHandler::sw2_press:
+ menu.scroll();
+ break;
+ case ButtonHandler::sw1_hold:
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (selected == menu_strings[demo]) {
+ if (modeJoin->start())
+ loraDemo();
+ } else if (selected == menu_strings[config]) {
+ configuration();
+ } else if (selected == menu_strings[single]) {
+ if (modeJoin->start())
+ surveySingle();
+ } else if (selected == menu_strings[sweep]) {
+ if (modeJoin->start())
+ surveySweep();
+ }
+
+ mode_selected = false;
+ }
+}
+
+void configuration() {
+ LayoutConfig lc(lcd);
+
+ // clear any stale signals
+ osSignalClear(main_id, buttonSignal | loraSignal);
+
+ lc.display();
+ logInfo("config mode");
+
+ while (true) {
+ osEvent e = Thread::signal_wait(buttonSignal);
+ if (e.status == osEventSignal) {
+ ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
+ switch (ev) {
+ case ButtonHandler::sw1_press:
+ break;
+ case ButtonHandler::sw2_press:
+ break;
+ case ButtonHandler::sw1_hold:
+ return;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void loraDemo() {
+ LayoutDemoHelp ldh(lcd);
+
+ // clear any stale signals
+ osSignalClear(main_id, buttonSignal | loraSignal);
+ ldh.display();
+ logInfo("demo mode");
+
+ while (true) {
osEvent e = Thread::signal_wait(buttonSignal);
if (e.status == osEventSignal) {
- ButtonEvent ev = buttons->getButtonEvent();
+ ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
switch (ev) {
- case sw1_press:
- logInfo("SW1 press");
- size = snprintf(buf, sizeof(buf), "SW1 press");
+ case ButtonHandler::sw1_press:
+ logInfo("trigger TX mode");
break;
- case sw1_hold:
- logInfo("SW1 hold");
- size = snprintf(buf, sizeof(buf), "SW1 hold");
+ case ButtonHandler::sw2_press:
+ logInfo("interval TX mode");
break;
- case sw2_press:
- logInfo("SW2 press");
- size = snprintf(buf, sizeof(buf), "SW2 press");
+ case ButtonHandler::sw1_hold:
+ return;
+ default:
break;
}
+ }
+ }
+}
- lcd->clearBuffer();
- lcd->startUpdate();
- lcd->writeText(0, 0, font_6x8, buf, size);
- lcd->endUpdate();
+void surveySingle() {
+ LayoutSingleHelp lsh(lcd);
+
+ // clear any stale signals
+ osSignalClear(main_id, buttonSignal | loraSignal);
+
+ lsh.display();
+ logInfo("survey single 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("datarate/power");
+ break;
+ case ButtonHandler::sw2_press:
+ logInfo("start survey");
+ break;
+ case ButtonHandler::sw1_hold:
+ return;
+ default:
+ break;
+ }
}
}
+}
- return 0;
+void surveySweep() {
+ LayoutSweepHelp lsh(lcd);
+
+ // clear any stale signals
+ osSignalClear(main_id, buttonSignal | loraSignal);
+
+ lsh.display();
+ logInfo("survey sweep 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("cancel");
+ break;
+ case ButtonHandler::sw2_press:
+ logInfo("start sweep");
+ break;
+ case ButtonHandler::sw1_hold:
+ return;
+ default:
+ break;
+ }
+ }
+ }
}
+