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

Committer:
kenjiArai
Date:
Wed Nov 16 13:15:35 2016 +0000
Revision:
6:be7123d400ae
Parent:
5:783b039f9119
Frequency counter library using GPS 1PPS signal

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 5:783b039f9119 1 /*
kenjiArai 5:783b039f9119 2 * mbed Library / Frequency Counter using GPS 1PPS gate pulse
kenjiArai 5:783b039f9119 3 * Frequency Counter program (Common part)
kenjiArai 5:783b039f9119 4 * Only for ST DISCO-F746NG and Nucleo-F411RE+F446RE
kenjiArai 5:783b039f9119 5 *
kenjiArai 5:783b039f9119 6 * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
kenjiArai 5:783b039f9119 7 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 5:783b039f9119 8 * http://mbed.org/users/kenjiArai/
kenjiArai 5:783b039f9119 9 * Started: October 18th, 2014
kenjiArai 5:783b039f9119 10 * Revised: January 1st, 2015
kenjiArai 5:783b039f9119 11 * Re-started: June 25th, 2016 ported from F411 board
kenjiArai 5:783b039f9119 12 * Re-started: October 5th, 2016 Change board -> DISCO-F746NG
kenjiArai 5:783b039f9119 13 * Re-started: October 17th, 2016 Continue F746 and back to F411
kenjiArai 5:783b039f9119 14 * Revised: November 13th, 2016
kenjiArai 5:783b039f9119 15 *
kenjiArai 5:783b039f9119 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
kenjiArai 5:783b039f9119 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
kenjiArai 5:783b039f9119 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
kenjiArai 5:783b039f9119 19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
kenjiArai 5:783b039f9119 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
kenjiArai 5:783b039f9119 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
kenjiArai 5:783b039f9119 22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
kenjiArai 5:783b039f9119 23 */
kenjiArai 5:783b039f9119 24
kenjiArai 5:783b039f9119 25 #include "fc_GPS1PPS.h"
kenjiArai 5:783b039f9119 26 #include "RingBuff.h"
kenjiArai 5:783b039f9119 27
kenjiArai 5:783b039f9119 28 #define ACTIVE_LED_TIMX 0
kenjiArai 5:783b039f9119 29 #define ACTIVE_LED_TIMZ 0
kenjiArai 5:783b039f9119 30
kenjiArai 5:783b039f9119 31 #if ACTIVE_LED_TIMX || ACTIVE_LED_TIMZ
kenjiArai 5:783b039f9119 32 DigitalOut irq_led1(LED1);
kenjiArai 5:783b039f9119 33 #endif
kenjiArai 5:783b039f9119 34
kenjiArai 5:783b039f9119 35 #if DEBUG
kenjiArai 5:783b039f9119 36 #define PRINTF(...) printf(__VA_ARGS__)
kenjiArai 5:783b039f9119 37 #else
kenjiArai 5:783b039f9119 38 #define PRINTF(...) {;}
kenjiArai 5:783b039f9119 39 #endif
kenjiArai 5:783b039f9119 40
kenjiArai 5:783b039f9119 41 namespace Frequency_counter
kenjiArai 5:783b039f9119 42 {
kenjiArai 5:783b039f9119 43
kenjiArai 5:783b039f9119 44 // TIMxPy IC + OverFlow & TIMz IC
kenjiArai 5:783b039f9119 45 static uint8_t timxpy_ready_flg;
kenjiArai 5:783b039f9119 46 static uint32_t timxpy_cnt_data;
kenjiArai 5:783b039f9119 47 static uint16_t time_count;
kenjiArai 5:783b039f9119 48 static uint16_t sw_ovrflw_timxpy;
kenjiArai 5:783b039f9119 49 static uint32_t timz_cnt_data;
kenjiArai 5:783b039f9119 50 static uint16_t time_count_onepps;
kenjiArai 5:783b039f9119 51 // TIMz IC (Reciprocal) + OverFlow
kenjiArai 5:783b039f9119 52 static uint16_t sw_ovrflw_timz;
kenjiArai 5:783b039f9119 53 static uint8_t recipro_step;
kenjiArai 5:783b039f9119 54 static uint32_t recipro_start;
kenjiArai 5:783b039f9119 55 static uint32_t recipro_stop;
kenjiArai 5:783b039f9119 56
kenjiArai 5:783b039f9119 57 #include "fc_hw_f411.h"
kenjiArai 5:783b039f9119 58 #include "fc_hw_f746.h"
kenjiArai 5:783b039f9119 59
kenjiArai 5:783b039f9119 60 //------------------------------------------------------------------------------
kenjiArai 5:783b039f9119 61 // Frequency Counter Library
kenjiArai 5:783b039f9119 62 //------------------------------------------------------------------------------
kenjiArai 5:783b039f9119 63 FRQ_CUNTR::FRQ_CUNTR(void)
kenjiArai 5:783b039f9119 64 {
kenjiArai 5:783b039f9119 65 initialize_TIMxPy(); // Use for base functuion (FC based on 1PPS)
kenjiArai 5:783b039f9119 66 initialize_TIMz(); // Use for reciprocal
kenjiArai 5:783b039f9119 67 }
kenjiArai 5:783b039f9119 68
kenjiArai 5:783b039f9119 69 // Read new frequency data
kenjiArai 5:783b039f9119 70 double FRQ_CUNTR::read_freq_data(void)
kenjiArai 5:783b039f9119 71 {
kenjiArai 5:783b039f9119 72 return read_freq_w_gate_time(1); // gate time is 1 second
kenjiArai 5:783b039f9119 73 }
kenjiArai 5:783b039f9119 74
kenjiArai 5:783b039f9119 75 // Read new frequency data with specific gate time
kenjiArai 5:783b039f9119 76 double FRQ_CUNTR::read_freq_w_gate_time(uint16_t gt)
kenjiArai 5:783b039f9119 77 {
kenjiArai 5:783b039f9119 78 freq_one f_new, f_old;
kenjiArai 5:783b039f9119 79
kenjiArai 5:783b039f9119 80 if (gt == 0){ return 0.0f;}
kenjiArai 5:783b039f9119 81 f_new.f_1sec_dt = fdt_buffer.ring_get_newest_dt(); // newest data
kenjiArai 5:783b039f9119 82 f_old.f_1sec_dt = fdt_buffer.ring_get_pointed_dt(gt);// gt[sec] before data
kenjiArai 5:783b039f9119 83 uint32_t new_cnt = (uint32_t)f_new.t_cnt;
kenjiArai 5:783b039f9119 84 uint32_t old_cnt = (uint32_t)f_old.t_cnt;
kenjiArai 5:783b039f9119 85 if (old_cnt > new_cnt){
kenjiArai 5:783b039f9119 86 new_cnt += 0x10000;
kenjiArai 5:783b039f9119 87 }
kenjiArai 5:783b039f9119 88 if ((new_cnt - old_cnt) == gt){ // make sure gt[sec]
kenjiArai 5:783b039f9119 89 uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
kenjiArai 5:783b039f9119 90 return (double)dt / (double)gt; // Calculate a frequency value
kenjiArai 5:783b039f9119 91 } else {
kenjiArai 5:783b039f9119 92 return 0.0f; // if gt isn't same as buffered number, cancel calculation
kenjiArai 5:783b039f9119 93 }
kenjiArai 5:783b039f9119 94 }
kenjiArai 5:783b039f9119 95
kenjiArai 5:783b039f9119 96 // Read status (new frequency data is available or not)
kenjiArai 5:783b039f9119 97 uint32_t FRQ_CUNTR::status_freq_update(void)
kenjiArai 5:783b039f9119 98 {
kenjiArai 5:783b039f9119 99 if (timxpy_ready_flg == 0){ // 1PPS is not comming yet
kenjiArai 5:783b039f9119 100 return 0;
kenjiArai 5:783b039f9119 101 } else { // Gate signal is comming
kenjiArai 5:783b039f9119 102 timxpy_ready_flg = 0;
kenjiArai 5:783b039f9119 103 return 1;
kenjiArai 5:783b039f9119 104 }
kenjiArai 5:783b039f9119 105 }
kenjiArai 5:783b039f9119 106
kenjiArai 5:783b039f9119 107 // Calculate diff between new & old 48bit data
kenjiArai 5:783b039f9119 108 uint64_t FRQ_CUNTR::get_diff(uint64_t new_dt, uint64_t old_dt){
kenjiArai 5:783b039f9119 109 uint64_t nw,od;
kenjiArai 5:783b039f9119 110
kenjiArai 5:783b039f9119 111 nw = new_dt & 0x0000ffffffffffff; // select 48bit data
kenjiArai 5:783b039f9119 112 od = old_dt & 0x0000ffffffffffff;
kenjiArai 5:783b039f9119 113 if (nw < od){ // 48bits counter overflow!
kenjiArai 5:783b039f9119 114 nw += 0x0001000000000000;
kenjiArai 5:783b039f9119 115 }
kenjiArai 5:783b039f9119 116 return (nw - od);
kenjiArai 5:783b039f9119 117 }
kenjiArai 5:783b039f9119 118
kenjiArai 5:783b039f9119 119 //------------------------------------------------------------------------------
kenjiArai 5:783b039f9119 120 // Frequency Counter / Reciprocal measurement
kenjiArai 5:783b039f9119 121 //------------------------------------------------------------------------------
kenjiArai 5:783b039f9119 122 /* // Example
kenjiArai 5:783b039f9119 123 int main(){
kenjiArai 5:783b039f9119 124 static double freq_recipro;
kenjiArai 5:783b039f9119 125 static uint32_t interval_recipro, base_clk,run2stop;
kenjiArai 5:783b039f9119 126
kenjiArai 5:783b039f9119 127 while(1){
kenjiArai 5:783b039f9119 128 fc.recipro_start_measure(); // step1
kenjiArai 5:783b039f9119 129 while (fc.recipro_check_trigger() == 0){ // step2
kenjiArai 5:783b039f9119 130 run2stop = tmr.read_ms();
kenjiArai 5:783b039f9119 131 if (run2stop >= 10000){ break;}
kenjiArai 5:783b039f9119 132 }
kenjiArai 5:783b039f9119 133 if (run2stop >= 100000){ // 10sec 0.01Hz
kenjiArai 5:783b039f9119 134 freq_recipro = 0;
kenjiArai 5:783b039f9119 135 } else {
kenjiArai 5:783b039f9119 136 interval_recipro = fc.recipro_read_data(); // step3
kenjiArai 5:783b039f9119 137 base_clk = fc.recipro_base_clk_data(1); // step4
kenjiArai 5:783b039f9119 138 if (interval_recipro >= 9000){// Measure less than 10KHz frequency
kenjiArai 5:783b039f9119 139 // step final
kenjiArai 5:783b039f9119 140 freq_recipro = (double)base_clk / (double)interval_recipro;
kenjiArai 5:783b039f9119 141 } else {
kenjiArai 5:783b039f9119 142 freq_recipro = 0;
kenjiArai 5:783b039f9119 143 }
kenjiArai 5:783b039f9119 144 }
kenjiArai 5:783b039f9119 145 printf("Freq: %11.5f [Hz]", freq_recipro);
kenjiArai 5:783b039f9119 146 printf("Raw: %11u", interval_recipro);
kenjiArai 5:783b039f9119 147 wait(1.0f); // next interval
kenjiArai 5:783b039f9119 148 }
kenjiArai 5:783b039f9119 149 }
kenjiArai 5:783b039f9119 150 */
kenjiArai 5:783b039f9119 151 // step1
kenjiArai 5:783b039f9119 152 void FRQ_CUNTR::recipro_start_measure(void)
kenjiArai 5:783b039f9119 153 {
kenjiArai 5:783b039f9119 154 recipro_step = 0; // initialize step
kenjiArai 5:783b039f9119 155 start_action();
kenjiArai 5:783b039f9119 156 }
kenjiArai 5:783b039f9119 157
kenjiArai 5:783b039f9119 158 // step2
kenjiArai 5:783b039f9119 159 uint32_t FRQ_CUNTR::recipro_check_trigger(void)
kenjiArai 5:783b039f9119 160 {
kenjiArai 5:783b039f9119 161 if (recipro_step == 2){ // check IC event happen or not
kenjiArai 5:783b039f9119 162 return 1; // happen
kenjiArai 5:783b039f9119 163 } else {
kenjiArai 5:783b039f9119 164 return 0; // not yet
kenjiArai 5:783b039f9119 165 }
kenjiArai 5:783b039f9119 166 }
kenjiArai 5:783b039f9119 167
kenjiArai 5:783b039f9119 168 // step3
kenjiArai 5:783b039f9119 169 uint32_t FRQ_CUNTR::recipro_read_data(void)
kenjiArai 5:783b039f9119 170 {
kenjiArai 5:783b039f9119 171 uint64_t dt;
kenjiArai 5:783b039f9119 172 if (recipro_stop < recipro_start){ // 32bit counter overflow
kenjiArai 5:783b039f9119 173 dt = 0x100000000 + recipro_stop;
kenjiArai 5:783b039f9119 174 dt -= recipro_stop;
kenjiArai 5:783b039f9119 175 } else {
kenjiArai 5:783b039f9119 176 dt = recipro_stop - recipro_start;
kenjiArai 5:783b039f9119 177 }
kenjiArai 5:783b039f9119 178 return (uint32_t)dt;
kenjiArai 5:783b039f9119 179 }
kenjiArai 5:783b039f9119 180
kenjiArai 5:783b039f9119 181 // step4
kenjiArai 5:783b039f9119 182 uint32_t FRQ_CUNTR::recipro_base_clk_data(uint16_t gt)
kenjiArai 5:783b039f9119 183 {
kenjiArai 5:783b039f9119 184 freq_one f_new, f_old;
kenjiArai 5:783b039f9119 185
kenjiArai 5:783b039f9119 186 if (gt == 0){ return 0.0f;}
kenjiArai 5:783b039f9119 187 f_new.f_1sec_dt = onepps_buf.ring_get_newest_dt(); // newest data
kenjiArai 5:783b039f9119 188 f_old.f_1sec_dt = onepps_buf.ring_get_pointed_dt(gt);// gt[sec] before data
kenjiArai 5:783b039f9119 189 uint32_t new_cnt = (uint32_t)f_new.t_cnt;
kenjiArai 5:783b039f9119 190 uint32_t old_cnt = (uint32_t)f_old.t_cnt;
kenjiArai 5:783b039f9119 191 if (old_cnt > new_cnt){
kenjiArai 5:783b039f9119 192 new_cnt += 0x10000;
kenjiArai 5:783b039f9119 193 }
kenjiArai 5:783b039f9119 194 if ((new_cnt - old_cnt) == gt){ // make sure gt
kenjiArai 5:783b039f9119 195 uint64_t dt = get_diff(f_new.f_1sec_dt, f_old.f_1sec_dt);
kenjiArai 5:783b039f9119 196 return (double)dt / (double)gt;
kenjiArai 5:783b039f9119 197 } else {
kenjiArai 5:783b039f9119 198 return 0.0f;
kenjiArai 5:783b039f9119 199 }
kenjiArai 5:783b039f9119 200 }
kenjiArai 5:783b039f9119 201
kenjiArai 5:783b039f9119 202 } // Frequency_counter