Factory firmware for the MultiTech Dotbox (MTDOT-BOX) and EVB (MTDOT-EVB) products.

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ModeGps.cpp Source File

ModeGps.cpp

00001 /* Copyright (c) <2016> <MultiTech Systems>, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 #include "ModeGps.h"
00020 #include "MTSLog.h"
00021 #include "rtos.h"
00022 #include "mbed.h"
00023 #include "limits.h"
00024 #define PACKETSIZE 11
00025 
00026 ModeGps::ModeGps(DOGS102* lcd, ButtonHandler* buttons, mDot* dot, LoRaHandler* lora, GPSPARSER* gps, SensorHandler* sensors, ModeJoin* join)
00027     : Mode(lcd, buttons, dot, lora, gps, sensors),
00028       _help(lcd),
00029       _sem(lcd, _band),
00030       _sem_join(lcd, _band),
00031       _join(join)
00032 {}
00033 
00034 string ModeGps::intToString(int num){
00035    char buf[4];
00036    snprintf(buf, sizeof(buf), "%d", num);
00037    return buf;
00038 }
00039 
00040 void ModeGps::init(){
00041     //resets all parameters when re-entering mode 
00042     _interval = 5;
00043     _padding = 0;
00044     _power = 20;
00045     _band = _dot->getFrequencyBand(); 
00046     _parameter = POWER;
00047     _drAll = false;
00048     _link_check = false;
00049     _GPS = false;
00050     _sub_band = _dot->getFrequencySubBand();
00051     _data_rate = _dot->getMinDatarate();
00052     _dot->setTxDataRate(_data_rate);
00053     _max_padding = _dot->getMaxPacketLength() - PACKETSIZE;
00054     _Sw2 = "Power";
00055     _Sw1 = intToString(_power);
00056     _help.display();
00057     osDelay(2000);
00058     
00059     if (lora::ChannelPlan::IsPlanDynamic(_band)) {
00060          _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
00061          _sem.initial();
00062          _state = PARAMETERS;
00063          _send_timer.start();
00064      } else { _state = BAND_CHANGE;
00065           _sem_join.displayEditFsb(_data_rate, _power, _sub_band, _dot->getNetworkName(), _dot->getNetworkPassphrase());
00066      }
00067 }
00068 
00069 void ModeGps::drIncrement(){
00070     _data_rate++;
00071     //no fsk and japan data rates are different
00072     if (_data_rate > _dot->getMaxDatarate() || _data_rate > mDot::DR6) {
00073         _drAll = true;
00074         _data_rate = _dot->getMinDatarate();
00075     }
00076     _dot->setTxDataRate(_data_rate);
00077     logInfo("new data rate %s, POWER %lu", mDot::DataRateStr(_data_rate).c_str(), _power);
00078     _max_padding = _dot->getMaxPacketLength() - PACKETSIZE;
00079 }
00080 
00081 void ModeGps::changeDataRate(){
00082     if(_drAll) {
00083         _data_rate = _dot->getMinDatarate() - 1;
00084         _drAll = false;
00085     }
00086     drIncrement();
00087 }
00088 
00089 void ModeGps::changeParameter(){
00090     _parameter++;
00091     if(lora::ChannelPlan::IsPlanDynamic(_band) && _parameter == FSB){
00092         _parameter++;
00093     }
00094     if(_parameter>INTERVAL){
00095     _parameter = 0;
00096     }
00097     switch(_parameter) {
00098         case DATA_RATE:
00099             _Sw2 = "Data Rate";
00100             _Sw1 = intToString(_data_rate);
00101             if(_drAll){
00102                 _Sw1 = "All";
00103             }
00104             break;
00105         case FSB:
00106             _Sw2 = "FSB";
00107             _Sw1 = intToString(_sub_band);
00108             break;
00109         case PADDING:
00110             _Sw2 = "Padding";
00111             _Sw1 = intToString(_padding);
00112             break;
00113         case POWER:
00114             _Sw2 = "Power";
00115             _Sw1 = intToString(_power);
00116             break;
00117         case INTERVAL:
00118             _Sw2 = "Interval";
00119             _Sw1 = intToString(_interval);
00120             break;
00121         default:
00122             break;
00123     }
00124 }
00125 
00126 void ModeGps::editParameter(){
00127     switch(_parameter) {
00128         case POWER:
00129             if(_power<20){
00130                 _power+=3;
00131             } else {
00132                 _power = 2;
00133             }
00134             _Sw1 = intToString(_power);
00135             _dot->setTxPower(_power);
00136             break;
00137             
00138         case DATA_RATE:
00139             changeDataRate();
00140             if(_drAll) {
00141                 _Sw1="All";
00142             } else {
00143                 _Sw1 = intToString(_data_rate);
00144             }
00145             break;
00146 
00147         case FSB:
00148             _send_timer.stop();
00149             _send_timer.reset();
00150             _state = BAND_CHANGE;
00151             _dot->resetNetworkSession();
00152             _lora->resetActivityLed();
00153             _sem_join.displayEditFsb(mDot::DR0, 20, _sub_band, _dot->getNetworkName(), _dot->getNetworkPassphrase());
00154             break;
00155 
00156         case PADDING:
00157             if(_padding<_max_padding){
00158                 _padding += 10 - (_padding % 10);
00159             } else {
00160                  _padding = 0;
00161             }
00162             if(_padding>_max_padding){
00163                 _padding = _max_padding;
00164             }
00165             _Sw1 = intToString(_padding);
00166             break;
00167 
00168         default:
00169             if(_interval<60){
00170                 _interval += 5;
00171             } else {
00172                 _interval = 5;
00173             }
00174             _Sw1 = intToString(_interval);
00175             break;
00176     }
00177 }
00178 
00179 void ModeGps::formatData(){
00180     _send_data.clear();
00181     uint32_t lat = 0;
00182     uint32_t lng = 0;
00183     double degrees = 0;
00184     double minutes = 0;
00185     double seconds = 0;
00186     _temp_C += 0.5;
00187 
00188     if(_GPS) {
00189         degrees = _latitude.degrees;
00190         minutes = _latitude.minutes;
00191         seconds = _latitude.seconds;
00192         if(degrees<0) {
00193               lat = ~(int)((degrees - minutes/60.0 - seconds/600000.0)*(-INT_MAX/90.0 + 1.5));
00194         } else {
00195             lat =  (int)((degrees + minutes/60.0 + seconds/600000.0)*(INT_MAX/90.0 + 0.5));
00196             }
00197         degrees = _longitude.degrees;
00198         minutes = _longitude.minutes;
00199         seconds = _longitude.seconds;
00200         if(degrees<0) {
00201              lng = ~(int)((degrees - minutes/60.0 - seconds/600000.0)*(-INT_MAX/180.0 + 1.5));
00202         } else { 
00203         lng =  (int)((degrees + minutes/60.0 + seconds/600000.0)*(INT_MAX/180.0 + 0.5));
00204         }
00205     }
00206     _send_data.push_back(0);
00207     _send_data.push_back((int8_t) _temp_C);
00208     _send_data.push_back(0);
00209     for(int i=24; i>=0; i-=8){
00210         _send_data.push_back((lat>>i)&0xFF);
00211     }
00212     for(int i=24; i>=0; i-=8){
00213         _send_data.push_back((lng>>i)&0xFF);
00214     }
00215     for(int i=0; i<(_padding>_max_padding ? _max_padding:_padding); i++){
00216          _send_data.push_back(0);
00217     }
00218 }
00219 
00220 void ModeGps::setBand(){
00221     _sub_band++;
00222     if(_sub_band > mDot::FSB_8) _sub_band = mDot::FSB_ALL;
00223     _dot->setFrequencySubBand(_sub_band);
00224 }
00225 
00226 void ModeGps::updateScreen(){
00227     _temp_C = _sensors->getTemp(SensorHandler::CELSIUS);
00228     if(_gps->getLockStatus() && _gps_available) {
00229         _GPS = true;
00230         _latitude = _gps->getLatitude();
00231         _longitude = _gps->getLongitude();
00232         _time = _gps->getTimestamp();
00233     } else {
00234          _GPS = false;
00235     }
00236     _sem.updateStats( _GPS, _longitude, _latitude, _time, _temp_C);
00237     _sem.updateSw1(_Sw1, _Sw2);
00238     _sem.updateSw2(_Sw2);
00239 }
00240 
00241 void ModeGps::send(){   
00242     _state = SENDING;
00243     _send_timer.stop();
00244      while(_dot->getNextTxMs()>0) {
00245          _sem.updateNextCh((int)(_dot->getNextTxMs()/1000));
00246          osDelay(250);
00247      }
00248     formatData();
00249     _sem.sending();
00250     _send_timer.reset();
00251     _send_timer.start();
00252     _lora->send(_send_data);
00253     osDelay(500);
00254 }
00255 
00256 bool ModeGps::start(){
00257     init();
00258     _button_timer.start();
00259     ButtonHandler::ButtonEvent be;
00260     uint32_t e;
00261     while (true) {
00262         if(_state==PARAMETERS){
00263             updateScreen();
00264         }
00265         e = osThreadFlagsWait(loraSignal | buttonSignal, osFlagsWaitAny, 250);
00266         if (e == buttonSignal) {
00267             be = _buttons->getButtonEvent();
00268 
00269             switch(be) {
00270                 case ButtonHandler::sw1_press:
00271                     switch(_state) {
00272                         case BAND_CHANGE:
00273                                 setBand();
00274                                 _sem_join.updateJoinFsb(_sub_band);
00275                                 break;
00276                                 
00277                             case PARAMETERS:
00278                                 editParameter();
00279                                 break;
00280                                 
00281                             default:
00282                                 break;
00283                         }
00284                         break;
00285                     case ButtonHandler::sw2_press:
00286                         switch(_state) {
00287                             case BAND_CHANGE:
00288                                 if(_join->start()){
00289                                     _state = PARAMETERS;
00290                                     _send_timer.start();
00291                                     _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, DATA_RATE);
00292                                     _sem.initial();
00293                                     _dot->setTxDataRate(_data_rate);
00294                                 } else _sem_join.displayEditFsb(mDot::DR0, 20, _sub_band, _dot->getNetworkName(), _dot->getNetworkPassphrase());
00295                                 break;
00296                                 
00297                             case PARAMETERS:
00298                                 changeParameter();
00299                                 break;
00300                                 
00301                             default:
00302                                 break;
00303                         }
00304                         break;
00305                         
00306                     case ButtonHandler::sw1_hold:
00307                         _send_timer.stop();
00308                         _send_timer.reset();
00309                         return true;
00310 
00311                     default:
00312                         break;
00313                 }
00314         }
00315         if (e == loraSignal) {
00316             _ls = _lora->getStatus();
00317             switch (_ls) {
00318 
00319                 case LoRaHandler::send_success:
00320                     _sem.sendResult("   Send Sucess!");
00321                     osDelay(500);
00322                     _link_check = true;
00323                     _snr = _dot->getSnrStats();
00324                     _rssi = _dot->getRssiStats();
00325                     _button_timer.reset();
00326                     _state = PARAMETERS;
00327                     _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
00328                     if(_drAll){
00329                         drIncrement();
00330                     }
00331                     break;
00332 
00333                 case LoRaHandler::send_failure:
00334                     _sem.sendResult("   Send Failed.");
00335                     osDelay(500);
00336                     _link_check = false;
00337                     _button_timer.reset();
00338                     _state = PARAMETERS;
00339                     _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
00340                      if(_drAll){
00341                         drIncrement();
00342                     }
00343                     break;
00344                  
00345             case LoRaHandler::send_failure_payload:
00346                     _sem.sendResult("Payload too large");
00347                     osDelay(1000);
00348                     _sem.sendResult("Change Datarate");
00349                     osDelay(1000);
00350                     _link_check = false;
00351                     _button_timer.reset();
00352                     _state = PARAMETERS;
00353                     _sem.display(_link_check, _snr, _rssi, _power, _sub_band, _padding, _data_rate);
00354                      if(_drAll){
00355                         drIncrement();
00356                     }
00357                     break;  
00358                 
00359                 default:
00360                     break;
00361             }
00362         }
00363         if(_send_timer.read_ms() > _interval*1000 && _button_timer.read_ms() > 3000){
00364              send();
00365         }
00366     }
00367 }