diff options
| author | Mike Fiore <mfiore@multitech.com> | 2015-11-17 13:04:00 -0600 | 
|---|---|---|
| committer | Mike Fiore <mfiore@multitech.com> | 2015-11-17 13:04:00 -0600 | 
| commit | 11ac166f3476116b08eeaffc25d80b163573089b (patch) | |
| tree | 0675e50c2377dbffc37ce3906967b17478f225c0 | |
| parent | b86c62d46385ff454a939f23277761b8ee6b8a0d (diff) | |
| download | mtdot-box-evb-factory-firmware-11ac166f3476116b08eeaffc25d80b163573089b.tar.gz mtdot-box-evb-factory-firmware-11ac166f3476116b08eeaffc25d80b163573089b.tar.bz2 mtdot-box-evb-factory-firmware-11ac166f3476116b08eeaffc25d80b163573089b.zip | |
join works, but only once - added object for running LoRa operations in a thread, lots of misc updates
| -rw-r--r-- | ButtonHandler/ButtonHandler.cpp | 12 | ||||
| -rw-r--r-- | ButtonHandler/ButtonHandler.h | 2 | ||||
| -rw-r--r-- | Layout/Layout.cpp | 29 | ||||
| -rw-r--r-- | Layout/Layout.h | 2 | ||||
| -rw-r--r-- | Layout/LayoutJoin.cpp | 93 | ||||
| -rw-r--r-- | Layout/LayoutJoin.h | 43 | ||||
| -rw-r--r-- | LoRaHandler/LoRaHandler.cpp | 166 | ||||
| -rw-r--r-- | LoRaHandler/LoRaHandler.h | 50 | ||||
| -rw-r--r-- | main.cpp | 196 | 
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 + @@ -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;              } | 
