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 Kenji Arai

Please refer following.
/users/kenjiArai/notebook/frequency-counters/

Revision:
13:1041596c416c
Parent:
11:20e7a45f1448
Child:
14:ba6ea409ab05
--- a/main.cpp	Fri Jan 02 10:57:25 2015 +0000
+++ b/main.cpp	Wed Nov 23 07:35:20 2016 +0000
@@ -1,460 +1,344 @@
-/*
- * mbed Application program / Frequency Counter with GPS 1PPS Compensation
- *
- * Copyright (c) 2014 Kenji Arai / JH1PJL
- *  http://www.page.sannet.ne.jp/kenjia/index.html
- *  http://mbed.org/users/kenjiArai/
- *      Created: October   18th, 2014
- *      Revised: January    2nd, 2015
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define USE_COM         // use Communication with PC(UART)
-#define SET_RTC
-//#define USE_DEBUG
-
-//  Include ---------------------------------------------------------------------------------------
-#include "mbed.h"
-#include "rtos.h"
-#include "TextLCD.h"
-#include "DRV8830.h"
-#include "ADT7410.h"
-#include "PID.h"
-#include "frq_cuntr_full.h"
-#include "CheckRTC.h"
-#include "iSerial.h"
-#include "gps.h"
-
-using namespace Frequency_counter;
-
-//  Definition ------------------------------------------------------------------------------------
-#ifdef USE_COM
-#define BAUD(x)         pc.baud(x)
-#define GETC(x)         pc.getc(x)
-#define PUTC(x)         pc.putc(x)
-#define PRINTF(...)     pc.printf(__VA_ARGS__)
-#define READABLE(x)     pc.readable(x)
-#else
-#define BAUD(x)         {;}
-#define GETC(x)         {;}
-#define PUTC(x)         {;}
-#define PRINTF(...)     {;}
-#define READABLE(x)     {;}
-#endif
-
-#ifdef USE_DEBUG
-#define DEBUGBAUD(x)    pc.baud(x)
-#define DEBUG(...)      pc.printf(__VA_ARGS__)
-#else
-#define DEBUGBAUD(x)    {;}
-#define DEBUG(...)      {;}
-#endif
-
-#define CLOCK_BASE      (24.999982f)
-
-#define GSP_BUF_B       (128 * 3)
-#define GPS_BUF_S       (128 * 2)
-
-//  Object ----------------------------------------------------------------------------------------
-DigitalOut  led_gate(LED1);
-//Serial      pc(USBTX, USBRX);
-iSerial     pc(USBTX, USBRX, 1024, 32);
-//Serial      gps(NC, PA_10); // GPS RX
-iSerial     gps(PA_9, PA_10, 32, 1024); // GPS RX
-I2C         i2cBus(PB_9,PB_8);  // SDA, SCL
-DRV8830     heater(i2cBus, (uint8_t)DRV8830ADDR_00);
-ADT7410     t(i2cBus, ADT7410ADDR_NN);
-TextLCD     lcd(PB_0, PA_4, PC_0, PC_1, PC_2, PC_3, TextLCD::LCD20x4); // rs, e, d4-d7
-PID         pid(14.0f, 50.0f, 1.5f, 1.0f);
-// PC_6,PC_7 & PB_6 use for Timer3 & 4(16+16bit)
-// PA_0,PA_1 & PB_10 use for Timer2(32bit)
-// PA_8 & PC_7 use for MCO (Test purpose)
-FRQ_CUNTR   fc(PC_6, 1.0, CLOCK_BASE); // Input port, gate time[sec] and External clock freq.
-
-//  RAM -------------------------------------------------------------------------------------------
-// Freq.
-uint32_t    counter_1pps;
-double      new_frequency;
-double      base_clock_1pps;
-// Temp Control
-float       volt = 0.0;
-float       tmp = 0;
-float       pid_val = 0;
-uint32_t    n = 0;
-// GPS
-uint32_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_GGA[GPS_BUF_S];
-// Time
-time_t      seconds;
-time_t      seconds_jst;
-struct tm   t_gps;
-// rtos
-Queue<uint32_t, 2> queue0;
-
-//  ROM / Constant data ---------------------------------------------------------------------------
-//                              12345678901234567890
-static char *const msg_clear = "                    ";
-static char *const msg_msg0  = "Frequency Counter   ";
-static char *const msg_msg1  = "  mbed Nucleo F411RE";
-static char *const msg_msg2  = "    by JH1PJL K.Arai";
-static char *const msg_msg3  = "    "__DATE__" ";
-
-//  Function prototypes ---------------------------------------------------------------------------
-uint32_t check_gps_ready(void);
-void get_time_and_date(struct tm *pt);
-void getline_gps(void);
-
-//-------------------------------------------------------------------------------------------------
-//  Control Program
-//-------------------------------------------------------------------------------------------------
-void measure_freq(void const *args)
-{
-    while(true) {
-        if (fc.status_freq_update() != 0) {
-            new_frequency = fc.read_freq_data();
-            queue0.put((uint32_t*)1);
-        }
-        if (fc.status_1pps() != 0) {
-            counter_1pps = fc.read_avarage_1pps();
-        }
-        Thread::wait(100);
-    }
-}
-
-void temp_control(void const *args)
-{
-    uint32_t error_count = 50;
-
-    t.set_config(OPERATION_MODE_CONT + RESOLUTION_16BIT);
-    pid.setInputLimits(0.0, 4.5);
-    pid.setOutputLimits(0.0, 5.0);
-    pid.setSetPoint(2.5);
-    while(true) {
-        tmp = t.read_temp();
-        pid.setProcessValue(tmp / 10);
-        pid_val = pid.compute();
-        volt = pid_val - 2.5f;
-        if (volt < -0.8f) {
-            volt = -0.8f;
-        } else if (volt > 0.8f) {
-            volt = 0.8f;
-        }
-        if ((volt == -0.800f) || (volt == 0.800f)){
-            if (--error_count == 0){
-                pid.reset();
-                error_count = 50;
-            }
-        } else {
-            error_count = 50;
-        }
-        heater.set_voltage(volt);
-        if (heater.status()) {
-            heater.reset();
-        }
-        /* Wait until it is time to check again. */
-        Thread::wait(1000);
-    }
-}
-
-// Get GAA data
-void gps_data_rcv(void const *args)
-{
-    int8_t i;
-    time_t old_ave_sec[2];
-    uint32_t diff;
-
-    gps.baud(9600);
-    seconds = time(NULL);
-    DEBUG("\r\nCurrent Time: %s\r\n", ctime(&seconds));
-    old_ave_sec[0] = 0;
-    old_ave_sec[1] = 0;
-    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;
-            DEBUG("GET RMC\r\n");
-            if (gps_status > 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);
-                        DEBUG("SET RTC\r\n");
-                    }
-                }
-            }
-        } 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;
-            DEBUG("GET GGA\r\n");
-            gps_status = check_gps_ready();
-        }
-    }
-}
-
-void display_data(void const *args)
-{
-    char buf[40];
-
-    BAUD(9600);
-    DEBUGBAUD(9600);
-    PRINTF("\r\nFrequency Counter by JH1PJL created on "__DATE__"\r\n");
-    // Initial screen
-    lcd.locate(0, 0);
-    lcd.printf(msg_msg0);
-    lcd.printf(msg_msg1);
-    lcd.printf(msg_msg2);
-    lcd.printf(msg_msg3);
-    Thread::wait(3000);
-    lcd.locate(0, 0);
-    lcd.printf(msg_clear);
-    lcd.printf(msg_clear);
-    lcd.printf(msg_clear);
-    lcd.printf(msg_clear);
-    while(true) {
-        osEvent evt = queue0.get();
-        PRINTF("FRQ= %11.1f Hz, ", new_frequency);
-        PRINTF("1PPS= %9d , %9d (new), ",counter_1pps, fc.read_newest_1pps());
-        PRINTF("%+6.3f dC, ", tmp);
-        PRINTF("PID= %+6.3f , ", volt);
-//        PRINTF("t= %5d S, ", n++);
-        seconds = time(NULL);
-        seconds_jst = seconds + 32400;   // +9 hours ->JST
-        //                 December 31,'14, 13:12:11
-//        strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds));
-        //                 31 Dec 2014 13:12:11
-//        strftime(buf,40, "%x %X ", localtime(&seconds));
-        //                 1:12:11 PM (2014/12/31)
-        strftime(buf,40, "%I:%M:%S %p %m/%d", localtime(&seconds_jst));
-        PRINTF("%s, ", buf);
-        if (fc.status_gps()) {
-            PRINTF("RDY");
-        } else {
-            PRINTF("NO ");
-        }
-        PRINTF("\r\n");
-        lcd.locate(0, 0);
-        lcd.printf("Freq= %11.2f Hz", new_frequency);
-        lcd.locate(0, 1);
-        lcd.printf("1PPS=%9d Hz", counter_1pps);
-        lcd.locate(0, 2);
-        strftime(buf,40, " %I:%M:%S %p (%m/%d)", localtime(&seconds_jst));
-        lcd.printf("%s, ", buf);
-        lcd.locate(0, 3);
-        lcd.printf("t= %+4.1f%cC", tmp, 0xdf);
-        if (fc.status_gps()) {
-            lcd.printf("   GPS RDY");
-        } else {
-            lcd.printf("   NO GPS ");
-        }
-        base_clock_1pps = (double)counter_1pps / 1000000;
-        double diff = base_clock_1pps - CLOCK_BASE;
-        if (diff < 0) {
-            diff *= -1;
-        }
-        if (diff < 0.00001) {   // less than 10Hz
-            fc.set_external_clock(base_clock_1pps);
-        }
-        /* Wait until it is time to check again. */
-        Thread::wait(100);
-    }
-}
-
-// Thread definition
-osThreadDef(measure_freq, osPriorityNormal,1024);
-osThreadDef(temp_control, osPriorityNormal,1024);
-osThreadDef(display_data, osPriorityNormal,1536);
-osThreadDef(gps_data_rcv, osPriorityNormal,1536);
-
-int main()
-{
-//    PA8 & PC9 uses for MCO_1 & MCO_2 -> Clock output for checking
-    fc.port_mco1_mco2_set(4);      // Clk/4 ->1/1(100MHz) cannot measure!!
-    osThreadCreate(osThread(measure_freq), NULL);
-    Thread::wait(5);   //wait
-    osThreadCreate(osThread(temp_control), NULL);
-    Thread::wait(8);   //wait
-    osThreadCreate(osThread(display_data), NULL);
-    Thread::wait(10);   //wait
-    if (CheckRTC() == OK) { // If RTC is NG, no need to start GPS RX function
-        DEBUG("\r\nGPS task starts\r\n");
-        osThreadCreate(osThread(gps_data_rcv), NULL);
-    }
-    while(true) {
-        /* Wait until it is time to check again. */
-        Thread::wait(5000);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// GPS data Analysis
-//
-//  PA6C GPS Module
-//      http://www.gtop-tech.com/en/product/MT3339_GPS_Module_03.html
-//      Update time: 1 second (1PPS: ±10ns RMS)
-//      MediaTek MT3339 Chipset, L1 Frequency, C/A code, 66 Channels
-//      NMEA 0183
-//
-//      current setting: GGA, VTG, GGA, RMC
-//
-///////////////////////////////////////////////////////////////////////////////
-// Get line of data from GPS
-void getline_gps(void)
-{
-    while (gps.getc() != '$') {
-        //DEBUG("GETC but not $\r\n");
-        Thread::yield();
-    }
-    GPS_Buffer[0] = '$';
-    for (int8_t i = 1; i < GSP_BUF_B; i++) {
-        GPS_Buffer[i] = gps.getc();
-        if (GPS_Buffer[i] == '\r' || GPS_Buffer[i] == '\n') {
-            GPS_Buffer[i] = '\r';
-            GPS_Buffer[i+1] = '\n';
-            GPS_Buffer[i+2] = 0;
-            GPS_Buffer[i+3] = 0;
-            //DEBUG("Get one GPS data\r\n");
-            return;
-        }
-    }
-}
-
-// 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 and number of satelites
-uint32_t check_gps_ready(void)
-{
-    char *p;
-    uint32_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 == '0') {
-        x = 0;
-    } else if (*p == '1') {
-        x = 0x10;
-    } else if (*p == '2') {
-        x = 0x20;
-    } else {
-        x= 0;
-    }
-    ++p;
-    if (*p == ',') {
-        ++p;
-        d = hex(*p++);
-        if (d != ERR) {
-            x += (uint32_t)d;
-            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;
-}
+/*
+ * mbed Application program / Frequency Counter with GPS 1PPS Compensation
+ *      Only for ST Nucleo-F746ZG
+ *
+ * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Created:    October   18th, 2014
+ *      Revised:    January    2nd, 2015
+ *      Re-started: June      25th, 2016    ported from F411 to F746
+ *      Revised:    Novemeber 23rd, 2016
+ *
+ * Base program: Frequency_counter_w_GPS_1PPS (only for Nucleo-F411RE board)
+ * https://developer.mbed.org/users/kenjiArai/code/Frequency_Counter_w_GPS_1PPS/
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+--------------------------------------------------------------------------------
+  Frequency Counter Functions
+    Mesurement frequency range:
+         10Hz to 100MHz (BNC Connector)
+    Extended range:
+         Up to 1GHz (1/10 prescaler) or more over (1/20) (SMA)
+    Gate time:
+         1 sec to 4095sec (extend to more if RAM is avairable)
+    Reciprocal measurement:
+         0.01Hz to 5KHz (extend more lower frequency change input I/F)
+    Base Internal Clock:
+         50MHz VCTCXO (Connor-Winfield TB514-050.0M)
+    1 PPS:
+         GPS receiver(u-blux7/NEO-7) with an external antenna (SMA)
+    Temperature controlled Oven:
+         32 degree Celsius +/-0.2 for 50MHz VCTCXO & 3.3V regulater
+  Hardware Configration
+    frequency input:                PC_6 & PA_3
+    50MHz base clock input:         PA_5
+    GPS 1PPS input:                 PA_1
+    Connect (for 1sec gate):        PA_7, PB_10 and PC_7 connected together
+  IMPORTANT!!!!
+    SB13 & SB181 must REMOVE from Nucleo-F746ZG board
+--------------------------------------------------------------------------------
+*/
+
+#define     USE_COM         // use Communication with PC(UART)
+#define     USE_DEBUG
+//#define     HW_TEST_GO    // activate Hardware test mode
+
+//  Include --------------------------------------------------------------------
+#include    "mbed.h"
+#include    "rtos.h"
+#include    "GPSrcvr.h"
+#include    "DRV8830.h"
+#include    "ADT7410.h"
+#include    "PID.h"
+#include    "frq_cuntr_f746.h"
+#include    "TextLCD.h"
+#include    "QEI.h"
+#include    "uif.h"
+
+//  Definition -----------------------------------------------------------------
+#ifdef  USE_COM
+#define BAUD(x)         pc.baud(x)
+#define GETC(x)         pc.getc(x)
+#define PUTC(x)         pc.putc(x)
+#define PRINTF(...)     pc.printf(__VA_ARGS__)
+#define READABLE(x)     pc.readable(x)
+#else
+#define BAUD(x)         {;}
+#define GETC(x)         {;}
+#define PUTC(x)         {;}
+#define PRINTF(...)     {;}
+#define READABLE(x)     {;}
+#endif
+
+#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 CLEAR_PD_2_RX_LINE() {UART5->ICR = 0; UART5->CR1 = 0; UART5->CR1 = 5;}
+
+#define CLOCK_BASE      (50.000000f)    // MHz
+#define TRGT_TEMP       (32.0f)         // degC
+
+#define RECIPRO_OVRFLW  10000           // = 5KHz
+#define RECIPRO_TIMEOUT 1000000         // = 0.001Hz
+
+#define GSP_BUF_B       (128 * 3)
+#define GPS_BUF_S       (128 * 2)
+
+using namespace Frequency_counter;
+
+//  Object ---------------------------------------------------------------------
+DigitalOut      led_gate(LED1);
+DigitalOut      in_frq_slct(PC_9);
+DigitalInOut    prescaler10or20(PC_5);
+DigitalIn       pa1(PA_1);
+Timer           tmr0;
+Timer           tmr1;
+Timer           tmr2;
+Ticker          enter_irq;
+
+//**** UART
+Serial          pc(USBTX, USBRX);
+
+//**** Req. Counter
+FRQ_CUNTR       fc(CLOCK_BASE); // External clock freq.
+
+//**** Peltier temperature control 
+I2C             i2cBus(PB_9,PB_8);  // SDA, SCL
+DRV8830         heater(i2cBus, (uint8_t)DRV8830ADDR_00); // H brige
+PID             pid(8.0f, 85.0f, 4.0f, 0.7f);            // PID for oven
+ADT7410         t(i2cBus, ADT7410ADDR_NN);               // inside oven temp.
+
+//  RAM ------------------------------------------------------------------------
+// all display data
+dispDef     disp_data;
+// Freq.
+double      new_frequency;
+double      freq_recipro;
+uint32_t    interval_recipro;
+uint8_t     recipro_new_data_ready;
+uint8_t     recipro_overflow;
+
+//  ROM / Constant data --------------------------------------------------------
+
+
+//  Function prototypes --------------------------------------------------------
+extern void dispay_LCD_and_UART(dispDef *dt);
+extern void select_input_div_1or10or20(uint8_t mode);
+
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+// Frequency measurement
+void measure_freq(void const *args)
+{
+    while(true) {
+        if (fc.status_freq_update() != 0) {
+            new_frequency = fc.read_freq_data();
+            disp_data.m_frq      = new_frequency;
+            disp_data.m_frq_comp = fc.read_compensated_freq_data_w_gt(1);
+            disp_data.m_frq_10   = fc.read_compensated_freq_data_w_gt(10);
+            disp_data.m_frq_100  = fc.read_compensated_freq_data_w_gt(100);
+            disp_data.m_frq_1000 = fc.read_compensated_freq_data_w_gt(1000);
+        }
+        if (fc.status_1pps() != 0) {
+            disp_data.b_1pps_new = fc.read_newest_1pps();
+            disp_data.b_1pps_lng = fc.read_avarage_1pps();
+        }
+        Thread::wait(100);  // 0.1sec
+    }
+}
+
+// Frequency measurement / Reciprocal measurement
+void measure_freq_recipro(void const *args)
+{
+    int32_t  run2stop;
+
+    while(true) {
+        tmr0.reset();
+        tmr0.start();
+        fc.recipro_start_measure();
+        while (fc.recipro_check_trigger() == 0){
+            Thread::wait(1);  // 1mS
+            run2stop = tmr0.read_ms();
+            if (run2stop >= RECIPRO_TIMEOUT){
+                break;
+            }
+        }
+        if (run2stop >= RECIPRO_TIMEOUT){
+            freq_recipro = 0;
+        } else {
+            interval_recipro = fc.recipro_read_data();
+            if (interval_recipro >= RECIPRO_OVRFLW){
+                // Measure less than 5KHz frequency
+                freq_recipro = CLOCK_BASE/(double)interval_recipro * 1000000;
+                recipro_overflow = 0;
+            } else {
+                freq_recipro = 0;
+                recipro_overflow = 1;
+            }
+        }
+        recipro_new_data_ready = 1;
+        disp_data.m_frq_recipro = freq_recipro; 
+        disp_data.recipro_of = recipro_overflow;
+        run2stop = tmr0.read_ms();
+        if (run2stop > 1000){
+            Thread::wait(run2stop % 1000);  // next interval          
+        } else {
+            run2stop = 1000 - run2stop;
+            /* Wait until it is time to check again. */
+            Thread::wait(run2stop);         // 1sec interval
+        }
+    }
+}
+
+// Constant temperature oven control
+void temp_control(void const *args)
+{
+    static double   volt = 0.0;
+    static double   tmp = 0;
+    static double   pid_val = 0;
+    static uint32_t error_count = 3600;
+    static int32_t  keep_1sec;
+
+    t.set_config(OPERATION_MODE_CONT + RESOLUTION_16BIT);
+    pid.setInputLimits(0.0f, 5.0f);
+    pid.setOutputLimits(0.0f, 5.0f);
+    pid.setSetPoint(TRGT_TEMP/10.0f);
+    while(true) {
+        tmr2.reset();
+        tmr2.start();
+        tmp = t.read_temp();
+        disp_data.box_tmp = tmp;
+        //PRINTF("Temp=%f degC\r\n", tmp);
+        pid.setProcessValue(tmp / 10.0f);
+        pid_val = pid.compute();
+        volt = pid_val - (TRGT_TEMP/10.0f);
+        if (volt < -5.0f) {
+            volt = -5.0f;
+        } else if (volt > 5.0f) {
+            volt = 5.0f;
+        }
+        if ((volt == -5.0f) || (volt == 5.0f)){
+            if (--error_count == 0){
+                pid.reset();
+                error_count = 3600;
+                pid.setInputLimits(0.0f, 5.0f);
+                pid.setOutputLimits(0.0f, 5.0f);
+                pid.setSetPoint(TRGT_TEMP/10.0f);
+            }
+        } else {
+            error_count = 3600;
+        }
+        heater.set_voltage(-volt);
+        //PRINTF("Volt=%f V\r\n", volt);
+        if (heater.status()) {
+            heater.reset();
+        }
+        if ((tmp > (TRGT_TEMP + 0.2f)) || (tmp < (TRGT_TEMP - 0.4f))){
+            disp_data.temp_is_okay = 0;
+        } else {
+            disp_data.temp_is_okay = 1;
+        }
+#if defined(HW_TEST_GO)
+        pc.printf("Volt=%+4.3f [V] , Oven Temp. %+6.3f [degC]", volt, tmp);
+        pc.printf(", Diff=%3.1f-x= %+6.3f \r\n", TRGT_TEMP, TRGT_TEMP - tmp);
+#endif
+        keep_1sec = 1000 - keep_1sec;
+        Thread::wait(keep_1sec);         // 1sec interval
+    }
+}
+
+void display_data(void const *args)
+{
+    int32_t tim_remain;
+
+    while(true){
+        tmr1.reset();
+        tmr1.start();
+        disp_data.gps_1pps_ave = fc.read_num_in_buffer();
+        disp_data.ready_1pps = check_gps_3d();
+        // User_IF    
+        dispay_LCD_and_UART(&disp_data); // separate files uif.cpp & uif.h
+        /* Wait */
+        tim_remain = 1000 - tmr1.read_ms();
+        Thread::wait(tim_remain);
+    }
+}
+
+void receive_gps(void const *args)
+{
+    gps_data_rcv(); // infinit loop -> never return
+    // separate files GPSrcvr.cpp & GPSrcvr.h
+}
+
+#if !defined(HW_TEST_GO)    // Normal control mode
+
+// Thread definition
+osThreadDef(measure_freq, osPriorityNormal,1024);
+osThreadDef(measure_freq_recipro, osPriorityNormal,1024);
+osThreadDef(temp_control, osPriorityNormal,2048);
+osThreadDef(receive_gps, osPriorityNormal,1024);
+osThreadDef(display_data, osPriorityNormal,2048);
+
+int main(){
+    disp_first_msg();
+    Thread::wait(1000); // 1sec
+    disp_wait_gps();
+    osThreadCreate(osThread(receive_gps), NULL);
+    PRINTF("\r\nStart GPS receiving!\r\n");
+    while (check_gps_is_okay() == false){;}  // wait till "true"
+    PRINTF("GPS data is valid!\r\n");
+    fc.debug_printf_internal_data();
+    osThreadCreate(osThread(measure_freq), NULL);
+    Thread::wait(5);    //wait
+    osThreadCreate(osThread(temp_control), NULL);
+    Thread::wait(8);    //wait
+    osThreadCreate(osThread(measure_freq_recipro), NULL);
+    Thread::wait(3);    //wait
+    osThreadCreate(osThread(display_data), NULL);
+    Thread::wait(10);   //wait
+    select_input_div_1or10or20(0);  // BNC (none presclaer)
+    while(true) {
+        /* Wait until it is time to check again. */
+        Thread::wait(60000);        // 1min.
+    }
+}
+
+#else               // Hardware Test mode
+
+#include "hw_tst.h"
+extern void hardware_test(void);
+
+int main(){
+    hardware_test();
+}
+
+double read_temperature(uint8_t n)
+{
+    if (n == 0){
+        t.set_config(OPERATION_MODE_CONT + RESOLUTION_16BIT);
+        return 0;
+    } else if (n == 1){
+        return t.read_temp();
+    }
+    return 0;
+}
+
+#endif // !defined(HW_TEST_GO)