GPS GMS-6 Module
GPSGms6.cpp
- Committer:
- Lucyjungz
- Date:
- 2016-05-19
- Revision:
- 7:333d46845050
- Parent:
- 5:9dd9ab613497
- Child:
- 9:12519423b85f
File content as of revision 7:333d46845050:
/** ****************************************************************************** * @file GPSGms6.cpp * @author Narut T * @version V1 * @date 19/05/2016 * @brief Library for GPS GMS6 ******************************************************************************/ #include "mbed.h" #include "GPSGms6.h" #include <string> /* ############### Method Defination ################## */ #define GET_GPRMC_SECTION_SIZE(state) (unsigned int)gprms_tbl[state].size #define GET_GPRMC_VARIABLE_ADDR(state) gprms_tbl[state].p_val #define GET_GPRMC_NEXT_STATE(state) (GPS_ProcessState)gprms_tbl[state+1].state GPRMC_Data_TypeDef m_gprmc; // Latest GPRMC data GPRMC_Data_TypeDef m_valid_gprmc; // Latest valid GPRMC Data char m_RxBuf[RX_BUF_SIZE]; // Reading Buffer bool m_available; // Flag to indicate availability of GPRMC data int m_index; // an index /** * Initializaion of the GPS Module by using serial and selected PIN */ Serial serial_gps(PA_9, PA_10); /** * Table for GPRMC structure that use for decoding GPRMC message of the GPS * This table contain 3 element which are index, section size and pointer to variable * Once GPS process routine is called data will be populated in variable that define in third column */ const GPRMC_Tbl_TypeDef gprms_tbl[] = { // index , section size , variable {GPS_Process_Start , INVALID_VALUE ,(char *)INVALID_VALUE}, {GPS_Process_Header , HEADER_SIZE , m_gprmc.header}, {GPS_Process_Time , GPRMC_TIME_SIZE , m_gprmc.time}, {GPS_Process_Status , GPRMC_STATUS_SIZE , m_gprmc.status}, {GPS_Process_Latitude , GPRMC_LATITUDE_SIZE , m_gprmc.latitude}, {GPS_Process_Latitude_hemis , GPRMC_LATITUDE_HEMI_SIZE , m_gprmc.latitude_hemi}, {GPS_Process_Longitude , GPRMC_LONGITUDE_SIZE , m_gprmc.longitude}, {GPS_Process_Longitude_hemis , GPRMC_LONGITUDE_HEMI_SIZE , m_gprmc.longitude_hemi}, {GPS_Process_Speed , GPRMC_SPEED_SIZE , m_gprmc.speed}, {GPS_Process_Course , GPRMC_COURSE_SIZE , m_gprmc.course}, {GPS_Process_Date , GPRMC_DATE_SIZE , m_gprmc.date}, {GPS_Process_Magnetic , GPRMC_MAGNETIC_SIZE , m_gprmc.magnetic}, {GPS_Process_Magnetic_Dir , GPRMC_MAGNETIC_DIR_SIZE , m_gprmc.magnetic_dir}, {GPS_Process_Indicator , GPRMC_INDICATOR_SIZE , m_gprmc.indicator}, {GPS_Process_Complete ,INVALID_VALUE ,(char *)INVALID_VALUE} }; /* Private function prototypes -----------------------------------------------*/ static void GPSGMS6_CompleteCallback(); static GPS_ProcessStatus GPSGMS6_ProcessGprmcSection(GPS_ProcessState state,char * buf , unsigned int buf_index,unsigned int buf_size, unsigned int section_size, char * ret_value); static void GPSGMS6_ByteCallback(); static void GPSGMS6_ProcessGpsData(char * buf, unsigned int size); /** * @brief Utility for processing GPRMC message from the GPS * @note * @param state : current state that program is processing * @param buf : pointer to buffer that supposed to have GPS message * @param buf index : index to the current offset of the buffer * @param buf size : size of the buffer * @param section size : size of the processing section * @retval pointer of return value */ static GPS_ProcessStatus GPSGMS6_ProcessGprmcSection(GPS_ProcessState state,char * buf , unsigned int buf_index,unsigned int buf_size, unsigned int section_size, char * ret_value) { /* Initialize status */ GPS_ProcessStatus status = GPS_Status_Valid; if (buf_index >= (buf_size - section_size)) { /* Data not Enough to process */ status = GPS_Status_NotEnough; } else if (buf[buf_index] == GPS_DELIMITER) { /* Empty Data */ status = GPS_Status_Empty; memset(ret_value,GPS_DEFAULT_DATA_VALUE, section_size); } else { /* Populate the data */ unsigned int idx; for(idx = 0; idx < section_size; idx++) { ret_value[idx] = buf[buf_index + idx]; } } /* Return status */ return status; } /** * @brief Utility for processing GPS data * @note this rely on gprmc table * @param buf : pointer to buffer that supposed to have GPS message * @param buf size : size of the buffer * @retval variable that define in the table will be populated the data */ static void GPSGMS6_ProcessGpsData(char * buf, unsigned int size) { unsigned int index; unsigned int adv_index = 0; /* Initialize status and state */ GPS_ProcessStatus status = GPS_Status_Valid; GPS_ProcessState state = GPS_Process_Start; /* Walk through the buffer */ for(index = 0; index < size; index++) { /* Start the process */ if (state == GPS_Process_Start) { /* Process the message */ if (buf[index] == GPS_MESSAGE_HEADER_PREFIX) { /* Found header */ state = GPS_Process_Header; } else { /* Continue searching */ continue; } } else if (state == GPS_Process_Header) { /* Process Header */ if (index < (size - HEADER_SIZE)) { /* Check for GPRMC */ if (IS_HEADER_GPRPC(buf)) { /* Populate the header to the variable */ unsigned int h_index; for(h_index = 0; h_index < HEADER_SIZE; h_index++) { m_gprmc.header[h_index] = buf[index + h_index]; } /* Move to the next section */ index += HEADER_SIZE; state = GPS_Process_Time; } } else { break; } } else { /* Process GRPMC section */ status = GPSGMS6_ProcessGprmcSection(state, buf ,index, size, GET_GPRMC_SECTION_SIZE(state), GET_GPRMC_VARIABLE_ADDR(state)); /* Move to the next section */ adv_index = GET_GPRMC_SECTION_SIZE(state); state = GET_GPRMC_NEXT_STATE(state) ; } if (status == GPS_Status_NotEnough || state == GPS_Process_Complete) { /* In case of status not normal, then done */ break; } else if (status == GPS_Status_Valid) { /* Status is valid, move on */ index += adv_index; } } /* Check validity of the data */ if (IS_INDICATOR_VALID(m_gprmc.indicator[0])) { /* If valid, populate to the valid variable */ m_available= true; memcpy(&m_valid_gprmc, &m_gprmc , sizeof(m_gprmc)); } } /** * @brief Callback function that process when the message is completed * @note Rx Serial Interrupt must be properly started * @retval */ static void GPSGMS6_CompleteCallback() { /* Process GPS Data once message is completed read */ GPSGMS6_ProcessGpsData(m_RxBuf, RX_BUF_SIZE); } /** * @brief Callback function that process when a charector is transfered * @note Rx Serial Interrupt must be properly started * @retval */ static void GPSGMS6_ByteCallback() { /* Note: you need to actually read from the serial to clear the RX interrupt */ m_RxBuf[m_index] = serial_gps.getc(); m_index++; if (m_index == RX_BUF_SIZE) { /* Buffer is full, call complete callback */ m_index = 0; GPSGMS6_CompleteCallback(); } } /** * @brief Constructor for GPS module * @note * @retval */ GPSGms6::GPSGms6() { m_index = 0; m_available = false; /* Talking on 9600 bps */ serial_gps.baud(GPS_BAUD_RATE); } /** * @brief Function to start GPS Module * @note after started, interrupt will always be active * @retval */ void GPSGms6::start_GPS() { /* Start Rx interrupt */ serial_gps.attach(&GPSGMS6_ByteCallback); } /** * @brief Function to get latest GPRMC data * @note * @retval latest GPRMC data */ GPRMC_Data_TypeDef * GPSGms6::latestGPRMC() { return (&m_gprmc); } /** * @brief Function to get latest and valid GPRMC * @note * @retval valid GPRMC data */ GPRMC_Data_TypeDef * GPSGms6::validGPRMC() { m_available = false; return (&m_valid_gprmc); } /** * @brief Function to get available flag of the valid GPRMC data * @note * @retval latest GPRMC data */ bool GPSGms6::available() { return (m_available); } /** * @brief Function to get UTC time * @note * @retval UTC time tn fm struct format */ tm GPSGms6::UTCTime() { struct tm t; /* Check available of date and time */ if (m_gprmc.date[GPS_TIME_DATE_OFFSET] != ' ' && m_gprmc.time[GPS_TIME_HOUR_OFFSET] != ' ' ) { /* Allocate buffer for buffering */ char str[GPS_STRING_BUFFER_SIZE]; /* populate the second */ memcpy( str, &m_gprmc.time[GPS_TIME_SECOND_OFFSET], GPS_TIME_SECOND_SIZE ); t.tm_sec = atoi(str); /* populate the minute */ memcpy( str, &m_gprmc.time[GPS_TIME_MINUTE_OFFSET], GPS_TIME_MINUTE_SIZE ); t.tm_min = atoi(str); /* populate the hour */ memcpy( str, &m_gprmc.time[GPS_TIME_HOUR_OFFSET], GPS_TIME_HOUR_SIZE ); t.tm_hour = atoi(str); /* populate the date */ memcpy( str, &m_gprmc.date[GPS_TIME_DATE_OFFSET], GPS_TIME_DATE_SIZE ); t.tm_mday = atoi(str); /* populate the month */ memcpy( str, &m_gprmc.date[GPS_TIME_MONTH_OFFSET], GPS_TIME_MONTH_SIZE ); t.tm_mon = atoi(str); /* populate the year */ memcpy( str, &m_gprmc.date[GPS_TIME_YEAR_OFFSET], GPS_TIME_YEAR_SIZE ); t.tm_year = atoi(str); } else { /* Found nothing */ t.tm_mday = INVALID_TIME_DATE; t.tm_mon = INVALID_TIME_MONTH; t.tm_year = INVALID_TIME_YEAR; } /* Return the time !! */ return (t); }