support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.

Dependents:   HTTPClient_Cellular_HelloWorld Cellular_HelloMQTT MbedSmartRestMain Car_Bon_car_module ... more

This library is intended to be used with u-blox products such as the C027 or a shield with u-blox cellular and GPS modules like the cellular and positioning shield from Embedded Artist.

For 2G/GSM and 3G/UMTS you need to:

  • have a SIM card and know its PIN number
  • need to know you network operators APN setting These setting should be passed to the connect or init and join functions. You can also extend the APN database in MDMAPN.h.

For CDMA products you need to make sure that you have provisioned and activated the modem with either Sprint or Verizon.

Files at this revision

API Documentation at this revision

Comitter:
mazgch
Date:
Thu May 15 22:20:42 2014 +0000
Parent:
73:2b32e0a21df2
Child:
75:ce6e12067d0c
Commit message:
initial version of restructured u-blox library

Changed in this revision

GPS.cpp Show annotated file Show diff for this revision Revisions of this file
GPS.h Show annotated file Show diff for this revision Revisions of this file
MDM.cpp Show annotated file Show diff for this revision Revisions of this file
MDM.h Show annotated file Show diff for this revision Revisions of this file
Pipe.h Show annotated file Show diff for this revision Revisions of this file
Relax.cpp Show annotated file Show diff for this revision Revisions of this file
Relax.h Show annotated file Show diff for this revision Revisions of this file
SerialPipe.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/GPS.cpp	Thu May 15 08:25:45 2014 +0000
+++ b/GPS.cpp	Thu May 15 22:20:42 2014 +0000
@@ -1,6 +1,26 @@
 #include "mbed.h"
 #include <ctype.h>
 #include "GPS.h"
+#include "Relax.h"
+#ifdef TARGET_UBLOX_C027
+ #include "C027_api.h"
+#endif
+
+GPSParser::~GPSParser(void) 
+{ 
+    powerOff(); 
+#ifdef TARGET_UBLOX_C027
+    if (_onboard)
+         c027_gps_powerOff();
+#endif
+}
+    
+void GPSParser::powerOff(void)
+{
+    // set the gps into backup mode using the command RMX-LPREQ
+    struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/};
+    sendUbx(0x02, 0x41, &msg, sizeof(msg));
+}
 
 int GPSParser::_getMessage(Pipe<char>* pipe, char* buf, int len)
 {
@@ -104,13 +124,6 @@
     return _send(buf, len);
 }
 
-void GPSParser::powerOff(void)
-{
-    // set the gps into backup mode using the command RMX-LPREQ
-    struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/};
-    sendUbx(0x02, 0x41, &msg, sizeof(msg));
-}
-
 int GPSParser::sendNmea(const char* buf, int len)
 {
     char head[1] = { '$' };
@@ -238,6 +251,26 @@
             SerialPipe(tx, rx, rxSize, txSize)
 {
     baud(baudrate);
+#ifdef TARGET_UBLOX_C027
+    _onboard = (tx == GPSTXD) || (rx == GPSRXD);
+    if (_onboard)
+        c027_gps_powerOn(); 
+#endif
+}
+
+bool GPSSerial::init(void)
+{
+    // send a byte to wakup the device again
+    putc(0);
+    // wait until we get some bytes
+    int size = _pipeRx.size();
+    int i = 30;
+    while (i--) {
+        RELAX_MS(10);
+        if(size != _pipeRx.size())
+            break;
+    }   
+    return (i >= 0);
 }
 
 int GPSSerial::getMessage(char* buf, int len)
@@ -261,18 +294,20 @@
             _i2cAdr(i2cAdr)
 {
     frequency(100000);
-    found = false;
+#ifdef TARGET_UBLOX_C027
+    _onboard = (sda == GPSSDA) && (scl == GPSSCL);
+    if (_onboard)
+        c027_gps_powerOn(); 
+#endif
 }
 
-bool GPSI2C::detect(void)
+bool GPSI2C::init(void)
 {
-    if (!found)
-    {
-        int w = I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM));
-        if (w == 0)
-            found = true;
-    }
-    return found;
+    DigitalOut pin(GPSINT, 0);
+    wait_us(1);
+    pin = 1;
+    RELAX_MS(100);
+    return !I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM));
 }
 
 int GPSI2C::getMessage(char* buf, int len)
@@ -294,7 +329,6 @@
     {
         if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true))
             sent = send(buf, len);
-        found = (len == sent);
         stop();
     }
     return sent;
@@ -305,7 +339,6 @@
     int sent = 0;
     if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true))
         sent = GPSParser::sendNmea(buf, len);
-    found = (len == sent);
     stop();
     return sent;
 }
@@ -315,7 +348,6 @@
     int sent = 0;
     if (!I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM),true))
         sent = GPSParser::sendUbx(cls, id, buf, len);
-    found = (len == sent);
     I2C::stop();
     return sent;
 }
@@ -336,12 +368,8 @@
                 !I2C::read(_i2cAdr,buf,size)) {
                 read = size;
             }
-            else 
-                found = false;
         }
     }
-    else 
-        found = false;
     return read;
 }
 
--- a/GPS.h	Thu May 15 08:25:45 2014 +0000
+++ b/GPS.h	Thu May 15 22:20:42 2014 +0000
@@ -5,12 +5,9 @@
 #include "SerialPipe.h"
 
 #ifdef TARGET_UBLOX_C027
- // if we detect the C027 platform we will assign the 
- // default pinname and baudrate in the constructor 
- // this helper macro will be used. 
- #define _C027DEFAULT(name) = name
+ #define _IF(onboard, shield) onboard
 #else
- #define _C027DEFAULT(name)
+ #define _IF(onboard, shield) shield
 #endif
 
 /** basic gps parser class 
@@ -18,6 +15,14 @@
 class GPSParser
 {
 public:
+
+    //! Constructor
+    ~GPSParser(void);
+   
+    /** Power on / Wake up the gps 
+    */
+    virtual bool init(void) = 0;
+    
     enum { 
         // getLine Responses
         WAIT      = -1, //!< wait for more incoming data (the start of a message was found, or no data available)
@@ -66,7 +71,7 @@
     */
     virtual int sendUbx(unsigned char cls, unsigned char id, 
                         const void* buf = NULL, int len = 0);
-          
+    
     /** Power off the gps, it can be again woken up by an 
         edge on the serial port on the external interrupt pin. 
     */
@@ -155,6 +160,9 @@
     virtual int _send(const void* buf, int len) = 0;
     
     static const char toHex[16]; //!< num to hex conversion
+#ifdef TARGET_UBLOX_C027
+    bool _onboard;
+#endif
 };
 
 /** gps class which uses a serial port 
@@ -170,12 +178,14 @@
         \param rxSize the size of the serial rx buffer
         \param txSize the size of the serial tx buffer
     */
-    GPSSerial(PinName tx    _C027DEFAULT( GPSTXD ), 
-              PinName rx    _C027DEFAULT( GPSRXD ), 
-              int baudrate  _C027DEFAULT( GPSBAUD ),
+    GPSSerial(PinName tx    _IF( = GPSTXD, /* = D8 */), // resistor on shield not populated 
+              PinName rx    _IF( = GPSRXD, /* = D9 */), // resistor on shield not populated 
+              int baudrate  _IF( = GPSBAUD, = 9600 ),
               int rxSize    = 256 , 
               int txSize    = 128 );
               
+    virtual bool init(void);
+    
     /** Get a line from the physical interface. 
         \param buf the buffer to store it
         \param len size of the buffer
@@ -205,15 +215,15 @@
         \param adr the I2C address of the GPS set to (66<<1)
         \param rxSize the size of the serial rx buffer
     */
-    GPSI2C(PinName sda          _C027DEFAULT( GPSSDA ), 
-           PinName scl          _C027DEFAULT( GPSSCL ),
-           unsigned char i2cAdr _C027DEFAULT( GPSADR ), 
+    GPSI2C(PinName sda          _IF( = GPSSDA, = D14 ), 
+           PinName scl          _IF( = GPSSCL, = D15 ),
+           unsigned char i2cAdr _IF( = GPSADR, = (66<<1) ), 
            int rxSize           = 256 );
-
+    
     /** helper function to probe the i2c device
         \return true if successfully detected the gps. 
     */ 
-    bool detect(void);
+    virtual bool init(void);
     
     /** Get a line from the physical interface. 
         \param buf the buffer to store it
@@ -277,7 +287,6 @@
     int _get(char* buf, int len);
     
     Pipe<char> _pipe;           //!< the rx pipe
-    bool found;                 //!< flag if device is detected.
     unsigned char _i2cAdr;      //!< the i2c address
     static const char REGLEN;   //!< the length i2c register address
     static const char REGSTREAM;//!< the stream i2c register address
--- a/MDM.cpp	Thu May 15 08:25:45 2014 +0000
+++ b/MDM.cpp	Thu May 15 22:20:42 2014 +0000
@@ -2,30 +2,34 @@
 #include <ctype.h>
 #include <string.h>
 #include "MDM.h"
+#include "Relax.h"
+#ifdef TARGET_UBLOX_C027
+ #include "C027_api.h"
+#endif
 
-#define TRACE           (1/*1=off,0=trace*/)?:printf
-//#define DEBUG         // enable this for AT command debugging
-#define PROFILE         "0"   // this is the psd profile used
-// some helper 
+#define PROFILE         "0"   //!< this is the psd profile used
+#define MAX_SIZE        128   //!< max expected messages
+//! test if it is a socket
 #define ISSOCKET(s)     (((s) >= 0) && ((s) < (sizeof(_sockets)/sizeof(*_sockets))))
-#define WAIT_MS(ms)     wait_ms(ms) // you may choose to use Thread::wait(ms)
 
-#define MAX_SIZE        128   // max expected messages
 
-#ifdef DEBUG
-void dump(const char* buf, int len)
+#ifdef MDM_DEBUG
+void dumpAtCmd(const char* buf, int len)
 {
+    printf(" %3d \"", len);
     while (len --) {
         char ch = *buf++;
-        if      (ch == '\r') printf("\\r");
-        else if (ch == '\n') printf("\\n");
-        else if (ch >= 0x20) printf("%c", ch);
+        if      (ch == '\r') puts("\\r");
+        else if (ch == '\n') puts("\\n");
+        else if (ch >= 0x20) putchar(ch);
         else                 printf("\\x%02x", ch);
     }
+    puts("\"\r\n");
 }
-
-Timer dbgTime; 
-
+ 
+ #define INFO  (_debugLevel >= 1) ? : printf
+ #define TRACE (_debugLevel >= 2) ? : printf
+ 
  #if 1 // colored terminal output using ANSI escape sequences
   #define COL(c,t) "\33[" c t "\33[" "39m"
  #else
@@ -39,6 +43,12 @@
  #define MAG(t) COL("35m",t)
  #define CYA(t) COL("36m",t)
  #define WHY(t) COL("37m",t)
+ 
+#else
+ 
+ #define INFO(...)  (void)0 // no tracing
+ #define TRACE(...) (void)0 // no tracing
+
 #endif
 
 MDMParser* MDMParser::inst;
@@ -52,18 +62,27 @@
     _net.ci = 0xFFFFFFFF;
     _ip        = NOIP;
     memset(_sockets, 0, sizeof(_sockets));
-#ifdef DEBUG
-    dbgTime.start();    
+#ifdef MDM_DEBUG
+    _debugTime.start();
+#endif
+}
+
+MDMParser::~MDMParser(void)
+{
+    powerOff();
+#ifdef TARGET_UBLOX_C027
+    if (_onboard)
+        c027_mdm_powerOff();
 #endif
 }
 
 int MDMParser::send(const char* buf, int len)
 {
-#ifdef DEBUG
-    printf("%10.3f ", dbgTime.read_ms()*0.001);
-    printf("AT send    %4d \"", len);
-    dump(buf,len);
-    printf("\"\r\n");
+#ifdef MDM_DEBUG
+    if (_debugLevel >= 3) {
+        printf("%10.3f AT send    ", _debugTime.read_ms()*0.001);
+        dumpAtCmd(buf,len);
+    }
 #endif
     return _send(buf, len);
 }
@@ -86,8 +105,8 @@
     timer.start();
     do {
         int ret = getLine(buf, sizeof(buf));
-#ifdef DEBUG
-        if ((ret != WAIT) && (ret != NOT_FOUND))
+#ifdef MDM_DEBUG
+        if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND))
         {
             int len = LENGTH(ret);
             int type = TYPE(ret);
@@ -98,10 +117,8 @@
                             (type == TYPE_PLUS)   ? CYA(" + ") : 
                             (type == TYPE_PROMPT) ? BLU(" > ") : 
                                                         "..."  ;
-            printf("%10.3f ", dbgTime.read_ms()*0.001);
-            printf("AT read %s %3d \"", s, len);
-            dump(buf, len);
-            printf("\"\r\n");
+            printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
+            dumpAtCmd(buf, len);
         }
 #endif        
         if ((ret != WAIT) && (ret != NOT_FOUND))
@@ -193,7 +210,7 @@
             }
         }
         // relax a bit
-        WAIT_MS(10); 
+        RELAX_MS(10); 
     }
     while ((timeout_ms == TIMEOUT_BLOCKING) || 
            (timer.read_ms() < timeout_ms));
@@ -225,46 +242,60 @@
 bool MDMParser::connect(
             const char* simpin, 
             const char* apn, const char* username, const char* password,
-            bool dump)
+            PinName pn)
 {
     DevStatus devStatus = {};
-    WAIT_MS(2000);
-    bool mdmOk = init(simpin, &devStatus);
-    if (dump) dumpDevStatus(&devStatus);
+    bool mdmOk = init(simpin, &devStatus, pn);  
+#ifdef MDM_DEBUG
+    if (_debugLevel >= 1) dumpDevStatus(&devStatus);
+#endif
     if (!mdmOk)
         return false;
     // wait until we are connected
-    int i = 60;
+    int i = 180;
     NetStatus netStatus = {};
+    INFO("Modem::register\r\n");
     while (!checkNetStatus(&netStatus))
     {
         if ((netStatus.reg == REG_DENIED) || (i == 0))
             break;;
         i --;
-        WAIT_MS(1000);
+        RELAX_MS(1000);
     }
-    if (dump) dumpNetStatus(&netStatus);
+#ifdef MDM_DEBUG
+    if (_debugLevel >= 1) dumpNetStatus(&netStatus);
+#endif
     if ((netStatus.reg == REG_DENIED) || (i == 0))
         return false;
     IP ip = join(apn,username,password);
-    if (dump) dumpIp(ip);
+#ifdef MDM_DEBUG
+    if (_debugLevel >= 1) dumpIp(ip);
+#endif
     if (ip == NOIP)
         return false; 
     return true;
 }
 
-bool MDMParser::init(const char* simpin, DevStatus* status)
+bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn)
 {
-    int i = 5;
-    // we should wait some time before 
-    while (i--) {
-        // check interface and disable local echo
-        sendFormated("AT\r\n");
-        if(RESP_OK == waitFinalResp(NULL,NULL,1000))
-            break;
+    int i = 10;
+    if (pn != NC) {
+        INFO("Modem::wakeup\r\n");
+        DigitalOut pin(pn, 1);
+        while (i--) {
+            pin = 0;
+            RELAX_MS(5); // SARA-G/U
+            pin = 1;
+            RELAX_MS(100);
+            // check interface and disable local echo
+            sendFormated("AT\r\n");
+            if(RESP_OK == waitFinalResp(NULL,NULL,500))
+                break;
+        }
+        if (i < 0)
+            return false;
     }
-    if (i < 0)
-        return false;
+    INFO("Modem::init\r\n");
     // echo off
     sendFormated("AT E0\r\n");
     if(RESP_OK != waitFinalResp())
@@ -277,7 +308,7 @@
     sendFormated("AT+IPR=115200\r\n");
     if (RESP_OK != waitFinalResp())
         return false;
-    WAIT_MS(40);
+    RELAX_MS(40);
     // identify the module 
     sendFormated("ATI\r\n");
     if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev))
@@ -334,14 +365,14 @@
             // Enter PIN if needed
             if (_dev.sim == SIM_PIN) {
                 if (!simpin) {
-                    TRACE("SIM PIN not available\r\n");
+                    INFO("SIM PIN not available\r\n");
                     return false;
                 }
                 sendFormated("AT+CPIN=%s\r\n", simpin);
                 if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim))
                     return false;
             } else if (_dev.sim != SIM_READY) {
-                WAIT_MS(1000);
+                RELAX_MS(1000);
             }
         }
         if (_dev.sim != SIM_READY)
@@ -403,6 +434,15 @@
     return true; 
 }
 
+bool MDMParser::powerOff(void)
+{
+    INFO("Modem::powerOff\r\n");
+    sendFormated("AT+CPWROFF\r\n");
+    if (RESP_OK != waitFinalResp(NULL,NULL,120*1000))
+        return false;
+    return true;
+}
+
 int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev)
 {
     if ((type == TYPE_UNKNOWN) && dev) {
@@ -538,19 +578,13 @@
     }
     return WAIT;
 }
-bool MDMParser::powerOff(void)
-{
-    sendFormated("AT+CPWROFF\r\n");
-    if (RESP_OK != waitFinalResp(NULL,NULL,120))
-        return false;
-    return true;
-}
 
 // ----------------------------------------------------------------
 // internet connection 
 
 MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, const char* password /*= NULL*/)
 {
+    TRACE("Modem::join\r\n");
     _ip = NOIP;
     if (_dev.dev == DEV_LISA_C200) {
         // TODO: is there something to do here?
@@ -565,7 +599,7 @@
     } else { 
         // check gprs attach status 
         sendFormated("AT+CGATT=1\r\n");
-        if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000))
+        if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) 
             return NOIP;
         
         // Check the profile
@@ -601,8 +635,10 @@
             return NOIP;
         // Activate the profile and make connection
         sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
-        if (RESP_OK != waitFinalResp(NULL,NULL,150*1000))
+        if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) {
+            INFO("Your modem APN/password/username may be wrong\r\n");
             return NOIP;
+        }
         //Get local IP address
         sendFormated("AT+UPSND=" PROFILE ",0\r\n");
         if (RESP_OK != waitFinalResp(_cbUPSND, &_ip))
@@ -655,6 +691,7 @@
 {
     if (_ip == NOIP)
         return true;
+    INFO("Modem::disconnect\r\n");
     if (_dev.dev == DEV_LISA_C200) {
         // TODO: is there something to do here?
     } else { 
@@ -738,7 +775,6 @@
     TRACE("socketIsConnected(%d)\r\n", socket);
     if (!ISSOCKET(socket))
         return false;
-    TRACE(" ... %d\r\n", _sockets[socket].state);
     return _sockets[socket].state == SOCK_CONNECTED;
 }
 
@@ -786,7 +822,7 @@
         sendFormated("AT+USOWR=%d,%d\r\n",socket,blk);
         if (RESP_PROMPT != waitFinalResp())
             return SOCKET_ERROR;
-        WAIT_MS(50);
+        RELAX_MS(50);
         send(buf, blk);
         if (RESP_OK != waitFinalResp()) 
             return SOCKET_ERROR;
@@ -807,7 +843,7 @@
        sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk);
         if (RESP_PROMPT != waitFinalResp())
             return SOCKET_ERROR;
-        WAIT_MS(50);
+        RELAX_MS(50);
         send(buf, blk);
         if (RESP_OK != waitFinalResp())
             return SOCKET_ERROR;
@@ -1034,7 +1070,17 @@
 }
    
 // ----------------------------------------------------------------
- 
+bool MDMParser::setDebug(int level) 
+{
+#ifdef MDM_DEBUG
+    if ((_debugLevel >= 0) && (level >= 0)) {
+        _debugLevel = level;
+        return true;
+    }
+#endif
+    return false;
+}
+
 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, 
             _DPRINT dprint, void* param) 
 {
@@ -1158,7 +1204,6 @@
     return o; 
 }
 
-
 int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len)
 {
     int unkn = 0;
@@ -1230,6 +1275,14 @@
             int rxSize /*= 256*/, int txSize /*= 128*/) : 
             SerialPipe(tx, rx, rxSize, txSize) 
 {
+#ifdef MDM_DEBUG
+    _debugLevel = (tx == USBTX) ? -1 : 1;
+#endif    
+#ifdef TARGET_UBLOX_C027
+    _onboard = (tx == MDMTXD) && (rx == MDMRXD);
+    if (_onboard)
+       c027_mdm_powerOn(false);
+#endif
     baud(baudrate);
 #if DEVICE_SERIAL_FC
     if ((rts != NC) || (cts != NC))
@@ -1257,8 +1310,16 @@
 // ----------------------------------------------------------------
 
 #ifdef HAVE_MDMUSB
-// TODO properly implement with USB 
-MDMUsb::MDMUsb(void)                             { }
+MDMUsb(void)                             
+{ 
+#ifdef MDM_DEBUG
+    _debugLevel = 1;
+#endif    
+#ifdef TARGET_UBLOX_C027
+    _onboard = true;
+    c027_mdm_powerOn(true);
+#endif
+}
 int MDMUsb::_send(const void* buf, int len)      { return len; }
 int MDMUsb::getLine(char* buffer, int length)    { return NOT_FOUND; }
 #endif
--- a/MDM.h	Thu May 15 08:25:45 2014 +0000
+++ b/MDM.h	Thu May 15 22:20:42 2014 +0000
@@ -7,14 +7,16 @@
 #include "SerialPipe.h"
 
 #ifdef TARGET_UBLOX_C027
- // if we detect the C027 platform we will assign the 
- // default pinname and baudrate in the constructor 
- // this helper macro will be used. 
- #define _C027DEFAULT(name) = name
+ #define _IF(onboard,shield) onboard
 #else
- #define _C027DEFAULT(name)
+ #define _IF(onboard,shield) shield
 #endif
 
+//! include debug capabilty on more powerful targets with a dedicated debug port 
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC4088) || defined(TARGET_K64F)
+ #define MDM_DEBUG 
+#endif 
+
 /** basic modem parser class 
 */
 class MDMParser
@@ -22,6 +24,8 @@
 public:
     //! Constructor 
     MDMParser();
+    //! Destructor 
+    ~MDMParser();
     //! get static instance
     static MDMParser* getInstance() { return inst; };
     
@@ -94,14 +98,15 @@
     */
     bool connect(const char* simpin, 
             const char* apn, const char* username, const char* password,
-            bool dump);    
+            PinName pn _IF( = MDMPWRON, = D4));    
 
     /** register (Attach) the MT to the GPRS service. 
         \param simpin a optional pin of the SIM card
         \param status an optional struture to with device information 
         \return true if successful, false otherwise
     */
-    bool init(const char* simpin = NULL, DevStatus* status = NULL);
+    bool init(const char* simpin = NULL, DevStatus* status = NULL, 
+                PinName pn _IF( = MDMPWRON, = D4));
     
     /** check if the network is available 
         \param status an optional structure to with network information 
@@ -279,9 +284,15 @@
     bool ussdCommand(const char* cmd, char* buf);
     
     // ----------------------------------------------------------------
-    // DUMP status to standard out (printf)
+    // DEBUG/DUMP status to standard out (printf)
     // ----------------------------------------------------------------
     
+    /*! Set the debug level 
+        \param level 0 = OFF, 1 = INFO(default), 2 = TRACE, 3 = ATCMD
+        \return true if successful, false not possible
+    */ 
+    bool setDebug(int level);
+
     //! helper type for DPRINT
     typedef int (*_DPRINT)(void* param, char const * format, ...);
     
@@ -294,7 +305,7 @@
     static void func(type arg, \
                 _DPRINT dprint = (_DPRINT)fprintf, \
                 void* param = (void*)stdout);
-        
+
     /** dump the device status to stdout using printf
         \param status the status to convert to textual form, 
                unavailable fields are ommited (not printed)
@@ -487,6 +498,13 @@
     // LISA-U and SARA-G have 7 sockets starting at index 1
     SockCtrl _sockets[32];
     static MDMParser* inst;
+#ifdef TARGET_UBLOX_C027
+    bool _onboard;
+#endif
+#ifdef MDM_DEBUG
+    int _debugLevel;
+    Timer _debugTime;
+#endif
 };
 
 // -----------------------------------------------------------------------
@@ -509,12 +527,12 @@
         \param rxSize the size of the serial rx buffer
         \param txSize the size of the serial tx buffer
     */
-    MDMSerial(PinName tx    _C027DEFAULT(MDMTXD), 
-              PinName rx    _C027DEFAULT(MDMRXD), 
-              int baudrate  _C027DEFAULT(MDMBAUD),
+    MDMSerial(PinName tx    _IF( = MDMTXD,  = D1 ), 
+              PinName rx    _IF( = MDMRXD,  = D2 ), 
+              int baudrate  _IF( = MDMBAUD, = 115200 ),
  #if DEVICE_SERIAL_FC
-              PinName rts   _C027DEFAULT(MDMRTS), 
-              PinName cts   _C027DEFAULT(MDMCTS),
+              PinName rts   _IF( = MDMRTS,  = NC ), 
+              PinName cts   _IF( = MDMCTS,  = NC ),
  #endif
               int rxSize    = 256 , 
               int txSize    = 128 );
--- a/Pipe.h	Thu May 15 08:25:45 2014 +0000
+++ b/Pipe.h	Thu May 15 22:20:42 2014 +0000
@@ -15,7 +15,7 @@
     */
     Pipe(int n, T* b = NULL)
     {
-        _a = b ? NULL : new T[n];
+        _a = b ? NULL : n ? new T[n] : NULL;
         _r = 0;
         _w = 0;
         _b = b ? b : _a;
@@ -98,7 +98,7 @@
             for (;;) // wait for space
             {
                 f = free();
-                if (f)  break;        // data avail
+                if (f > 0) break;     // data avail
                 if (!t) return n - c; // no more space and not blocking
             }
             // check free space
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Relax.cpp	Thu May 15 22:20:42 2014 +0000
@@ -0,0 +1,8 @@
+
+#include "Relax.h"
+
+// weak override wait function from cmsis_os.h on non rtos builds
+extern "C" WEAK void osDelay(uint32_t ms) { 
+    wait_ms(ms); 
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Relax.h	Thu May 15 22:20:42 2014 +0000
@@ -0,0 +1,16 @@
+#pragma once 
+
+#include "mbed.h"
+
+// declare the osDelay (usually from cmsis_os.h)
+extern "C" void osDelay(uint32_t ms);
+
+/** A wait function that is independent whether the OS is includes or not
+    if rtos is included the Thread will yield for a certain time 
+    otherwise (without rtos) it will just stay in a busy loop.
+    
+    \param ms number of milliseconds to wait
+*/
+inline void RELAX_MS(int ms) { 
+    osDelay(ms); 
+}
\ No newline at end of file
--- a/SerialPipe.cpp	Thu May 15 08:25:45 2014 +0000
+++ b/SerialPipe.cpp	Thu May 15 22:20:42 2014 +0000
@@ -2,10 +2,13 @@
 
 #include "SerialPipe.h"
 
-SerialPipe::SerialPipe(PinName tx, PinName rx, int rxSize, int txSize) 
-    : _SerialPipeBase(tx,rx), _pipeRx(rxSize), _pipeTx(txSize)
+SerialPipe::SerialPipe(PinName tx, PinName rx, int rxSize, int txSize) : 
+            _SerialPipeBase(tx,rx), 
+            _pipeRx( (rx!=NC) ? rxSize : 0), 
+            _pipeTx( (tx!=NC) ? txSize : 0)
 {
-    attach(this, &SerialPipe::rxIrqBuf, RxIrq);
+    if (rx!=NC)
+        attach(this, &SerialPipe::rxIrqBuf, RxIrq);
 }
 
 SerialPipe::~SerialPipe(void)