MTDOT-BOX-EVB-Factory-Firmware

Dependencies:   NCP5623B GpsParser ISL29011 libmDot-mbed5 MTS-Serial MMA845x DOGS102 MPL3115A2

Revision:
7:a31236c2e75c
Child:
12:05435282f899
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mode/ModeGps.cpp	Fri Nov 04 17:27:05 2016 -0500
@@ -0,0 +1,356 @@
+/* Copyright (c) <2016> <MultiTech Systems>, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ModeGps.h"
+#include "MTSLog.h"
+#include "rtos.h"
+#include "mbed.h"
+#include "limits.h"
+#define PACKETSIZE 11
+
+ModeGps::ModeGps(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps, SensorHandler* sensors, ModeJoin* join)
+    : Mode(lcd, buttons, dot, lora, gps, sensors),
+      _help(lcd),
+      _sem(lcd, _band),
+      _sem_join(lcd, _band),
+      _join(join)
+{}
+
+string ModeGps::intToString(int num){
+   char buf[3];
+   snprintf(buf, sizeof(buf), "%d", num);
+   return buf;
+}
+
+void ModeGps::init(){
+    //resets all parameters when re-entering mode 
+    _interval = 5;
+    _padding = 0;
+    _power = 20;
+    _band = _dot->getFrequencyBand(); 
+    _parameter = POWER;
+    _drAll = false;
+    _link_check = false;
+    _GPS = false;
+    _sub_band = _dot->getFrequencySubBand();
+    _data_rate = mDot::DR0;
+    _max_padding = _dot->getMaxPacketLength() - PACKETSIZE;
+    _Sw2 = "Power";
+    _Sw1 = intToString(_power);
+    _help.display();
+    osDelay(2000);
+    
+    if(_band == mDot::FB_EU868){
+         _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
+         _sem.initial();
+         _state = PARAMETERS;
+         _send_timer.start();
+     } else { _state = BAND_CHANGE;
+          _sem_join.displayEditFsb(_data_rate, _power, _sub_band, _dot->getNetworkName(), _dot->getNetworkPassphrase());
+     }
+}
+
+void ModeGps::drIncrement(){
+    _data_rate++;
+    if ((_data_rate > mDot::DR4 && (_band == mDot::FB_US915 || _band == mDot::FB_AU915)) || _data_rate > mDot::DR6) {
+        _drAll = true;
+        _data_rate = 0;
+    }
+    _dot->setTxDataRate(_data_rate);
+    logInfo("new data rate %s, POWER %lu", mDot::DataRateStr(_data_rate).c_str(), _power);
+    _max_padding = _dot->getMaxPacketLength() - PACKETSIZE;
+}
+
+void ModeGps::changeDataRate(){
+    if(_drAll) {
+        _data_rate = -1;
+        _drAll = false;
+    }
+    drIncrement();
+}
+
+void ModeGps::changeParameter(){
+    _parameter++;
+    if(_band == mDot::FB_EU868 && _parameter == FSB){
+        _parameter++;
+    }
+    if(_parameter>INTERVAL){
+    _parameter = 0;
+    }
+    switch(_parameter) {
+        case DATA_RATE:
+            _Sw2 = "Data Rate";
+            _Sw1 = intToString(_data_rate);
+            if(_drAll){
+                _Sw1 = "All";
+            }
+            break;
+        case FSB:
+            _Sw2 = "FSB";
+            _Sw1 = intToString(_sub_band);
+            break;
+        case PADDING:
+            _Sw2 = "Padding";
+            _Sw1 = intToString(_padding);
+            break;
+        case POWER:
+            _Sw2 = "Power";
+            _Sw1 = intToString(_power);
+            break;
+        case INTERVAL:
+            _Sw2 = "Interval";
+            _Sw1 = intToString(_interval);
+            break;
+        default:
+            break;
+    }
+}
+
+void ModeGps::editParameter(){
+    switch(_parameter) {
+        case POWER:
+            if(_power<20){
+                _power+=3;
+            } else {
+                _power = 2;
+            }
+            _Sw1 = intToString(_power);
+            _dot->setTxPower(_power);
+            break;
+            
+        case DATA_RATE:
+            changeDataRate();
+            if(_drAll) {
+                _Sw1="All";
+            } else {
+                _Sw1 = intToString(_data_rate);
+            }
+            break;
+
+        case FSB:
+            _send_timer.stop();
+            _send_timer.reset();
+            _state = BAND_CHANGE;
+            _dot->resetNetworkSession();
+            _lora->resetActivityLed();
+            _sem_join.displayEditFsb(mDot::DR0, 20, _sub_band, _dot->getNetworkName(), _dot->getNetworkPassphrase());
+            break;
+
+        case PADDING:
+            if(_padding<_max_padding){
+                _padding += 10 - (_padding % 10);
+            } else {
+                 _padding = 0;
+            }
+            if(_padding>_max_padding){
+                _padding = _max_padding;
+            }
+            _Sw1 = intToString(_padding);
+            break;
+
+        default:
+            if(_interval<60){
+                _interval += 5;
+            } else {
+                _interval = 5;
+            }
+            _Sw1 = intToString(_interval);
+            break;
+    }
+}
+
+void ModeGps::formatData(){
+    _send_data.clear();
+    uint32_t lat = 0;
+    uint32_t lng = 0;
+    double degrees = 0;
+    double minutes = 0;
+    double seconds = 0;
+    _temp_C += 0.5;
+
+    if(_GPS) {
+        degrees = _latitude.degrees;
+        minutes = _latitude.minutes;
+        seconds = _latitude.seconds;
+        if(degrees<0) {
+              lat = ~(int)((degrees - minutes/60.0 - seconds/600000.0)*(-INT_MAX/90.0 + 1.5));
+        } else {
+            lat =  (int)((degrees + minutes/60.0 + seconds/600000.0)*(INT_MAX/90.0 + 0.5));
+            }
+        degrees = _longitude.degrees;
+        minutes = _longitude.minutes;
+        seconds = _longitude.seconds;
+        if(degrees<0) {
+             lng = ~(int)((degrees - minutes/60.0 - seconds/600000.0)*(-INT_MAX/180.0 + 1.5));
+        } else { 
+        lng =  (int)((degrees + minutes/60.0 + seconds/600000.0)*(INT_MAX/180.0 + 0.5));
+        }
+    }
+    _send_data.push_back(0);
+    _send_data.push_back((int8_t) _temp_C);
+    _send_data.push_back(0);
+    for(int i=24; i>=0; i-=8){
+        _send_data.push_back((lat>>i)&0xFF);
+    }
+    for(int i=24; i>=0; i-=8){
+        _send_data.push_back((lng>>i)&0xFF);
+    }
+    for(int i=0; i<(_padding>_max_padding ? _max_padding:_padding); i++){
+         _send_data.push_back(0);
+    }
+}
+
+void ModeGps::setBand(){
+    _sub_band++;
+    if(_sub_band > mDot::FSB_8) _sub_band = mDot::FSB_ALL;
+    _dot->setFrequencySubBand(_sub_band);
+}
+
+void ModeGps::updateScreen(){
+    _temp_C = _sensors->getTemp(SensorHandler::CELSIUS);
+    if(_gps->getLockStatus() && _gps_available) {
+        _GPS = true;
+        _latitude = _gps->getLatitude();
+        _longitude = _gps->getLongitude();
+        _time = _gps->getTimestamp();
+    } else {
+         _GPS = false;
+    }
+    _sem.updateStats( _GPS, _longitude, _latitude, _time, _temp_C);
+    _sem.updateSw1(_Sw1, _Sw2);
+    _sem.updateSw2(_Sw2);
+}
+
+void ModeGps::send(){   
+    _state = SENDING;
+    _send_timer.stop();
+    if(_band == mDot::FB_EU868) {
+        while(_dot->getNextTxMs()>0) {
+            _sem.updateNextCh((int)(_dot->getNextTxMs()/1000));
+            osDelay(250);
+        }
+    }
+    formatData();
+    _sem.sending();
+    _send_timer.reset();
+    _send_timer.start();
+    _lora->send(_send_data);
+    osDelay(500);
+}
+
+bool ModeGps::start(){
+    init();
+    _button_timer.start();
+    ButtonHandler::ButtonEvent be;
+    osSignalClear(_main_id, buttonSignal | loraSignal);
+    while (true) {
+        if(_state==PARAMETERS){
+            updateScreen();
+        }
+        osEvent e = Thread::signal_wait(0, 250);
+        if (e.status == osEventSignal) {
+            if (e.value.signals & buttonSignal) {
+                _button_timer.reset();
+                be = _buttons->getButtonEvent();
+
+                switch(be) {
+                    case ButtonHandler::sw1_press:
+                        switch(_state) {
+                            case BAND_CHANGE:
+                                setBand();
+                                _sem_join.updateJoinFsb(_sub_band);
+                                break;
+                                
+                            case PARAMETERS:
+                                editParameter();
+                                break;
+                                
+                            default:
+                                break;
+                        }
+                        break;
+                    case ButtonHandler::sw2_press:
+                        switch(_state) {
+                            case BAND_CHANGE:
+                                if(_join->start()){
+                                    _state = PARAMETERS;
+                                    _send_timer.start();
+                                    _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, DATA_RATE);
+                                    _sem.initial();
+                                    _dot->setTxDataRate(_data_rate);
+                                } else _sem_join.displayEditFsb(mDot::DR0, 20, _sub_band, _dot->getNetworkName(), _dot->getNetworkPassphrase());
+                                break;
+                                
+                            case PARAMETERS:
+                                changeParameter();
+                                break;
+                                
+                            default:
+                                break;
+                        }
+                        break;
+                        
+                    case ButtonHandler::sw1_hold:
+                        _send_timer.stop();
+                        _send_timer.reset();
+                        return true;
+
+                    default:
+                        break;
+                }
+            }
+        }
+        if (e.value.signals & loraSignal) {
+            _ls = _lora->getStatus();
+            switch (_ls) {
+
+                case LoRaHandler::send_success:
+                    _sem.sendResult("   Send Sucess!");
+                    osDelay(500);
+                    _link_check = true;
+                    _snr = _dot->getSnrStats();
+                    _rssi = _dot->getRssiStats();
+                    _button_timer.reset();
+                    _state = PARAMETERS;
+                    _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
+                    if(_drAll){
+                        drIncrement();
+                    }
+                    break;
+
+                case LoRaHandler::send_failure:
+                    _sem.sendResult("   Send Failed.");
+                    osDelay(500);
+                    _link_check = false;
+                    _button_timer.reset();
+                    _state = PARAMETERS;
+                    _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
+                     if(_drAll){
+                        drIncrement();
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+        }
+        if(_send_timer.read_ms() > _interval*1000 && _button_timer.read_ms() > 3000){
+             send();
+        }
+    }
+}