NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ATIf.cpp Source File

ATIf.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "ATIf.h"
00025 #include "mbed.h"
00026 #include <cstdarg>
00027 
00028 #define READ_TIMEOUT 100
00029 #define TMP_BUF_SIZE 128//512
00030 
00031 #define SERIAL_BUF_LEN 512 //Huge buf needed for PPP (esp. when transferring big data chunks, using TCP)
00032 
00033 #define BAUDRATE 9600//9600//115200// 19200
00034 
00035 #include "netCfg.h"
00036 #if NET_GPRS
00037 
00038 //#define __DEBUG
00039 #include "dbg/dbg.h"
00040 
00041 ATIf::ATIf() : SerialBuf(SERIAL_BUF_LEN), m_isOpen(false)//, m_signalsEnable(false), m_isOpen(false), m_pCurrentSignal(NULL), m_signals() 
00042 {
00043   DBG("New AT If@%p\n", this);
00044 
00045   m_readTimeout = READ_TIMEOUT; //default 1s
00046   //tmpBuf = NULL;
00047   m_lineMode = false;
00048   m_tmpBuf = new char[TMP_BUF_SIZE];
00049 }
00050 
00051 ATIf::~ATIf()
00052 {
00053   if(m_tmpBuf)
00054     delete[] m_tmpBuf;
00055 }
00056 
00057 int ATIf::printf(const char* format, ... )
00058 {
00059 
00060 /*if(!m_tmpBuf)
00061     m_tmpBuf = new char[TMP_BUF_SIZE]; //is it really necessary ??*/
00062   *m_tmpBuf=0;
00063      
00064   int len = 0;
00065   
00066   //
00067 //  flushBuffer();
00068 //wait(1);
00069   //
00070     
00071   va_list argp;
00072   
00073   va_start(argp, format);
00074   len += vsprintf(m_tmpBuf, format, argp);
00075   va_end(argp);
00076   
00077   //DBG("\r\nOutBuf is : %s, mode is %d.", m_tmpBuf, m_lineMode);
00078   
00079   int err = write( m_tmpBuf, m_lineMode );
00080   if (err<0)
00081     return 0;
00082     
00083   return len;
00084   
00085 }
00086 
00087 int ATIf::scanf(const char* format, ... )
00088 {
00089 /*if(!m_tmpBuf)
00090     m_tmpBuf = new char[TMP_BUF_SIZE];*/
00091   int err = read( m_tmpBuf, TMP_BUF_SIZE - 1,  m_readTimeout, m_lineMode, 1/*Ensure at least one char is read*/ );
00092   if (err<0)
00093     return -1;//EOF
00094     
00095   DBG("Scanf'ing:\r\n%s\r\n",m_tmpBuf);
00096     
00097   int len = 0;
00098   
00099   if(strchr(format,'%')) //Ugly, determines wether format string is null or not
00100   {
00101     va_list argp;
00102     
00103     va_start(argp, format);
00104     len += vsscanf(m_tmpBuf, format, argp);
00105     va_end(argp);
00106   }
00107   else //No varargs, call strncmp
00108   {
00109  /*   if(strlen(m_tmpBuf) == 0 )
00110       return -1;*/
00111     if( !strncmp(m_tmpBuf, format, strlen(format)) )
00112     {
00113       return 0;
00114     }
00115     else
00116     {
00117       return -1;
00118     }
00119   }
00120   
00121   return len;
00122   
00123 }
00124 
00125 void ATIf::setTimeout(int timeout) //used by scanf
00126 {
00127   m_readTimeout = timeout;
00128 }
00129 
00130 void ATIf::setLineMode(bool lineMode) //Switch btw line & raw fns
00131 {
00132   m_lineMode = lineMode;
00133 }
00134 
00135 #if 0
00136 void ATIf::setSignals(bool signalsEnable)
00137 {
00138   m_signalsEnable=signalsEnable;
00139 }
00140 #endif
00141 
00142 #if 0
00143 template<class T>
00144 void ATIf::attachSignal( const char* sigName, T* pItem, bool (T::*pMethod)(ATIf*, bool, bool*) ) //Attach Signal ("Unsollicited response code" in Telit_AT_Reference_Guide.pdf) to an handler fn
00145 {
00146   ATSigHandler sig(sigName, (ATSigHandler::CDummy*)pItem, (bool (ATSigHandler::CDummy::*)(ATIf*, bool, bool*))pMethod);
00147   m_signals.push_back(sig);
00148 }
00149 #endif
00150 
00151 #if 0
00152 void ATIf::detachSignal( const char* sigName )
00153 {
00154   list<ATSigHandler>::iterator it;
00155   
00156   for ( it = m_signals.begin(); it != m_signals.end(); it++ )
00157   {
00158     if( !strcmp((*it).m_name,sigName) )
00159     {
00160       m_signals.erase(it);
00161       break;
00162     }
00163   }
00164 }
00165 #endif
00166 
00167 ATErr ATIf::open(Serial* pSerial) //Deactivate echo, etc
00168 {
00169   DBG("Opening...\n");
00170   m_isOpen = true; //Must be set so that the serial port-related fns work
00171   //Setup options  
00172 //  pSerial->baud(BAUDRATE); //FIXME
00173   SerialBuf::attach(pSerial);
00174 
00175   setReadMode(false); //Discard chars
00176   setTimeout(1000);
00177   setLineMode(true); //Line Mode
00178   
00179   DBG("Trmt...\n");
00180  // printf("AT+IPR=%d", BAUDRATE); //FIXME
00181   printf("ATZ"); //Reset
00182   wait(.100);
00183   printf("ATE"); //Deactivate echo
00184   wait(.500);
00185   flushBuffer();
00186   
00187   DBG("ATZ ATE...\n");
00188   
00189   int len = writeLine("ATV1");
00190   ATErr err = AT_OK;
00191   if(len<0)
00192     err=(ATErr)len;
00193     
00194   if(!err)
00195   {
00196     err = checkOK();
00197     if (err) //No ACK from module
00198     {
00199       DBG("\r\nOpening port, error %d.", err);
00200       if(err==AT_TIMEOUT)
00201         err = AT_NOANSWER;
00202     }
00203   }
00204   
00205   if(err)
00206   {
00207     SerialBuf::detach();
00208     m_isOpen = false;
00209     return err;
00210   }
00211   
00212   DBG("\r\nNo error.");
00213   #if 0//FIXME
00214   m_signalsEnable = true;
00215   #endif
00216   //FIXME:
00217 //  m_pSerial->attach<ATIf>(this, &ATIf::onSerialInterrupt);
00218   
00219   return AT_OK;
00220 }
00221 
00222 #if NET_USB_SERIAL
00223 ATErr ATIf::open(UsbSerial* pUsbSerial) //Deactivate echo, etc
00224 {
00225   DBG("Opening...\n");
00226   m_isOpen = true; //Must be set so that the serial port-related fns work
00227   //Setup options  
00228   SerialBuf::attach(pUsbSerial);
00229 
00230   setReadMode(false); //Discard chars
00231   setTimeout(1000);
00232   setLineMode(true); //Line Mode
00233 
00234   printf("ATZ"); //Reinit
00235   wait(.500);  
00236   //flushBuffer();
00237 //  printf("ATE0 ^CURC=0"); //Deactivate echo & notif
00238   printf("ATE0"); //Deactivate echo & notif
00239   wait(.500);
00240   flushBuffer();
00241   
00242   DBG("ATZ ATE...\n");
00243   
00244   int len = writeLine("ATQ0 V1 S0=0 &C1 &D2 +FCLASS=0");//writeLine("ATQ0 V1 S0=0 &C1 &D2 +FCLASS=0");
00245   ATErr err = AT_OK;
00246   if(len<0)
00247     err=(ATErr)len;
00248     
00249   if(!err)
00250   {
00251     err = checkOK();
00252     if (err) //No ACK from module
00253     {
00254       DBG("Opening port, error %d.\n", err);
00255       if(err==AT_TIMEOUT)
00256         err = AT_NOANSWER;
00257     }
00258   }
00259   
00260   if(err)
00261   {
00262     SerialBuf::detach();
00263     m_isOpen = false;
00264     return err;
00265   }
00266   
00267   DBG("No error.\n");
00268   #if 0//FIXME
00269   m_signalsEnable = true;
00270   #endif
00271   //FIXME:
00272 //  m_pSerial->attach<ATIf>(this, &ATIf::onSerialInterrupt);
00273   
00274   return AT_OK;
00275 }
00276 #endif
00277 
00278 ATErr ATIf::close() //Release port
00279 {
00280   SerialBuf::detach(); //Detach serial buf
00281   m_isOpen = false;
00282   //m_signalsEnable = false;
00283   return AT_OK;
00284 }
00285 
00286 ATErr ATIf::flushBuffer()
00287 {
00288   if(!m_isOpen)
00289     return AT_CLOSED;
00290   
00291   int len=0;
00292   //char c;
00293   while(readable())
00294   {
00295     //DBG("Readable\n"); 
00296     /*c =*/ getc();
00297     //DBG("\r\n[%c] discarded.", c);    
00298  //   wait(0.01);
00299     len++;
00300   }
00301   
00302   DBG("\r\n%d chars discarded.", len);
00303   
00304   return AT_OK;
00305 }
00306 
00307 ATErr ATIf::flushLine(int timeout)
00308 {
00309   if(!m_isOpen)
00310     return AT_CLOSED;
00311     
00312   Timer timer;
00313   
00314   timer.start();
00315   
00316   int len=0;
00317   char c=0;
00318   while(true)
00319   {
00320     while(!readable())
00321     {      if(timer.read_ms()>timeout)
00322       {
00323  //       DBG("Timeout!!0");
00324         return AT_TIMEOUT;
00325       }
00326     }
00327     if(c=='\x0D')
00328     {
00329       c = getc();
00330       len++;
00331       if(c=='\x0A')
00332         break;
00333     }
00334     else
00335     {
00336       c = getc();
00337       len++;
00338     }
00339   }
00340   
00341 //  DBG("\r\n%d chars discarded.", len);
00342   
00343   return AT_OK;
00344 }
00345 
00346 #if 0
00347 bool ATIf::onRead()
00348 {
00349   if(!m_signalsEnable)
00350     return false;
00351 
00352   //Save Usermode params
00353   volatile int u_readTimeout = m_readTimeout;
00354   volatile bool u_lineMode = m_lineMode;
00355 //  bool u_isOpen = m_isOpen;
00356   SerialBuf::setReadMode(true);
00357   
00358   m_readTimeout = 0; //No timeout in an interrupt fn!
00359   
00360   bool handled;
00361   if(!!flushLine(0))
00362   {
00363     SerialBuf::resetRead();
00364     //Not a complete line here, wait...
00365     handled = false;
00366   }
00367   else
00368   {
00369    SerialBuf::resetRead();
00370    handled = true; 
00371    if( handleSignal() ) //Was that a signal ?
00372     {
00373       //OK, discard data since it has been processed
00374       SerialBuf::flushRead();
00375     }
00376     else
00377     {
00378       //Keep data since it has not been processed yet
00379       //Have to be processed in usermode
00380       SerialBuf::resetRead();
00381 //      handled = false; 
00382     }
00383   }  
00384   //Restore Usermode params
00385   m_readTimeout = u_readTimeout;
00386   m_lineMode = u_lineMode;
00387   //m_isOpen = u_isOpen;
00388   return handled;
00389 }
00390 #endif
00391 
00392 ATErr ATIf::rawOpen(Serial* pSerial, int baudrate) //Simple open function for similar non-conforming protocols
00393 {
00394   DBG("\r\nOpening...");
00395   m_isOpen = true; //Must be set so that the serial port-related fns work
00396   //Setup options  
00397   pSerial->baud(baudrate);
00398   SerialBuf::attach(pSerial);
00399 
00400   return AT_OK;
00401 }
00402 
00403 #if 0
00404 ATErr ATIf::command(const char* cmd, char* result, int resultLen, int timeout) ////WARN/FIXME: result has to be long enough!!!
00405 {  
00406   if(!m_isOpen)
00407     return AT_CLOSED;
00408   
00409   flushBuffer();
00410   
00411   int err;
00412   err = writeLine(cmd);
00413   
00414   if(err<0)
00415     { m_receiveStatus = AT_READY; return (ATErr)err; }
00416     
00417   err = readLine(result, resultLen, timeout);
00418   
00419   if(err<0)
00420     { m_receiveStatus = AT_READY; return (ATErr)err; }
00421       
00422   m_receiveStatus = AT_READY;
00423     
00424   return AT_OK;
00425   
00426 }
00427 #endif
00428 
00429 ATErr ATIf::write(const char* cmd, bool lineMode /*= false*/)
00430 {
00431   if(!m_isOpen)
00432     return AT_CLOSED;
00433 
00434   int err;  
00435   err = lineMode ? writeLine(cmd) : writeRaw(cmd);
00436 
00437   if(err<0)
00438     return (ATErr)err;
00439       
00440   return AT_OK;
00441 }
00442 
00443 
00444 ATErr ATIf::read(char* result, int resultMaxLen, int timeout, bool lineMode /*= false*/, int resultMinLen/* = 0*/)
00445 {
00446   if(!m_isOpen)
00447     return AT_CLOSED;
00448   
00449   int err;  
00450   err = lineMode ? readLine(result, resultMaxLen, timeout) :  readRaw(result, resultMaxLen, timeout, resultMinLen);
00451   
00452   if(err<0)
00453     return (ATErr)err;
00454     
00455   return AT_OK;
00456 }
00457 
00458 bool ATIf::isOpen()
00459 {
00460   return m_isOpen;
00461 }
00462 
00463 ATErr ATIf::checkOK() //Helper fn to quickly check that OK has been returned
00464 {
00465   char ret[16] = {0};
00466   int err = readLine(ret,16,m_readTimeout);
00467   
00468   if(err<0)
00469   {
00470     DBG("\r\nError in check (%s).\r\n", ret);
00471     flushBuffer(); //Discard anything in buf to avoid misparsing in the following calls
00472     return (ATErr)err;
00473   }
00474   
00475   if(!!strcmp("OK",ret))
00476   {
00477     DBG("\r\nNot an OK <%s>.\r\n", ret);
00478     flushBuffer();
00479     return AT_ERROR;
00480   }
00481   
00482   DBG("\r\nCHECK OK\r\n");
00483   
00484   return AT_OK;
00485 }
00486 
00487 #if 0
00488 void ATIf::onSerialInterrupt() //Callback from m_pSerial
00489 {
00490 return;//FIXME
00491 
00492   if(m_receiveStatus == AT_READING)
00493     return;
00494 
00495   if( m_cbObj && m_cbMeth )
00496     return (m_cbObj->*m_cbMeth)();
00497 }
00498 #endif
00499 
00500 int ATIf::readLine(char* line, int maxLen, int timeout) //Read a single line from serial port, return length or ATErr(<0)
00501 {
00502 #ifdef OLDREADLINE
00503   if(!m_isOpen)
00504     return AT_CLOSED;
00505     
00506   int len = 0;
00507   
00508   Timer timer;
00509   
00510   timer.start();
00511 #ifdef __START_CLRF_MANDAT
00512   for( int i=0; i<2; i++ )
00513   {
00514     while(!readable())
00515     {
00516       if(timer.read_ms()>timeout)
00517       {
00518 //        DBG("Timeout!!0");
00519         return AT_TIMEOUT;
00520       }
00521       wait_ms(10); //Wait 10ms
00522     }
00523     *line = getc();
00524   //  DBG("In readLine(), read : %c", *line);
00525     if( ( (i == 0) && (*line!='\x0D') )
00526      || ( (i == 1) && (*line!='\x0A') ) )
00527      return AT_PARSE;
00528   }
00529 #else
00530   
00531 #endif
00532 
00533   for( ; len < maxLen ; len++ )
00534   {
00535     timer.reset();
00536     while(!readable())
00537     {
00538       if(timer.read_ms()>timeout)
00539       {
00540 //        DBG("Timeout!!1");
00541         return AT_TIMEOUT;
00542       }
00543       wait_ms(10); //Wait 10ms
00544     }
00545     *line = getc();
00546     //DBG("In readLine(), read : %c", *line);
00547 
00548     if(*line=='\x0D')
00549     {
00550       timer.reset();
00551       while(!readable())
00552       {
00553         if(timer.read_ms()>timeout)
00554         {
00555           return AT_TIMEOUT;
00556         }
00557         wait_ms(10); //Wait 1ms
00558       }
00559       *line = getc();
00560     //  DBG("In readLine(), read : %c", *line);
00561       if(*line=='\x0A')
00562       {
00563         if(len==0)
00564         {
00565           //Start of line
00566           len--;
00567           continue;
00568         }
00569         else
00570         {
00571           *line=0; //End of line
00572           break;
00573         }
00574       }
00575       else
00576       {
00577         //Should not happen, must have lost some bytes somewhere or non AT protocol
00578         return AT_PARSE;
00579       }
00580     }
00581     line++;
00582   }
00583   
00584   if(len==maxLen)
00585     return AT_INCOMPLETE; //Buffer full, must call this method again to get end of line
00586   
00587   return len;
00588 #else
00589  if(!m_isOpen)
00590     return AT_CLOSED;
00591   
00592   Timer timer;  
00593   timer.start();
00594 
00595   int len = 0;
00596   while( len < maxLen )
00597   {
00598     timer.reset();
00599     while(!readable())
00600     {
00601       if(timer.read_ms()>timeout)
00602       {
00603         return AT_TIMEOUT;
00604       }
00605       wait_ms(10); //Wait 10ms
00606     }
00607     *line = getc();
00608 
00609     if( (*line=='\x0D') || (*line=='\x0A') )
00610     {
00611     
00612       if(len==0)
00613       {
00614         //Start of line
00615         continue;
00616       }
00617       else
00618       {
00619         *line=0; //End of line
00620         break;
00621       }
00622     }
00623     len++;  
00624     line++;
00625   }
00626   
00627   if(len==maxLen)
00628     return AT_INCOMPLETE; //Buffer full, must call this method again to get end of line
00629   
00630   return len;
00631 #endif
00632 }
00633 
00634 int ATIf::writeLine(const char* line) //Write a single line to serial port
00635 {
00636 //  char* line = (char*) _line;
00637   if(!m_isOpen)
00638     return AT_CLOSED;
00639   
00640 //  DBG("\n\rIn writeline.");
00641   
00642   int len = 0;
00643 
00644   while(*line)
00645   {
00646     putc(*line);
00647     line++;
00648     len++;
00649   }
00650   
00651  /* putc('\r');
00652   
00653     putc('\n');*/
00654   
00655   putc('\x0D');
00656 //  putc('\x0A');
00657 
00658 // DBG("\n\rWritten %d + 1", len);
00659   
00660   return len;
00661  
00662 }
00663 
00664 
00665     
00666 int ATIf::readRaw(char* str, int maxLen, int timeout /*= 0*/, int minLen /*= 0*/) //Read from serial port in buf
00667 {
00668   if(!m_isOpen)
00669     return AT_CLOSED;
00670     
00671   int len = 0;
00672   
00673   Timer timer;
00674   
00675   timer.start();
00676 
00677   for( ; len < maxLen ; len++ )
00678   {
00679     while( (len < minLen) && !readable())
00680     {
00681       if(timer.read_ms()>timeout)
00682       {
00683         return AT_TIMEOUT;
00684       }
00685       wait(.01); //Wait 10ms
00686     }
00687     
00688     if(!readable()) //Buffer read entirely
00689       break;
00690       
00691     *str = getc();
00692     str++;
00693     len++;
00694   }
00695   
00696   *str = 0; //End char
00697   
00698   return len;
00699   
00700 }
00701 
00702 int ATIf::writeRaw(const char* str) //Write directly to serial port    
00703 {
00704   if(!m_isOpen)
00705     return AT_CLOSED;
00706     
00707   int len = 0;
00708 
00709   while(*str)
00710   {
00711     putc(*str);
00712     str++;
00713     len++;
00714   }
00715   
00716   return len;
00717 }    
00718 
00719 #if 0
00720 bool ATIf::handleSignal()
00721 {
00722   bool beg = false;
00723   
00724 //  SerialBuf::setReadMode(true); //Keep chars in buf when read  
00725 //  SerialBuf::resetRead();
00726    
00727   //if( !m_pCurrentSignal ) //If no signal asked for this line
00728   if(true) //Check anyway, could have been some parsing error before
00729   {
00730     //Extract Signal Name
00731     char sigName[32]; //Should not be longer than that
00732     setLineMode(true); //Read one line  
00733 
00734     int len = scanf("%[^:]:%*[^\n]", sigName);
00735     if(len != 1)
00736       return false; //This is not a signal      
00737  //   DBG("\r\nGot signal %s\r\n", sigName);
00738   
00739     list<ATSigHandler>::iterator it;
00740 
00741     for ( it = m_signals.begin(); it != m_signals.end(); it++ )
00742     {
00743       if( !strcmp((*it).m_name, sigName) )
00744       {
00745   //      DBG("\r\nFound signal %s\r\n", sigName);
00746         m_pCurrentSignal = &(*it);
00747         beg = true;
00748         break;
00749       }
00750     }
00751     
00752     
00753   }
00754   
00755   if( !m_pCurrentSignal ) 
00756     return false; //This is not a signal or it cannot be handled
00757     
00758   bool moreData = false;
00759   //Call signal handling routine
00760   SerialBuf::resetRead(); //Rollback so that the handling fn can call scanf properly
00761   bool result = ((m_pCurrentSignal->m_cbObj)->*(m_pCurrentSignal->m_cbMeth))(this, beg, &moreData);
00762   
00763   if( !moreData ) //Processing completed
00764   {
00765     m_pCurrentSignal = NULL;
00766   }
00767   
00768   return result;
00769 }
00770 #endif
00771 
00772 #endif