Frequency counter library only for DISCO-F746NG & NucleoF411RE +F446RE

Dependencies:   RingBuff

Dependents:   FreqCntr_GPS1PPS_F746F4xx_w_recipro Freq_Cntr_GPS1PPS_F746NG_GUI

Fork of Frq_cuntr_full by Kenji Arai

Revision:
5:783b039f9119
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fc_common.cpp	Wed Nov 16 13:13:09 2016 +0000
@@ -0,0 +1,202 @@
+/*
+ * mbed Library / Frequency Counter using GPS 1PPS gate pulse
+ *      Frequency Counter program (Common part)
+ *      Only for ST DISCO-F746NG and Nucleo-F411RE+F446RE
+ *
+ * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
+ *  http://www.page.sannet.ne.jp/kenjia/index.html
+ *  http://mbed.org/users/kenjiArai/
+ *      Started:    October   18th, 2014
+ *      Revised:    January    1st, 2015
+ *      Re-started: June      25th, 2016    ported from F411 board
+ *      Re-started: October    5th, 2016    Change board -> DISCO-F746NG
+ *      Re-started: October   17th, 2016    Continue F746 and back to F411
+ *      Revised:    November  13th, 2016
+ *
+ * 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.
+ */
+
+#include    "fc_GPS1PPS.h"
+#include    "RingBuff.h"
+
+#define     ACTIVE_LED_TIMX     0
+#define     ACTIVE_LED_TIMZ     0
+
+#if ACTIVE_LED_TIMX || ACTIVE_LED_TIMZ
+DigitalOut irq_led1(LED1);
+#endif
+
+#if DEBUG
+#define PRINTF(...)     printf(__VA_ARGS__)
+#else
+#define PRINTF(...)     {;}
+#endif
+
+namespace Frequency_counter
+{
+
+// TIMxPy IC + OverFlow & TIMz IC
+static uint8_t  timxpy_ready_flg;
+static uint32_t timxpy_cnt_data;
+static uint16_t time_count;
+static uint16_t sw_ovrflw_timxpy;
+static uint32_t timz_cnt_data;
+static uint16_t time_count_onepps;
+// TIMz IC (Reciprocal) + OverFlow
+static uint16_t sw_ovrflw_timz;
+static uint8_t  recipro_step;
+static uint32_t recipro_start;
+static uint32_t recipro_stop;
+
+#include    "fc_hw_f411.h"
+#include    "fc_hw_f746.h"
+
+//------------------------------------------------------------------------------
+//  Frequency Counter Library
+//------------------------------------------------------------------------------
+FRQ_CUNTR::FRQ_CUNTR(void)
+{
+    initialize_TIMxPy();    // Use for base functuion (FC based on 1PPS)
+    initialize_TIMz();      // Use for reciprocal
+}
+
+// Read new frequency data
+double FRQ_CUNTR::read_freq_data(void)
+{
+    return read_freq_w_gate_time(1);    // gate time is 1 second
+}
+
+// Read new frequency data with specific gate time
+double FRQ_CUNTR::read_freq_w_gate_time(uint16_t gt)
+{
+    freq_one f_new, f_old;
+
+    if (gt == 0){ return 0.0f;}
+    f_new.f_1sec_dt = fdt_buffer.ring_get_newest_dt();   // newest data
+    f_old.f_1sec_dt = fdt_buffer.ring_get_pointed_dt(gt);// gt[sec] before data
+    uint32_t new_cnt = (uint32_t)f_new.t_cnt;
+    uint32_t old_cnt = (uint32_t)f_old.t_cnt;
+    if (old_cnt > new_cnt){
+        new_cnt += 0x10000;
+    }
+    if ((new_cnt - old_cnt) == gt){  // make sure gt[sec]
+        uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
+        return (double)dt / (double)gt; // Calculate a frequency value
+    } else {
+        return 0.0f;  // if gt isn't same as buffered number, cancel calculation
+    }
+}
+
+// Read status (new frequency data is available or not)
+uint32_t FRQ_CUNTR::status_freq_update(void)
+{
+    if (timxpy_ready_flg == 0){ // 1PPS is not comming yet
+        return 0;
+    } else {                    // Gate signal is comming
+        timxpy_ready_flg = 0;
+        return 1;
+    }
+}
+
+// Calculate diff between new & old 48bit data
+uint64_t FRQ_CUNTR::get_diff(uint64_t new_dt, uint64_t old_dt){
+    uint64_t nw,od;
+
+    nw = new_dt & 0x0000ffffffffffff;   // select 48bit data
+    od = old_dt & 0x0000ffffffffffff;
+    if (nw < od){ // 48bits counter overflow!
+        nw += 0x0001000000000000;
+    }
+    return (nw - od);
+}
+
+//------------------------------------------------------------------------------
+//  Frequency Counter / Reciprocal measurement
+//------------------------------------------------------------------------------
+/*  // Example
+int main(){
+    static double       freq_recipro;
+    static uint32_t     interval_recipro, base_clk,run2stop;
+
+    while(1){
+        fc.recipro_start_measure();                         // step1
+        while (fc.recipro_check_trigger() == 0){            // step2
+            run2stop = tmr.read_ms();
+            if (run2stop >= 10000){  break;}
+        }
+        if (run2stop >= 100000){ // 10sec 0.01Hz
+            freq_recipro = 0;
+        } else {
+            interval_recipro = fc.recipro_read_data();      // step3
+            base_clk = fc.recipro_base_clk_data(1);         // step4
+            if (interval_recipro >= 9000){// Measure less than 10KHz frequency
+                                                            // step final
+                freq_recipro = (double)base_clk / (double)interval_recipro;
+            } else {
+                freq_recipro = 0;
+            }
+        }
+        printf("Freq: %11.5f [Hz]", freq_recipro);
+        printf("Raw:  %11u", interval_recipro);
+        wait(1.0f);  // next interval
+    }
+}
+ */
+// step1
+void FRQ_CUNTR::recipro_start_measure(void)
+{
+    recipro_step = 0;               // initialize step
+    start_action();
+}
+
+// step2
+uint32_t FRQ_CUNTR::recipro_check_trigger(void)
+{
+    if (recipro_step == 2){         // check IC event happen or not
+        return 1;                   // happen
+    } else {
+        return 0;                   // not yet
+    }
+}
+
+// step3
+uint32_t FRQ_CUNTR::recipro_read_data(void)
+{
+    uint64_t dt;
+    if (recipro_stop < recipro_start){  // 32bit counter overflow
+        dt =  0x100000000 +  recipro_stop;
+        dt -=  recipro_stop;
+    } else {
+        dt = recipro_stop - recipro_start;
+    }
+    return (uint32_t)dt;
+}
+
+// step4
+uint32_t FRQ_CUNTR::recipro_base_clk_data(uint16_t gt)
+{
+    freq_one f_new, f_old;
+
+    if (gt == 0){ return 0.0f;}
+    f_new.f_1sec_dt = onepps_buf.ring_get_newest_dt();   // newest data
+    f_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(gt);// gt[sec] before data
+    uint32_t new_cnt = (uint32_t)f_new.t_cnt;
+    uint32_t old_cnt = (uint32_t)f_old.t_cnt;
+    if (old_cnt > new_cnt){
+        new_cnt += 0x10000;
+    }
+    if ((new_cnt - old_cnt) == gt){  // make sure gt
+        uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
+        return (double)dt / (double)gt;
+    } else {
+        return 0.0f;
+    }
+}
+
+}   // Frequency_counter