summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ButtonHandler/ButtonHandler.cpp12
-rw-r--r--ButtonHandler/ButtonHandler.h2
-rw-r--r--Layout/Layout.cpp29
-rw-r--r--Layout/Layout.h2
-rw-r--r--Layout/LayoutJoin.cpp93
-rw-r--r--Layout/LayoutJoin.h43
-rw-r--r--LoRaHandler/LoRaHandler.cpp166
-rw-r--r--LoRaHandler/LoRaHandler.h50
-rw-r--r--main.cpp196
9 files changed, 572 insertions, 21 deletions
diff --git a/ButtonHandler/ButtonHandler.cpp b/ButtonHandler/ButtonHandler.cpp
index e32cb42..25cf08e 100644
--- a/ButtonHandler/ButtonHandler.cpp
+++ b/ButtonHandler/ButtonHandler.cpp
@@ -1,6 +1,7 @@
#include "ButtonHandler.h"
+#include "MTSLog.h"
-#define signal (uint32_t)0xFF
+#define signal (int32_t)0xA0
typedef enum {
b_none = 0,
@@ -13,13 +14,14 @@ typedef enum {
InternalButtonEvent event = b_none;
bool check_sw1 = false;
-void worker(void const* argument) {
+void b_worker(void const* argument) {
ButtonHandler* b = (ButtonHandler*)argument;
osEvent e;
while (true) {
e = Thread::signal_wait(signal, 250);
if (e.status == osEventSignal) {
+ logInfo("button worker received signal");
switch (event) {
case b_sw1_fall:
if (! b->_sw1_running) {
@@ -84,7 +86,7 @@ void worker(void const* argument) {
ButtonHandler::ButtonHandler(osThreadId main)
: _main(main),
- _thread(worker, (void*)this),
+ _thread(b_worker, (void*)this),
_sw1(PA_12),
_sw2(PA_11),
_sw1_time(0),
@@ -113,20 +115,24 @@ ButtonHandler::ButtonEvent ButtonHandler::getButtonEvent() {
void ButtonHandler::sw1_fall() {
event = b_sw1_fall;
_thread.signal_set(signal);
+ _thread.signal_clr(signal);
}
void ButtonHandler::sw1_rise() {
event = b_sw1_rise;
_thread.signal_set(signal);
+ _thread.signal_clr(signal);
}
void ButtonHandler::sw2_fall() {
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 00898c6..e99c767 100644
--- a/ButtonHandler/ButtonHandler.h
+++ b/ButtonHandler/ButtonHandler.h
@@ -4,7 +4,7 @@
#include "mbed.h"
#include "rtos.h"
-#define buttonSignal (uint32_t)0x01
+#define buttonSignal (int32_t)0x01
class ButtonHandler {
public:
diff --git a/Layout/Layout.cpp b/Layout/Layout.cpp
index a38cc4f..7b0c375 100644
--- a/Layout/Layout.cpp
+++ b/Layout/Layout.cpp
@@ -46,6 +46,7 @@ bool Layout::writeField(const Field& field, const std::string& value, bool apply
if (apply)
startUpdate();
+ // fill the whole length with blank space in case the previous value was longer than this one
while (v.size() < field._maxSize)
v += " ";
@@ -57,6 +58,27 @@ bool Layout::writeField(const Field& field, const std::string& value, bool apply
return true;
}
+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();
+
+ snprintf(buf, s, "%s", value);
+
+ ret = writeText(field._col, field._row, value, field._maxSize);
+
+ if (apply)
+ endUpdate();
+
+ return true;
+}
+
bool Layout::writeImage(const Image& image, bool apply) {
bool ret;
@@ -71,6 +93,13 @@ bool Layout::writeImage(const Image& image, bool apply) {
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);
diff --git a/Layout/Layout.h b/Layout/Layout.h
index 5e7ece2..29d59ff 100644
--- a/Layout/Layout.h
+++ b/Layout/Layout.h
@@ -44,7 +44,9 @@ class Layout {
void endUpdate();
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);
diff --git a/Layout/LayoutJoin.cpp b/Layout/LayoutJoin.cpp
new file mode 100644
index 0000000..1b0fb20
--- /dev/null
+++ b/Layout/LayoutJoin.cpp
@@ -0,0 +1,93 @@
+#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="),
+ _fStatus(0, 0, 17),
+ _fId(3, 1, 14),
+ _fKey(3, 2, 14),
+ _fFsb(4, 3, 2),
+ _fRate(3, 5, 2),
+ _fPower(8, 5, 2),
+ _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);
+
+ 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::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..f2b7e41
--- /dev/null
+++ b/Layout/LayoutJoin.h
@@ -0,0 +1,43 @@
+#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 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;
+
+ Field _fStatus;
+ Field _fId;
+ Field _fKey;
+ Field _fFsb;
+ Field _fRate;
+ Field _fPower;
+ Field _fCountdown;
+ Field _fCountdownLabel;
+ Field _fCancel;
+ uint8_t _band;
+};
+
+#endif
diff --git a/LoRaHandler/LoRaHandler.cpp b/LoRaHandler/LoRaHandler.cpp
new file mode 100644
index 0000000..3e28782
--- /dev/null
+++ b/LoRaHandler/LoRaHandler.cpp
@@ -0,0 +1,166 @@
+#include "LoRaHandler.h"
+#include "MTSLog.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) {
+ logInfo("LoRa worker received signal");
+ 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;
+ }
+ logInfo("LoRa worker signaling main");
+ 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;
+ logInfo("LoRa worker signaling main");
+ osSignalSet(l->_main, loraSignal);
+ break;
+
+ case l_join:
+ logInfo("LoRa worker joining");
+ l->_mutex.lock();
+ ret = l->_dot->joinNetworkOnce();
+ l->_mutex.unlock();
+ if (ret == mDot::MDOT_OK) {
+ logInfo("LoRa worker signaling main - success");
+ l->_status = LoRaHandler::join_success;
+ } else {
+ logInfo("LoRa worker signaling main - failure");
+ l->_status = LoRaHandler::join_failure;
+ }
+ osSignalSet(l->_main, loraSignal);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+LoRaHandler::LoRaHandler(osThreadId main)
+ : _main(main),
+ _thread(l_worker, (void*)this),
+ _status(none)
+{
+ logInfo("starting");
+ _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/main.cpp b/main.cpp
index cd89699..864c86b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,6 +4,7 @@
// MTS headers
#include "mDot.h"
#include "MTSLog.h"
+#include "MTSText.h"
// sensor headers
#include "ISL29011.h"
#include "MMA845x.h"
@@ -14,8 +15,11 @@
#include "NCP5623B.h"
#include "LayoutStartup.h"
#include "LayoutScrollSelect.h"
+#include "LayoutJoin.h"
// button header
#include "ButtonHandler.h"
+// LoRa header
+#include "LoRaHandler.h"
// misc heders
#include <string>
@@ -27,31 +31,41 @@ 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;
+
// Serial debug port
Serial debug(USBTX, USBRX);
// Prototypes
void mainMenu();
+void join();
+void configuration();
int main() {
debug.baud(115200);
- MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
- logInfo("starting...");
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();
+
// display startup screen for 3 seconds
LayoutStartup ls(lcd);
ls.display();
osDelay(3000);
- osThreadId main_id = Thread::gettid();
- buttons = new ButtonHandler(main_id);
-
+ //MTSLog::setLogLevel(MTSLog::TRACE_LEVEL);
+ MTSLog::setLogLevel(MTSLog::INFO_LEVEL);
logInfo("displaying main menu");
mainMenu();
@@ -59,6 +73,16 @@ int main() {
}
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",
@@ -69,32 +93,170 @@ void mainMenu() {
};
std::vector<std::string> items;
- items.push_back(menu_strings[2]); // demo
- items.push_back(menu_strings[3]); // config
- items.push_back(menu_strings[4]); // single
- items.push_back(menu_strings[5]); // sweep
+ items.push_back(menu_strings[demo]);
+ items.push_back(menu_strings[config]);
+ items.push_back(menu_strings[single]);
+ items.push_back(menu_strings[sweep]);
+
+ while (true) {
+ LayoutScrollSelect menu(lcd, items, menu_strings[0], menu_strings[1]);
+ menu.display();
+
+ while (! mode_selected) {
+ osEvent e = Thread::signal_wait(buttonSignal);
+ logInfo("main - received signal %#X", e.value.signals);
+ if (e.status == osEventSignal) {
+ ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
+ switch (ev) {
+ case ButtonHandler::sw1_press:
+ logInfo("sw1 press");
+ selected = menu.select();
+ logInfo("selected %s", selected.c_str());
+ mode_selected = true;
+ break;
+ case ButtonHandler::sw2_press:
+ logInfo("sw2 press");
+ menu.scroll();
+ break;
+ case ButtonHandler::sw1_hold:
+ logInfo("sw1 hold - already in main menu");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (selected == menu_strings[demo]) {
+ join();
+ } else if (selected == menu_strings[config]) {
+ configuration();
+ } else if (selected == menu_strings[single]) {
+ join();
+ } else if (selected == menu_strings[sweep]) {
+ join();
+ }
+
+ mode_selected = false;
+ }
+}
- LayoutScrollSelect menu(lcd, items, menu_strings[0], menu_strings[1]);
- menu.display();
+void join() {
+ uint32_t next_tx;
+ uint8_t rate;
+ uint8_t power;
+ uint8_t band;
+ bool joined = false;
+ ButtonHandler::ButtonEvent ev;
+ LoRaHandler::LoRaStatus status;
+
+ // 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!
+
+ power = 20;
+ band = dot->getFrequencyBand();
+ if (band == mDot::FB_915)
+ rate = mDot::SF_10;
+ else
+ rate = mDot::SF_12;
+
+ logInfo("joining");
+ LayoutJoin lj(lcd, band);
+ 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)
+ lj.updateFsb(dot->getFrequencySubBand());
+ lj.updateRate(dot->DataRateStr(rate));
+ lj.updatePower(power);
+
+ lora = new LoRaHandler(main_id);
+ lora->setDataRate(rate);
+ lora->setPower(power);
+
+ while (! joined) {
+ next_tx = lora->getNextTx();
+ if (next_tx) {
+ lj.updateCountdown(next_tx * 1000);
+ } else {
+ logInfo("main joining");
+ lj.updateStatus("Joining...");
+ if (! lora->join())
+ logError("cannot join - LoRa layer busy");
+ }
+
+ osEvent e = Thread::signal_wait(0, 250);
+ logInfo("main - received signal %#X", e.value.signals);
+ if (e.status == osEventSignal) {
+ if (e.value.signals & buttonSignal) {
+ logInfo("main - button signal");
+ ev = buttons->getButtonEvent();
+ switch (ev) {
+ case ButtonHandler::sw1_press:
+ logInfo("sw1 press");
+ return;
+ case ButtonHandler::sw2_press:
+ logInfo("sw2 press");
+ break;
+ case ButtonHandler::sw1_hold:
+ logInfo("sw1 hold");
+ return;
+ }
+ }
+ if (e.value.signals & loraSignal) {
+ logInfo("main - LoRa signal");
+ status = lora->getStatus();
+ switch (status) {
+ case LoRaHandler::join_success:
+ logInfo("main - join success");
+ lj.updateStatus("Join Success!");
+ lj.displayCancel(false);
+ joined = true;
+ osDelay(2000);
+ break;
+
+ case LoRaHandler::join_failure:
+ logInfo("main - join failure");
+ lj.updateStatus("Join Failure!");
+ osDelay(2000);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void configuration() {
+ logInfo("config mode");
while (true) {
osEvent e = Thread::signal_wait(buttonSignal);
+ logInfo("main - received signal %#X", e.value.signals);
if (e.status == osEventSignal) {
ButtonHandler::ButtonEvent ev = buttons->getButtonEvent();
- std::string selected;
switch (ev) {
case ButtonHandler::sw1_press:
logInfo("sw1 press");
- selected = menu.select();
- logInfo("selected %s", selected.c_str());
break;
case ButtonHandler::sw2_press:
logInfo("sw2 press");
- menu.scroll();
break;
case ButtonHandler::sw1_hold:
- logInfo("sw1 hold - already in main menu");
- break;
+ logInfo("sw1 hold");
+ return;
default:
break;
}