1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/lupyuen-LoRaMac-node-nuttx

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
gps.c 17 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
Miguel Luis Отправлено 6 лет назад f8ff234
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
/*!
* \file gps.c
*
* \brief GPS driver implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*/
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "utilities.h"
#include "board.h"
#include "rtc-board.h"
#include "gps-board.h"
#include "gps.h"
#define TRIGGER_GPS_CNT 10
/* Various type of NMEA data we can receive with the Gps */
const char NmeaDataTypeGPGGA[] = "GPGGA";
const char NmeaDataTypeGPGSA[] = "GPGSA";
const char NmeaDataTypeGPGSV[] = "GPGSV";
const char NmeaDataTypeGPRMC[] = "GPRMC";
/* Value used for the conversion of the position from DMS to decimal */
const int32_t MaxNorthPosition = 8388607; // 2^23 - 1
const int32_t MaxSouthPosition = 8388608; // -2^23
const int32_t MaxEastPosition = 8388607; // 2^23 - 1
const int32_t MaxWestPosition = 8388608; // -2^23
NmeaGpsData_t NmeaGpsData;
static double HasFix = false;
static double Latitude = 0;
static double Longitude = 0;
static int32_t LatitudeBinary = 0;
static int32_t LongitudeBinary = 0;
static int16_t Altitude = ( int16_t )0xFFFF;
static uint32_t PpsCnt = 0;
bool PpsDetected = false;
void GpsPpsHandler( bool *parseData )
{
PpsDetected = true;
PpsCnt++;
*parseData = false;
if( PpsCnt >= TRIGGER_GPS_CNT )
{
PpsCnt = 0;
*parseData = true;
}
}
void GpsInit( void )
{
PpsDetected = false;
GpsMcuInit( );
}
void GpsStart( void )
{
GpsMcuStart( );
}
void GpsStop( void )
{
GpsMcuStop( );
}
void GpsProcess( void )
{
GpsMcuProcess( );
}
bool GpsGetPpsDetectedState( void )
{
bool state = false;
CRITICAL_SECTION_BEGIN( );
state = PpsDetected;
PpsDetected = false;
CRITICAL_SECTION_END( );
return state;
}
bool GpsHasFix( void )
{
return HasFix;
}
void GpsConvertPositionIntoBinary( void )
{
long double temp;
if( Latitude >= 0 ) // North
{
temp = Latitude * MaxNorthPosition;
LatitudeBinary = temp / 90;
}
else // South
{
temp = Latitude * MaxSouthPosition;
LatitudeBinary = temp / 90;
}
if( Longitude >= 0 ) // East
{
temp = Longitude * MaxEastPosition;
LongitudeBinary = temp / 180;
}
else // West
{
temp = Longitude * MaxWestPosition;
LongitudeBinary = temp / 180;
}
}
void GpsConvertPositionFromStringToNumerical( void )
{
int i;
double valueTmp1;
double valueTmp2;
double valueTmp3;
double valueTmp4;
// Convert the latitude from ASCII to uint8_t values
for( i = 0 ; i < 10 ; i++ )
{
NmeaGpsData.NmeaLatitude[i] = NmeaGpsData.NmeaLatitude[i] & 0xF;
}
// Convert latitude from degree/minute/second (DMS) format into decimal
valueTmp1 = ( double )NmeaGpsData.NmeaLatitude[0] * 10.0 + ( double )NmeaGpsData.NmeaLatitude[1];
valueTmp2 = ( double )NmeaGpsData.NmeaLatitude[2] * 10.0 + ( double )NmeaGpsData.NmeaLatitude[3];
valueTmp3 = ( double )NmeaGpsData.NmeaLatitude[5] * 1000.0 + ( double )NmeaGpsData.NmeaLatitude[6] * 100.0 +
( double )NmeaGpsData.NmeaLatitude[7] * 10.0 + ( double )NmeaGpsData.NmeaLatitude[8];
Latitude = valueTmp1 + ( ( valueTmp2 + ( valueTmp3 * 0.0001 ) ) / 60.0 );
if( NmeaGpsData.NmeaLatitudePole[0] == 'S' )
{
Latitude *= -1;
}
// Convert the longitude from ASCII to uint8_t values
for( i = 0 ; i < 10 ; i++ )
{
NmeaGpsData.NmeaLongitude[i] = NmeaGpsData.NmeaLongitude[i] & 0xF;
}
// Convert longitude from degree/minute/second (DMS) format into decimal
valueTmp1 = ( double )NmeaGpsData.NmeaLongitude[0] * 100.0 + ( double )NmeaGpsData.NmeaLongitude[1] * 10.0 + ( double )NmeaGpsData.NmeaLongitude[2];
valueTmp2 = ( double )NmeaGpsData.NmeaLongitude[3] * 10.0 + ( double )NmeaGpsData.NmeaLongitude[4];
valueTmp3 = ( double )NmeaGpsData.NmeaLongitude[6] * 1000.0 + ( double )NmeaGpsData.NmeaLongitude[7] * 100;
valueTmp4 = ( double )NmeaGpsData.NmeaLongitude[8] * 10.0 + ( double )NmeaGpsData.NmeaLongitude[9];
Longitude = valueTmp1 + ( valueTmp2 / 60.0 ) + ( ( ( valueTmp3 + valueTmp4 ) * 0.0001 ) / 60.0 );
if( NmeaGpsData.NmeaLongitudePole[0] == 'W' )
{
Longitude *= -1;
}
}
uint8_t GpsGetLatestGpsPositionDouble( double *lati, double *longi )
{
uint8_t status = FAIL;
if( HasFix == true )
{
status = SUCCESS;
}
else
{
GpsResetPosition( );
}
*lati = Latitude;
*longi = Longitude;
return status;
}
uint8_t GpsGetLatestGpsPositionBinary( int32_t *latiBin, int32_t *longiBin )
{
uint8_t status = FAIL;
CRITICAL_SECTION_BEGIN( );
if( HasFix == true )
{
status = SUCCESS;
}
else
{
GpsResetPosition( );
}
*latiBin = LatitudeBinary;
*longiBin = LongitudeBinary;
CRITICAL_SECTION_END( );
return status;
}
int16_t GpsGetLatestGpsAltitude( void )
{
CRITICAL_SECTION_BEGIN( );
if( HasFix == true )
{
Altitude = atoi( NmeaGpsData.NmeaAltitude );
}
else
{
Altitude = ( int16_t )0xFFFF;
}
CRITICAL_SECTION_END( );
return Altitude;
}
/*!
* Calculates the checksum for a NMEA sentence
*
* Skip the first '$' if necessary and calculate checksum until '*' character is
* reached (or buffSize exceeded).
*
* \retval chkPosIdx Position of the checksum in the sentence
*/
int32_t GpsNmeaChecksum( int8_t *nmeaStr, int32_t nmeaStrSize, int8_t * checksum )
{
int i = 0;
uint8_t checkNum = 0;
// Check input parameters
if( ( nmeaStr == NULL ) || ( checksum == NULL ) || ( nmeaStrSize <= 1 ) )
{
return -1;
}
// Skip the first '$' if necessary
if( nmeaStr[i] == '$' )
{
i += 1;
}
// XOR until '*' or max length is reached
while( nmeaStr[i] != '*' )
{
checkNum ^= nmeaStr[i];
i += 1;
if( i >= nmeaStrSize )
{
return -1;
}
}
// Convert checksum value to 2 hexadecimal characters
checksum[0] = Nibble2HexChar( checkNum / 16 ); // upper nibble
checksum[1] = Nibble2HexChar( checkNum % 16 ); // lower nibble
return i + 1;
}
/*!
* Calculate the checksum of a NMEA frame and compare it to the checksum that is
* present at the end of it.
* Return true if it matches
*/
static bool GpsNmeaValidateChecksum( int8_t *serialBuff, int32_t buffSize )
{
int32_t checksumIndex;
int8_t checksum[2]; // 2 characters to calculate NMEA checksum
checksumIndex = GpsNmeaChecksum( serialBuff, buffSize, checksum );
// could we calculate a verification checksum ?
if( checksumIndex < 0 )
{
return false;
}
// check if there are enough char in the serial buffer to read checksum
if( checksumIndex >= ( buffSize - 2 ) )
{
return false;
}
// check the checksum
if( ( serialBuff[checksumIndex] == checksum[0] ) && ( serialBuff[checksumIndex + 1] == checksum[1] ) )
{
return true;
}
else
{
return false;
}
}
uint8_t GpsParseGpsData( int8_t *rxBuffer, int32_t rxBufferSize )
{
uint8_t i = 1;
uint8_t j = 0;
uint8_t fieldSize = 0;
if( rxBuffer[0] != '$' )
{
GpsMcuInvertPpsTrigger( );
return FAIL;
}
if( GpsNmeaValidateChecksum( rxBuffer, rxBufferSize ) == false )
{
return FAIL;
}
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 6 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaDataType[j] = rxBuffer[i];
}
// Parse the GPGGA data
if( strncmp( ( const char* )NmeaGpsData.NmeaDataType, ( const char* )NmeaDataTypeGPGGA, 5 ) == 0 )
{
// NmeaUtcTime
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 11 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaUtcTime[j] = rxBuffer[i];
}
// NmeaLatitude
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 10 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLatitude[j] = rxBuffer[i];
}
// NmeaLatitudePole
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLatitudePole[j] = rxBuffer[i];
}
// NmeaLongitude
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 11 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLongitude[j] = rxBuffer[i];
}
// NmeaLongitudePole
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLongitudePole[j] = rxBuffer[i];
}
// NmeaFixQuality
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaFixQuality[j] = rxBuffer[i];
}
// NmeaSatelliteTracked
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 3 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaSatelliteTracked[j] = rxBuffer[i];
}
// NmeaHorizontalDilution
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 6 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaHorizontalDilution[j] = rxBuffer[i];
}
// NmeaAltitude
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 8 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaAltitude[j] = rxBuffer[i];
}
// NmeaAltitudeUnit
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaAltitudeUnit[j] = rxBuffer[i];
}
// NmeaHeightGeoid
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 8 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaHeightGeoid[j] = rxBuffer[i];
}
// NmeaHeightGeoidUnit
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaHeightGeoidUnit[j] = rxBuffer[i];
}
GpsFormatGpsData( );
return SUCCESS;
}
else if ( strncmp( ( const char* )NmeaGpsData.NmeaDataType, ( const char* )NmeaDataTypeGPRMC, 5 ) == 0 )
{
// NmeaUtcTime
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 11 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaUtcTime[j] = rxBuffer[i];
}
// NmeaDataStatus
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaDataStatus[j] = rxBuffer[i];
}
// NmeaLatitude
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 10 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLatitude[j] = rxBuffer[i];
}
// NmeaLatitudePole
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLatitudePole[j] = rxBuffer[i];
}
// NmeaLongitude
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 11 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLongitude[j] = rxBuffer[i];
}
// NmeaLongitudePole
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 2 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaLongitudePole[j] = rxBuffer[i];
}
// NmeaSpeed
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 8 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaSpeed[j] = rxBuffer[i];
}
// NmeaDetectionAngle
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 8 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaDetectionAngle[j] = rxBuffer[i];
}
// NmeaDate
fieldSize = 0;
while( rxBuffer[i + fieldSize++] != ',' )
{
if( fieldSize > 8 )
{
return FAIL;
}
}
for( j = 0; j < fieldSize; j++, i++ )
{
NmeaGpsData.NmeaDate[j] = rxBuffer[i];
}
GpsFormatGpsData( );
return SUCCESS;
}
else
{
return FAIL;
}
}
void GpsFormatGpsData( void )
{
if( strncmp( ( const char* )NmeaGpsData.NmeaDataType, ( const char* )NmeaDataTypeGPGGA, 5 ) == 0 )
{
HasFix = ( NmeaGpsData.NmeaFixQuality[0] > 0x30 ) ? true : false;
}
else if ( strncmp( ( const char* )NmeaGpsData.NmeaDataType, ( const char* )NmeaDataTypeGPRMC, 5 ) == 0 )
{
HasFix = ( NmeaGpsData.NmeaDataStatus[0] == 0x41 ) ? true : false;
}
GpsConvertPositionFromStringToNumerical( );
GpsConvertPositionIntoBinary( );
}
void GpsResetPosition( void )
{
Altitude = ( int16_t )0xFFFF;
Latitude = 0;
Longitude = 0;
LatitudeBinary = 0;
LongitudeBinary = 0;
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/lupyuen-LoRaMac-node-nuttx.git
git@gitlife.ru:oschina-mirror/lupyuen-LoRaMac-node-nuttx.git
oschina-mirror
lupyuen-LoRaMac-node-nuttx
lupyuen-LoRaMac-node-nuttx
v4.5.1