Csr location class shows location and satellite information, which supports H13467 + ST F103RB/NXP LCP1549 boards now.
Dependents: CsrLocationDemo CsrLocationDemo
Fork of CsrLocation by
Diff: CsrLocation.cpp
- Revision:
- 0:aba381fc8158
- Child:
- 1:bbaf9b8d646a
--- /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"); +}