GPS GMS-6 Module
Diff: GPSGms6.cpp
- Revision:
- 1:dceb4eaf697e
- Parent:
- 0:7ef27b349b37
- Child:
- 2:3064a132bc39
--- a/GPSGms6.cpp Tue May 10 06:33:57 2016 +0000 +++ b/GPSGms6.cpp Sun May 15 09:56:11 2016 +0000 @@ -2,19 +2,31 @@ #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; -GPRMC_Data_TypeDef m_valid_gprmc; -char m_RxBuf[RX_BUF_SIZE]; -bool m_available; -int m_index; +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 + */ GPRMC_Tbl_TypeDef gprms_tbl[] = { - // index , section size , variable + // 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}, @@ -32,153 +44,279 @@ {GPS_Process_Complete ,INVALID_VALUE ,(char *)INVALID_VALUE} }; + +/** + * @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 GPS_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)) { + if (buf_index >= (buf_size - section_size)) + { + /* Data not Enough to process */ status = GPS_Status_NotEnough; - } else if (buf[buf_index] == ',') { + } + else if (buf[buf_index] == ',') + { + /* Empty Data */ status = GPS_Status_Empty; memset(ret_value,' ', section_size); - } else { + } + else + { + /* Populate the data */ 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 */ 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 GPS_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; - for(index = 0; index < size; index++) { - if (state == GPS_Process_Start) { - if (buf[index] == '$') { + + /* Walk through the buffer */ + for(index = 0; index < size; index++) + { + /* Start the process */ + if (state == GPS_Process_Start) + { + /* Process the message */ + if (buf[index] == '$') + { + /* Found header */ state = GPS_Process_Header; - } else { + } + else + { + /* Continue searching */ continue; } - } else if (state == GPS_Process_Header) { - if (index < (size - HEADER_SIZE)) { + } + else if (state == GPS_Process_Header) + { + /* Process Header */ + if (index < (size - HEADER_SIZE)) + { + /* Check for GPRMC */ if (buf[index] == 'G' && buf[index+1] == 'P' && buf[index+2] == 'R' && buf[index+3] == 'M' && buf[index+4] == 'C' - ) { + ) + { + + /* 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 { + } + else + { break; } - } else { + } + else + { + /* Process GRPMC section */ status = GPS_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) { + if (status == GPS_Status_NotEnough || state == GPS_Process_Complete) + { + /* In case of status not normal, then done */ break; - } else if (status == GPS_Status_Valid) { + } + else if (status == GPS_Status_Valid) + { + /* Status is valid, move on */ index += adv_index; } } + /* Check validity of the data */ if (m_gprmc.indicator[0] == (char)'A' && m_gprmc.indicator[0] == (char)'D' && m_gprmc.indicator[0] == (char)'E' - ) { + ) + { + /* 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 + */ void complete_callback() { + /* Process GPS Data once message is completed read */ GPS_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 + */ void byte_callback() { - // Note: you need to actually read from the serial to clear the RX interrupt - //printf("%c", gps.getc()); + /* Note: you need to actually read from the serial to clear the RX interrupt */ m_RxBuf[m_index] = serial_gps.getc(); - //printf("%c", m_RxBuf[m_index]); m_index++; - if (m_index == RX_BUF_SIZE) { + if (m_index == RX_BUF_SIZE) + { + /* Buffer is full, call complete callback */ m_index = 0; complete_callback(); } -// myled = !myled; } + + +/** + * @brief Constructor for GPS module + * @note + * @retval + */ GPSGms6::GPSGms6() { m_index = 0; m_available = false; + /* Talking on 9600 bps */ serial_gps.baud(9600); } + +/** + * @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(&byte_callback); } + +/** + * @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[0] != ' ' && m_gprmc.time[0] != ' ' ) { + + /* Allocate buffer for buffering */ char str[3]; + /* populate the second */ memcpy( str, &m_gprmc.time[4], 2 ); t.tm_sec = atoi(str); + + /* populate the minute */ memcpy( str, &m_gprmc.time[2], 2 ); t.tm_min = atoi(str); + + /* populate the hour */ memcpy( str, &m_gprmc.time[0], 2 ); t.tm_hour = atoi(str); + /* populate the date */ memcpy( str, &m_gprmc.date[0], 2 ); t.tm_mday = atoi(str); + /* populate the month */ memcpy( str, &m_gprmc.date[2], 2 ); t.tm_mon = atoi(str); + /* populate the year */ memcpy( str, &m_gprmc.date[4], 2 ); t.tm_year = atoi(str); } else { + /* Found nothing */ t.tm_mday = 0; t.tm_mon = 0; t.tm_year = 0; } + + /* Return the time !! */ return (t); } \ No newline at end of file