Csr location class shows location and satellite information, which supports H13467 + ST F103RB/NXP LCP1549 boards now.

Dependents:   CsrLocationDemo CsrLocationDemo

Fork of CsrLocation by jie zhao

Files at this revision

API Documentation at this revision

Comitter:
zhjcpi
Date:
Wed May 21 08:55:55 2014 +0000
Parent:
2:d4fe184925f2
Child:
4:0d9b711fb646
Commit message:
Unify code for different platform.

Changed in this revision

CsrLocation.cpp Show annotated file Show diff for this revision Revisions of this file
CsrLocation.h Show annotated file Show diff for this revision Revisions of this file
--- a/CsrLocation.cpp	Wed Mar 26 09:16:55 2014 +0000
+++ b/CsrLocation.cpp	Wed May 21 08:55:55 2014 +0000
@@ -17,6 +17,8 @@
 static uint8_t sOspSwitch2NmeaReq[] = {0xA0, 0xA2, 0x00, 0x18, 0x81, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x05, 0x01, 0x01, 0x01, 0x00, 
                                 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x12, 0xC0, 0x01, 0x64, 0xB0, 0xB3};
 static char sNmeaSwitch2OspReq[] = "$PSRF100,0,115200,8,1,0*04\r\n";
+static char sNmeaStopReq[] = "$PSRF117,16*0B\r\n";
+
 
 CsrLocation::CsrLocation(tCsrLocConfig *pLocConfig)
 {
@@ -56,7 +58,7 @@
 	_CsrLocHwReset();
 }
 
-void CsrLocation::CsrLocStart(ePowerMode pwrMode)
+void CsrLocation::CsrLocStart(ePowerMode pwrMode, eProto proto)
 {
     csrLocInst.pwrMode = pwrMode;
 
@@ -64,10 +66,22 @@
     {
         /* Csr Location SDK version */
         CSR_LOG_INFO("==== CSR LOC SDK version: %s Date: %s ====\r\n", CSR_LOC_SDK_VER, __DATE__ "  " __TIME__);
+
+        csrLocInst.proto = proto;
+        
         /* open UART */
-        CSR_LOG_INFO("Checking OSP protocol...\r\n");
-        csrLocInst.protoState  = PROTO_STATE_DET_OSP;
-        csrLocInst.baudRate    = BAUDRATE_OSP;
+        if(proto == PROTO_NMEA)
+        {
+            CSR_LOG_INFO("Checking NMEA protocol...\r\n");
+            csrLocInst.protoState  = PROTO_STATE_DET_NMEA;
+            csrLocInst.baudRate    = BAUDRATE_NMEA;
+        }
+        else
+        {
+            CSR_LOG_INFO("Checking OSP protocol...\r\n");
+            csrLocInst.protoState  = PROTO_STATE_DET_OSP;
+            csrLocInst.baudRate    = BAUDRATE_OSP;
+        }
         _CsrLocUartInit();
 
         /* trigger on_off */
@@ -103,8 +117,15 @@
         /* in sleep mode, trigger on_off firstly */
         _CsrLocHwOnoff();
         wait_ms(500);
-    }    
-    _CsrLocSendData(SEND_DATA_TYPE_OSP_STOP_REQ);
+    }
+    if(csrLocInst.proto == PROTO_NMEA)
+    {
+        _CsrLocSendData(SEND_DATA_TYPE_NMEA_STOP_REQ);
+    }
+    else
+    {
+        _CsrLocSendData(SEND_DATA_TYPE_OSP_STOP_REQ);
+    }
     wait_ms(10);
     _CsrLocHwReset();
     csrLocInst.locState = CSR_LOC_STATE_IDLE;
@@ -166,6 +187,25 @@
     tCsrLocInst *pLocInst = &csrLocInst;
     uint8_t    data;
 
+    if(pLocInst->bTimeoutFlag)
+    {
+        pLocInst->pTimeoutChk->detach();
+        pLocInst->bTimeoutFlag = false;
+        if(pLocInst->protoState == PROTO_STATE_DET_OSP || pLocInst->protoState == PROTO_STATE_DET_OSP_FROM_NMEA)
+        {
+            _CsrLocDetProtoOspTimeout();
+        }
+        else if(pLocInst->protoState == PROTO_STATE_DET_NMEA || pLocInst->protoState == PROTO_STATE_DET_NMEA_FROM_OSP)
+        {
+            _CsrLocDetProtoNmeaTimeout();
+        }
+        else
+        {
+            CSR_LOG_INFO("timeout in unknown protocol state %d.\r\n", pLocInst->protoState);
+        }
+        return;
+    }
+
     if(pLocInst->in != pLocInst->out)
     {
         data = pLocInst->serialBuf[pLocInst->out++];
@@ -174,13 +214,21 @@
         {
         case PROTO_STATE_DET_OSP:
         case PROTO_STATE_DET_OSP_FROM_NMEA:
-            _CsrLocDetProtoOsp(data);
+            _CsrLocProcessRawOspStream(data);
             break;
         case PROTO_STATE_DET_NMEA:
-            _CsrLocDetProtoNmea(data);
+        case PROTO_STATE_DET_NMEA_FROM_OSP:
+            _CsrLocProcessRawNmeaStream(data);
             break;
         case PROTO_STATE_DET_OK:
-            _CsrLocProcessRawOspStream(data);
+            if(pLocInst->proto == PROTO_NMEA)
+            {
+                _CsrLocProcessRawNmeaStream(data);
+            }
+            else
+            {
+                _CsrLocProcessRawOspStream(data);
+            }
             break;
         default:
             /* Discard received data */
@@ -190,16 +238,23 @@
     }
 }
 
-void CsrLocation::_CsrLocDetProtoOsp(uint8_t data)
+void CsrLocation::_CsrLocDetProtoOspTimeout(void)
 {
     tCsrLocInst *pLocInst = &csrLocInst;
 
-    if(pLocInst->bTimeoutFlag)
+    if(pLocInst->proto == PROTO_NMEA)
+    {
+        /* Failed to detect OSP */
+        pLocInst->pSerialLoc->attach(NULL);
+        pLocInst->protoState = PROTO_STATE_DET_INVALID;
+        pLocInst->baudRate = BAUDRATE_NMEA;
+        CSR_LOG_INFO("Checking OSP failed.\r\n");
+        pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 1);
+    }
+    else
     {
         /* Failed to detect OSP and try to detect NMEA */
         pLocInst->pSerialLoc->attach(NULL);
-        pLocInst->pTimeoutChk->detach();
-        pLocInst->bTimeoutFlag = false;
         if(pLocInst->protoState == PROTO_STATE_DET_OSP)
         {
             pLocInst->protoState = PROTO_STATE_DET_NMEA;
@@ -213,29 +268,48 @@
             CSR_LOG_INFO("Checking switched OSP protocol failed.\r\n");
             pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 1);
         }
-        return;
     }
-
-    _CsrLocProcessRawOspStream(data);
 }
 
-void CsrLocation::_CsrLocDetProtoNmea(uint8_t data)
+void CsrLocation::_CsrLocDetProtoNmeaTimeout(void)
 {
     tCsrLocInst *pLocInst = &csrLocInst;
 
-    if(pLocInst->bTimeoutFlag)
+    CSR_LOG_INFO("Checking NMEA protocol failed\r\n");
+
+    if(pLocInst->proto == PROTO_NMEA)
     {
-        /* Failed to detect OSP and try to detect NMEA */
+        /* Failed to detect NMEA and try to detect OSP */
         pLocInst->pSerialLoc->attach(NULL);
-        pLocInst->pTimeoutChk->detach();
-        pLocInst->bTimeoutFlag = false;
+        if(pLocInst->protoState == PROTO_STATE_DET_NMEA)
+        {
+            pLocInst->protoState = PROTO_STATE_DET_OSP;
+            pLocInst->baudRate = BAUDRATE_OSP;
+            CSR_LOG_INFO("Checking NMEA protocol failed, now check OSP protocol...\r\n");
+            _CsrLocUartInit();
+        }
+        else
+        {
+            pLocInst->protoState = PROTO_STATE_DET_INVALID;
+            CSR_LOG_INFO("Checking switched NMEA protocol failed.\r\n");
+            pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 1);
+        }
+    }
+    else
+    {
+        /* Failed to detect NEMA */
+        pLocInst->pSerialLoc->attach(NULL);
         pLocInst->protoState = PROTO_STATE_DET_INVALID;
         pLocInst->baudRate = BAUDRATE_OSP;
         CSR_LOG_INFO("Checking NMEA failed.\r\n");
         pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 1);
-        return;
     }
+}
 
+void CsrLocation::_CsrLocProcessRawNmeaStream(uint8_t data)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+    
     switch (pLocInst->protoDetState)
     {
     case STATE_START1:
@@ -249,6 +323,8 @@
         if (NMEA_MSG_HEAD1 == data)
         {
             pLocInst->protoDetState = STATE_END1;
+            pLocInst->decodeIndex = 0;
+            pLocInst->serialPkt[pLocInst->decodeIndex++] = data;
         }
         else if (NMEA_MSG_HEAD0 == data)
         {
@@ -262,24 +338,49 @@
     case STATE_END1:
         if (NMEA_MSG_TAIL0 == data)
         {
-            pLocInst->pSerialLoc->attach(NULL);
             pLocInst->pTimeoutChk->detach();
             pLocInst->bTimeoutFlag = false;
-            pLocInst->protoState = PROTO_STATE_SWI_OSP_FROM_NMEA;
-            pLocInst->protoDetState = STATE_START1;
-            CSR_LOG_INFO("Checking OSP protocol OK, switching to OSP...\r\n");
-            _CsrLocSendData(SEND_DATA_TYPE_NMEA_SWITCH2OSP_REQ);
-            wait_ms(100);
+            if(pLocInst->proto == PROTO_NMEA)
+            {
+                pLocInst->protoDetState = STATE_START1;
+                if(pLocInst->protoState == PROTO_STATE_DET_NMEA || pLocInst->protoState == PROTO_STATE_DET_NMEA_FROM_OSP)
+                {
+                    CSR_LOG_INFO("Checking NMEA protocol OK.\r\n");
+                    pLocInst->protoState = PROTO_STATE_DET_OK;
+                    pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 0);
+                }
 
-            pLocInst->protoState = PROTO_STATE_DET_OSP_FROM_NMEA;
-            pLocInst->baudRate = BAUDRATE_OSP;
-            CSR_LOG_INFO("Checking switched OSP protocol...\r\n");
-            _CsrLocUartInit();
+                pLocInst->serialPkt[pLocInst->decodeIndex++] = '\0';
+                _CsrLocProcessRawNmeaPkt();
+            }
+            else
+            {
+                pLocInst->pSerialLoc->attach(NULL);
+                
+                CSR_LOG_INFO("Checking NMEA protocol OK, switching to OSP...\r\n");
+                _CsrLocSendData(SEND_DATA_TYPE_NMEA_SWITCH2OSP_REQ);
+                wait_ms(100);
+                pLocInst->protoState = PROTO_STATE_DET_OSP_FROM_NMEA;
+                pLocInst->baudRate = BAUDRATE_OSP;
+                CSR_LOG_INFO("Checking switched OSP protocol...\r\n");
+                _CsrLocUartInit();
+            }
         }
         else if (NMEA_MSG_HEAD0 == data)
         {               
             pLocInst->protoDetState = STATE_START2;
         }
+        else
+        {
+            if(pLocInst->decodeIndex < (MAX_SERIAL_PKT_LEN - 2))
+            {
+                pLocInst->serialPkt[pLocInst->decodeIndex++] = data;
+            }
+            else
+            {
+                pLocInst->protoDetState = STATE_START1;
+            }
+        }
         break;
     default:
         break;
@@ -418,16 +519,32 @@
         {
             pLocInst->pTimeoutChk->detach();
             pLocInst->bTimeoutFlag = false;
+            pLocInst->protoDetState = STATE_START1;
 
-            if(pLocInst->protoState == PROTO_STATE_DET_OSP || pLocInst->protoState == PROTO_STATE_DET_OSP_FROM_NMEA)
+            if(pLocInst->proto == PROTO_NMEA)
             {
-                CSR_LOG_INFO("Checking OSP protocol OK.\r\n");
-                pLocInst->protoState = PROTO_STATE_DET_OK;
-                pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 0);
+                pLocInst->pSerialLoc->attach(NULL);
+                
+                CSR_LOG_INFO("Checking OSP protocol OK, switching to NMEA...\r\n");
+                _CsrLocSendData(SEND_DATA_TYPE_OSP_SWITCH2NMEA_REQ);
+                wait_ms(100);
+                pLocInst->protoState = PROTO_STATE_DET_NMEA_FROM_OSP;
+                pLocInst->baudRate = BAUDRATE_NMEA;
+                CSR_LOG_INFO("Checking switched NMEA protocol...\r\n");
+                _CsrLocUartInit();
+
             }
-            
-            _CsrLocProcessRawOspPkt();
-            pLocInst->protoDetState = STATE_START1;
+            else
+            {
+                if(pLocInst->protoState == PROTO_STATE_DET_OSP || pLocInst->protoState == PROTO_STATE_DET_OSP_FROM_NMEA)
+                {
+                    CSR_LOG_INFO("Checking OSP protocol OK.\r\n");
+                    pLocInst->protoState = PROTO_STATE_DET_OK;
+                    pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 0);
+                }
+                
+                _CsrLocProcessRawOspPkt();
+            }
         }
         else
         {
@@ -445,6 +562,61 @@
     
 }
 
+void CsrLocation::_CsrLocProcessRawNmeaPkt(void)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+    tLocPosResp pos;
+    const char *pNmeaGga = "GPGGA";
+    float       deg, min;
+	char        ns, ew;
+	int         svUsed;
+	float       horDop;
+    int         valid;
+    int         i, cnt;
+
+    if(strncmp((char *)pLocInst->serialPkt, pNmeaGga, strlen(pNmeaGga)) == 0)
+    {
+        cnt = 0;
+        for(i = 0; i < (int)strlen((char *)pLocInst->serialPkt); i++)
+        {
+            if(pLocInst->serialPkt[i] == ',')
+            {
+                cnt++;
+                if(cnt == 6)
+                {
+                    break;
+                }
+            }
+        }
+        if(cnt != 6)
+        {
+            return;
+        }
+        i++;
+        sscanf((char *)(&pLocInst->serialPkt[i]), "%d,", &valid);
+        if(valid == 0)
+        {
+            return;
+        }
+        
+        /* Parse GPGGA and output position information */
+        memset(&pos, 0, sizeof(tLocPosResp));
+        if(sscanf((char *)pLocInst->serialPkt, "GPGGA,%f,%lf,%c,%lf,%c,%d,%d,%f,%lf", &pos.u.utcTime, &pos.lat, &ns, &pos.lon, &ew, &valid, &svUsed, &horDop, &pos.alt) >= 1)
+        {
+			if(ns == 'S') {	pos.lat  *= -1.0; }
+			if(ew == 'W') {	pos.lon *= -1.0; }
+			deg = (float)(static_cast<int>(pos.lat * 0.01f));
+			min = pos.lat - (deg * 100.0f);
+			pos.lat = deg + min / 60.0f;	
+			deg = (float)(static_cast<int>(pos.lon * 0.01f));
+			min = pos.lon - (deg * 100.0f);
+			pos.lon = deg + min / 60.0f;
+
+            csrLocInst.appOutCb(LOC_OUTPUT_LOCATION, &pos, sizeof(tLocPosResp));
+        }
+    }
+}
+
 void CsrLocation::_CsrLocProcessRawOspPkt(void)
 {
     tCsrLocInst *pLocInst = &csrLocInst;
@@ -582,8 +754,8 @@
             *pMsgLen = sizeof(*pPos);
 
             ptr += 2;
-            pPos->gps_week  = BINARY_IMPORT_UINT16(ptr);
-            pPos->tow       = BINARY_IMPORT_UINT32(ptr);
+            pPos->u.gpsTime.gps_week = BINARY_IMPORT_UINT16(ptr);
+            pPos->u.gpsTime.tow      = BINARY_IMPORT_UINT32(ptr);
             ptr += 12;
             pPos->lat       = (double)BINARY_IMPORT_SINT32(ptr);
             pPos->lat      *= 1e-7;
@@ -785,7 +957,7 @@
     pLocInst->in &= (MAX_SERIAL_BUF_LEN-1);
     if(pLocInst->in == pLocInst->out)
     {
-        CSR_LOG_INFO("rx overwritten %d %d.\r\n", pLocInst->in, pLocInst->out);
+        CSR_LOG_INFO("rx overwritten %lu %lu.\r\n", pLocInst->in, pLocInst->out);
     }
 }
 
@@ -821,7 +993,11 @@
         pData = (const uint8_t *)sNmeaSwitch2OspReq;
         size  = strlen(sNmeaSwitch2OspReq);
         break;
-        
+    case SEND_DATA_TYPE_NMEA_STOP_REQ:
+        pData = (const uint8_t *)sNmeaStopReq;
+        size  = strlen(sNmeaStopReq);
+        break;
+    
     default:
         pData = NULL;
     }
--- a/CsrLocation.h	Wed Mar 26 09:16:55 2014 +0000
+++ b/CsrLocation.h	Wed May 21 08:55:55 2014 +0000
@@ -14,6 +14,31 @@
 #define CSR_RESULT_SUCCESS  ((CsrResult) 0x0000)
 #define CSR_RESULT_FAILURE  ((CsrResult) 0xFFFF)
 
+#ifdef TARGET_LPC1768
+#define PINMAP_UART_DEBUG_TX        USBTX
+#define PINMAP_UART_DEBUG_RX        USBRX
+#define PINMAP_UART_LOC_TX          D8
+#define PINMAP_UART_LOC_RX          D9
+#define PINMAP_GPIO_LOC_ONOFF       D11
+#define PINMAP_GPIO_LOC_RESET       D12
+#define LOC_LED1                    LED1
+#define LOC_LED2                    LED2
+#define DBG_SERIAL_TYPE             RawSerial
+#define LOC_SERIAL_TYPE             RawSerial
+#elif defined(TARGET_LPC1549) || defined(TARGET_NUCLEO_F103RB)
+#define PINMAP_UART_DEBUG_TX        D1
+#define PINMAP_UART_DEBUG_RX        D0
+#define PINMAP_UART_LOC_TX          D8
+#define PINMAP_UART_LOC_RX          D2
+#define PINMAP_GPIO_LOC_ONOFF       D3
+#define PINMAP_GPIO_LOC_RESET       D4
+#define LOC_LED1                    LED1
+#define LOC_LED2                    LED2
+#define DBG_SERIAL_TYPE             Serial
+#define LOC_SERIAL_TYPE             RawSerial
+#endif
+
+
 /* OSP protocol related definitions */
 #define MAX_VERSION_LENGTH 80
 
@@ -86,6 +111,9 @@
 /* Indicates the outputted sv status information */
 #define LOC_OUTPUT_SV_STATUS            (2)
 
+#if 0
+#define CSR_LOG_INFO    printf
+#else
 #define CSR_LOG_INFO(...) \
 {\
     if(csrLocInst.pSerialDebug != NULL)\
@@ -93,6 +121,7 @@
         (csrLocInst.pSerialDebug->printf(__VA_ARGS__));\
     }\
 }
+#endif
 
 /** Location enent definitions */
 typedef enum
@@ -112,6 +141,15 @@
     PWR_PTF,
 }ePowerMode;
 
+/** Power mode selection */
+typedef enum
+{
+    /** NMEA protocol */
+    PROTO_NMEA,
+    /** OSP protocol */
+    PROTO_OSP,
+}eProto;
+
 /* Protocol detection state */
 typedef enum
 {
@@ -139,8 +177,10 @@
    PROTO_STATE_DET_INVALID = 0,
    PROTO_STATE_DET_OSP,
    PROTO_STATE_DET_NMEA,
-   PROTO_STATE_SWI_OSP_FROM_NMEA,
+//   PROTO_STATE_SWI_OSP_FROM_NMEA,
    PROTO_STATE_DET_OSP_FROM_NMEA,
+//   PROTO_STATE_SWI_NMEA_FROM_OSP,
+   PROTO_STATE_DET_NMEA_FROM_OSP,
    PROTO_STATE_DET_OK,
 }eProtoState;
 
@@ -161,16 +201,26 @@
     SEND_DATA_TYPE_OSP_LPM_REQ,
     SEND_DATA_TYPE_OSP_FPM_REQ,
     SEND_DATA_TYPE_OSP_SWITCH2NMEA_REQ,
-    SEND_DATA_TYPE_NMEA_SWITCH2OSP_REQ
+    SEND_DATA_TYPE_NMEA_SWITCH2OSP_REQ,
+    SEND_DATA_TYPE_NMEA_STOP_REQ
 }eSendDataType;
 
-/** Structure to hold Position Response Message Information. */
-typedef struct LocPosResp
+typedef struct GpsTime
 {
     /** Week part of GPS time */
     uint16_t            gps_week;
     /** Time of second part of GPS time */
     uint32_t            tow;
+}tGpsTime;
+
+/** Structure to hold Position Response Message Information. */
+typedef struct LocPosResp
+{
+    union
+    {
+        tGpsTime      gpsTime;
+        float         utcTime;
+    }u;
     /** Latitude */
     double            lat;
     /** Longitude */
@@ -256,9 +306,9 @@
 typedef struct CsrLocConfig
 {
     /** Debug serial port to print debug information */
-    RawSerial       *pSerialDebug;
+    DBG_SERIAL_TYPE *pSerialDebug;
     /** location serail port to communicate between mbed host side and location chip */
-    RawSerial       *pSerialLoc;
+    LOC_SERIAL_TYPE *pSerialLoc;
     /** GPIO pin to control location chip on, a rising edge is uset to activate location chip. Please note, before activate chip, reset pin should be pull high */
     DigitalOut      *pPinOnoff;
     /** GPIO pin to control location chip reset, low level will keep location chip in hibernation state and high level will permit location chip to be activated */
@@ -280,6 +330,7 @@
     bool            bPwrModeRsp;
     bool            bVerRsp;
 
+    eProto          proto;
     eCsrLocState    locState;
     eProtoState     protoState;
     ePowerMode      pwrMode;
@@ -295,8 +346,8 @@
 
     tLocSvStatus    svStatus;   /* 2 kind of messages contribute the svStaus */
 
-    RawSerial       *pSerialDebug;
-    RawSerial       *pSerialLoc;
+    DBG_SERIAL_TYPE *pSerialDebug;
+    LOC_SERIAL_TYPE *pSerialLoc;
     DigitalOut      *pPinOnoff;
     DigitalOut      *pPinReset;
 
@@ -336,7 +387,7 @@
     void CsrLocReset(void);
 
     /** Start location request, activate location chip */
-    void CsrLocStart(ePowerMode pwrMode);
+    void CsrLocStart(ePowerMode pwrMode, eProto proto);
 
     /** Process location data from chip and update location and satellite information */
     void CsrLocUpdate(void);
@@ -364,15 +415,21 @@
     /* Process the raw stream from location seraial port */
     void _CsrLocProcessRawStream(void);
 
-    /* Detect the OSP protocol outputted from location serial port */
-    void _CsrLocDetProtoOsp(uint8_t data);
+    /* Detect the OSP protocol detection timeout */
+    void _CsrLocDetProtoOspTimeout(void);
 
     /* Detect the NMEA protocol outputted from location serial port */
-    void _CsrLocDetProtoNmea(uint8_t data);
+    void _CsrLocDetProtoNmeaTimeout(void);
+
+    /* Process the raw NMEA stream, remove the NMEA header, tail, and save the NMEA data into interal buffer */
+    void _CsrLocProcessRawNmeaStream(uint8_t data);
 
     /* Process the raw OSP stream, remove the OSP header, size, check sum, and save the OSP data into interal buffer */
     void _CsrLocProcessRawOspStream(uint8_t data);
 
+    /* Process the saved nmea data and decode them */
+    void _CsrLocProcessRawNmeaPkt(void);
+
     /* Process the saved OSP data and decode them */
     void _CsrLocProcessRawOspPkt(void);
 
@@ -404,3 +461,4 @@
 
 
 #endif /* CSRLOCATION_H */
+