Frequency counter library only for NucleoF411RE

Dependents:   Frequency_Counter_w_GPS_1PPS

frq_cuntr_full.h

Committer:
kenjiArai
Date:
2014-11-22
Revision:
1:102230f2879d
Parent:
0:bfdc6ed58a06
Child:
2:194f82ad3041

File content as of revision 1:102230f2879d:

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

#ifndef        MBED_FRQ_CUNTR
#define        MBED_FRQ_CUNTR

#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 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);

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