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/
Diff: GPS_rcvr/GPSrcvr.cpp
- Revision:
- 0:52c5dc2b2b68
diff -r 000000000000 -r 52c5dc2b2b68 GPS_rcvr/GPSrcvr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GPS_rcvr/GPSrcvr.cpp Sat Nov 19 05:32:06 2016 +0000 @@ -0,0 +1,386 @@ +/* + * 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; +}