Frequency Counter. User interface are used DISCO-F746NG GUI with touch panel.
Dependencies: BSP_DISCO_F746NG F746_GUI LCD_DISCO_F746NG RingBuffer TS_DISCO_F746NG fc_GPS1PPS_f746_f4xx mbed
Please refer following.
/users/kenjiArai/notebook/frequency-counters/
GPS_rcvr/GPSrcvr.cpp
- Committer:
- kenjiArai
- Date:
- 2016-11-19
- Revision:
- 0:52c5dc2b2b68
File content as of revision 0:52c5dc2b2b68:
/* * 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 13th, 2016 */ // Include -------------------------------------------------------------------- #include <string.h> #include "mbed.h" #include "GPSrcvr.h" #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE) #include "iSerial.h" #elif defined(TARGET_STM32F746NG) #include "RingBuffer.h" #endif // 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 --------------------------------------------------------------------- #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE) DigitalIn gps_rx(PC_7); // for checking GPS RX line iSerial gps(NC, PC_7, 0, 1024); // GPS Data receive #error "This is only on DISCO-F746NG!!" #elif defined(TARGET_STM32F746NG) RingBuffer rxbuf(1024); // can receive all information every one sec DigitalIn gps_rx(PF_6); // for checking GPS RX line Serial gps(NC, PF_6); // GPS Data receive #else #error "Target is only Nucleo-F411RE(F446RE) or DISCO-F746NG!!!" #endif 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); #if defined(TARGET_STM32F746NG) void iGPSrcv_initialize(void); int iGPS_readable(void); int iGPS_getc(void); #endif //////////////////////////////////////////////////////////////////////////////// // 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 //////////////////////////////////////////////////////////////////////////////// #if defined(TARGET_STM32F746NG) // ------ Interrupt Function ------ void rx_handler(void) { uint32_t reg = UART7->ISR; if (reg && USART_ISR_RXNE){ // data is ready to read UART7->ISR &= ~(USART_ISR_RXNE + USART_ISR_PE + USART_ISR_FE + USART_ISR_NE + USART_ISR_ORE); rxbuf.save((unsigned char)UART7->RDR); } } void iGPSrcv_initialize(void) { __disable_irq(); UART7->CR1 &= ~(USART_CR1_TE + USART_CR1_TCIE + USART_CR1_TXEIE + USART_CR1_PEIE + USART_CR1_IDLEIE); UART7->CR1 |= (USART_CR1_RXNEIE + USART_CR1_RE + USART_CR1_UE); NVIC_SetVector(UART7_IRQn, (uint32_t)rx_handler); NVIC_ClearPendingIRQ(UART7_IRQn); NVIC_EnableIRQ(UART7_IRQn); __enable_irq(); #if 0 printf("UART7->CR1 0x%08x:0x%08x\r\n", &UART7->CR1, UART7->CR1); printf("UART7->CR2 0x%08x:0x%08x\r\n", &UART7->CR2, UART7->CR2); printf("UART7->CR3 0x%08x:0x%08x\r\n", &UART7->CR3, UART7->CR3); printf("UART7->BRR 0x%08x:0x%08x\r\n", &UART7->BRR, UART7->BRR); printf("UART7->GTPR 0x%08x:0x%08x\r\n", &UART7->GTPR, UART7->GTPR); printf("UART7->RTOR 0x%08x:0x%08x\r\n", &UART7->RTOR, UART7->RTOR); printf("UART7->RQR 0x%08x:0x%08x\r\n", &UART7->RQR, UART7->RQR); printf("UART7->ISR 0x%08x:0x%08x\r\n", &UART7->ISR, UART7->ISR); printf("UART7->ICR 0x%08x:0x%08x\r\n", &UART7->ICR, UART7->ICR); #endif } int iGPS_readable(void) { return rxbuf.check(); } int iGPS_getc(void) { while(!rxbuf.check()){;} // wait receiving a character return rxbuf.read(); } #endif //////////////////////////////////////////////////////////////////////////////// // 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"); #if defined(TARGET_STM32F746NG) // Clear GPS RX line errors(over run) UART7->ICR = 0; UART7->CR1 = 0; UART7->CR1 = 5; iGPSrcv_initialize(); #endif U_DEBUG("Start GPS!!"); 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; DBG('2'); if (gps_ready == 3) { DBG('3'); 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); DBG('4'); return; } } } } 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(); DBG('x'); } 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(); DBG('1'); } } } 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 defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE) while (gps.getc() != '$'){;} #elif defined(TARGET_STM32F746NG) while (iGPS_getc() != '$'){;} #endif *p++ = '$'; #if 0 U_DEBUG("\r\n"); #else pc.printf("\r\n"); #endif for (char i= 0;i < 150;i++){ #if defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F446RE) *p = gps.getc(); #elif defined(TARGET_STM32F746NG) *p = iGPS_getc(); #endif #if 0 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; }