GPS GMS-6 Module
Diff: GPSGms6.cpp
- Revision:
- 0:7ef27b349b37
- Child:
- 1:dceb4eaf697e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GPSGms6.cpp Tue May 10 06:33:57 2016 +0000 @@ -0,0 +1,184 @@ +#include "mbed.h" +#include "GPSGms6.h" +#include <string> + +#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; +GPRMC_Data_TypeDef m_valid_gprmc; +char m_RxBuf[RX_BUF_SIZE]; +bool m_available; +int m_index; +Serial serial_gps(PA_9, PA_10); +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} + +}; +static GPS_ProcessStatus GPS_ProcessGprmcSection(GPS_ProcessState state,char * buf , unsigned int buf_index,unsigned int buf_size, unsigned int section_size, char * ret_value) +{ + GPS_ProcessStatus status = GPS_Status_Valid; + if (buf_index >= (buf_size - section_size)) { + status = GPS_Status_NotEnough; + } else if (buf[buf_index] == ',') { + status = GPS_Status_Empty; + memset(ret_value,' ', section_size); + } else { + unsigned int idx; +// printf("\r\n state = %d =",state); + for(idx = 0; idx < section_size; idx++) { + ret_value[idx] = buf[buf_index + idx]; + } + + } + return status; + +} +static void GPS_ProcessGpsData(char * buf, unsigned int size) +{ + unsigned int index; + unsigned int adv_index = 0; + GPS_ProcessStatus status = GPS_Status_Valid; + GPS_ProcessState state = GPS_Process_Start; + for(index = 0; index < size; index++) { + if (state == GPS_Process_Start) { + if (buf[index] == '$') { + state = GPS_Process_Header; + } else { + continue; + } + } else if (state == GPS_Process_Header) { + if (index < (size - HEADER_SIZE)) { + if (buf[index] == 'G' && + buf[index+1] == 'P' && + buf[index+2] == 'R' && + buf[index+3] == 'M' && + buf[index+4] == 'C' + ) { + unsigned int h_index; + for(h_index = 0; h_index < HEADER_SIZE; h_index++) { + m_gprmc.header[h_index] = buf[index + h_index]; + } + index += HEADER_SIZE; + state = GPS_Process_Time; + } + } else { + break; + } + + } else { + status = GPS_ProcessGprmcSection(state, buf ,index, size, GET_GPRMC_SECTION_SIZE(state), GET_GPRMC_VARIABLE_ADDR(state)); + adv_index = GET_GPRMC_SECTION_SIZE(state); + state = GET_GPRMC_NEXT_STATE(state) ; + } + + + if (status == GPS_Status_NotEnough || state == GPS_Process_Complete) { + break; + } else if (status == GPS_Status_Valid) { + index += adv_index; + } + } + + if (m_gprmc.indicator[0] == (char)'A' && + m_gprmc.indicator[0] == (char)'D' && + m_gprmc.indicator[0] == (char)'E' + ) { + m_available= true; + memcpy(&m_valid_gprmc, &m_gprmc , sizeof(m_gprmc)); + } +} + + +void complete_callback() +{ + GPS_ProcessGpsData(m_RxBuf, RX_BUF_SIZE); + +} +void byte_callback() +{ + // Note: you need to actually read from the serial to clear the RX interrupt + //printf("%c", gps.getc()); + m_RxBuf[m_index] = serial_gps.getc(); + //printf("%c", m_RxBuf[m_index]); + m_index++; + if (m_index == RX_BUF_SIZE) { + m_index = 0; + complete_callback(); + } +// myled = !myled; +} +GPSGms6::GPSGms6() +{ + + m_index = 0; + m_available = false; + + serial_gps.baud(9600); + +} +void GPSGms6::start_GPS() +{ + serial_gps.attach(&byte_callback); +} +GPRMC_Data_TypeDef GPSGms6::latestGPRMC() +{ + return (m_gprmc); +} +GPRMC_Data_TypeDef GPSGms6::validGPRMC() +{ + m_available = false; + return (m_valid_gprmc); +} +bool GPSGms6::available() +{ + return (m_available); +} +tm GPSGms6::UTCTime() +{ + struct tm t; + if (m_gprmc.date[0] != ' ' && m_gprmc.time[0] != ' ' ) + { + char str[3]; + + memcpy( str, &m_gprmc.time[4], 2 ); + t.tm_sec = atoi(str); + memcpy( str, &m_gprmc.time[2], 2 ); + t.tm_min = atoi(str); + memcpy( str, &m_gprmc.time[0], 2 ); + t.tm_hour = atoi(str); + + memcpy( str, &m_gprmc.date[0], 2 ); + t.tm_mday = atoi(str); + + memcpy( str, &m_gprmc.date[2], 2 ); + t.tm_mon = atoi(str); + + memcpy( str, &m_gprmc.date[4], 2 ); + t.tm_year = atoi(str); + } + else + { + t.tm_mday = 0; + t.tm_mon = 0; + t.tm_year = 0; + } + return (t); +} \ No newline at end of file