Frequency counter library using GPS 1PPS signal and temperature controlled 50MHz Base clock. Ported from F411 Frequency Counter.

Dependencies:   RingBuff

Dependents:   Frequency_Cntr_1PPS_F746ZG

Fork of Frq_cuntr_full by Kenji Arai

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

Revision:
1:102230f2879d
Parent:
0:bfdc6ed58a06
Child:
2:194f82ad3041
diff -r bfdc6ed58a06 -r 102230f2879d frq_cuntr_full.h
--- a/frq_cuntr_full.h	Sat Nov 22 04:01:41 2014 +0000
+++ b/frq_cuntr_full.h	Sat Nov 22 23:02:39 2014 +0000
@@ -1,13 +1,14 @@
 /*
- * mbed Application program / Frequency Counter with GPS 1PPS Compensation
+ * mbed Library / Frequency Counter with GPS 1PPS Compensation
  *      Frequency Counter Hardware relataed program
+ *      Only for ST Nucleo F411RE
  *
  * Copyright (c) 2014 Kenji Arai / JH1PJL
  *  http://www.page.sannet.ne.jp/kenjia/index.html
  *  http://mbed.org/users/kenjiArai/
  *      Additional functions and modification
  *      started: October   18th, 2014
- *      Revised: Nobember  22nd, 2014
+ *      Revised: Nobember  23rd, 2014
  *
  * 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
@@ -21,105 +22,163 @@
 
 #include "mbed.h"
 
+#define DEBUG           // use Communication with PC(UART)
+/*
+    CAUTION:
+    If you select internal clock (100MHz), you need consider PLL clock behavior.
+    PLL clock drifts over 60Hz (increase frequency) within 30 to 40 second
+    then suddenly back to low frequency and increase again.
+    Even you prepare precision external clock, this frequency drift cannot avoid.
+ */
+#define BASE_EXTERNAL_CLOCK
+
 namespace Frequency_counter
 {
-    #define DEBUG           // use Communication with PC(UART)
-    #define IRQ_DRIVE
-    //#define BASE_EXTERNAL_CLOCK
-    
-    #if defined(BASE_EXTERNAL_CLOCK)
-    #define CNT_UPPER       (0xffffffff - 100)
-    #define CNT_LOWER       (0          + 100)
-    //#define CNT_UPPER       (30000000 + 1000000)
-    //#define CNT_LOWER       (30000000 - 1000000)
-    #else
-    #define CNT_UPPER       (0xffffffff - 100)
-    #define CNT_LOWER       (0          + 100)
-    //#define CNT_UPPER       (100000000 - 100000)
-    //#define CNT_LOWER       (100000000 + 100000)
-    #endif
-    
-    #if defined(BASE_EXTERNAL_CLOCK)
-    #define ONE_SECOND_COUNT    0xe4e1c0
-    #else
-    #define ONE_SECOND_COUNT    0x2faf080
-    #endif
-    
-    #define CNT_BF_SIZE     120
-    
-    //#if defined(IRQ_DRIVE)
-    // 1PPS data
-    extern uint32_t onepps_cnt[CNT_BF_SIZE];
-    extern uint32_t onepps_num;
-    extern uint64_t  onepps_cnt_avarage;
-    extern uint8_t  onepps_buf_full;
-    extern uint8_t  onepps_ready_flg;
-    // TIM2
-    extern uint8_t  tim2_ready_flg;
-    extern uint32_t tim2_cnt_data;
-    extern uint32_t tim2_old_cnt_data;
-    // TIM3+4
-    extern uint8_t  tim3p4_ready_flg;
-    extern uint32_t tim3p4_cnt_data;
-    extern uint32_t tim3p4_old_cnt_data;
-    
-    // TIM2 IC2 Interrupt control
-    void irq_ic2_TIM2(void);
-    // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1)
-    void irq_ic2_TIM3P4(void);
+#define CNT_BASE        29999978        // 30MHz
+#define CNT_FIX_BASE    600000          // 0.03sec
+
+#if defined(BASE_EXTERNAL_CLOCK)
+#define CNT_UPPER       (CNT_BASE + 20)
+#define CNT_LOWER       (CNT_BASE - 20)
+#else
+#define CNT_UPPER       (0xffffffff - 100)
+#define CNT_LOWER       (0          + 100)
+#endif
+
+#if defined(BASE_EXTERNAL_CLOCK)
+#define ONE_SECOND_COUNT    (CNT_BASE - CNT_FIX_BASE)
+#else
+#define ONE_SECOND_COUNT    0x2faf080   // 50MHz
+#endif
+
+#define CNT_BF_SIZE     120             // 1PPS data save size
+
+/** Frequency Counter program
+ * Only for ST Nucleo F411RE Board
+ *
+ * @code
+ * #include "mbed.h"
+ *
+ * // PC_6,PC_7 & PB6 use for Timer3 & 4(16+16bit)
+ * // PA_0,PA_1 & PB10 use for Timer2(32bit)
+ * FRQ_CUNTR fc(PC_6, 1.0);    // Input port(Fixed) & gate time[sec]
+ *
+ * int main() {
+ *   // This is for test purpose
+ *   fc.port_mco1_mco2_set(2);      // Clk/2 ->1/1(100MHz) cannot measure!!
+ *   fc.read_frequency_TIM2(1.0);   // read TIM2 source frequency (test)
+ *   fc.read_frequency_TIM3P4(1.0); // read TIM3 source frequency (test)
+ *   while(true) {
+ *      while (fc.status_1pps() == 0) {;}
+ *      counter_1pps = fc.read_avarage_1pps();
+ *      while (fc.status_freq_update() == 0) {;}
+ *      new_frequency = fc.read_freq_data();
+ *      print("1PPS/ave = %9d , FREQUENCY = %9d\r\n", counter_1pps, new_frequency);
+ *   }
+ * }
+ * @endcode
+ */
+
+class FRQ_CUNTR
+{
+public:
+    /** Configure data pin (Not changeable)
+      * @param Freq. input pin
+      */
+    FRQ_CUNTR(PinName f_in, double gt);
+
+    /** Set gate time
+      * @param gate time [sec]
+      * @return !=0: new data is avairable, 0: not yet
+      */
+    double set_gate_time(double gt);
+
+    /** Read status (new frequency data is available or not)
+      * @param none
+      * @return !=0: new data is avairable, 0: not yet
+      */
+    uint32_t status_freq_update(void);
+
+    /** Read new frequency data
+      * @param none
+      * @return frequency data
+      */
+    uint32_t read_freq_data(void);
 
-    class FRQ_CUNTR
-    {
-    public:
-    
-        FRQ_CUNTR(PinName f_in);
-    
-        void initialize_Freq_counter(void);
-        
-        // Read TIM2 captured counter value
-        uint32_t read_ic2_counter_TIM2(void);
-        
-        // Check TIM2 IC2 status
-        uint32_t check_ic2_status_TIM2(void);
-    
-        // Read TIM3+4(as 32bit) captured counter value
-        uint32_t read_ic2_counter_TIM3P4(void);
-        
-        // Check TIM3 IC2 & TIM4 IC1 status
-        uint32_t check_ic2_status_TIM3P4(void);
-       
-        // Avarage measued data GPS 1PPS by 50MHz Internal Clock
-        void avarage_1pps(void);
-    
-        //  Frequency check for test purpose
-        uint32_t read_frequency_TIM2(float gate_time);
-        uint32_t read_frequency_TIM3P4(float gate_time);
-        
-        //  Clock output for test purpose
-        void port_mco1_mco2_set(uint8_t select);
-    
-    protected:
-        DigitalIn _pin;
-    
-        // Initialize TIM2
-        // Internal clock (50MHz) and IC2 for GPS 1pps signal measurement
-        void initialize_TIM2(void);
-        
-        // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit))
-        //      TIM3 clock input is unkown freq.(measuring freq.) and TIM4 is slave counter
-        //      1sec gate signal connected both TIM3 IC2 and TIM4 IC1 
-        void initialize_TIM3P4(void);
-    
-    private:
-        #if defined(IRQ_DRIVE)
-        // 1PPS data
-        uint32_t onepps_cnt[CNT_BF_SIZE];
-        uint32_t onepps_num;
-        uint64_t  onepps_cnt_avarage;
-        uint8_t  onepps_buf_full;
-        uint8_t  onepps_ready_flg;
-        #endif
-    };
+    /** Read avarage measued data GPS 1PPS
+      * @param none
+      * @return Frequency
+      */
+    uint32_t read_avarage_1pps(void);
+
+    /** Read status (new 1PPS data is available or not)
+      * @param none
+      * @return !=0: new data is avairable, 0: not yet
+      */
+    uint32_t status_1pps(void);
+
+    /** This is a test purpose function
+      * Check PA0 pin input or internal clock frequency
+      * @param none
+      * @return Frequency
+      */
+    uint32_t read_frequency_TIM2(float gate_time);
+
+    /** This is a test purpose function
+      * Check PC6 pin input frequency
+      * @param none
+      * @return Frequency
+      */
+    uint32_t read_frequency_TIM3P4(float gate_time);
+
+    /** This is a test purpose function
+      * Output clock from pin PA8 & PC9 uses for MCO_1 & MCO_2
+      * @param none
+      * @return none
+      */
+    void port_mco1_mco2_set(uint8_t select);
+
+protected:
+    DigitalIn _pin;
+
+    void initialize_Freq_counter(void);     // Initialize timers
+    // Internal clock (50MHz) and IC2 for GPS 1pps signal measurement
+    void initialize_TIM2(void);
+    // Initialize TIM3 and TIM4 as 32bit counter (TIM3(16bit) + TIM4(16bit))
+    void initialize_TIM3P4(void);
+    uint32_t set_1PPS_data(void);           // Set GPS 1PPS counter value
+    uint32_t read_ic2_counter_TIM2(void);   // Read TIM2 captured counter value
+    uint32_t check_ic2_status_TIM2(void);   // Check TIM2 IC2 status
+    uint32_t read_ic2_counter_TIM3P4(void); // Read TIM3+4(as 32bit) captured counter value
+    uint32_t check_ic2_status_TIM3P4(void); // Check TIM3 IC2 & TIM4 IC1 status
+    uint8_t  read_oc_port_status(void);     // Check TIM2 OC port
+
+private:
+    // TIM2
+    double   gate_time;
+    uint32_t counter_tim2;
+    uint32_t old_cntr_tim2;
+    // TIM3+4
+    uint32_t counter_tim3p4;
+    uint32_t old_cntr_tim3p4;
+    // 1PPS data
+    uint32_t onepps_newest;
+    uint32_t onepps_cnt[CNT_BF_SIZE];
+    uint32_t onepps_num;
+    uint64_t onepps_cnt_avarage;
+    uint8_t  onepps_buf_full;
+    uint8_t  onepps_ready_flg;
+};
+
+/*
+    Interrupt handler does NOT work following code
+    NVIC_SetVector(TIM2_IRQn, (uint32_t)FRQ_CUNTR::irq_ic2_TIM2);
+    From this reason, I wrote below code and set interrupt handler out side "FRQ_CUNTR" class
+    NVIC_SetVector(TIM2_IRQn, (uint32_t)irq_ic2_TIM2);
+ */
+void irq_ic2_TIM2(void);    // TIM2 IC2 Interrupt control
+void irq_ic2_TIM3P4(void);  // TIM3 IC2 Interrupt control (same signal connected to TIM4 IC1)
+
 }   // Frequency_counter
 
-#endif      // MBED_FRQ_CUNTR
+#endif  // MBED_FRQ_CUNTR