NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
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
Generated on Tue Jul 12 2022 11:52:56 by
![doxygen](doxygen.png)