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

fc_common.cpp

Committer:
kenjiArai
Date:
2016-11-16
Revision:
5:783b039f9119

File content as of revision 5:783b039f9119:

/*
 * 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