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:
Mon Mar 24 08:23:25 2014 +0000
Child:
1:bbaf9b8d646a
Commit message:
First edition for the CsrLocation lib.

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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CsrLocation.cpp	Mon Mar 24 08:23:25 2014 +0000
@@ -0,0 +1,838 @@
+
+/* CsrLocation class for mbed Microcontroller
+ * Copyright 2014 CSR plc
+ */
+
+
+#include "mbed.h"
+#include "CsrLocation.h"
+
+
+const static CsrUint8 sOspStopReq[] = {0xa0, 0xa2, 0x00, 0x02, 0xcd, 0x10, 0x00, 0xdd, 0xb0, 0xb3};
+const static CsrUint8 sOspVerReq[] = {0xA0, 0xA2, 0x00, 0x02, 0x84, 0x00, 0x00, 0x84, 0xB0, 0xB3};
+const static CsrUint8 sOspLpmReq[] = {0xA0, 0xA2, 0x00, 0x2A, 0xDA, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x01, 0x00, 0x78, 0x00, 0x1E,
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x63, 0xB0, 0xB3};
+const static CsrUint8 sOspFpmReq[] = {0xA0, 0xA2, 0x00, 0x03, 0xDA, 0x00, 0x00, 0x00, 0xDA, 0xB0, 0xB3};
+const static CsrUint8 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};
+const static CsrCharString sNmeaSwitch2OspReq[] = "$PSRF100,0,115200,8,1,0*04\r\n";
+
+CsrLocation::CsrLocation(tCsrLocConfig *pLocConfig)
+{
+    memset(&csrLocInst, 0, sizeof(tCsrLocInst));
+    csrLocInst.pSerialDebug = pLocConfig->pSerialDebug;
+    csrLocInst.pSerialLoc   = pLocConfig->pSerialLoc;
+    csrLocInst.pPinOnoff    = pLocConfig->pPinOnoff;
+    csrLocInst.pPinReset    = pLocConfig->pPinReset;
+    csrLocInst.pTimeoutChk  = new Timeout();
+
+    csrLocInst.pPinReset->write(1);
+    csrLocInst.pPinOnoff->write(0);
+}
+
+CsrLocation::~CsrLocation(void)
+{
+    if(csrLocInst.pTimeoutChk != NULL)
+    {
+        delete csrLocInst.pTimeoutChk;
+        csrLocInst.pTimeoutChk = NULL;
+    }
+    csrLocInst.pSerialLoc->attach(NULL);
+    csrLocInst.pPinReset->write(0);
+    csrLocInst.pPinOnoff->write(0);
+    memset(&csrLocInst, 0, sizeof(tCsrLocInst));
+
+}
+
+void CsrLocation::CsrLocRegOutput(csr_app_output_callback app_output_cb, csr_app_event_callback app_event_cb)
+{
+    csrLocInst.appOutCb = app_output_cb;
+    csrLocInst.appEventCb = app_event_cb;
+}
+
+void CsrLocation::CsrLocReset(void)
+{
+	_CsrLocHwReset();
+}
+
+void CsrLocation::CsrLocStart(ePowerMode pwrMode)
+{
+    csrLocInst.pwrMode = pwrMode;
+
+    if(csrLocInst.locState == CSR_LOC_STATE_IDLE)
+    {
+        /* Csr Location SDK version */
+        CSR_LOG_INFO("==== CSR LOC SDK version: %s Date: %s ====\r\n", CSR_LOC_SDK_VER, __DATE__ "  " __TIME__);
+        /* open UART */
+        CSR_LOG_INFO("Checking OSP protocol...\r\n");
+        csrLocInst.protoState  = PROTO_STATE_DET_OSP;
+        csrLocInst.baudRate    = BAUDRATE_OSP;
+        _CsrLocUartInit();
+
+        /* trigger on_off */
+        _CsrLocHwOnoff();
+
+        csrLocInst.locState = CSR_LOC_STATE_RUN;
+    }
+    else
+    {
+        CSR_LOG_INFO("Already started.\r\n");
+    }
+}
+
+void CsrLocation::CsrLocUpdate(void)
+{
+    if(csrLocInst.locState == CSR_LOC_STATE_RUN)
+    {
+        /* wait and process uart data */
+        _CsrLocProcessRawStream();
+    }
+}
+
+void CsrLocation::CsrLocStop(void)
+{
+    csrLocInst.pSerialLoc->attach(NULL);
+    CSR_LOG_INFO("Stop command processed.\r\n");
+
+    if(csrLocInst.locState == CSR_LOC_STATE_RUN && csrLocInst.pwrMode == PWR_PTF && csrLocInst.engStatus == ENGINE_STATUS_NOTOK2SEND)
+    {
+        /* in sleep mode, trigger on_off firstly */
+        _CsrLocHwOnoff();
+        wait_ms(500);
+    }    
+    _CsrLocSendData(SEND_DATA_TYPE_OSP_STOP_REQ);
+    wait_ms(10);
+    _CsrLocHwReset();
+    csrLocInst.locState = CSR_LOC_STATE_IDLE;
+    csrLocInst.appEventCb(CSR_LOC_EVENT_STOP_RESULT, 0);
+
+}
+
+void CsrLocation::CsrLocLpmGetPos(void)
+{
+    if(csrLocInst.locState == CSR_LOC_STATE_RUN && csrLocInst.pwrMode == PWR_PTF && csrLocInst.engStatus == ENGINE_STATUS_NOTOK2SEND)
+    {
+        CSR_LOG_INFO("LpmGetPos ");
+        _CsrLocHwOnoff();
+    }    
+}
+
+void CsrLocation::CsrLocDebugSwitch2Nmea(void)
+{
+    if(csrLocInst.locState == CSR_LOC_STATE_RUN)
+    {
+        _CsrLocSendData(SEND_DATA_TYPE_OSP_SWITCH2NMEA_REQ);
+        wait_ms(200);
+        _CsrLocHwReset();
+    }    
+}
+
+void CsrLocation::_CsrLocUartInit(void)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+
+    pLocInst->in            = 0;
+    pLocInst->out           = 0;
+    memset(pLocInst->serialBuf, 0 , MAX_SERIAL_BUF_LEN);
+    memset(pLocInst->serialPkt, 0 , MAX_SERIAL_PKT_LEN);
+
+    pLocInst->isOspHeader   = FALSE;
+    pLocInst->isNmeaHeader  = FALSE;
+    
+    pLocInst->checksum      = 0;
+    pLocInst->msgSize       = 0;
+    pLocInst->decodeIndex   = 0;
+    pLocInst->protoDetState = STATE_START1;
+    pLocInst->pTimeoutChk->attach(this, &CsrLocation::_CsrLocTimeout, PROTO_CHECK_TIMEOUT);
+
+    pLocInst->pSerialLoc->baud(pLocInst->baudRate);
+    pLocInst->pSerialLoc->attach(this, &CsrLocation::_CsrLocRxHandler );
+}
+
+void CsrLocation::_CsrLocProcessRawStream(void)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+    CsrUint8    data;
+
+    if(pLocInst->in != pLocInst->out)
+    {
+        data = pLocInst->serialBuf[pLocInst->out++];
+        pLocInst->out &= (MAX_SERIAL_BUF_LEN-1);
+        switch(pLocInst->protoState)
+        {
+        case PROTO_STATE_DET_OSP:
+            _CsrLocDetProtoOsp(data);
+            break;
+        case PROTO_STATE_DET_NMEA:
+            _CsrLocDetProtoNmea(data);
+            break;
+        case PROTO_STATE_DET_OSP_FROM_NMEA:
+            _CsrLocDetProtoOsp(data);
+            break;
+        case PROTO_STATE_DET_OK:
+            _CsrLocProcessRawOspStream(data);
+            break;
+        default:
+            /* Discard received data */
+            pLocInst->out = pLocInst->in;
+            break;
+        }
+    }
+    else
+    {
+        wait_ms(1);
+    }
+}
+
+void CsrLocation::_CsrLocDetProtoOsp(CsrUint8 data)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+
+    if(pLocInst->bTimeoutFlag)
+    {
+        /* 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;
+            pLocInst->baudRate = BAUDRATE_NMEA;
+            CSR_LOG_INFO("Checking OSP protocol failed, now check NMEA protocol...\r\n");
+            _CsrLocUartInit();
+        }
+        else
+        {
+            pLocInst->protoState = PROTO_STATE_DET_INVALID;
+            CSR_LOG_INFO("Checking switched OSP protocol failed.\r\n");
+            pLocInst->appEventCb(CSR_LOC_EVENT_START_RESULT, 1);
+        }
+        return;
+    }
+
+    _CsrLocProcessRawOspStream(data);
+}
+
+void CsrLocation::_CsrLocDetProtoNmea(CsrUint8 data)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+
+    if(pLocInst->bTimeoutFlag)
+    {
+        /* Failed to detect OSP and try to detect NMEA */
+        pLocInst->pSerialLoc->attach(NULL);
+        pLocInst->pTimeoutChk->detach();
+        pLocInst->bTimeoutFlag = FALSE;
+        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;
+    }
+
+    switch (pLocInst->protoDetState)
+    {
+    case STATE_START1:
+        if (NMEA_MSG_HEAD0 == data)
+        {
+            pLocInst->protoDetState = STATE_START2;
+        }
+        break;
+
+    case STATE_START2:
+        if (NMEA_MSG_HEAD1 == data)
+        {
+            pLocInst->protoDetState = STATE_END1;
+        }
+        else if (NMEA_MSG_HEAD0 == data)
+        {
+            pLocInst->protoDetState = STATE_START2;
+        }
+        else
+        {
+            pLocInst->protoDetState = STATE_START1;
+        }
+        break;
+    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);
+
+            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;
+        }
+        break;
+    default:
+        break;
+    }        
+}
+
+void CsrLocation::_CsrLocProcessRawOspStream(CsrUint8 data)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+
+    switch (pLocInst->protoDetState)
+    {
+    case STATE_START1:
+        if (OSP_MSG_HEAD0 == data)
+        {
+            pLocInst->protoDetState = STATE_START2;
+        }
+        break;
+
+    case STATE_START2:
+        if (OSP_MSG_HEAD1 == data)
+        {
+            pLocInst->protoDetState = STATE_SIZE1;
+        }
+        else if (OSP_MSG_HEAD0 == data)
+        {
+            pLocInst->protoDetState = STATE_START2;
+        }
+        else
+        {
+            pLocInst->protoDetState = STATE_START1;
+        }
+        break;
+
+    case STATE_SIZE1:
+        pLocInst->msgSize = data ;
+        pLocInst->msgSize <<= 8;  /* high CsrUint8 */
+        pLocInst->protoDetState = STATE_SIZE2;
+        break;
+
+    case STATE_SIZE2:
+        pLocInst->msgSize += data ;
+        if (MAX_SERIAL_PKT_LEN < pLocInst->msgSize || 0 == pLocInst->msgSize)
+        {
+            if (OSP_MSG_HEAD0 == data)
+            {
+                pLocInst->protoDetState = STATE_START2;
+            }
+            else
+            {
+                pLocInst->protoDetState = STATE_START1;
+            }
+        }
+        else
+        {
+            pLocInst->computedCheckSum = 0;
+            pLocInst->decodeIndex = 0;
+            pLocInst->protoDetState = STATE_PAYLOAD;
+        }
+        break;
+
+    case STATE_PAYLOAD:
+        /* check for a catastrophic error case */
+        if (MAX_SERIAL_PKT_LEN <= pLocInst->decodeIndex)
+        {
+            /* This is really bad.  And should never happen since we 
+             * gurantee that msgSize is always less than RECEIVE_PACKET_SIZE
+             * Change the state back to STATE_START1 and start over */
+            if (OSP_MSG_HEAD0 == data)
+            {
+                pLocInst->protoDetState = STATE_START2;
+            }
+            else
+            {
+                pLocInst->protoDetState = STATE_START1;
+            }
+            break;
+        }
+        /* Store the byte */
+        pLocInst->serialPkt[pLocInst->decodeIndex++] = data;
+        pLocInst->computedCheckSum += data;
+
+        /* Check to see if we've read the full payload */
+        if (0 == (--pLocInst->msgSize))
+        {
+            pLocInst->computedCheckSum &= 0x7FFF;
+            pLocInst->protoDetState = STATE_CHECKSUM1;
+        }
+        break;
+
+    case STATE_CHECKSUM1:
+        pLocInst->checksum = data ;
+        pLocInst->checksum <<= 8;
+        pLocInst->protoDetState = STATE_CHECKSUM2;
+        break;
+
+    case STATE_CHECKSUM2:
+        pLocInst->checksum += data;
+        if (pLocInst->computedCheckSum != pLocInst->checksum)
+        {
+            if (OSP_MSG_HEAD0 == data)
+            {
+                pLocInst->protoDetState = STATE_START2;
+            }
+            else
+            {
+                pLocInst->protoDetState = STATE_START1;
+            }
+        }
+        else
+        {
+            pLocInst->protoDetState = STATE_END1;
+        }
+        break;
+
+    case STATE_END1:
+        if (OSP_MSG_TAIL0 == data)
+        {
+            pLocInst->protoDetState = STATE_END2;
+        }
+        else
+        {               
+            if (OSP_MSG_HEAD0 == data)
+            {
+                pLocInst->protoDetState = STATE_START2;
+            }
+            else
+            {
+                pLocInst->protoDetState = STATE_START1;
+            }
+        }
+        break;
+
+    case STATE_END2:
+        if (OSP_MSG_TAIL1 == data)
+        {
+            pLocInst->pTimeoutChk->detach();
+            pLocInst->bTimeoutFlag = FALSE;
+
+            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();
+            pLocInst->protoDetState = STATE_START1;
+        }
+        else
+        {
+            if (OSP_MSG_HEAD0 == data)
+            {
+                pLocInst->protoDetState = STATE_START2;
+            }
+            else
+            {
+                pLocInst->protoDetState = STATE_START1;
+            }
+        }            
+        break;
+    }   /* switch. */
+    
+}
+
+void CsrLocation::_CsrLocProcessRawOspPkt(void)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+    tOspMsg     *pOspMsg;
+    CsrUint32    msgSize;
+    CsrResult    result;
+    
+    msgSize = _CsrLocCalcMsgSize();
+    if(msgSize > 0)
+    {
+        msgSize += sizeof(tOspMsg);
+        pOspMsg = (tOspMsg *)malloc(msgSize);
+        if(pOspMsg != NULL)
+        {
+            memset(pOspMsg, 0, msgSize);
+        }
+        else
+        {
+            CSR_LOG_INFO("No memory for received OSP message.\r\n");
+            return;
+        }
+    }
+    else
+    {
+        /* discard the unprocessed message */
+        return;
+    }
+
+    result = _CsrLocDecodeOspPkt(pLocInst->serialPkt,pLocInst->decodeIndex, &pOspMsg->msgId, pOspMsg->payload, &pOspMsg->length);
+    if ( CSR_RESULT_SUCCESS == result)
+    {
+         _CsrLocProcessOspPkt(pOspMsg);
+    }
+
+	free(pOspMsg);
+}
+
+CsrUint32 CsrLocation::_CsrLocCalcMsgSize(void)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+    CsrUint8 	*ptr = pLocInst->serialPkt;
+    CsrUint32 	 msgSize = 0;
+    CsrUint32 	 msgId;
+    CsrUint8 	 mid, sid = 0;
+
+    mid   = BINARY_IMPORT_UINT8(ptr);
+    msgId = OSP_MAKE_MSG_ID(mid,sid);
+
+    if(OSP_MSG_PWR_MODE_RSP == msgId || OSP_MSG_MULTI_CONSTELLATION == msgId)
+    {
+		/* add the sub-id to the message id */
+        sid   = BINARY_IMPORT_UINT8(ptr);
+		msgId = OSP_MAKE_MSG_ID(mid,sid);
+    }
+
+    switch(msgId)
+    {
+    case OSP_MSG_OK_TO_SEND:
+    case OSP_MSG_PWR_MODE_FPM_RSP:
+    case OSP_MSG_PWR_MODE_LPM_RSP:
+    case OSP_MSG_HW_CONFIG_REQ :
+        msgSize = sizeof(CsrUint8);
+        break;
+    case OSP_MSG_SW_VERSION :
+        msgSize = MAX_VERSION_LENGTH;
+        break;
+    case OSP_MSG_GEODETIC_NAVIGATION:
+        msgSize = sizeof(tLocPosResp);
+        break;
+    case OSP_MSG_GNSS_SAT_DATA:
+        msgSize = sizeof(CsrUint8);
+        break;
+    case OSP_MSG_GNSS_NAV_DATA:
+        msgSize = sizeof(CsrUint8);
+        break;
+
+    default :
+        msgSize = 0;
+        break;
+    }   
+
+    return msgSize;
+}
+
+CsrResult CsrLocation::_CsrLocDecodeOspPkt( CsrUint8 *pPayload, CsrUint32 payloadLen, CsrUint32 *pMsgId, void *pMsgData, CsrUint32 *pMsgLen)
+{
+    CsrResult tRet = CSR_RESULT_SUCCESS;
+    CsrUint8 *ptr = pPayload;
+    CsrUint32 i;
+    CsrUint8 mid, sid = 0;
+
+    mid         = BINARY_IMPORT_UINT8(ptr);
+    *pMsgId     = OSP_MAKE_MSG_ID(mid,sid);
+    *pMsgLen    = 0;
+
+    /*   add the sub-id to the message id */
+    if (OSP_MSG_PWR_MODE_RSP == *pMsgId || OSP_MSG_MULTI_CONSTELLATION == *pMsgId)
+    {
+        sid     = BINARY_IMPORT_UINT8(ptr);
+		*pMsgId = OSP_MAKE_MSG_ID(mid,sid);
+    }
+
+    switch (*pMsgId)
+    {
+    case OSP_MSG_SW_VERSION: /* 0x06 */
+        *pMsgLen = BINARY_IMPORT_UINT8(ptr);
+        ptr++;
+		if(*pMsgLen >= MAX_VERSION_LENGTH)
+	    {
+            tRet = CSR_RESULT_FAILURE;
+	    }
+        else
+        {
+            memcpy(pMsgData, ptr, *pMsgLen);
+        }
+        break;
+
+    case OSP_MSG_OK_TO_SEND: /* 0x12 */
+        *((CsrUint8 *)pMsgData) = BINARY_IMPORT_UINT8(ptr);
+        *pMsgLen = sizeof(CsrUint8);
+        break;
+
+    case OSP_MSG_GEODETIC_NAVIGATION: /* 0x29 */
+    {
+        tLocPosResp *pPos = (tLocPosResp*) pMsgData;
+        CsrUint16   valid;
+
+        valid = BINARY_IMPORT_UINT16(ptr);
+        if(valid != 0)
+        {
+            tRet = CSR_RESULT_FAILURE;
+        }
+        else
+        {
+            *pMsgLen = sizeof(*pPos);
+
+            ptr += 2;
+            pPos->gps_week  = BINARY_IMPORT_UINT16(ptr);
+            pPos->tow       = BINARY_IMPORT_UINT32(ptr);
+            ptr += 12;
+            pPos->lat       = (CsrDouble)BINARY_IMPORT_SINT32(ptr);
+            pPos->lat      *= 1e-7;
+            pPos->lon       = (CsrDouble)BINARY_IMPORT_SINT32(ptr);
+            pPos->lon      *= 1e-7;
+            ptr += 4;
+            pPos->alt       = (CsrDouble)BINARY_IMPORT_SINT32(ptr);
+            pPos->alt      *= 1e-2;
+        }
+        break;
+    }
+    
+    case OSP_MSG_GNSS_NAV_DATA: /* 0x43, 0x01 */
+    {
+        tLocSvStatus *pSvStatus = &csrLocInst.svStatus;
+
+        *pMsgLen = sizeof(*pSvStatus);
+        
+        ptr += 100;
+        pSvStatus->svUsedInFixMask      = BINARY_IMPORT_UINT32(ptr);
+        pSvStatus->sbasSvUsedInFixMask  = BINARY_IMPORT_UINT32(ptr);
+        pSvStatus->gloSvUsedInFixMask   = BINARY_IMPORT_UINT32(ptr);
+        pSvStatus->qzssSvUsedInFixMask  = BINARY_IMPORT_UINT32(ptr);
+        break;         
+    }
+
+    case OSP_MSG_GNSS_SAT_DATA: /* 0x43, 0x10 */
+    {
+        tLocSvStatus *pSvStatus = &csrLocInst.svStatus;
+        CsrUint16 week;
+        CsrUint32 tow;
+        CsrUint32 towSubMs;
+        CsrUint8  info;
+        CsrInt32  nMsg = 0;
+        CsrUint16 satInfo;
+        CsrUint16 az;
+        CsrUint16 el;
+        CsrUint16 cno;
+        CsrUint8  gnssType;
+        CsrUint16 index = 0;
+
+        *pMsgLen = sizeof(*pSvStatus);
+
+        week        = BINARY_IMPORT_UINT16(ptr);
+        tow         = BINARY_IMPORT_UINT32(ptr);
+        towSubMs    = BINARY_IMPORT_UINT32(ptr);
+        ptr        += 4;
+        info        = BINARY_IMPORT_UINT8(ptr);
+        
+        nMsg        = info & 0x0F;
+        if(nMsg == 1)
+        {
+            memset(pSvStatus, 0, sizeof(tLocSvStatus));
+            pSvStatus->gps_week     = week;
+            pSvStatus->tow          = tow;
+            pSvStatus->tow_sub_ms   = towSubMs;
+        }
+        
+        ptr++;
+        for (i = 0; i < GNSS_SAT_DATA_NUM_OF_SATS; i++)
+        {
+            satInfo = BINARY_IMPORT_UINT16(ptr);
+            az      = BINARY_IMPORT_UINT16(ptr);
+            el      = BINARY_IMPORT_UINT16(ptr);
+            cno     = BINARY_IMPORT_UINT16(ptr);
+            ptr    += 4;
+            
+            gnssType = (CsrUint8)((satInfo>>13)&0x0003);
+            if(0 == gnssType || 1 == gnssType) // GPS, SBAS, QZSS
+            {
+                index = pSvStatus->numOfSVs;
+                if(index < LOC_MAX_GNSS_SVS && cno >0)
+                {
+                    pSvStatus->svList[index].prn = (CsrUint8)(satInfo & 0xFF);
+                    pSvStatus->svList[index].cno = (CsrFloat)(cno/10.0); // Scale: 10
+                    pSvStatus->svList[index].elevation = (CsrFloat)(el/10.0); // Scale: 10
+                    pSvStatus->svList[index].azimuth = (CsrFloat)(az/10.0); // Scale: 10
+                    pSvStatus->numOfSVs++;
+                    pSvStatus->ephemerisMask |= 0x1 << (pSvStatus->svList[index].prn-1); // prn range: 1-32
+                }
+            }
+            else if(2 == gnssType) // GLONASS
+            {
+                index = pSvStatus->numOfGloSVs;
+                if(index < CODEC_GLO_MAX_CHANNELS && cno>0)
+                {
+                    CsrInt16 freqChan = (satInfo & 0X1F00)>>8;
+                    CsrInt16 slotNum  = (satInfo & 0X00FF);
+                    if(slotNum > 0)
+                    {
+                        if(freqChan & 0X0010)
+                        {
+                            freqChan |= 0xFFE0;
+                        }
+                        pSvStatus->gloSvList[index].prn = (CsrUint8)(freqChan + LOC_GLO_FREQ_OFFSET);
+                        pSvStatus->gloSvList[index].sno = (CsrUint8)slotNum;
+                        pSvStatus->gloSvList[index].cno = (CsrFloat)(cno/10.0); // Scale: 10
+                        pSvStatus->gloSvList[index].elevation = (CsrFloat)(el/10.0); // Scale: 10
+                        pSvStatus->gloSvList[index].azimuth = (CsrFloat)(az/10.0); // Scale: 10
+                        pSvStatus->numOfGloSVs++;
+                        pSvStatus->gloEphemerisMask |= 0x1 << (pSvStatus->gloSvList[index].prn-LOC_GLO_FREQ_ID_START);
+                    }
+                }
+            }
+        }
+
+        break;
+    }
+
+    case  OSP_MSG_HW_CONFIG_REQ: /* 0x47 */
+        break;
+
+    case OSP_MSG_PWR_MODE_FPM_RSP: /* 0x5A, 0x00 */
+        break;
+
+    case OSP_MSG_PWR_MODE_LPM_RSP: /* 0x5A, 0x06 */
+        *((CsrUint8 *)pMsgData) = *ptr;
+        *pMsgLen = sizeof(CsrUint8);
+        break;
+
+    default:
+        tRet = CSR_RESULT_FAILURE;
+        break;
+    }
+
+    /* check if length does not match */
+    if(tRet == CSR_RESULT_FAILURE)
+    {
+        *pMsgId = *pMsgLen = 0;
+    }
+
+   return tRet;
+
+} /* CsrUlocCodecSsbDecode() */
+
+void CsrLocation::_CsrLocProcessOspPkt(tOspMsg *pOspMsg)
+{
+    switch(pOspMsg->msgId)
+    {
+    case OSP_MSG_GEODETIC_NAVIGATION:
+        csrLocInst.appOutCb(LOC_OUTPUT_LOCATION, pOspMsg->payload, sizeof(tLocPosResp));
+        break;
+    case OSP_MSG_GNSS_SAT_DATA:
+        break;
+    case OSP_MSG_GNSS_NAV_DATA:
+        csrLocInst.appOutCb(LOC_OUTPUT_SV_STATUS, &csrLocInst.svStatus, sizeof(tLocSvStatus));
+        break;
+    case OSP_MSG_OK_TO_SEND:
+        csrLocInst.engStatus = (*(pOspMsg->payload)) ? ENGINE_STATUS_OK2SEND : ENGINE_STATUS_NOTOK2SEND;
+        CSR_LOG_INFO("Ok to send %u\r\n", csrLocInst.engStatus);
+        break;
+    case OSP_MSG_SW_VERSION:
+        CSR_LOG_INFO("Ver: %s\r\n", pOspMsg->payload);
+        break;
+    case OSP_MSG_HW_CONFIG_REQ:
+        CSR_LOG_INFO("hw config req.\r\n");
+        if(csrLocInst.pwrMode == PWR_PTF)
+        {
+            _CsrLocSendData(SEND_DATA_TYPE_OSP_VER_REQ);
+            _CsrLocSendData(SEND_DATA_TYPE_OSP_LPM_REQ);
+        }
+        else
+        {
+            _CsrLocSendData(SEND_DATA_TYPE_OSP_FPM_REQ);
+            _CsrLocSendData(SEND_DATA_TYPE_OSP_VER_REQ);
+        }
+        break;
+    case OSP_MSG_PWR_MODE_LPM_RSP:
+        CSR_LOG_INFO("lpm response.\r\n");
+        break;
+    case OSP_MSG_PWR_MODE_FPM_RSP:
+        CSR_LOG_INFO("fpm response.\r\n");
+        break;
+    default:
+        CSR_LOG_INFO("Unknown OSP message 0x%lx.\r\n", pOspMsg->msgId);
+        break;
+    }
+}
+
+void CsrLocation::_CsrLocTimeout(void)
+{
+    csrLocInst.bTimeoutFlag = TRUE;
+}
+
+void CsrLocation::_CsrLocRxHandler(void)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+
+    pLocInst->serialBuf[pLocInst->in++] = pLocInst->pSerialLoc->getc();
+    pLocInst->in &= (MAX_SERIAL_BUF_LEN-1);
+    if(pLocInst->in == pLocInst->out)
+    {
+        CSR_LOG_INFO("rx overwritten.\r\n");
+    }
+}
+
+void CsrLocation::_CsrLocSendData(eSendDataType type)
+{
+    tCsrLocInst *pLocInst = &csrLocInst;
+    CsrUint32 i, size;
+    const CsrUint8 *pData;
+
+    switch(type)
+    {
+    case SEND_DATA_TYPE_OSP_STOP_REQ:
+        pData = sOspStopReq;
+        size  = sizeof(sOspStopReq);
+        break;
+    case SEND_DATA_TYPE_OSP_VER_REQ:
+        pData = sOspVerReq;
+        size  = sizeof(sOspVerReq);
+        break;
+    case SEND_DATA_TYPE_OSP_LPM_REQ:
+        pData = sOspLpmReq;
+        size  = sizeof(sOspLpmReq);
+        break;
+    case SEND_DATA_TYPE_OSP_FPM_REQ:
+        pData = sOspFpmReq;
+        size  = sizeof(sOspFpmReq);
+        break;
+    case SEND_DATA_TYPE_OSP_SWITCH2NMEA_REQ:
+        pData = sOspSwitch2NmeaReq;
+        size  = sizeof(sOspSwitch2NmeaReq);
+        break;
+    case SEND_DATA_TYPE_NMEA_SWITCH2OSP_REQ:
+        pData = (const CsrUint8 *)sNmeaSwitch2OspReq;
+        size  = strlen(sNmeaSwitch2OspReq);
+        break;
+        
+    default:
+        pData = NULL;
+    }
+
+    if(pData != NULL)
+    {
+        for (i = 0; i < size; i++)
+        {
+            while(pLocInst->pSerialLoc->writeable() == 0) {}
+            pLocInst->pSerialLoc->putc(pData[i]);
+        }
+    }
+}
+
+void CsrLocation::_CsrLocHwOnoff(void)
+{
+	csrLocInst.pPinOnoff->write(1);
+	wait_ms(10);
+	csrLocInst.pPinOnoff->write(0);
+	CSR_LOG_INFO("Onoff pulse given.\r\n");
+}
+
+void CsrLocation::_CsrLocHwReset(void)
+{
+	csrLocInst.pPinReset->write(1);
+	wait_ms(10);
+	csrLocInst.pPinReset->write(0);
+	CSR_LOG_INFO("Reset pulse given.\r\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CsrLocation.h	Mon Mar 24 08:23:25 2014 +0000
@@ -0,0 +1,444 @@
+
+/* CsrLocation class for mbed Microcontroller
+ * Copyright 2014 CSR plc
+ */
+
+
+#ifndef CSRLOCATION_H
+#define CSRLOCATION_H
+
+
+#define CSR_LOC_SDK_VER                 "CSR-LOC-SDK-0.5"
+
+/* Data type definitions */
+#undef  FALSE
+#define FALSE (0)
+
+#undef  TRUE
+#define TRUE (1)
+
+/* Unsigned fixed width types */
+typedef unsigned char CsrUint8;
+typedef unsigned short CsrUint16;
+typedef unsigned int CsrUint32;
+
+/* Signed fixed width types */
+typedef signed char CsrInt8;
+typedef signed short CsrInt16;
+typedef signed int CsrInt32;
+
+/* Boolean */
+typedef CsrUint8 CsrBool;
+
+/* String types */
+typedef char CsrCharString;
+typedef CsrUint8 CsrUtf8String;
+typedef CsrUint16 CsrUtf16String;   /* 16-bit UTF16 strings */
+typedef CsrUint32 CsrUint24;
+
+/*
+ * Floating point
+ *
+ * Note: If a given compiler does not support floating point, it is
+ * OK to omit these definitions;  alternative versions of the code using
+ * these types may be available.  Consult the relevant documentation
+ * or the customer support group for information on this.
+ */
+typedef float CsrFloat;
+typedef double CsrDouble;
+
+typedef CsrUint16 CsrResult;
+#define CSR_RESULT_SUCCESS  ((CsrResult) 0x0000)
+#define CSR_RESULT_FAILURE  ((CsrResult) 0xFFFF)
+/* The end of data type definitions */
+
+/* OSP protocol related definitions */
+#define MAX_VERSION_LENGTH 80
+
+/* OSP message header */
+#define OSP_MSG_HEAD0                   (0xA0)
+#define OSP_MSG_HEAD1                   (0xA2)
+/* OSP message footer */
+#define OSP_MSG_TAIL0                   (0xB0)
+#define OSP_MSG_TAIL1                   (0xB3)
+
+/* NMEA message header */
+#define NMEA_MSG_HEAD0                  ('$')
+#define NMEA_MSG_HEAD1                  ('G')
+/* NMEA message footer */
+#define NMEA_MSG_TAIL0                  ('*')
+
+#define CSR_SWAPIN16(bytestream) (((CsrUint16)*((bytestream)+0) << 8) | ((CsrUint16)*((bytestream)+1)))
+
+#define CSR_SWAPIN32(bytestream)\
+   ( ((CsrUint32)*((bytestream)+0) << 24)\
+   | ((CsrUint32)*((bytestream)+1) << 16)\
+   | ((CsrUint32)*((bytestream)+2) <<  8)\
+   | ((CsrUint32)*((bytestream)+3)      ))
+
+
+/* import macros for little endian: */
+/* NOTE: must use {} around these macros when calling in a loop */
+#define BINARY_IMPORT_UINT8(bytestream) (                      *((bytestream)++))
+#define BINARY_IMPORT_UINT16(bytestream) ((CsrUint16) CSR_SWAPIN16((bytestream))); bytestream+=2
+#define BINARY_IMPORT_UINT32(bytestream) ((CsrUint32) CSR_SWAPIN32((bytestream))); bytestream+=4
+#define BINARY_IMPORT_SINT32(bytestream) ((CsrInt32)  CSR_SWAPIN32((bytestream))); bytestream+=4
+
+
+#define OSP_MAKE_MSG_ID(mid, sid) ((((mid) & 0xFF) << 8) | ((sid) & 0xFF))
+
+#define OSP_MSG_SW_VERSION              OSP_MAKE_MSG_ID(0x06, 0x0)
+#define OSP_MSG_OK_TO_SEND              OSP_MAKE_MSG_ID(0x12, 0x0)
+#define OSP_MSG_GEODETIC_NAVIGATION     OSP_MAKE_MSG_ID(0x29, 0x0)
+#define OSP_MSG_MULTI_CONSTELLATION     OSP_MAKE_MSG_ID(0x43, 0x0)
+    #define OSP_MSG_GNSS_NAV_DATA       OSP_MAKE_MSG_ID(0x43, 0x01)
+    #define OSP_MSG_GNSS_SAT_DATA       OSP_MAKE_MSG_ID(0x43, 0x10)
+#define OSP_MSG_HW_CONFIG_REQ           OSP_MAKE_MSG_ID(0x47, 0x0)
+#define OSP_MSG_PWR_MODE_RSP            OSP_MAKE_MSG_ID(0x5A, 0x0)
+    #define OSP_MSG_PWR_MODE_FPM_RSP    OSP_MAKE_MSG_ID(0x5A, 0x0)
+    #define OSP_MSG_PWR_MODE_LPM_RSP    OSP_MAKE_MSG_ID(0x5A, 0x6)
+
+   
+#define GNSS_SAT_DATA_NUM_OF_SATS       (15)
+#define CODEC_GLO_MAX_CHANNELS          (14)
+/* The end of OSP protocol definitions */
+
+
+#define LOC_MAX_GNSS_SVS                (32)
+#define LOC_GLO_FREQ_OFFSET             (77)
+#define LOC_GLO_FREQ_ID_START           (70)
+#define LOC_GLO_FREQ_ID_END             (83)
+#define LOC_NUM_OF_GLO_FREQ_CHANNELS    (1+LOC_GLO_FREQ_ID_END-LOC_GLO_FREQ_ID_START)
+
+#define MAX_PORT_NUM_STRING_LENGTH      (16)
+#define MAX_SERIAL_BUF_LEN              (2048)
+#define MAX_SERIAL_PKT_LEN              (512)
+
+#define BAUDRATE_NMEA                   4800
+#define BAUDRATE_OSP                    115200
+
+#define PROTO_CHECK_TIMEOUT             (2.0)
+
+/** Indicates the outputted location information */
+#define LOC_OUTPUT_LOCATION             (1)
+/* Indicates the outputted sv status information */
+#define LOC_OUTPUT_SV_STATUS            (2)
+
+#define CSR_LOG_INFO(...) \
+{\
+    if(csrLocInst.pSerialDebug != NULL)\
+    {\
+        (csrLocInst.pSerialDebug->printf(__VA_ARGS__));\
+    }\
+}
+
+/** Location enent definitions */
+typedef enum
+{
+    /** Start result event */
+    CSR_LOC_EVENT_START_RESULT,
+    /** Stop result event */
+    CSR_LOC_EVENT_STOP_RESULT,
+}eCsrLocEventType;
+
+/** Power mode selection */
+typedef enum
+{
+    /** full power mode */
+    PWR_FULL,
+    /** Low power push to fix mode */
+    PWR_PTF,
+}ePowerMode;
+
+/* Protocol detection state */
+typedef enum
+{
+    STATE_START1,       /* Indicates the first byte of the OSP or NMEA message header*/
+    STATE_START2,       /* Indicates the second byte of the OSP or NMEA message header */
+    STATE_SIZE1,        /* Indicates the first byte of the OSP message length */
+    STATE_SIZE2,        /* Indicates the second byte of the OSP message length  */
+    STATE_PAYLOAD,      /* Indicates the start of payload of the OSP message */
+    STATE_CHECKSUM1,    /* Indicates the first byte of the OSP message checksum  */
+    STATE_CHECKSUM2,    /* Indicates the second byte of the OSP message checksum  */
+    STATE_END1,         /* Indicates the first byte of the OSP or NMEA message footer  */
+    STATE_END2          /* Indicates the second byte of the OSP message footer  */
+}eProtoDetState;
+
+/* Csr Location state */
+typedef enum
+{
+    CSR_LOC_STATE_IDLE,
+    CSR_LOC_STATE_RUN,
+}eCsrLocState;
+
+/* Locatin chip protocol detection state */
+typedef enum
+{
+   PROTO_STATE_DET_INVALID = 0,
+   PROTO_STATE_DET_OSP,
+   PROTO_STATE_DET_NMEA,
+   PROTO_STATE_SWI_OSP_FROM_NMEA,
+   PROTO_STATE_DET_OSP_FROM_NMEA,
+   PROTO_STATE_DET_OK,
+}eProtoState;
+
+/* Locaiton chip status */
+typedef enum
+{
+    /* Location chip is going to hibernation mode and cannot accept message any more */
+    ENGINE_STATUS_NOTOK2SEND,
+    /* Locaitn come back from hibernation mode and can accept message now */
+    ENGINE_STATUS_OK2SEND
+}eEngineStatus;
+
+/* OSP data type to be sent to location chip */
+typedef enum
+{
+    SEND_DATA_TYPE_OSP_STOP_REQ,
+    SEND_DATA_TYPE_OSP_VER_REQ,
+    SEND_DATA_TYPE_OSP_LPM_REQ,
+    SEND_DATA_TYPE_OSP_FPM_REQ,
+    SEND_DATA_TYPE_OSP_SWITCH2NMEA_REQ,
+    SEND_DATA_TYPE_NMEA_SWITCH2OSP_REQ
+}eSendDataType;
+
+/** Structure to hold Position Response Message Information. */
+typedef struct LocPosResp
+{
+    /** Week part of GPS time */
+    CsrUint16            gps_week;
+    /** Time of second part of GPS time */
+    CsrUint32            tow;
+    /** Latitude */
+    CsrDouble            lat;
+    /** Longitude */
+    CsrDouble            lon;
+    /** Altitude */
+    CsrDouble            alt;
+} tLocPosResp;
+
+/** Structure to hold Satellite Information. */
+typedef struct LocSvInfo
+{
+    /** Prn or svId */
+    CsrUint8             prn;
+    /** The ratio of carrier and noise */
+    CsrFloat             cno;
+    /** elevation */
+    CsrFloat             elevation;
+    /** azimuth */
+    CsrFloat             azimuth;
+    /** satellite state */
+    CsrUint16            state;
+} tLocSvInfo;
+
+/** Structure to hold Satellite Information for GLONASS */
+typedef struct LocGloSvInfo
+{
+    /** Prn or svId */
+    CsrUint8             prn;
+    /** Slot number */
+    CsrUint8             sno;
+    /** The ratio of carrier and noise */
+    CsrFloat             cno;
+    /** elevation */
+    CsrFloat             elevation;
+    /** azimuth */
+    CsrFloat             azimuth;
+    /** satellite state */
+    CsrUint16            state;
+} tLocGloSvInfo;
+
+/** Structure to hold Satellite Status Information. */
+typedef struct LocSvStatus
+{
+    /** Week part of GPS time */
+    CsrUint16           gps_week;
+    /** Time of second part of GPS time */
+    CsrUint32           tow;
+    /** Time of millisecond part of GPS time */
+    CsrUint32           tow_sub_ms;
+   
+    /**Number of GPS SVs currently visible **/
+    CsrUint8            numOfSVs;
+    /**Number of GLONASS SVs currently visible **/
+    CsrUint8            numOfGloSVs;
+    /** GPS SVs information */
+    tLocSvInfo          svList[LOC_MAX_GNSS_SVS];
+    /** GLONASS SVs information */
+    tLocGloSvInfo       gloSvList[LOC_NUM_OF_GLO_FREQ_CHANNELS];
+    /** Bit mask indicating which SVs have ephemeris data **/
+    CsrUint32           ephemerisMask;
+    /** Bit mask indicating which GLONASS SVs have ephemeris data **/
+    CsrUint32           gloEphemerisMask;
+    /** Bit mask indicating which SVs were used in latest sent fix **/
+    CsrUint32           svUsedInFixMask;
+    /** Bit mask indicating which GLONASS SVs were used in latest sent fix **/
+    CsrUint32           gloSvUsedInFixMask;
+    /** Bit mask indicating which QZSS SVs were used in latest sent fix **/   
+    CsrUint32           qzssSvUsedInFixMask;
+    /** Bit mask indicating which SBAS SVs were used in latest sent fix **/   
+    CsrUint32           sbasSvUsedInFixMask;
+} tLocSvStatus;
+
+
+/** Applicaiton register this out callback function and CsrLocaiton class will pass outputted information to application */
+typedef void (*csr_app_output_callback)(CsrUint32  msgId, void * const pMsgData, CsrUint32 msgLength);
+
+/** Applicaiton register this event callback function and CsrLocaiton class will pass internal porcessing event to application */
+typedef void (*csr_app_event_callback)(eCsrLocEventType event, CsrUint32 data);
+
+/** tCsrLocConfig structure
+ * Application needs to decides and pass the configuration into CsrLocation class.
+ */
+typedef struct CsrLocConfig
+{
+    /** Debug serial port to print debug information */
+    Serial          *pSerialDebug;
+    /** location serail port to communicate between mbed host side and location chip */
+    Serial          *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 */
+    DigitalOut      *pPinReset;
+}tCsrLocConfig;
+
+/* General OSP mesasge format */
+typedef struct OspMsg
+{
+   CsrUint32        msgId;   
+   CsrUint32        length;
+   CsrUint8         payload[4];
+} tOspMsg;
+
+/* keep the internal data of CsrLocation class */
+typedef struct CsrLocInst
+{
+    CsrBool         bStopFlag;
+
+    eCsrLocState    locState;
+    eProtoState     protoState;
+    ePowerMode      pwrMode;
+    CsrUint32       baudRate;
+    CsrBool         isOspHeader;
+    CsrBool         isNmeaHeader;
+    CsrInt32        computedCheckSum;
+    CsrInt32        checksum;
+    CsrInt32        msgSize;
+    CsrInt32        decodeIndex;
+    eProtoDetState  protoDetState;
+    Timeout         *pTimeoutChk;    /* timeout process */
+    CsrBool         bTimeoutFlag;
+    eEngineStatus   engStatus;
+
+    tLocSvStatus    svStatus;   /* 2 kind of messages contribute the svStaus */
+
+    Serial          *pSerialDebug;
+    Serial          *pSerialLoc;
+    DigitalOut      *pPinOnoff;
+    DigitalOut      *pPinReset;
+
+    CsrUint8        serialBuf[MAX_SERIAL_BUF_LEN]; /* buffer the serial data from uart callback function */
+    CsrUint8        serialPkt[MAX_SERIAL_PKT_LEN]; /* decoded osp data */
+    CsrUint16       in;
+    CsrUint16       out;
+    
+    csr_app_output_callback appOutCb;
+    csr_app_event_callback  appEventCb;
+}tCsrLocInst;
+
+/** CsrLocation class.
+ *  A location interface to control location chip and get position and satellite information.
+ */
+class CsrLocation
+{
+public:
+    /** Constructor: CsrLocaiton
+     * Create the CsrLocation, accept specified configuration
+     * @param pLocConfig Configuration including debug serial port, location communication serail port, onoff pin, reset pin
+     */
+    CsrLocation(tCsrLocConfig *pLocConfig);
+    
+    /** Destructor: CsrLocation
+     * Free allocated resource
+     */
+    ~CsrLocation();
+    
+    /** Register output callback and enent callback functions
+     * @param app_output_cb CsrLocation class output the loaction and satellite information to application
+     * @param app_event_cb CsrLocation class output the start and stop result to application
+     */
+    void CsrLocRegOutput(csr_app_output_callback app_output_cb, csr_app_event_callback app_event_cb);
+
+    /** hw reset to get location chip into hibernation mode */
+    void CsrLocReset(void);
+
+    /** Start location request, activate location chip */
+    void CsrLocStart(ePowerMode pwrMode);
+
+    /** Process location data from chip and update location and satellite information */
+    void CsrLocUpdate(void);
+
+    /** Stop location request, get location chip into hibernation mode */
+    void CsrLocStop(void);
+
+    /** Speical for low power PTF mode. 
+      * During low power PTF mode, after reporting position, chip will go to hibernation mode automatically.
+      * After 30 seconds, chip will recover and report position again. Then chip will go to hibernation mode again.
+      * During the hibernation, application can call CsrLocLpmGetPos to get position immediately and no need to wait for the whole interval.
+      */
+    void CsrLocLpmGetPos(void);
+
+    /* A debug interface to switch location chip protocol from OSP at 115200bps to NMEA at 4800bps */
+    void CsrLocDebugSwitch2Nmea(void);
+    
+private:
+    /* Internal kept data */
+    tCsrLocInst csrLocInst;
+
+    /* Initialize the serial port and open it */
+    void _CsrLocUartInit(void);
+
+    /* Process the raw stream from location seraial port */
+    void _CsrLocProcessRawStream(void);
+
+    /* Detect the OSP protocol outputted from location serial port */
+    void _CsrLocDetProtoOsp(CsrUint8 data);
+
+    /* Detect the NMEA protocol outputted from location serial port */
+    void _CsrLocDetProtoNmea(CsrUint8 data);
+
+    /* Process the raw OSP stream, remove the OSP header, size, check sum, and save the OSP data into interal buffer */
+    void _CsrLocProcessRawOspStream(CsrUint8 data);
+
+    /* Process the saved OSP data and decode them */
+    void _CsrLocProcessRawOspPkt(void);
+
+    /* Calculate the OSP message size to allcate buffer to save the decoded OSP data */
+    CsrUint32 _CsrLocCalcMsgSize(void);
+
+    /* Decode OSP data into pakcet data structure */
+    CsrResult _CsrLocDecodeOspPkt( CsrUint8 *payload, CsrUint32 payload_length, CsrUint32 *message_id, void   *message_structure, CsrUint32 *message_length);
+
+    /* Process the decode OSP packet and pass to application when needed */
+    void _CsrLocProcessOspPkt(tOspMsg *pOspMsg);
+
+    /* Timeout process, such as detect OSP and NMEA protocol */
+    void _CsrLocTimeout(void);
+
+    /* Location serial port data recevier */
+    void _CsrLocRxHandler(void);
+
+    /* Send special OSP messges to location chip */
+    void _CsrLocSendData(eSendDataType type);
+
+    /* Trigger a pulse on the onoff pin */
+    void _CsrLocHwOnoff(void);
+
+    /* Trigger a reset on the reset pin */
+    void _CsrLocHwReset(void);
+};
+
+
+
+#endif /* CSRLOCATION_H */