Frequency counter using GPS 1PPS signal and temperature controlled 50MHz Base clock. Ported from F411 Frequency Counter.
Dependencies: QEI DRV8830 PID ADT7410 TextLCD Frq_cuntr_Nucleo-F746ZG RingBuffer
Fork of Frequency_Counter_w_GPS_1PPS by
Please refer following.
/users/kenjiArai/notebook/frequency-counters/
GPS_rcvr/GPSrcvr.cpp
- Committer:
- kenjiArai
- Date:
- 2019-12-22
- Revision:
- 15:ae0413277bc6
- Parent:
- 13:1041596c416c
File content as of revision 15:ae0413277bc6:
/* * mbed Application program / GPS receiver control and 1PPS output * * Copyright (c) 2004,'09,'10,'16 Kenji Arai / JH1PJL * http://www.page.sannet.ne.jp/kenjia/index.html * http://mbed.org/users/kenjiArai/ * Created: March 28th, 2004 Kenji Arai * updated: July 25th, 2009 for PIC24USB * updated: January 16th, 2010 change to GPS-GM318 * updated: April 24th, 2010 for mbed / NXP LPC1768 * Revised: Nomeber 22nd, 2016 */ // Include -------------------------------------------------------------------- #include <string.h> #include "mbed.h" #include "RingBuffer.h" #include "GPSrcvr.h" // Definition ----------------------------------------------------------------- //#define USE_DEBUG #ifdef USE_DEBUG #define U_DEBUGBAUD(x) pc.baud(x) #define U_DEBUG(...) pc.printf(__VA_ARGS__) #define DBG(c) pc.putc(c) #else #define U_DEBUGBAUD(x) {;} #define U_DEBUG(...) {;} #define DBG(c) {;} #endif #define GSP_BUF_B (128 * 3) #define GPS_BUF_S (128 * 2) // Object --------------------------------------------------------------------- DigitalIn gps_rx(PD_2); // for checking GPS RX line Serial gps(PC_12, PD_2); // GPS Data receive RingBuffer rxbuf(1024); // can receive all information every one sec extern Serial pc; // RAM ------------------------------------------------------------------------ bool gps_is_okay_flag; uint8_t gps_ready; uint8_t gps_status; uint8_t gps_rmc_ready; char GPS_Buffer[GSP_BUF_B]; //GPS data buffer char MsgBuf_RMC[GPS_BUF_S]; char MsgBuf_GSA[GPS_BUF_S]; char MsgBuf_GGA[GPS_BUF_S]; // Function prototypes -------------------------------------------------------- uint8_t check_gps_3d(void); uint8_t check_gps_ready(void); void get_time_and_date(struct tm *pt); void getline_gps(void); void gps_data_rcv(void); void iGPSrcv_initialize(void); int iGPS_readable(void); int iGPS_getc(void); //////////////////////////////////////////////////////////////////////////////// // Receive GPS data using Interrupt handler // // !!! Takes urgent and dirty solution by due to IRQ restriction // on mbed library (reason is unknown as of today) // reference source file:stm32f746xx.h // under /mbed-dev/targets/cmsis/TARGET_STM/TARGET_NUCLEO_F746ZG //////////////////////////////////////////////////////////////////////////////// // ------ Interrupt Function ------ void rx_handler(void) { uint32_t reg = UART5->ISR; if (reg && USART_ISR_RXNE){ // data is ready to read UART5->ISR &= ~(USART_ISR_RXNE + USART_ISR_PE + USART_ISR_FE + USART_ISR_NE + USART_ISR_ORE); rxbuf.save((unsigned char)UART5->RDR); } } void iGPSrcv_initialize(void) { __disable_irq(); UART5->CR1 &= ~(USART_CR1_TE + USART_CR1_TCIE + USART_CR1_TXEIE + USART_CR1_PEIE + USART_CR1_IDLEIE); UART5->CR1 |= (USART_CR1_RXNEIE + USART_CR1_RE + USART_CR1_UE); NVIC_SetVector(UART5_IRQn, (uint32_t)rx_handler); NVIC_ClearPendingIRQ(UART5_IRQn); NVIC_EnableIRQ(UART5_IRQn); __enable_irq(); #if 0 printf("UART5->CR1 0x%08x:0x%08x\r\n", &UART5->CR1, UART5->CR1); printf("UART5->CR2 0x%08x:0x%08x\r\n", &UART5->CR2, UART5->CR2); printf("UART5->CR3 0x%08x:0x%08x\r\n", &UART5->CR3, UART5->CR3); printf("UART5->BRR 0x%08x:0x%08x\r\n", &UART5->BRR, UART5->BRR); printf("UART5->GTPR 0x%08x:0x%08x\r\n", &UART5->GTPR, UART5->GTPR); printf("UART5->RTOR 0x%08x:0x%08x\r\n", &UART5->RTOR, UART5->RTOR); printf("UART5->RQR 0x%08x:0x%08x\r\n", &UART5->RQR, UART5->RQR); printf("UART5->ISR 0x%08x:0x%08x\r\n", &UART5->ISR, UART5->ISR); printf("UART5->ICR 0x%08x:0x%08x\r\n", &UART5->ICR, UART5->ICR); #endif } int iGPS_readable(void) { return rxbuf.check(); } int iGPS_getc(void) { while(!rxbuf.check()){;} // wait receiving a character return rxbuf.read(); } //////////////////////////////////////////////////////////////////////////////// // Parse GPS data // Module Type: u-blux7 NEO-7M //////////////////////////////////////////////////////////////////////////////// // Get RMC & GAA data void gps_data_rcv(void) { int8_t i; time_t old_ave_sec[2]; uint32_t diff = 0; time_t seconds; struct tm t_gps; seconds = time(NULL); U_DEBUG("\r\nCurrent Time: %s\r\n", ctime(&seconds)); old_ave_sec[0] = 0; old_ave_sec[1] = 0; // Wait long interval (every 1sec) for (uint32_t i = 0; i < 100000; i++){ if (gps_rx == 0){ i = 0; } } U_DEBUG("GPS line is Hi\r\n"); // Clear GPS RX line errors(over run) UART5->ICR = 0; UART5->CR1 = 0; UART5->CR1 = 5; iGPSrcv_initialize(); U_DEBUG("Start GPS!!"); gps_is_okay_flag = false; while(true) { getline_gps(); // Get GPS data from UART if (strncmp(GPS_Buffer, "$GPRMC",6) == 0) { for (i=0; GPS_Buffer[i] != 0; i++) {// Copy msg to RMC buffer MsgBuf_RMC[i] = GPS_Buffer[i]; } MsgBuf_RMC[i+1] = 0; #if 0 U_DEBUG("Get GPRMC\r\n"); #else if (gps_is_okay_flag == false){ pc.printf("GPRMC,"); } #endif if (gps_ready == 3) { U_DEBUG("3D condition\r\n"); get_time_and_date(&t_gps); seconds = mktime(&t_gps); if (old_ave_sec[0] == 0){ old_ave_sec[0] = seconds; } else if (old_ave_sec[1] == 0){ old_ave_sec[1] = seconds; } else { if (old_ave_sec[0] >= old_ave_sec[1]){ diff = old_ave_sec[0] - old_ave_sec[1]; } else { diff = old_ave_sec[1] - old_ave_sec[0]; } if (diff > 100 ){ old_ave_sec[0] = seconds; old_ave_sec[1] = 0; } else { if (old_ave_sec[0] > old_ave_sec[1]){ diff = seconds - old_ave_sec[0]; if (diff < 100){ old_ave_sec[1] = seconds; } } else { diff = seconds - old_ave_sec[1]; if (diff < 100){ old_ave_sec[0] = seconds; } } set_time(seconds); U_DEBUG("Set time and GPS is okay!\r\n"); gps_is_okay_flag = true; } } } } else if (strncmp(GPS_Buffer, "$GPGSA",6) == 0) { for (i=0; GPS_Buffer[i] != 0; i++) {// Copy msg to GSA buffer MsgBuf_GSA[i] = GPS_Buffer[i]; } MsgBuf_GSA[i+1] = 0; gps_ready = check_gps_3d(); #if 0 U_DEBUG("Get GPGSA\r\n"); #else if (gps_is_okay_flag == false){ pc.printf("GPGSA,"); } #endif } else if (strncmp(GPS_Buffer, "$GPGGA",6) == 0) { for (i=0; GPS_Buffer[i] != 0; i++) {// Copy msg to GGA buffer MsgBuf_GGA[i] = GPS_Buffer[i]; } MsgBuf_GGA[i+1] = 0; gps_status = check_gps_ready(); #if 0 U_DEBUG("Get GPGGA\r\n"); #else if (gps_is_okay_flag == false){ pc.printf("GPGGA,"); } #endif } } } bool check_gps_is_okay() { return gps_is_okay_flag; } // Get line of data from GPS void getline_gps(void) { char *p = GPS_Buffer; #if 1 while (iGPS_getc() != '$'){;} #else while (iGPS_getc() != '$') { Thread::yield(); } #endif *p++ = '$'; #if 1 U_DEBUG("\r\n"); #else pc.printf("\r\n"); #endif for (char i= 0;i < 150;i++){ *p = iGPS_getc(); #if 1 DBG(*p); #else pc.putc(*p); #endif if (*p == '\r'){ *++p = '\n'; *++p = 0; *++p = 0; U_DEBUG("Get one GPS data\r\n"); return; } else { p++; } } *++p = 0; *++p = 0; } // ASCII to hex uint8_t hex(char c){ if(c<= '/') return( ERR ); if(((c -= '0')<= 9 || 10 <= ( c -= 'A' - '0' - 10)) && c <= 15) { return((uint8_t)c); } return(ERR); } // Search next ',' (comma) char *next_comma( char *p ){ while (1) { if ( *p== ',' ) { return ++p; } else if ( *p == 0 ) { return (char*)-1; } else { p++; } } } // 2 digits ASCII char to one byte hex unsigned char change_acii_hex( char*p ){ unsigned char c; c = hex(*p++); /* No concern ERR condition! */ c = (c * 10) + hex(*p++); return c; } // Skip number of comma char *num_of_comma( char *p, int8_t n ){ for (; n> 0; n--) { if ( (p = next_comma(p)) == (char*) -1 ) { return (char*)-1; } } return p; } // Get GPS status (1=Not fix, 2=2D, 3=3D) uint8_t check_gps_3d(void){ char *p; uint8_t x; uint8_t d; // pick-up time p = MsgBuf_GSA; p = num_of_comma(p,1); // skip ',' // reach to "Position Fix Indicator" if (*p == 'A') { ++p; //',' ++p; // 1 or 2 or 3 d = hex(*p++); if (d != ERR) { x = d; } else { x = 1; } } else { x = 1; } return x; } // Get GPS status and number of satelites uint8_t check_gps_ready(void){ char *p; uint8_t x; uint8_t d; // pick-up time p = MsgBuf_GGA; p = num_of_comma(p,6); // skip ',' // reach to "Position Fix Indicator" if (*p == '1' || *p == '2') { ++p; //',' ++p; // Number d = hex(*p++); if (d != ERR) { x = d * 10; x += (uint32_t)hex(*p++); if (*p != ',') { x = 0; } } else { x = 0; } } else { x = 0; } return x; } // Get time(UTC) from GPS data void get_time_and_date(struct tm *pt){ char *p; p = MsgBuf_RMC; p = num_of_comma(p,1); /* skip one ',' */ pt->tm_hour = change_acii_hex(p); p += 2; pt->tm_min = change_acii_hex(p); p += 2; pt->tm_sec = change_acii_hex(p); p = MsgBuf_RMC; p = num_of_comma(p,9); /* skip one ',' */ pt->tm_mday = change_acii_hex(p); p += 2; pt->tm_mon = change_acii_hex(p) - 1; p += 2; pt->tm_year = change_acii_hex(p) + 100; }